/[gxemul]/trunk/src/cpus/cpu_sh_instr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/cpus/cpu_sh_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 40 - (show annotations)
Mon Oct 8 16:22:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 95559 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1539 2007/05/01 04:03:51 debug Exp $
20070415	Landisk PCLOCK should be 33.33 MHz, not 50 MHz. (This makes
		the clock run at correct speed.)
		FINALLY found and fixed the bug which caused OpenBSD/landisk
		to randomly bug out: an &-sign was missing in the special case
		handling of FPSCR in the 'LDS.L @Rm+,FPSCR' instruction.
		Adding similar special case handling for 'LDC.L @Rm+,SR'
		(calling sh_update_sr() instead of just loading).
		Implementing the 'FCNVSD FPUL,DRn' and 'FCNVDS DRm,FPUL'
		SuperH instructions.
		The 'LDC Rm,SR' instruction now immediately breaks out of the
		dyntrans loop if an interrupt is to be triggered.
20070416	In memory_rw.c, if mapping a page as writable, make sure to
		invalidate code translations even if the data access was a
		read.
		Minor SuperH updates.
20070418	Removing the dummy M68K emulation mode.
		Minor SH update (turning unnecessary sts_mach_rn, sts_macl_rn,
		and sts_pr_rn instruction handlers into mov_rm_rn).
20070419	Beginning to add a skeleton for an M88K mode: Adding a hack to
		allow OpenBSD/m88k a.out binaries to be loaded, and disassembly
		of a few simple 88K instructions.
		Commenting out the 'LDC Rm,SR' fix from a few days ago, because
		it made Linux/dreamcast bug out.
		Adding a hack to dev_sh4.c (an extra translation cache
		invalidation), which allows OpenBSD/landisk to boot ok after
		an install. Upgrading the Landisk machine mode to stable,
		updating documentation, etc.
20070420	Experimenting with adding a PCI controller (pcic) to dev_sh4.
		Adding a dummy Realtek 8139C+ skeleton device (dev_rtl8139c).
		Implementing the first M88K instructions (br, or[.u] imm), and
		adding disassembly of some more instructions.
20070421	Continuing a little on dev_rtl8139c.
20070422	Implementing the 9346 EEPROM "read" command for dev_rtl8139c.
		Finally found and fixed an old bug in the log n symbol search
		(it sometimes missed symbols). Debug trace (-i, -t etc) should
		now show more symbols. :-)
20070423	Continuing a little on M88K disassembly.
20070428	Fixing a memset arg order bug in src/net/net.c (thanks to
		Nigel Horne for noticing the bug).
		Applying parts of a patch from Carl van Schaik to clear out
		bottom bits of MIPS addresses more correctly, when using large
		page sizes, and doing some other minor cleanup/refactoring.
		Fixing a couple of warnings given by gcc with the -W option (a
		few more warnings than just plain -Wall).
		Reducing SuperH dyntrans physical address space from 64-bit to
		32-bit (since SH5/SH64 isn't imlemented yet anyway).
		Adding address-to-symbol annotation to a few more instructions
		in the SuperH instruction trace output.
		Beginning regression testing for the next release.
		Reverting the value of SCIF_DELAYED_TX_VALUE from 1 to 2,
		because OpenBSD/landisk may otherwise hang randomly.
20070429	The ugly hack/workaround to get OpenBSD/landisk booting without
		crashing does NOT work anymore (with the April 21 snapshot
		of OpenBSD/landisk). Strangely enough, removing the hack
		completely causes OpenBSD/landisk to work (!).
		More regression testing (re-testing everything SuperH-related,
		and some other things).
		Cobalt interrupts were actually broken; fixing by commenting
		out the DEC21143s in the Cobalt machine.
20070430	More regression testing.
20070501	Updating the OpenBSD/landisk install instructions to use
		4.1 instead of the current snapshot.
		GAAAH! OpenBSD/landisk 4.1 _needs_ the ugly hack/workaround;
		reintroducing it again. (The 4.1 kernel is actually from
		2007-03-11.)
		Simplifying the NetBSD/evbarm install instructions a bit.
		More regression testing.

==============  RELEASE 0.4.5.1  ==============


1 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_sh_instr.c,v 1.56 2007/04/19 15:49:39 debug Exp $
29 *
30 * SH instructions.
31 *
32 * Individual functions should keep track of cpu->n_translated_instrs.
33 * (If no instruction was executed, then it should be decreased. If, say, 4
34 * instructions were combined into one function and executed, then it should
35 * be increased by 3.)
36 */
37
38
39 #define SYNCH_PC { \
40 int low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page) \
41 / sizeof(struct sh_instr_call); \
42 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) \
43 << SH_INSTR_ALIGNMENT_SHIFT); \
44 cpu->pc += (low_pc << SH_INSTR_ALIGNMENT_SHIFT); \
45 }
46
47 #define RES_INST_IF_NOT_MD \
48 if (!(cpu->cd.sh.sr & SH_SR_MD)) { \
49 SYNCH_PC; \
50 sh_exception(cpu, EXPEVT_RES_INST, 0, 0); \
51 return; \
52 }
53
54 #define FLOATING_POINT_AVAILABLE_CHECK \
55 if (cpu->cd.sh.sr & SH_SR_FD) { \
56 /* FPU disabled: Cause exception. */ \
57 SYNCH_PC; \
58 if (cpu->delay_slot) \
59 sh_exception(cpu, EXPEVT_FPU_SLOT_DISABLE, 0, 0);\
60 else \
61 sh_exception(cpu, EXPEVT_FPU_DISABLE, 0, 0); \
62 return; \
63 }
64
65
66 /*
67 * nop: Nothing
68 */
69 X(nop)
70 {
71 }
72
73
74 /*
75 * sleep: Wait for interrupt
76 */
77 X(sleep)
78 {
79 RES_INST_IF_NOT_MD;
80
81 /*
82 * If there is an interrupt, then just return. Otherwise
83 * re-run the sleep instruction (after a delay).
84 */
85 if (cpu->cd.sh.int_to_assert > 0 && !(cpu->cd.sh.sr & SH_SR_BL)
86 && ((cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT)
87 < cpu->cd.sh.int_level)
88 return;
89
90 cpu->cd.sh.next_ic = ic;
91 cpu->is_halted = 1;
92 cpu->has_been_idling = 1;
93
94 /*
95 * There was no interrupt. Let the host sleep for a while.
96 *
97 * TODO:
98 *
99 * Think about how to actually implement this usleep stuff,
100 * in an SMP and/or timing accurate environment.
101 */
102
103 if (cpu->machine->ncpus == 1) {
104 static int x = 0;
105 if ((++x) == 600) {
106 usleep(10);
107 x = 0;
108 }
109 cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
110 }
111 }
112
113
114 /*
115 * sett: t = 1
116 * sets: s = 1
117 * clrt: t = 1
118 * clrs: s = 1
119 * movt_rn: rn = t
120 * clrmac: mach = macl = 0
121 *
122 * arg[1] = ptr to rn
123 */
124 X(sett) { cpu->cd.sh.sr |= SH_SR_T; }
125 X(sets) { cpu->cd.sh.sr |= SH_SR_S; }
126 X(clrt) { cpu->cd.sh.sr &= ~SH_SR_T; }
127 X(clrs) { cpu->cd.sh.sr &= ~SH_SR_S; }
128 X(movt_rn) { reg(ic->arg[1]) = cpu->cd.sh.sr & SH_SR_T? 1 : 0; }
129 X(clrmac) { cpu->cd.sh.macl = cpu->cd.sh.mach = 0; }
130
131
132 /*
133 * mov_rm_rn: rn = rm
134 * neg_rm_rn: rn = -rm
135 * negc_rm_rn: rn = -rm - t, t = borrow
136 * not_rm_rn: rn = ~rm
137 * swap_b_rm_rn: rn = rm with lowest 2 bytes swapped
138 * swap_w_rm_rn: rn = rm with high and low 16-bit words swapped
139 * exts_b_rm_rn: rn = (int8_t) rm
140 * extu_b_rm_rn: rn = (uint8_t) rm
141 * exts_w_rm_rn: rn = (int16_t) rm
142 * extu_w_rm_rn: rn = (uint16_t) rm
143 *
144 * arg[0] = ptr to rm
145 * arg[1] = ptr to rn
146 */
147 X(mov_rm_rn) { reg(ic->arg[1]) = reg(ic->arg[0]); }
148 X(not_rm_rn) { reg(ic->arg[1]) = ~reg(ic->arg[0]); }
149 X(neg_rm_rn) { reg(ic->arg[1]) = -reg(ic->arg[0]); }
150 X(negc_rm_rn)
151 {
152 uint64_t res = 0;
153 res -= (uint64_t) reg(ic->arg[0]);
154 if (cpu->cd.sh.sr & SH_SR_T)
155 res --;
156 if ((res >> 32) & 1)
157 cpu->cd.sh.sr |= SH_SR_T;
158 else
159 cpu->cd.sh.sr &= ~SH_SR_T;
160 reg(ic->arg[1]) = (uint32_t) res;
161 }
162 X(swap_b_rm_rn)
163 {
164 uint32_t r = reg(ic->arg[0]);
165 reg(ic->arg[1]) = (r & 0xffff0000) | ((r >> 8)&0xff) | ((r&0xff) << 8);
166 }
167 X(swap_w_rm_rn)
168 {
169 uint32_t r = reg(ic->arg[0]);
170 reg(ic->arg[1]) = (r >> 16) | (r << 16);
171 }
172 X(exts_b_rm_rn) { reg(ic->arg[1]) = (int8_t)reg(ic->arg[0]); }
173 X(extu_b_rm_rn) { reg(ic->arg[1]) = (uint8_t)reg(ic->arg[0]); }
174 X(exts_w_rm_rn) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); }
175 X(extu_w_rm_rn) { reg(ic->arg[1]) = (uint16_t)reg(ic->arg[0]); }
176
177
178 /*
179 * and_imm_r0: r0 &= imm
180 * xor_imm_r0: r0 ^= imm
181 * tst_imm_r0: t = (r0 & imm) == 0
182 * or_imm_r0: r0 |= imm
183 *
184 * arg[0] = imm
185 */
186 X(and_imm_r0) { cpu->cd.sh.r[0] &= ic->arg[0]; }
187 X(xor_imm_r0) { cpu->cd.sh.r[0] ^= ic->arg[0]; }
188 X(or_imm_r0) { cpu->cd.sh.r[0] |= ic->arg[0]; }
189 X(tst_imm_r0)
190 {
191 if (cpu->cd.sh.r[0] & ic->arg[0])
192 cpu->cd.sh.sr &= ~SH_SR_T;
193 else
194 cpu->cd.sh.sr |= SH_SR_T;
195 }
196
197
198 /*
199 * xor_b_imm_r0_gbr: mem[r0+gbr] |= imm
200 * or_b_imm_r0_gbr: mem[r0+gbr] ^= imm
201 * and_b_imm_r0_gbr: mem[r0+gbr] &= imm
202 *
203 * arg[0] = imm
204 */
205 X(xor_b_imm_r0_gbr)
206 {
207 uint32_t addr = cpu->cd.sh.gbr + cpu->cd.sh.r[0];
208 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
209
210 if (p != NULL) {
211 p[addr & 0xfff] ^= ic->arg[0];
212 } else {
213 uint8_t data;
214 SYNCH_PC;
215 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
216 sizeof(data), MEM_READ, CACHE_DATA)) {
217 /* Exception. */
218 return;
219 }
220 data ^= ic->arg[0];
221 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
222 sizeof(data), MEM_WRITE, CACHE_DATA)) {
223 /* Exception. */
224 return;
225 }
226 }
227 }
228 X(or_b_imm_r0_gbr)
229 {
230 uint32_t addr = cpu->cd.sh.gbr + cpu->cd.sh.r[0];
231 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
232
233 if (p != NULL) {
234 p[addr & 0xfff] |= ic->arg[0];
235 } else {
236 uint8_t data;
237 SYNCH_PC;
238 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
239 sizeof(data), MEM_READ, CACHE_DATA)) {
240 /* Exception. */
241 return;
242 }
243 data |= ic->arg[0];
244 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
245 sizeof(data), MEM_WRITE, CACHE_DATA)) {
246 /* Exception. */
247 return;
248 }
249 }
250 }
251 X(and_b_imm_r0_gbr)
252 {
253 uint32_t addr = cpu->cd.sh.gbr + cpu->cd.sh.r[0];
254 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
255
256 if (p != NULL) {
257 p[addr & 0xfff] &= ic->arg[0];
258 } else {
259 uint8_t data;
260 SYNCH_PC;
261 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
262 sizeof(data), MEM_READ, CACHE_DATA)) {
263 /* Exception. */
264 return;
265 }
266 data &= ic->arg[0];
267 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
268 sizeof(data), MEM_WRITE, CACHE_DATA)) {
269 /* Exception. */
270 return;
271 }
272 }
273 }
274
275
276 /*
277 * mov_imm_rn: Set rn to a signed 8-bit value
278 * add_imm_rn: Add a signed 8-bit value to Rn
279 *
280 * arg[0] = int8_t imm, extended to at least int32_t
281 * arg[1] = ptr to rn
282 */
283 X(mov_imm_rn) { reg(ic->arg[1]) = (int32_t)ic->arg[0]; }
284 X(add_imm_rn) { reg(ic->arg[1]) += (int32_t)ic->arg[0]; }
285
286
287 /*
288 * mov_b_rm_predec_rn: mov.b reg,@-Rn
289 * mov_w_rm_predec_rn: mov.w reg,@-Rn
290 * mov_l_rm_predec_rn: mov.l reg,@-Rn
291 * stc_l_rm_predec_rn_md: mov.l reg,@-Rn, with MD status bit check
292 *
293 * arg[0] = ptr to rm (or other register)
294 * arg[1] = ptr to rn
295 */
296 X(mov_b_rm_predec_rn)
297 {
298 uint32_t addr = reg(ic->arg[1]) - sizeof(uint8_t);
299 int8_t *p = (int8_t *) cpu->cd.sh.host_store[addr >> 12];
300 int8_t data = reg(ic->arg[0]);
301 if (p != NULL) {
302 p[addr & 0xfff] = data;
303 reg(ic->arg[1]) = addr;
304 } else {
305 SYNCH_PC;
306 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
307 sizeof(data), MEM_WRITE, CACHE_DATA)) {
308 /* Exception. */
309 return;
310 }
311 /* The store was ok: */
312 reg(ic->arg[1]) = addr;
313 }
314 }
315 X(mov_w_rm_predec_rn)
316 {
317 uint32_t addr = reg(ic->arg[1]) - sizeof(uint16_t);
318 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
319 uint16_t data = reg(ic->arg[0]);
320
321 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
322 data = LE16_TO_HOST(data);
323 else
324 data = BE16_TO_HOST(data);
325
326 if (p != NULL) {
327 p[(addr & 0xfff) >> 1] = data;
328 reg(ic->arg[1]) = addr;
329 } else {
330 SYNCH_PC;
331 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
332 sizeof(data), MEM_WRITE, CACHE_DATA)) {
333 /* Exception. */
334 return;
335 }
336 /* The store was ok: */
337 reg(ic->arg[1]) = addr;
338 }
339 }
340 X(mov_l_rm_predec_rn)
341 {
342 uint32_t addr = reg(ic->arg[1]) - sizeof(uint32_t);
343 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
344 uint32_t data = reg(ic->arg[0]);
345
346 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
347 data = LE32_TO_HOST(data);
348 else
349 data = BE32_TO_HOST(data);
350
351 if (p != NULL) {
352 p[(addr & 0xfff) >> 2] = data;
353 reg(ic->arg[1]) = addr;
354 } else {
355 SYNCH_PC;
356 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
357 sizeof(data), MEM_WRITE, CACHE_DATA)) {
358 /* Exception. */
359 return;
360 }
361 /* The store was ok: */
362 reg(ic->arg[1]) = addr;
363 }
364 }
365 X(stc_l_rm_predec_rn_md)
366 {
367 uint32_t addr = reg(ic->arg[1]) - sizeof(uint32_t);
368 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
369 uint32_t data = reg(ic->arg[0]);
370
371 RES_INST_IF_NOT_MD;
372
373 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
374 data = LE32_TO_HOST(data);
375 else
376 data = BE32_TO_HOST(data);
377
378 if (p != NULL) {
379 p[(addr & 0xfff) >> 2] = data;
380 reg(ic->arg[1]) = addr;
381 } else {
382 SYNCH_PC;
383 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
384 sizeof(data), MEM_WRITE, CACHE_DATA)) {
385 /* Exception. */
386 return;
387 }
388 /* The store was ok: */
389 reg(ic->arg[1]) = addr;
390 }
391 }
392
393
394 /*
395 * mov_l_disp_pc_rn: Load a 32-bit value into a register,
396 * from an immediate address relative to the pc.
397 *
398 * arg[0] = offset from beginning of the current pc's page
399 * arg[1] = ptr to rn
400 */
401 X(mov_l_disp_pc_rn)
402 {
403 uint32_t addr = ic->arg[0] + (cpu->pc &
404 ~((SH_IC_ENTRIES_PER_PAGE-1) << SH_INSTR_ALIGNMENT_SHIFT));
405 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
406 uint32_t data;
407
408 if (p != NULL) {
409 data = p[(addr & 0xfff) >> 2];
410 } else {
411 SYNCH_PC;
412 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
413 sizeof(data), MEM_READ, CACHE_DATA)) {
414 /* Exception. */
415 return;
416 }
417 }
418 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
419 data = LE32_TO_HOST(data);
420 else
421 data = BE32_TO_HOST(data);
422 reg(ic->arg[1]) = data;
423 }
424
425
426 /*
427 * mova_r0: Set r0 to an address close to the program counter.
428 *
429 * arg[0] = relative offset from beginning of the current pc's page
430 */
431 X(mova_r0)
432 {
433 cpu->cd.sh.r[0] = ic->arg[0] + (cpu->pc &
434 ~((SH_IC_ENTRIES_PER_PAGE-1) << SH_INSTR_ALIGNMENT_SHIFT));
435 }
436
437
438 /*
439 * mov_w_disp_pc_rn: Load a 16-bit value into a register,
440 * from an immediate address relative to the pc.
441 *
442 * arg[0] = offset from beginning of the current pc's page
443 * arg[1] = ptr to rn
444 */
445 X(mov_w_disp_pc_rn)
446 {
447 uint32_t addr = ic->arg[0] + (cpu->pc &
448 ~((SH_IC_ENTRIES_PER_PAGE-1) << SH_INSTR_ALIGNMENT_SHIFT));
449 uint16_t *p = (uint16_t *) cpu->cd.sh.host_load[addr >> 12];
450 uint16_t data;
451
452 if (p != NULL) {
453 data = p[(addr & 0xfff) >> 1];
454 } else {
455 SYNCH_PC;
456 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
457 sizeof(data), MEM_READ, CACHE_DATA)) {
458 /* Exception. */
459 return;
460 }
461 }
462
463 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
464 data = LE16_TO_HOST(data);
465 else
466 data = BE16_TO_HOST(data);
467
468 reg(ic->arg[1]) = (int16_t)data;
469 }
470
471
472 /*
473 * load_b_rm_rn: Load an int8_t value into Rn from address Rm.
474 * load_w_rm_rn: Load an int16_t value into Rn from address Rm.
475 * load_l_rm_rn: Load a 32-bit value into Rn from address Rm.
476 * fmov_rm_frn: Load a floating point value into FRn from address Rm.
477 * fmov_r0_rm_frn: Load a floating point value into FRn from address R0+Rm.
478 * fmov_rm_postinc_frn: Load a floating point value into FRn from address Rm.
479 * mov_b_r0_rm_rn: Load an int8_t value into Rn from address Rm + R0.
480 * mov_w_r0_rm_rn: Load an int16_t value into Rn from address Rm + R0.
481 * mov_l_r0_rm_rn: Load a 32-bit value into Rn from address Rm + R0.
482 * mov_l_disp_rm_rn: Load a 32-bit value into Rn from address Rm + disp.
483 * mov_b_disp_rn_r0: Load an int8_t from Rn+disp into R0.
484 * mov_w_disp_rn_r0: Load an int16_t from Rn+disp into R0.
485 * mov_b_disp_gbr_r0: Load an int8_t from GBR+disp into R0.
486 * mov_w_disp_gbr_r0: Load an int16_t from GBR+disp into R0.
487 * mov_l_disp_gbr_r0: Load an int32_t from GBR+disp into R0.
488 * mov_b_arg1_postinc_to_arg0:
489 * mov_w_arg1_postinc_to_arg0:
490 * mov_l_arg1_postinc_to_arg0:
491 * mov_l_arg1_postinc_to_arg0_md: With MD (privilege level) check.
492 * mov_l_arg1_postinc_to_arg0_fp: With FP check.
493 *
494 * arg[0] = ptr to rm (or rm + (lo4 << 4) for disp)
495 * arg[1] = ptr to rn
496 */
497 X(load_b_rm_rn)
498 {
499 uint32_t addr = reg(ic->arg[0]);
500 uint8_t *p = (uint8_t *) cpu->cd.sh.host_load[addr >> 12];
501 uint8_t data;
502
503 if (p != NULL) {
504 data = p[addr & 0xfff];
505 } else {
506 SYNCH_PC;
507 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
508 sizeof(data), MEM_READ, CACHE_DATA)) {
509 /* Exception. */
510 return;
511 }
512 }
513 reg(ic->arg[1]) = (int8_t) data;
514 }
515 X(load_w_rm_rn)
516 {
517 uint32_t addr = reg(ic->arg[0]);
518 int16_t *p = (int16_t *) cpu->cd.sh.host_load[addr >> 12];
519 int16_t data;
520
521 if (p != NULL) {
522 data = p[(addr & 0xfff) >> 1];
523 } else {
524 SYNCH_PC;
525 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
526 sizeof(data), MEM_READ, CACHE_DATA)) {
527 /* Exception. */
528 return;
529 }
530 }
531 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
532 data = LE16_TO_HOST(data);
533 else
534 data = BE16_TO_HOST(data);
535 reg(ic->arg[1]) = data;
536 }
537 X(load_l_rm_rn)
538 {
539 uint32_t addr = reg(ic->arg[0]);
540 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
541 uint32_t data;
542
543 if (p != NULL) {
544 data = p[(addr & 0xfff) >> 2];
545 } else {
546 SYNCH_PC;
547 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
548 sizeof(data), MEM_READ, CACHE_DATA)) {
549 /* Exception. */
550 return;
551 }
552 }
553
554 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
555 data = LE32_TO_HOST(data);
556 else
557 data = BE32_TO_HOST(data);
558 reg(ic->arg[1]) = data;
559 }
560 X(fmov_rm_frn)
561 {
562 uint32_t addr = reg(ic->arg[0]);
563 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
564 uint32_t data;
565
566 FLOATING_POINT_AVAILABLE_CHECK;
567
568 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
569 fatal("fmov_rm_frn: sz=1 (register pair): TODO\n");
570 exit(1);
571 }
572
573 if (p != NULL) {
574 data = p[(addr & 0xfff) >> 2];
575 } else {
576 SYNCH_PC;
577 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
578 sizeof(data), MEM_READ, CACHE_DATA)) {
579 /* Exception. */
580 return;
581 }
582 }
583
584 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
585 data = LE32_TO_HOST(data);
586 else
587 data = BE32_TO_HOST(data);
588
589 reg(ic->arg[1]) = data;
590 }
591 X(fmov_r0_rm_frn)
592 {
593 uint32_t data, addr = reg(ic->arg[0]) + cpu->cd.sh.r[0];
594 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
595
596 FLOATING_POINT_AVAILABLE_CHECK;
597
598 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
599 fatal("fmov_rm_frn: sz=1 (register pair): TODO\n");
600 exit(1);
601 }
602
603 if (p != NULL) {
604 data = p[(addr & 0xfff) >> 2];
605 } else {
606 SYNCH_PC;
607 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
608 sizeof(data), MEM_READ, CACHE_DATA)) {
609 /* Exception. */
610 return;
611 }
612 }
613
614 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
615 data = LE32_TO_HOST(data);
616 else
617 data = BE32_TO_HOST(data);
618
619 reg(ic->arg[1]) = data;
620 }
621 X(fmov_rm_postinc_frn)
622 {
623 int d = cpu->cd.sh.fpscr & SH_FPSCR_SZ;
624 uint32_t data, data2, addr = reg(ic->arg[0]);
625 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
626 size_t r1 = ic->arg[1];
627
628 if (d) {
629 /* xd instead of dr? */
630 int ofs = (r1 - (size_t)&cpu->cd.sh.fr[0]) / sizeof(uint32_t);
631 if (ofs & 1)
632 r1 = (size_t)&cpu->cd.sh.xf[ofs & ~1];
633 }
634
635 FLOATING_POINT_AVAILABLE_CHECK;
636
637 if (p != NULL) {
638 data = p[(addr & 0xfff) >> 2];
639 } else {
640 SYNCH_PC;
641 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
642 sizeof(data), MEM_READ, CACHE_DATA)) {
643 /* Exception. */
644 return;
645 }
646 }
647
648 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
649 data = LE32_TO_HOST(data);
650 else
651 data = BE32_TO_HOST(data);
652
653 if (d) {
654 /* Double-precision load: */
655 addr += 4;
656 SYNCH_PC;
657 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned
658 char *)&data2, sizeof(data2), MEM_READ, CACHE_DATA))
659 return;
660
661 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
662 data2 = LE32_TO_HOST(data2);
663 else
664 data2 = BE32_TO_HOST(data2);
665 reg(r1 + 4) = data2;
666 }
667
668 reg(r1) = data;
669 reg(ic->arg[0]) = addr + sizeof(uint32_t);
670 }
671 X(mov_b_disp_gbr_r0)
672 {
673 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
674 int8_t *p = (int8_t *) cpu->cd.sh.host_load[addr >> 12];
675 int8_t data;
676 if (p != NULL) {
677 data = p[addr & 0xfff];
678 } else {
679 SYNCH_PC;
680 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
681 sizeof(data), MEM_READ, CACHE_DATA)) {
682 /* Exception. */
683 return;
684 }
685 }
686 cpu->cd.sh.r[0] = data;
687 }
688 X(mov_w_disp_gbr_r0)
689 {
690 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
691 int16_t *p = (int16_t *) cpu->cd.sh.host_load[addr >> 12];
692 int16_t data;
693 if (p != NULL) {
694 data = p[(addr & 0xfff) >> 1];
695 } else {
696 SYNCH_PC;
697 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
698 sizeof(data), MEM_READ, CACHE_DATA)) {
699 /* Exception. */
700 return;
701 }
702 }
703 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
704 data = LE16_TO_HOST(data);
705 else
706 data = BE16_TO_HOST(data);
707 cpu->cd.sh.r[0] = data;
708 }
709 X(mov_l_disp_gbr_r0)
710 {
711 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
712 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
713 uint32_t data;
714 if (p != NULL) {
715 data = p[(addr & 0xfff) >> 2];
716 } else {
717 SYNCH_PC;
718 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
719 sizeof(data), MEM_READ, CACHE_DATA)) {
720 /* Exception. */
721 return;
722 }
723 }
724 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
725 data = LE32_TO_HOST(data);
726 else
727 data = BE32_TO_HOST(data);
728 cpu->cd.sh.r[0] = data;
729 }
730 X(mov_b_arg1_postinc_to_arg0)
731 {
732 uint32_t addr = reg(ic->arg[1]);
733 int8_t *p = (int8_t *) cpu->cd.sh.host_load[addr >> 12];
734 int8_t data;
735 if (p != NULL) {
736 data = p[addr & 0xfff];
737 } else {
738 SYNCH_PC;
739 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
740 sizeof(data), MEM_READ, CACHE_DATA)) {
741 /* Exception. */
742 return;
743 }
744 }
745 /* The load was ok: */
746 reg(ic->arg[1]) = addr + sizeof(int8_t);
747 reg(ic->arg[0]) = data;
748 }
749 X(mov_w_arg1_postinc_to_arg0)
750 {
751 uint32_t addr = reg(ic->arg[1]);
752 uint16_t *p = (uint16_t *) cpu->cd.sh.host_load[addr >> 12];
753 uint16_t data;
754
755 if (p != NULL) {
756 data = p[(addr & 0xfff) >> 1];
757 } else {
758 SYNCH_PC;
759 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
760 sizeof(data), MEM_READ, CACHE_DATA)) {
761 /* Exception. */
762 return;
763 }
764 }
765
766 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
767 data = LE16_TO_HOST(data);
768 else
769 data = BE16_TO_HOST(data);
770 reg(ic->arg[1]) = addr + sizeof(data);
771 reg(ic->arg[0]) = (int16_t)data;
772 }
773 X(mov_l_arg1_postinc_to_arg0)
774 {
775 uint32_t addr = reg(ic->arg[1]);
776 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
777 uint32_t data;
778
779 if (p != NULL) {
780 data = p[(addr & 0xfff) >> 2];
781 } else {
782 SYNCH_PC;
783 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
784 sizeof(data), MEM_READ, CACHE_DATA)) {
785 /* Exception. */
786 return;
787 }
788 }
789 /* The load was ok: */
790 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
791 data = LE32_TO_HOST(data);
792 else
793 data = BE32_TO_HOST(data);
794 reg(ic->arg[1]) = addr + sizeof(data);
795 reg(ic->arg[0]) = data;
796 }
797 X(mov_l_arg1_postinc_to_arg0_md)
798 {
799 uint32_t addr = reg(ic->arg[1]);
800 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
801 uint32_t data;
802
803 RES_INST_IF_NOT_MD;
804
805 if (p != NULL) {
806 data = p[(addr & 0xfff) >> 2];
807 } else {
808 SYNCH_PC;
809 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
810 sizeof(data), MEM_READ, CACHE_DATA)) {
811 /* Exception. */
812 return;
813 }
814 }
815 /* The load was ok: */
816 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
817 data = LE32_TO_HOST(data);
818 else
819 data = BE32_TO_HOST(data);
820 reg(ic->arg[1]) = addr + sizeof(data);
821
822 /* Special case when loading into the SR register: */
823 if (ic->arg[0] == (size_t)&cpu->cd.sh.sr)
824 sh_update_sr(cpu, data);
825 else
826 reg(ic->arg[0]) = data;
827 }
828 X(mov_l_arg1_postinc_to_arg0_fp)
829 {
830 uint32_t addr = reg(ic->arg[1]);
831 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
832 uint32_t data;
833
834 FLOATING_POINT_AVAILABLE_CHECK;
835
836 if (p != NULL) {
837 data = p[(addr & 0xfff) >> 2];
838 } else {
839 SYNCH_PC;
840 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
841 sizeof(data), MEM_READ, CACHE_DATA)) {
842 /* Exception. */
843 return;
844 }
845 }
846 /* The load was ok: */
847 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
848 data = LE32_TO_HOST(data);
849 else
850 data = BE32_TO_HOST(data);
851 reg(ic->arg[1]) = addr + sizeof(data);
852
853 /* Ugly special case for FPSCR: */
854 if (ic->arg[0] == (size_t)&cpu->cd.sh.fpscr)
855 sh_update_fpscr(cpu, data);
856 else
857 reg(ic->arg[0]) = data;
858 }
859 X(mov_b_r0_rm_rn)
860 {
861 uint32_t addr = reg(ic->arg[0]) + cpu->cd.sh.r[0];
862 int8_t *p = (int8_t *) cpu->cd.sh.host_load[addr >> 12];
863 int8_t data;
864
865 if (p != NULL) {
866 data = p[addr & 0xfff];
867 } else {
868 SYNCH_PC;
869 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
870 sizeof(data), MEM_READ, CACHE_DATA)) {
871 /* Exception. */
872 return;
873 }
874 }
875
876 reg(ic->arg[1]) = data;
877 }
878 X(mov_w_r0_rm_rn)
879 {
880 uint32_t addr = reg(ic->arg[0]) + cpu->cd.sh.r[0];
881 int16_t *p = (int16_t *) cpu->cd.sh.host_load[addr >> 12];
882 int16_t data;
883
884 if (p != NULL) {
885 data = p[(addr & 0xfff) >> 1];
886 } else {
887 SYNCH_PC;
888 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
889 sizeof(data), MEM_READ, CACHE_DATA)) {
890 /* Exception. */
891 return;
892 }
893 }
894
895 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
896 data = LE16_TO_HOST(data);
897 else
898 data = BE16_TO_HOST(data);
899 reg(ic->arg[1]) = data;
900 }
901 X(mov_l_r0_rm_rn)
902 {
903 uint32_t addr = reg(ic->arg[0]) + cpu->cd.sh.r[0];
904 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
905 uint32_t data;
906
907 if (p != NULL) {
908 data = p[(addr & 0xfff) >> 2];
909 } else {
910 SYNCH_PC;
911 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
912 sizeof(data), MEM_READ, CACHE_DATA)) {
913 /* Exception. */
914 return;
915 }
916 }
917
918 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
919 data = LE32_TO_HOST(data);
920 else
921 data = BE32_TO_HOST(data);
922 reg(ic->arg[1]) = data;
923 }
924 X(mov_l_disp_rm_rn)
925 {
926 uint32_t addr = cpu->cd.sh.r[ic->arg[0] & 0xf] +
927 ((ic->arg[0] >> 4) << 2);
928 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
929 uint32_t data;
930
931 if (p != NULL) {
932 data = p[(addr & 0xfff) >> 2];
933 } else {
934 SYNCH_PC;
935 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
936 sizeof(data), MEM_READ, CACHE_DATA)) {
937 /* Exception. */
938 return;
939 }
940 }
941
942 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
943 data = LE32_TO_HOST(data);
944 else
945 data = BE32_TO_HOST(data);
946 reg(ic->arg[1]) = data;
947 }
948 X(mov_b_disp_rn_r0)
949 {
950 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
951 uint8_t *p = (uint8_t *) cpu->cd.sh.host_load[addr >> 12];
952 uint8_t data;
953
954 if (p != NULL) {
955 data = p[addr & 0xfff];
956 } else {
957 SYNCH_PC;
958 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
959 sizeof(data), MEM_READ, CACHE_DATA)) {
960 /* Exception. */
961 return;
962 }
963 }
964
965 cpu->cd.sh.r[0] = (int8_t) data;
966 }
967 X(mov_w_disp_rn_r0)
968 {
969 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
970 uint16_t *p = (uint16_t *) cpu->cd.sh.host_load[addr >> 12];
971 uint16_t data;
972
973 if (p != NULL) {
974 data = p[(addr & 0xfff) >> 1];
975 } else {
976 SYNCH_PC;
977 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
978 sizeof(data), MEM_READ, CACHE_DATA)) {
979 /* Exception. */
980 return;
981 }
982 }
983
984 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
985 data = LE16_TO_HOST(data);
986 else
987 data = BE16_TO_HOST(data);
988 cpu->cd.sh.r[0] = (int16_t) data;
989 }
990
991
992 /*
993 * mov_b_store_rm_rn: Store Rm to address Rn (8-bit).
994 * mov_w_store_rm_rn: Store Rm to address Rn (16-bit).
995 * mov_l_store_rm_rn: Store Rm to address Rn (32-bit).
996 * fmov_frm_rn: Store FRm to address Rn.
997 * fmov_frm_r0_rn: Store FRm to address R0 + Rn.
998 * fmov_frm_predec_rn: Store FRm to address Rn - 4 (or 8), update Rn.
999 * mov_b_rm_r0_rn: Store Rm to address Rn + R0 (8-bit).
1000 * mov_w_rm_r0_rn: Store Rm to address Rn + R0 (16-bit).
1001 * mov_l_rm_r0_rn: Store Rm to address Rn + R0 (32-bit).
1002 * mov_b_r0_disp_gbr: Store R0 to address disp + GBR (8-bit).
1003 * mov_w_r0_disp_gbr: Store R0 to address disp + GBR (16-bit).
1004 * mov_l_r0_disp_gbr: Store R0 to address disp + GBR (32-bit).
1005 * mov_l_rm_disp_rn: Store Rm to address disp + Rn.
1006 * mov_b_r0_disp_rn: Store R0 to address disp + Rn (8-bit).
1007 * mov_w_r0_disp_rn: Store R0 to address disp + Rn (16-bit).
1008 *
1009 * arg[0] = ptr to rm
1010 * arg[1] = ptr to rn (or Rn+(disp<<4) for mov_l_rm_disp_rn)
1011 * (or disp for mov_*_r0_disp_gbr)
1012 */
1013 X(mov_b_store_rm_rn)
1014 {
1015 uint32_t addr = reg(ic->arg[1]);
1016 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
1017 uint8_t data = reg(ic->arg[0]);
1018
1019 if (p != NULL) {
1020 p[addr & 0xfff] = data;
1021 } else {
1022 SYNCH_PC;
1023 if (!cpu->memory_rw(cpu, cpu->mem, addr, &data,
1024 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1025 /* Exception. */
1026 return;
1027 }
1028 }
1029 }
1030 X(mov_w_store_rm_rn)
1031 {
1032 uint32_t addr = reg(ic->arg[1]);
1033 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1034 uint16_t data = reg(ic->arg[0]);
1035
1036 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1037 data = LE16_TO_HOST(data);
1038 else
1039 data = BE16_TO_HOST(data);
1040
1041 if (p != NULL) {
1042 p[(addr & 0xfff) >> 1] = data;
1043 } else {
1044 SYNCH_PC;
1045 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1046 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1047 /* Exception. */
1048 return;
1049 }
1050 }
1051 }
1052 X(mov_l_store_rm_rn)
1053 {
1054 uint32_t addr = reg(ic->arg[1]);
1055 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1056 uint32_t data = reg(ic->arg[0]);
1057
1058 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1059 data = LE32_TO_HOST(data);
1060 else
1061 data = BE32_TO_HOST(data);
1062
1063 if (p != NULL) {
1064 p[(addr & 0xfff) >> 2] = data;
1065 } else {
1066 SYNCH_PC;
1067 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1068 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1069 /* Exception. */
1070 return;
1071 }
1072 }
1073 }
1074 X(fmov_frm_rn)
1075 {
1076 uint32_t addr = reg(ic->arg[1]);
1077 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1078 uint32_t data = reg(ic->arg[0]);
1079
1080 FLOATING_POINT_AVAILABLE_CHECK;
1081
1082 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1083 fatal("fmov_frm_rn: sz=1 (register pair): TODO\n");
1084 exit(1);
1085 }
1086
1087 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1088 data = LE32_TO_HOST(data);
1089 else
1090 data = BE32_TO_HOST(data);
1091
1092 if (p != NULL) {
1093 p[(addr & 0xfff) >> 2] = data;
1094 } else {
1095 SYNCH_PC;
1096 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1097 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1098 /* Exception. */
1099 return;
1100 }
1101 }
1102 }
1103 X(fmov_frm_r0_rn)
1104 {
1105 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1106 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1107 uint32_t data = reg(ic->arg[0]);
1108
1109 FLOATING_POINT_AVAILABLE_CHECK;
1110
1111 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1112 fatal("fmov_frm_r0_rn: sz=1 (register pair): TODO\n");
1113 exit(1);
1114 }
1115
1116 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1117 data = LE32_TO_HOST(data);
1118 else
1119 data = BE32_TO_HOST(data);
1120
1121 if (p != NULL) {
1122 p[(addr & 0xfff) >> 2] = data;
1123 } else {
1124 SYNCH_PC;
1125 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1126 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1127 /* Exception. */
1128 return;
1129 }
1130 }
1131 }
1132 X(fmov_frm_predec_rn)
1133 {
1134 int d = cpu->cd.sh.fpscr & SH_FPSCR_SZ? 1 : 0;
1135 uint32_t data, addr = reg(ic->arg[1]) - (d? 8 : 4);
1136 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1137 size_t r0 = ic->arg[0];
1138
1139 if (d) {
1140 /* xd instead of dr? */
1141 int ofs0 = (r0 - (size_t)&cpu->cd.sh.fr[0]) / sizeof(uint32_t);
1142 if (ofs0 & 1)
1143 r0 = (size_t)&cpu->cd.sh.xf[ofs0 & ~1];
1144 }
1145
1146 data = reg(r0);
1147
1148 FLOATING_POINT_AVAILABLE_CHECK;
1149
1150 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1151 data = LE32_TO_HOST(data);
1152 else
1153 data = BE32_TO_HOST(data);
1154
1155 if (p != NULL) {
1156 p[(addr & 0xfff) >> 2] = data;
1157 } else {
1158 SYNCH_PC;
1159 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1160 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1161 /* Exception. */
1162 return;
1163 }
1164 }
1165
1166 if (d) {
1167 /* Store second single-precision floating point word: */
1168 data = reg(r0 + 4);
1169 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1170 data = LE32_TO_HOST(data);
1171 else
1172 data = BE32_TO_HOST(data);
1173 SYNCH_PC;
1174 if (!cpu->memory_rw(cpu, cpu->mem, addr + 4, (unsigned
1175 char *)&data, sizeof(data), MEM_WRITE, CACHE_DATA))
1176 return;
1177 }
1178
1179 reg(ic->arg[1]) = addr;
1180 }
1181 X(mov_b_rm_r0_rn)
1182 {
1183 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1184 int8_t *p = (int8_t *) cpu->cd.sh.host_store[addr >> 12];
1185 int8_t data = reg(ic->arg[0]);
1186 if (p != NULL) {
1187 p[addr & 0xfff] = data;
1188 } else {
1189 SYNCH_PC;
1190 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1191 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1192 /* Exception. */
1193 return;
1194 }
1195 }
1196 }
1197 X(mov_w_rm_r0_rn)
1198 {
1199 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1200 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1201 uint16_t data = reg(ic->arg[0]);
1202
1203 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1204 data = LE16_TO_HOST(data);
1205 else
1206 data = BE16_TO_HOST(data);
1207
1208 if (p != NULL) {
1209 p[(addr & 0xfff) >> 1] = data;
1210 } else {
1211 SYNCH_PC;
1212 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1213 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1214 /* Exception. */
1215 return;
1216 }
1217 }
1218 }
1219 X(mov_l_rm_r0_rn)
1220 {
1221 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1222 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1223 uint32_t data = reg(ic->arg[0]);
1224
1225 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1226 data = LE32_TO_HOST(data);
1227 else
1228 data = BE32_TO_HOST(data);
1229
1230 if (p != NULL) {
1231 p[(addr & 0xfff) >> 2] = data;
1232 } else {
1233 SYNCH_PC;
1234 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1235 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1236 /* Exception. */
1237 return;
1238 }
1239 }
1240 }
1241 X(mov_b_r0_disp_gbr)
1242 {
1243 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
1244 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
1245 uint8_t data = cpu->cd.sh.r[0];
1246 if (p != NULL) {
1247 p[addr & 0xfff] = data;
1248 } else {
1249 SYNCH_PC;
1250 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1251 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1252 /* Exception. */
1253 return;
1254 }
1255 }
1256 }
1257 X(mov_w_r0_disp_gbr)
1258 {
1259 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
1260 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1261 uint16_t data = cpu->cd.sh.r[0];
1262
1263 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1264 data = LE16_TO_HOST(data);
1265 else
1266 data = BE16_TO_HOST(data);
1267
1268 if (p != NULL) {
1269 p[(addr & 0xfff) >> 1] = data;
1270 } else {
1271 SYNCH_PC;
1272 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1273 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1274 /* Exception. */
1275 return;
1276 }
1277 }
1278 }
1279 X(mov_l_r0_disp_gbr)
1280 {
1281 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
1282 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1283 uint32_t data = cpu->cd.sh.r[0];
1284
1285 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1286 data = LE32_TO_HOST(data);
1287 else
1288 data = BE32_TO_HOST(data);
1289
1290 if (p != NULL) {
1291 p[(addr & 0xfff) >> 2] = data;
1292 } else {
1293 SYNCH_PC;
1294 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1295 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1296 /* Exception. */
1297 return;
1298 }
1299 }
1300 }
1301 X(mov_l_rm_disp_rn)
1302 {
1303 uint32_t addr = cpu->cd.sh.r[ic->arg[1] & 0xf] +
1304 ((ic->arg[1] >> 4) << 2);
1305 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1306 uint32_t data = reg(ic->arg[0]);
1307
1308 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1309 data = LE32_TO_HOST(data);
1310 else
1311 data = BE32_TO_HOST(data);
1312
1313 if (p != NULL) {
1314 p[(addr & 0xfff) >> 2] = data;
1315 } else {
1316 SYNCH_PC;
1317 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1318 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1319 /* Exception. */
1320 return;
1321 }
1322 }
1323 }
1324 X(mov_b_r0_disp_rn)
1325 {
1326 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
1327 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
1328 uint8_t data = cpu->cd.sh.r[0];
1329
1330 if (p != NULL) {
1331 p[addr & 0xfff] = data;
1332 } else {
1333 SYNCH_PC;
1334 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1335 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1336 /* Exception. */
1337 return;
1338 }
1339 }
1340 }
1341 X(mov_w_r0_disp_rn)
1342 {
1343 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
1344 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1345 uint16_t data = cpu->cd.sh.r[0];
1346
1347 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1348 data = LE16_TO_HOST(data);
1349 else
1350 data = BE16_TO_HOST(data);
1351
1352 if (p != NULL) {
1353 p[(addr & 0xfff) >> 1] = data;
1354 } else {
1355 SYNCH_PC;
1356 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1357 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1358 /* Exception. */
1359 return;
1360 }
1361 }
1362 }
1363
1364
1365 /*
1366 * add_rm_rn: rn = rn + rm
1367 * addc_rm_rn: rn = rn + rm + t
1368 * and_rm_rn: rn = rn & rm
1369 * xor_rm_rn: rn = rn ^ rm
1370 * or_rm_rn: rn = rn | rm
1371 * sub_rm_rn: rn = rn - rm
1372 * subc_rm_rn: rn = rn - rm - t; t = borrow
1373 * tst_rm_rn: t = ((rm & rn) == 0)
1374 * xtrct_rm_rn: rn = (rn >> 16) | (rm << 16)
1375 *
1376 * arg[0] = ptr to rm
1377 * arg[1] = ptr to rn
1378 */
1379 X(add_rm_rn) { reg(ic->arg[1]) += reg(ic->arg[0]); }
1380 X(addc_rm_rn)
1381 {
1382 uint64_t res = reg(ic->arg[1]);
1383 res += (uint64_t) reg(ic->arg[0]);
1384 if (cpu->cd.sh.sr & SH_SR_T)
1385 res ++;
1386 if ((res >> 32) & 1)
1387 cpu->cd.sh.sr |= SH_SR_T;
1388 else
1389 cpu->cd.sh.sr &= ~SH_SR_T;
1390 reg(ic->arg[1]) = (uint32_t) res;
1391 }
1392 X(and_rm_rn) { reg(ic->arg[1]) &= reg(ic->arg[0]); }
1393 X(xor_rm_rn) { reg(ic->arg[1]) ^= reg(ic->arg[0]); }
1394 X(or_rm_rn) { reg(ic->arg[1]) |= reg(ic->arg[0]); }
1395 X(sub_rm_rn) { reg(ic->arg[1]) -= reg(ic->arg[0]); }
1396 X(subc_rm_rn)
1397 {
1398 uint64_t res = reg(ic->arg[1]);
1399 res -= (uint64_t) reg(ic->arg[0]);
1400 if (cpu->cd.sh.sr & SH_SR_T)
1401 res --;
1402 if ((res >> 32) & 1)
1403 cpu->cd.sh.sr |= SH_SR_T;
1404 else
1405 cpu->cd.sh.sr &= ~SH_SR_T;
1406 reg(ic->arg[1]) = (uint32_t) res;
1407 }
1408 X(tst_rm_rn)
1409 {
1410 if (reg(ic->arg[1]) & reg(ic->arg[0]))
1411 cpu->cd.sh.sr &= ~SH_SR_T;
1412 else
1413 cpu->cd.sh.sr |= SH_SR_T;
1414 }
1415 X(xtrct_rm_rn)
1416 {
1417 uint32_t rn = reg(ic->arg[1]), rm = reg(ic->arg[0]);
1418 reg(ic->arg[1]) = (rn >> 16) | (rm << 16);
1419 }
1420
1421
1422 /*
1423 * div0u: Division step 0; prepare for unsigned division.
1424 * div0s_rm_rn: Division step 0; prepare for signed division.
1425 * div1_rm_rn: Division step 1.
1426 *
1427 * arg[0] = ptr to rm
1428 * arg[1] = ptr to rn
1429 */
1430 X(div0u)
1431 {
1432 cpu->cd.sh.sr &= ~(SH_SR_Q | SH_SR_M | SH_SR_T);
1433 }
1434 X(div0s_rm_rn)
1435 {
1436 int q = reg(ic->arg[1]) >> 31, m = reg(ic->arg[0]) >> 31;
1437 cpu->cd.sh.sr &= ~(SH_SR_Q | SH_SR_M | SH_SR_T);
1438 if (q)
1439 cpu->cd.sh.sr |= SH_SR_Q;
1440 if (m)
1441 cpu->cd.sh.sr |= SH_SR_M;
1442 if (m ^ q)
1443 cpu->cd.sh.sr |= SH_SR_T;
1444 }
1445 X(div1_rm_rn)
1446 {
1447 uint32_t q, old_q = (cpu->cd.sh.sr & SH_SR_Q)? 1 : 0;
1448 uint32_t m = (cpu->cd.sh.sr & SH_SR_M)? 1 : 0;
1449 uint32_t t = (cpu->cd.sh.sr & SH_SR_T)? 1 : 0;
1450 uint32_t op1 = reg(ic->arg[0]), op2 = reg(ic->arg[1]);
1451 uint64_t op2_64;
1452
1453 q = op2 >> 31;
1454 op2_64 = (uint32_t) ((op2 << 1) + t);
1455 if (old_q == m)
1456 op2_64 -= (uint64_t)op1;
1457 else
1458 op2_64 += (uint64_t)op1;
1459 q ^= m ^ ((op2_64 >> 32) & 1);
1460 t = 1 - (q ^ m);
1461 cpu->cd.sh.sr &= ~(SH_SR_Q | SH_SR_T);
1462 if (q)
1463 cpu->cd.sh.sr |= SH_SR_Q;
1464 if (t)
1465 cpu->cd.sh.sr |= SH_SR_T;
1466 reg(ic->arg[1]) = (uint32_t) op2_64;
1467 }
1468
1469
1470 /*
1471 * mul_l_rm_rn: MACL = Rm * Rn (32-bit)
1472 * muls_w_rm_rn: MACL = Rm * Rn (signed 16-bit * 16-bit ==> 32-bit)
1473 * mulu_w_rm_rn: MACL = Rm * Rn (unsigned 16-bit * 16-bit ==> 32-bit)
1474 * dmuls_l_rm_rn: MACH:MACL = Rm * Rn (signed, 64-bit result)
1475 * dmulu_l_rm_rn: MACH:MACL = Rm * Rn (unsigned, 64-bit result)
1476 *
1477 * arg[0] = ptr to rm
1478 * arg[1] = ptr to rn
1479 */
1480 X(mul_l_rm_rn)
1481 {
1482 cpu->cd.sh.macl = reg(ic->arg[0]) * reg(ic->arg[1]);
1483 }
1484 X(muls_w_rm_rn)
1485 {
1486 cpu->cd.sh.macl = (int32_t)(int16_t)reg(ic->arg[0]) *
1487 (int32_t)(int16_t)reg(ic->arg[1]);
1488 }
1489 X(mulu_w_rm_rn)
1490 {
1491 cpu->cd.sh.macl = (int32_t)(uint16_t)reg(ic->arg[0]) *
1492 (int32_t)(uint16_t)reg(ic->arg[1]);
1493 }
1494 X(dmuls_l_rm_rn)
1495 {
1496 uint64_t rm = (int32_t)reg(ic->arg[0]), rn = (int32_t)reg(ic->arg[1]);
1497 uint64_t res = rm * rn;
1498 cpu->cd.sh.mach = (uint32_t) (res >> 32);
1499 cpu->cd.sh.macl = (uint32_t) res;
1500 }
1501 X(dmulu_l_rm_rn)
1502 {
1503 uint64_t rm = reg(ic->arg[0]), rn = reg(ic->arg[1]), res;
1504 res = rm * rn;
1505 cpu->cd.sh.mach = (uint32_t) (res >> 32);
1506 cpu->cd.sh.macl = (uint32_t) res;
1507 }
1508
1509
1510 /*
1511 * cmpeq_imm_r0: rn == int8_t immediate
1512 * cmpeq_rm_rn: rn == rm
1513 * cmphs_rm_rn: rn >= rm, unsigned
1514 * cmpge_rm_rn: rn >= rm, signed
1515 * cmphi_rm_rn: rn > rm, unsigned
1516 * cmpgt_rm_rn: rn > rm, signed
1517 * cmppz_rn: rn >= 0, signed
1518 * cmppl_rn: rn > 0, signed
1519 * cmp_str_rm_rn: t=1 if any bytes in rm and rn match, 0 otherwise
1520 *
1521 * arg[0] = ptr to rm (or imm, for cmpeq_imm_r0)
1522 * arg[1] = ptr to rn
1523 */
1524 X(cmpeq_imm_r0)
1525 {
1526 if (cpu->cd.sh.r[0] == (uint32_t)ic->arg[0])
1527 cpu->cd.sh.sr |= SH_SR_T;
1528 else
1529 cpu->cd.sh.sr &= ~SH_SR_T;
1530 }
1531 X(cmpeq_rm_rn)
1532 {
1533 if (reg(ic->arg[1]) == reg(ic->arg[0]))
1534 cpu->cd.sh.sr |= SH_SR_T;
1535 else
1536 cpu->cd.sh.sr &= ~SH_SR_T;
1537 }
1538 X(cmphs_rm_rn)
1539 {
1540 if (reg(ic->arg[1]) >= reg(ic->arg[0]))
1541 cpu->cd.sh.sr |= SH_SR_T;
1542 else
1543 cpu->cd.sh.sr &= ~SH_SR_T;
1544 }
1545 X(cmpge_rm_rn)
1546 {
1547 if ((int32_t)reg(ic->arg[1]) >= (int32_t)reg(ic->arg[0]))
1548 cpu->cd.sh.sr |= SH_SR_T;
1549 else
1550 cpu->cd.sh.sr &= ~SH_SR_T;
1551 }
1552 X(cmphi_rm_rn)
1553 {
1554 if (reg(ic->arg[1]) > reg(ic->arg[0]))
1555 cpu->cd.sh.sr |= SH_SR_T;
1556 else
1557 cpu->cd.sh.sr &= ~SH_SR_T;
1558 }
1559 X(cmpgt_rm_rn)
1560 {
1561 if ((int32_t)reg(ic->arg[1]) > (int32_t)reg(ic->arg[0]))
1562 cpu->cd.sh.sr |= SH_SR_T;
1563 else
1564 cpu->cd.sh.sr &= ~SH_SR_T;
1565 }
1566 X(cmppz_rn)
1567 {
1568 if ((int32_t)reg(ic->arg[1]) >= 0)
1569 cpu->cd.sh.sr |= SH_SR_T;
1570 else
1571 cpu->cd.sh.sr &= ~SH_SR_T;
1572 }
1573 X(cmppl_rn)
1574 {
1575 if ((int32_t)reg(ic->arg[1]) > 0)
1576 cpu->cd.sh.sr |= SH_SR_T;
1577 else
1578 cpu->cd.sh.sr &= ~SH_SR_T;
1579 }
1580 X(cmp_str_rm_rn)
1581 {
1582 uint32_t r0 = reg(ic->arg[0]), r1 = reg(ic->arg[1]);
1583 int t = 0;
1584 if ((r0 & 0xff000000) == (r1 & 0xff000000))
1585 t = 1;
1586 else if ((r0 & 0xff0000) == (r1 & 0xff0000))
1587 t = 1;
1588 else if ((r0 & 0xff00) == (r1 & 0xff00))
1589 t = 1;
1590 else if ((r0 & 0xff) == (r1 & 0xff))
1591 t = 1;
1592 if (t)
1593 cpu->cd.sh.sr |= SH_SR_T;
1594 else
1595 cpu->cd.sh.sr &= ~SH_SR_T;
1596 }
1597
1598
1599 /*
1600 * shll_rn: Shift rn left by 1 (t = bit that was shifted out)
1601 * shlr_rn: Shift rn right by 1 (t = bit that was shifted out)
1602 * rotl_rn: Shift rn left by 1 (t = bit that was shifted out)
1603 * rotr_rn: Shift rn right by 1 (t = bit that was shifted out)
1604 * shar_rn: Shift rn right arithmetically by 1 (t = bit that was shifted out)
1605 * shllX_rn: Shift rn left logically by X bits
1606 * shlrX_rn: Shift rn right logically by X bits
1607 * rotcl_rn: Rotate rn left via the t bit
1608 * rotcr_rn: Rotate rn right via the t bit
1609 * dt_rn: Decrease rn; t = (rn == 0)
1610 *
1611 * arg[1] = ptr to rn
1612 */
1613 X(shll_rn)
1614 {
1615 uint32_t rn = reg(ic->arg[1]);
1616 if (rn >> 31)
1617 cpu->cd.sh.sr |= SH_SR_T;
1618 else
1619 cpu->cd.sh.sr &= ~SH_SR_T;
1620 reg(ic->arg[1]) = rn << 1;
1621 }
1622 X(shlr_rn)
1623 {
1624 uint32_t rn = reg(ic->arg[1]);
1625 if (rn & 1)
1626 cpu->cd.sh.sr |= SH_SR_T;
1627 else
1628 cpu->cd.sh.sr &= ~SH_SR_T;
1629 reg(ic->arg[1]) = rn >> 1;
1630 }
1631 X(rotl_rn)
1632 {
1633 uint32_t rn = reg(ic->arg[1]);
1634 if (rn >> 31)
1635 cpu->cd.sh.sr |= SH_SR_T;
1636 else
1637 cpu->cd.sh.sr &= ~SH_SR_T;
1638 reg(ic->arg[1]) = (rn << 1) | (rn >> 31);
1639 }
1640 X(rotr_rn)
1641 {
1642 uint32_t rn = reg(ic->arg[1]);
1643 if (rn & 1)
1644 cpu->cd.sh.sr |= SH_SR_T;
1645 else
1646 cpu->cd.sh.sr &= ~SH_SR_T;
1647 reg(ic->arg[1]) = (rn >> 1) | (rn << 31);
1648 }
1649 X(shar_rn)
1650 {
1651 int32_t rn = reg(ic->arg[1]);
1652 if (rn & 1)
1653 cpu->cd.sh.sr |= SH_SR_T;
1654 else
1655 cpu->cd.sh.sr &= ~SH_SR_T;
1656 reg(ic->arg[1]) = rn >> 1;
1657 }
1658 X(rotcl_rn)
1659 {
1660 uint32_t rn = reg(ic->arg[1]), top;
1661 top = rn & 0x80000000;
1662 rn <<= 1;
1663 if (cpu->cd.sh.sr & SH_SR_T)
1664 rn ++;
1665 if (top)
1666 cpu->cd.sh.sr |= SH_SR_T;
1667 else
1668 cpu->cd.sh.sr &= ~SH_SR_T;
1669 reg(ic->arg[1]) = rn;
1670 }
1671 X(rotcr_rn)
1672 {
1673 uint32_t rn = reg(ic->arg[1]), bottom;
1674 bottom = rn & 1;
1675 rn >>= 1;
1676 if (cpu->cd.sh.sr & SH_SR_T)
1677 rn |= 0x80000000;
1678 if (bottom)
1679 cpu->cd.sh.sr |= SH_SR_T;
1680 else
1681 cpu->cd.sh.sr &= ~SH_SR_T;
1682 reg(ic->arg[1]) = rn;
1683 }
1684 X(dt_rn)
1685 {
1686 uint32_t rn = reg(ic->arg[1]) - 1;
1687 if (rn == 0)
1688 cpu->cd.sh.sr |= SH_SR_T;
1689 else
1690 cpu->cd.sh.sr &= ~SH_SR_T;
1691 reg(ic->arg[1]) = rn;
1692 }
1693 X(shll2_rn) { reg(ic->arg[1]) <<= 2; }
1694 X(shll8_rn) { reg(ic->arg[1]) <<= 8; }
1695 X(shll16_rn) { reg(ic->arg[1]) <<= 16; }
1696 X(shlr2_rn) { reg(ic->arg[1]) >>= 2; }
1697 X(shlr8_rn) { reg(ic->arg[1]) >>= 8; }
1698 X(shlr16_rn) { reg(ic->arg[1]) >>= 16; }
1699
1700
1701 /*
1702 * shad: Shift Rn arithmetic left/right, as indicated by Rm. Result in Rn.
1703 * shld: Shift Rn logically left/right, as indicated by Rm. Result in Rn.
1704 *
1705 * arg[0] = ptr to rm
1706 * arg[1] = ptr to rn
1707 */
1708 X(shad)
1709 {
1710 int32_t rn = reg(ic->arg[1]);
1711 int32_t rm = reg(ic->arg[0]);
1712 int sa = rm & 0x1f;
1713
1714 if (rm >= 0)
1715 rn <<= sa;
1716 else if (sa != 0)
1717 rn >>= (32 - sa);
1718 else if (rn < 0)
1719 rn = -1;
1720 else
1721 rn = 0;
1722
1723 reg(ic->arg[1]) = rn;
1724 }
1725 X(shld)
1726 {
1727 uint32_t rn = reg(ic->arg[1]);
1728 int32_t rm = reg(ic->arg[0]);
1729 int sa = rm & 0x1f;
1730
1731 if (rm >= 0)
1732 rn <<= sa;
1733 else if (sa != 0)
1734 rn >>= (32 - sa);
1735 else
1736 rn = 0;
1737
1738 reg(ic->arg[1]) = rn;
1739 }
1740
1741
1742 /*
1743 * bra: Branch using PC relative immediace displacement (with delay-slot)
1744 * bsr: Like bra, but also sets PR to the return address
1745 * braf: Like bra, but using a register instead of an immediate
1746 * bsrf: Like braf, but also sets PR to the return address
1747 *
1748 * arg[0] = immediate offset relative to start of page
1749 * arg[1] = ptr to Rn (for braf/bsrf)
1750 */
1751 X(bra)
1752 {
1753 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1754 SH_INSTR_ALIGNMENT_SHIFT);
1755 target += ic->arg[0];
1756 cpu->delay_slot = TO_BE_DELAYED;
1757 ic[1].f(cpu, ic+1);
1758 cpu->n_translated_instrs ++;
1759 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1760 cpu->pc = target;
1761 cpu->delay_slot = NOT_DELAYED;
1762 quick_pc_to_pointers(cpu);
1763 } else
1764 cpu->delay_slot = NOT_DELAYED;
1765 }
1766 X(bsr)
1767 {
1768 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1769 SH_INSTR_ALIGNMENT_SHIFT);
1770 uint32_t old_pc;
1771 SYNCH_PC;
1772 old_pc = cpu->pc;
1773 target += ic->arg[0];
1774 cpu->delay_slot = TO_BE_DELAYED;
1775 ic[1].f(cpu, ic+1);
1776 cpu->n_translated_instrs ++;
1777 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1778 cpu->cd.sh.pr = old_pc + 4;
1779 cpu->pc = target;
1780 cpu->delay_slot = NOT_DELAYED;
1781 quick_pc_to_pointers(cpu);
1782 } else
1783 cpu->delay_slot = NOT_DELAYED;
1784 }
1785 X(braf_rn)
1786 {
1787 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1788 SH_INSTR_ALIGNMENT_SHIFT);
1789 target += ic->arg[0] + reg(ic->arg[1]);
1790 cpu->delay_slot = TO_BE_DELAYED;
1791 ic[1].f(cpu, ic+1);
1792 cpu->n_translated_instrs ++;
1793 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1794 cpu->pc = target;
1795 cpu->delay_slot = NOT_DELAYED;
1796 quick_pc_to_pointers(cpu);
1797 } else
1798 cpu->delay_slot = NOT_DELAYED;
1799 }
1800 X(bsrf_rn)
1801 {
1802 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1803 SH_INSTR_ALIGNMENT_SHIFT);
1804 uint32_t old_pc;
1805 SYNCH_PC;
1806 old_pc = cpu->pc;
1807 target += ic->arg[0] + reg(ic->arg[1]);
1808 cpu->delay_slot = TO_BE_DELAYED;
1809 ic[1].f(cpu, ic+1);
1810 cpu->n_translated_instrs ++;
1811 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1812 cpu->cd.sh.pr = old_pc + 4;
1813 cpu->pc = target;
1814 cpu->delay_slot = NOT_DELAYED;
1815 quick_pc_to_pointers(cpu);
1816 } else
1817 cpu->delay_slot = NOT_DELAYED;
1818 }
1819
1820
1821 /*
1822 * bt: Branch if true
1823 * bf: Branch if false
1824 * bt/s: Branch if true (with delay-slot)
1825 * bf/s: Branch if false (with delay-slot)
1826 *
1827 * arg[0] = immediate offset relative to start of page
1828 */
1829 X(bt)
1830 {
1831 if (cpu->cd.sh.sr & SH_SR_T) {
1832 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1833 SH_INSTR_ALIGNMENT_SHIFT);
1834 cpu->pc += ic->arg[0];
1835 quick_pc_to_pointers(cpu);
1836 }
1837 }
1838 X(bf)
1839 {
1840 if (!(cpu->cd.sh.sr & SH_SR_T)) {
1841 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1842 SH_INSTR_ALIGNMENT_SHIFT);
1843 cpu->pc += ic->arg[0];
1844 quick_pc_to_pointers(cpu);
1845 }
1846 }
1847 X(bt_s)
1848 {
1849 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1850 SH_INSTR_ALIGNMENT_SHIFT);
1851 int cond = cpu->cd.sh.sr & SH_SR_T;
1852 target += ic->arg[0];
1853 cpu->delay_slot = TO_BE_DELAYED;
1854 ic[1].f(cpu, ic+1);
1855 cpu->n_translated_instrs ++;
1856 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1857 cpu->delay_slot = NOT_DELAYED;
1858 if (cond) {
1859 cpu->pc = target;
1860 quick_pc_to_pointers(cpu);
1861 } else
1862 cpu->cd.sh.next_ic ++;
1863 } else
1864 cpu->delay_slot = NOT_DELAYED;
1865 }
1866 X(bf_s)
1867 {
1868 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1869 SH_INSTR_ALIGNMENT_SHIFT);
1870 int cond = !(cpu->cd.sh.sr & SH_SR_T);
1871 target += ic->arg[0];
1872 cpu->delay_slot = TO_BE_DELAYED;
1873 ic[1].f(cpu, ic+1);
1874 cpu->n_translated_instrs ++;
1875 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1876 cpu->delay_slot = NOT_DELAYED;
1877 if (cond) {
1878 cpu->pc = target;
1879 quick_pc_to_pointers(cpu);
1880 } else
1881 cpu->cd.sh.next_ic ++;
1882 } else
1883 cpu->delay_slot = NOT_DELAYED;
1884 }
1885
1886
1887 /*
1888 * jmp_rn: Jump to Rn
1889 * jsr_rn: Jump to Rn, store return address in PR.
1890 *
1891 * arg[0] = ptr to rn
1892 */
1893 X(jmp_rn)
1894 {
1895 MODE_int_t target = reg(ic->arg[0]);
1896 cpu->delay_slot = TO_BE_DELAYED;
1897 ic[1].f(cpu, ic+1);
1898 cpu->n_translated_instrs ++;
1899 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1900 cpu->pc = target;
1901 cpu->delay_slot = NOT_DELAYED;
1902 quick_pc_to_pointers(cpu);
1903 } else
1904 cpu->delay_slot = NOT_DELAYED;
1905 }
1906 X(jmp_rn_trace)
1907 {
1908 MODE_int_t target = reg(ic->arg[0]);
1909 cpu->delay_slot = TO_BE_DELAYED;
1910 ic[1].f(cpu, ic+1);
1911 cpu->n_translated_instrs ++;
1912 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1913 cpu->pc = target;
1914 #if 0
1915 /* NOTE: Jmp works like both a return, and a subroutine
1916 call. */
1917 cpu_functioncall_trace_return(cpu);
1918 cpu_functioncall_trace(cpu, cpu->pc);
1919 #endif
1920 cpu->delay_slot = NOT_DELAYED;
1921 quick_pc_to_pointers(cpu);
1922 } else
1923 cpu->delay_slot = NOT_DELAYED;
1924 }
1925 X(jsr_rn)
1926 {
1927 MODE_int_t target = reg(ic->arg[0]), retaddr;
1928 cpu->delay_slot = TO_BE_DELAYED;
1929 retaddr = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1930 SH_INSTR_ALIGNMENT_SHIFT);
1931 ic[1].f(cpu, ic+1);
1932 cpu->n_translated_instrs ++;
1933 cpu->cd.sh.pr = retaddr + (int32_t)ic->arg[1];
1934 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1935 cpu->pc = target;
1936 cpu->delay_slot = NOT_DELAYED;
1937 quick_pc_to_pointers(cpu);
1938 } else
1939 cpu->delay_slot = NOT_DELAYED;
1940 }
1941 X(jsr_rn_trace)
1942 {
1943 MODE_int_t target = reg(ic->arg[0]), retaddr;
1944 cpu->delay_slot = TO_BE_DELAYED;
1945 retaddr = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1946 SH_INSTR_ALIGNMENT_SHIFT);
1947 ic[1].f(cpu, ic+1);
1948 cpu->n_translated_instrs ++;
1949 cpu->cd.sh.pr = retaddr + (int32_t)ic->arg[1];
1950 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1951 cpu->pc = target;
1952 cpu_functioncall_trace(cpu, cpu->pc);
1953 cpu->delay_slot = NOT_DELAYED;
1954 quick_pc_to_pointers(cpu);
1955 } else
1956 cpu->delay_slot = NOT_DELAYED;
1957 }
1958
1959
1960 /*
1961 * rts: Jump to PR.
1962 */
1963 X(rts)
1964 {
1965 MODE_int_t target = cpu->cd.sh.pr;
1966 cpu->delay_slot = TO_BE_DELAYED;
1967 ic[1].f(cpu, ic+1);
1968 cpu->n_translated_instrs ++;
1969 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1970 cpu->pc = target;
1971 cpu->delay_slot = NOT_DELAYED;
1972 quick_pc_to_pointers(cpu);
1973 } else
1974 cpu->delay_slot = NOT_DELAYED;
1975 }
1976 X(rts_trace)
1977 {
1978 MODE_int_t target = cpu->cd.sh.pr;
1979 cpu->delay_slot = TO_BE_DELAYED;
1980 ic[1].f(cpu, ic+1);
1981 cpu->n_translated_instrs ++;
1982 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1983 cpu->pc = target;
1984 cpu_functioncall_trace_return(cpu);
1985 cpu->delay_slot = NOT_DELAYED;
1986 quick_pc_to_pointers(cpu);
1987 } else
1988 cpu->delay_slot = NOT_DELAYED;
1989 }
1990
1991
1992 /*
1993 * rte: Return from exception.
1994 */
1995 X(rte)
1996 {
1997 RES_INST_IF_NOT_MD;
1998
1999 cpu->delay_slot = TO_BE_DELAYED;
2000 ic[1].f(cpu, ic+1);
2001 cpu->n_translated_instrs ++;
2002 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
2003 cpu->pc = cpu->cd.sh.spc;
2004 cpu->delay_slot = NOT_DELAYED;
2005 sh_update_sr(cpu, cpu->cd.sh.ssr);
2006 quick_pc_to_pointers(cpu);
2007 } else
2008 cpu->delay_slot = NOT_DELAYED;
2009 }
2010
2011
2012 /*
2013 * ldtlb: Load UTLB entry.
2014 */
2015 X(ldtlb)
2016 {
2017 uint32_t old_hi, old_lo;
2018 int urc = (cpu->cd.sh.mmucr & SH4_MMUCR_URC_MASK)
2019 >> SH4_MMUCR_URC_SHIFT;
2020
2021 RES_INST_IF_NOT_MD;
2022
2023 old_hi = cpu->cd.sh.utlb_hi[urc];
2024 old_lo = cpu->cd.sh.utlb_lo[urc];
2025
2026 cpu->cd.sh.utlb_hi[urc] = cpu->cd.sh.pteh;
2027 cpu->cd.sh.utlb_lo[urc] = cpu->cd.sh.ptel;
2028
2029 /* Invalidate the old mapping, if it belonged to the same ASID: */
2030 if ((old_hi & SH4_PTEH_ASID_MASK) ==
2031 (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK)) {
2032 if ((old_lo & SH4_PTEL_SZ_MASK) == SH4_PTEL_SZ_4K)
2033 cpu->invalidate_translation_caches(cpu,
2034 old_hi & 0xfffff000, INVALIDATE_VADDR);
2035 else
2036 cpu->invalidate_translation_caches(cpu,
2037 0, INVALIDATE_ALL);
2038 }
2039 }
2040
2041
2042 /*
2043 * copy_privileged_register: Copy normal into privileged register, or vice
2044 * versa, after checking the MD status bit.
2045 *
2046 * arg[0] = ptr to source register
2047 * arg[1] = ptr to destination register
2048 */
2049 X(copy_privileged_register)
2050 {
2051 RES_INST_IF_NOT_MD;
2052 reg(ic->arg[1]) = reg(ic->arg[0]);
2053 }
2054
2055
2056 /*
2057 * ldc_rm_sr: Copy Rm into SR, after checking the MD status bit.
2058 *
2059 * arg[1] = ptr to rm
2060 */
2061 X(ldc_rm_sr)
2062 {
2063 RES_INST_IF_NOT_MD;
2064 sh_update_sr(cpu, reg(ic->arg[1]));
2065
2066 #if 0
2067 /* NOTE: This code causes NetBSD/landisk to get past a point where it
2068 otherwise hangs, but it causes Linux/Dreamcast to bug out instead. :/ */
2069
2070 if (!(cpu->cd.sh.sr & SH_SR_BL) && cpu->cd.sh.int_to_assert > 0 &&
2071 ( (cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT)
2072 < cpu->cd.sh.int_level) {
2073 /* Cause interrupt immediately, by dropping out of the
2074 main dyntrans loop: */
2075 cpu->cd.sh.next_ic = &nothing_call;
2076 }
2077 #endif
2078 }
2079
2080
2081 /*
2082 * trapa: Immediate trap.
2083 *
2084 * arg[0] = imm << 2
2085 */
2086 X(trapa)
2087 {
2088 SYNCH_PC;
2089
2090 if (cpu->delay_slot) {
2091 sh_exception(cpu, EXPEVT_SLOT_INST, 0, 0);
2092 return;
2093 }
2094
2095 cpu->cd.sh.tra = ic->arg[0];
2096 sh_exception(cpu, EXPEVT_TRAPA, 0, 0);
2097 }
2098
2099
2100 /*
2101 * copy_fp_register: Copy a register into another, with FP avail check.
2102 * lds_rm_fpscr: Copy Rm into FPSCR.
2103 *
2104 * arg[0] = ptr to source
2105 * arg[1] = ptr to destination
2106 */
2107 X(copy_fp_register)
2108 {
2109 FLOATING_POINT_AVAILABLE_CHECK;
2110 reg(ic->arg[1]) = reg(ic->arg[0]);
2111 }
2112 X(lds_rm_fpscr)
2113 {
2114 FLOATING_POINT_AVAILABLE_CHECK;
2115 sh_update_fpscr(cpu, reg(ic->arg[1]));
2116 }
2117
2118
2119 /*
2120 * fmov_frm_frn: Copy one floating-point register (or pair) to another.
2121 *
2122 * arg[0] = ptr to source float register or pair
2123 * arg[1] = ptr to destination float register or pair
2124 */
2125 X(fmov_frm_frn)
2126 {
2127 size_t r0, r1;
2128 int ofs0, ofs1;
2129
2130 FLOATING_POINT_AVAILABLE_CHECK;
2131
2132 /* Simplest case, single-precision: */
2133 if (!(cpu->cd.sh.fpscr & SH_FPSCR_SZ)) {
2134 reg(ic->arg[1]) = reg(ic->arg[0]);
2135 return;
2136 }
2137
2138 /* Double-precision: */
2139 r0 = ic->arg[0]; r1 = ic->arg[1];
2140 ofs0 = (r0 - (size_t)&cpu->cd.sh.fr[0]) / sizeof(uint32_t);
2141 ofs1 = (r1 - (size_t)&cpu->cd.sh.fr[0]) / sizeof(uint32_t);
2142 if (ofs0 & 1)
2143 r0 = (size_t)&cpu->cd.sh.xf[ofs0 & ~1];
2144 if (ofs1 & 1)
2145 r1 = (size_t)&cpu->cd.sh.xf[ofs1 & ~1];
2146
2147 reg(r1) = reg(r0);
2148 reg(r1 + 4) = reg(r0 + 4);
2149 }
2150
2151
2152 /*
2153 * float_fpul_frn: Load FPUL into float register.
2154 *
2155 * arg[0] = ptr to float register, or float register pair
2156 */
2157 X(float_fpul_frn)
2158 {
2159 int32_t fpul = cpu->cd.sh.fpul;
2160
2161 FLOATING_POINT_AVAILABLE_CHECK;
2162
2163 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2164 /* Double-precision, using a pair of registers: */
2165 uint64_t ieee = ieee_store_float_value(fpul, IEEE_FMT_D, 0);
2166 reg(ic->arg[0]) = (uint32_t) (ieee >> 32);
2167 reg(ic->arg[0] + sizeof(uint32_t)) = (uint32_t) ieee;
2168 } else {
2169 /* Single-precision: */
2170 uint32_t ieee = ieee_store_float_value(fpul, IEEE_FMT_S, 0);
2171 reg(ic->arg[0]) = (uint32_t) ieee;
2172 }
2173 }
2174
2175
2176 /*
2177 * ftrc_frm_fpul: Truncate a float register into FPUL.
2178 *
2179 * arg[0] = ptr to float register, or float register pair
2180 */
2181 X(ftrc_frm_fpul)
2182 {
2183 struct ieee_float_value op1;
2184
2185 FLOATING_POINT_AVAILABLE_CHECK;
2186
2187 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2188 /* Double-precision, using a pair of registers: */
2189 int64_t r1 = ((uint64_t)reg(ic->arg[0]) << 32) +
2190 reg(ic->arg[0] + sizeof(uint32_t));
2191 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2192 cpu->cd.sh.fpul = (int32_t) op1.f;
2193 } else {
2194 /* Single-precision: */
2195 ieee_interpret_float_value(reg(ic->arg[0]), &op1, IEEE_FMT_S);
2196 cpu->cd.sh.fpul = (int32_t) op1.f;
2197 }
2198 }
2199
2200
2201 /*
2202 * fcnvsd_fpul_drn: Convert single-precision to double-precision.
2203 * fcnvds_drm_fpul: Convert double-precision to single-precision.
2204 *
2205 * arg[0] = ptr to destination (double- or single-precision float)
2206 */
2207 X(fcnvsd_fpul_drn)
2208 {
2209 struct ieee_float_value op1;
2210 int64_t ieee;
2211
2212 FLOATING_POINT_AVAILABLE_CHECK;
2213
2214 ieee_interpret_float_value(cpu->cd.sh.fpul, &op1, IEEE_FMT_S);
2215 cpu->cd.sh.fpul = (int32_t) op1.f;
2216
2217 /* Store double-precision result: */
2218 ieee = ieee_store_float_value(op1.f, IEEE_FMT_D, 0);
2219 reg(ic->arg[0]) = (uint32_t) (ieee >> 32);
2220 reg(ic->arg[0] + sizeof(uint32_t)) = (uint32_t) ieee;
2221 }
2222 X(fcnvds_drm_fpul)
2223 {
2224 struct ieee_float_value op1;
2225 int64_t r1;
2226
2227 FLOATING_POINT_AVAILABLE_CHECK;
2228
2229 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2230 ((uint64_t)reg(ic->arg[0]) << 32);
2231 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2232
2233 cpu->cd.sh.fpul = ieee_store_float_value(op1.f, IEEE_FMT_S, 0);
2234 }
2235
2236
2237 /*
2238 * fsca_fpul_drn: Sinus/cosinus approximation.
2239 *
2240 * Note: This is an interesting instruction. It is not included in the SH4
2241 * manual. Some googling indicated that this might be an SH4X instruction.
2242 * On the other hand, it is used by Dreamcast code (and the Dreamcast has an
2243 * SH4), and a cvs comment for gdb said that this is an SH4 instruction, not
2244 * an SH4A instruction. Well well...
2245 *
2246 * arg[0] = ptr to single-precision float register pair
2247 */
2248 X(fsca_fpul_drn)
2249 {
2250 double fpul = ((double) (int32_t)cpu->cd.sh.fpul) / 32768.0;
2251
2252 FLOATING_POINT_AVAILABLE_CHECK;
2253
2254 reg(ic->arg[0]) = ieee_store_float_value(sin(fpul), IEEE_FMT_S, 0);
2255 reg(ic->arg[0] + sizeof(uint32_t)) =
2256 ieee_store_float_value(cos(fpul), IEEE_FMT_S, 0);
2257 }
2258
2259
2260 /*
2261 * ftrv_xmtrx_fvn: Matrix * vector ==> vector
2262 *
2263 * arg[0] = ptr to FVn
2264 */
2265 X(ftrv_xmtrx_fvn)
2266 {
2267 int i;
2268 struct ieee_float_value xmtrx[16], frn[4];
2269 double frnp0 = 0.0, frnp1 = 0.0, frnp2 = 0.0, frnp3 = 0.0;
2270
2271 ieee_interpret_float_value(reg(ic->arg[0] + 0), &frn[0], IEEE_FMT_S);
2272 ieee_interpret_float_value(reg(ic->arg[0] + 4), &frn[1], IEEE_FMT_S);
2273 ieee_interpret_float_value(reg(ic->arg[0] + 8), &frn[2], IEEE_FMT_S);
2274 ieee_interpret_float_value(reg(ic->arg[0] + 12), &frn[3], IEEE_FMT_S);
2275
2276 for (i=0; i<16; i++)
2277 ieee_interpret_float_value(cpu->cd.sh.xf[i],
2278 &xmtrx[i], IEEE_FMT_S);
2279
2280 for (i=0; i<4; i++)
2281 frnp0 += xmtrx[i*4].f * frn[i].f;
2282
2283 for (i=0; i<4; i++)
2284 frnp1 += xmtrx[i*4 + 1].f * frn[i].f;
2285
2286 for (i=0; i<4; i++)
2287 frnp2 += xmtrx[i*4 + 2].f * frn[i].f;
2288
2289 for (i=0; i<4; i++)
2290 frnp3 += xmtrx[i*4 + 3].f * frn[i].f;
2291
2292 reg(ic->arg[0] + 0) = ieee_store_float_value(frnp0, IEEE_FMT_S, 0);
2293 reg(ic->arg[0] + 4) = ieee_store_float_value(frnp1, IEEE_FMT_S, 0);
2294 reg(ic->arg[0] + 8) = ieee_store_float_value(frnp2, IEEE_FMT_S, 0);
2295 reg(ic->arg[0] + 12) = ieee_store_float_value(frnp3, IEEE_FMT_S, 0);
2296 }
2297
2298
2299 /*
2300 * fldi: Load immediate (0.0 or 1.0) into floating point register.
2301 * fneg: Negate a floating point register
2302 * fabs: Get the absolute value of a floating point register
2303 * fsqrt: Calculate square root
2304 *
2305 * arg[0] = ptr to fp register
2306 * arg[1] = (uint32_t) immediate value (for fldi)
2307 */
2308 X(fldi_frn)
2309 {
2310 FLOATING_POINT_AVAILABLE_CHECK;
2311 reg(ic->arg[0]) = ic->arg[1];
2312 }
2313 X(fneg_frn)
2314 {
2315 FLOATING_POINT_AVAILABLE_CHECK;
2316 /* Note: This also works for double-precision. */
2317 reg(ic->arg[0]) ^= 0x80000000;
2318 }
2319 X(fabs_frn)
2320 {
2321 FLOATING_POINT_AVAILABLE_CHECK;
2322 /* Note: This also works for double-precision. */
2323 reg(ic->arg[0]) &= 0x7fffffff;
2324 }
2325 X(fsqrt_frn)
2326 {
2327 struct ieee_float_value op1;
2328
2329 FLOATING_POINT_AVAILABLE_CHECK;
2330
2331 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2332 /* Double-precision: */
2333 int64_t r1, ieee;
2334 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2335 ((uint64_t)reg(ic->arg[0]) << 32);
2336 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2337 ieee = ieee_store_float_value(sqrt(op1.f), IEEE_FMT_D, 0);
2338 reg(ic->arg[0]) = (uint32_t) (ieee >> 32);
2339 reg(ic->arg[0] + sizeof(uint32_t)) = (uint32_t) ieee;
2340 } else {
2341 /* Single-precision: */
2342 int32_t ieee, r1 = reg(ic->arg[0]);
2343 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2344 ieee = ieee_store_float_value(sqrt(op1.f), IEEE_FMT_S, 0);
2345 reg(ic->arg[0]) = ieee;
2346 }
2347 }
2348
2349
2350 /*
2351 * fadd_frm_frn: Floating point addition.
2352 * fsub_frm_frn: Floating point subtraction.
2353 * fmul_frm_frn: Floating point multiplication.
2354 * fdiv_frm_frn: Floating point division.
2355 * fmac_fr0_frm_frn: Multiply-and-accumulate.
2356 * fcmp_eq_frm_frn: Floating point greater-than comparison.
2357 * fcmp_gt_frm_frn: Floating point greater-than comparison.
2358 *
2359 * arg[0] = ptr to float register FRm
2360 * arg[1] = ptr to float register FRn
2361 */
2362 X(fadd_frm_frn)
2363 {
2364 struct ieee_float_value op1, op2;
2365
2366 FLOATING_POINT_AVAILABLE_CHECK;
2367
2368 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2369 /* Double-precision, using a pair of registers: */
2370 int64_t r1, r2, ieee;
2371 double result;
2372
2373 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2374 ((uint64_t)reg(ic->arg[0]) << 32);
2375 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2376 ((uint64_t)reg(ic->arg[1]) << 32);
2377 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2378 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2379
2380 result = op2.f + op1.f;
2381 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2382 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2383 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2384 } else {
2385 /* Single-precision: */
2386 uint32_t r1, r2, ieee;
2387 double result;
2388
2389 r1 = reg(ic->arg[0]);
2390 r2 = reg(ic->arg[1]);
2391 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2392 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2393
2394 result = op2.f + op1.f;
2395 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2396 reg(ic->arg[1]) = (uint32_t) ieee;
2397 }
2398 }
2399 X(fsub_frm_frn)
2400 {
2401 struct ieee_float_value op1, op2;
2402
2403 FLOATING_POINT_AVAILABLE_CHECK;
2404
2405 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2406 /* Double-precision, using a pair of registers: */
2407 int64_t r1, r2, ieee;
2408 double result;
2409 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2410 ((uint64_t)reg(ic->arg[0]) << 32);
2411 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2412 ((uint64_t)reg(ic->arg[1]) << 32);
2413 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2414 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2415 result = op2.f - op1.f;
2416 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2417 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2418 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2419 } else {
2420 /* Single-precision: */
2421 uint32_t r1, r2, ieee;
2422 double result;
2423 r1 = reg(ic->arg[0]);
2424 r2 = reg(ic->arg[1]);
2425 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2426 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2427 result = op2.f - op1.f;
2428 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2429 reg(ic->arg[1]) = (uint32_t) ieee;
2430 }
2431 }
2432 X(fmul_frm_frn)
2433 {
2434 struct ieee_float_value op1, op2;
2435
2436 FLOATING_POINT_AVAILABLE_CHECK;
2437
2438 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2439 /* Double-precision, using a pair of registers: */
2440 int64_t r1, r2, ieee;
2441 double result;
2442
2443 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2444 ((uint64_t)reg(ic->arg[0]) << 32);
2445 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2446 ((uint64_t)reg(ic->arg[1]) << 32);
2447 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2448 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2449
2450 result = op2.f * op1.f;
2451 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2452 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2453 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2454 } else {
2455 /* Single-precision: */
2456 uint32_t r1, r2, ieee;
2457 double result;
2458
2459 r1 = reg(ic->arg[0]);
2460 r2 = reg(ic->arg[1]);
2461 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2462 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2463
2464 result = op2.f * op1.f;
2465 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2466 reg(ic->arg[1]) = (uint32_t) ieee;
2467 }
2468 }
2469 X(fdiv_frm_frn)
2470 {
2471 struct ieee_float_value op1, op2;
2472
2473 FLOATING_POINT_AVAILABLE_CHECK;
2474
2475 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2476 /* Double-precision, using a pair of registers: */
2477 int64_t r1, r2, ieee;
2478 double result;
2479
2480 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2481 ((uint64_t)reg(ic->arg[0]) << 32);
2482 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2483 ((uint64_t)reg(ic->arg[1]) << 32);
2484 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2485 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2486
2487 if (op1.f != 0.0)
2488 result = op2.f / op1.f;
2489 else
2490 result = 0.0;
2491
2492 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2493
2494 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2495 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2496 } else {
2497 /* Single-precision: */
2498 uint32_t r1, r2, ieee;
2499 double result;
2500
2501 r1 = reg(ic->arg[0]);
2502 r2 = reg(ic->arg[1]);
2503 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2504 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2505
2506 if (op1.f != 0.0)
2507 result = op2.f / op1.f;
2508 else
2509 result = 0.0;
2510
2511 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2512
2513 reg(ic->arg[1]) = (uint32_t) ieee;
2514 }
2515 }
2516 X(fmac_fr0_frm_frn)
2517 {
2518 struct ieee_float_value op1, op2, op0;
2519 int32_t r1, r2, fr0 = cpu->cd.sh.fr[0], ieee;
2520
2521 FLOATING_POINT_AVAILABLE_CHECK;
2522
2523 r1 = reg(ic->arg[0]), r2 = reg(ic->arg[1]);
2524 ieee_interpret_float_value(fr0, &op0, IEEE_FMT_S);
2525 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2526 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2527 ieee = ieee_store_float_value(op0.f * op1.f + op2.f, IEEE_FMT_S, 0);
2528 reg(ic->arg[1]) = ieee;
2529 }
2530 X(fcmp_eq_frm_frn)
2531 {
2532 struct ieee_float_value op1, op2;
2533
2534 FLOATING_POINT_AVAILABLE_CHECK;
2535
2536 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2537 /* Double-precision, using a pair of registers: */
2538 int64_t r1, r2;
2539 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2540 ((uint64_t)reg(ic->arg[0]) << 32);
2541 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2542 ((uint64_t)reg(ic->arg[1]) << 32);
2543 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2544 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2545 } else {
2546 /* Single-precision: */
2547 uint32_t r1 = reg(ic->arg[0]), r2 = reg(ic->arg[1]);
2548 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2549 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2550 }
2551
2552 if (op2.f == op1.f)
2553 cpu->cd.sh.sr |= SH_SR_T;
2554 else
2555 cpu->cd.sh.sr &= ~SH_SR_T;
2556 }
2557 X(fcmp_gt_frm_frn)
2558 {
2559 struct ieee_float_value op1, op2;
2560
2561 FLOATING_POINT_AVAILABLE_CHECK;
2562
2563 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2564 /* Double-precision, using a pair of registers: */
2565 int64_t r1, r2;
2566 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2567 ((uint64_t)reg(ic->arg[0]) << 32);
2568 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2569 ((uint64_t)reg(ic->arg[1]) << 32);
2570 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2571 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2572 } else {
2573 /* Single-precision: */
2574 uint32_t r1 = reg(ic->arg[0]), r2 = reg(ic->arg[1]);
2575 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2576 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2577 }
2578
2579 if (op2.f > op1.f)
2580 cpu->cd.sh.sr |= SH_SR_T;
2581 else
2582 cpu->cd.sh.sr &= ~SH_SR_T;
2583 }
2584
2585
2586 /*
2587 * frchg: Change floating-point register banks.
2588 * fschg: Change floating-point register size.
2589 */
2590 X(frchg)
2591 {
2592 FLOATING_POINT_AVAILABLE_CHECK;
2593 sh_update_fpscr(cpu, cpu->cd.sh.fpscr ^ SH_FPSCR_FR);
2594 }
2595 X(fschg)
2596 {
2597 FLOATING_POINT_AVAILABLE_CHECK;
2598 sh_update_fpscr(cpu, cpu->cd.sh.fpscr ^ SH_FPSCR_SZ);
2599 }
2600
2601
2602 /*
2603 * pref_rn: Prefetch.
2604 *
2605 * arg[1] = ptr to Rn
2606 */
2607 X(pref_rn)
2608 {
2609 uint32_t addr = reg(ic->arg[1]), extaddr;
2610 int sq_nr, ofs;
2611
2612 if (addr < 0xe0000000 || addr >= 0xe4000000)
2613 return;
2614
2615 /* Send Store Queue contents to external memory: */
2616 extaddr = addr & 0x03ffffe0;
2617 sq_nr = addr & 0x20? 1 : 0;
2618
2619 if (cpu->cd.sh.mmucr & SH4_MMUCR_AT) {
2620 fatal("Store Queue to external memory, when "
2621 "MMU enabled: TODO\n");
2622 exit(1);
2623 }
2624
2625 if (sq_nr == 0)
2626 extaddr |= (((cpu->cd.sh.qacr0 >> 2) & 7) << 26);
2627 else
2628 extaddr |= (((cpu->cd.sh.qacr1 >> 2) & 7) << 26);
2629
2630 /* fatal("extaddr = 0x%08x\n", extaddr); */
2631
2632 SYNCH_PC;
2633 for (ofs = 0; ofs < 32; ofs += sizeof(uint32_t)) {
2634 uint32_t word;
2635 cpu->memory_rw(cpu, cpu->mem, 0xe0000000 + ofs
2636 + sq_nr * 0x20, (unsigned char *)
2637 &word, sizeof(word), MEM_READ, PHYSICAL);
2638 cpu->memory_rw(cpu, cpu->mem, extaddr+ofs, (unsigned char *)
2639 &word, sizeof(word), MEM_WRITE, PHYSICAL);
2640 }
2641 }
2642
2643
2644 /*
2645 * tas_b_rn: Test-and-Set.
2646 *
2647 * arg[1] = ptr to Rn
2648 */
2649 X(tas_b_rn)
2650 {
2651 uint32_t addr = reg(ic->arg[1]);
2652 uint8_t byte, newbyte;
2653
2654 SYNCH_PC;
2655
2656 if (!cpu->memory_rw(cpu, cpu->mem, addr, &byte, 1, MEM_READ,
2657 CACHE_DATA)) {
2658 /* Exception. */
2659 return;
2660 }
2661
2662 newbyte = byte | 0x80;
2663
2664 if (!cpu->memory_rw(cpu, cpu->mem, addr, &newbyte, 1, MEM_WRITE,
2665 CACHE_DATA)) {
2666 /* Exception. */
2667 return;
2668 }
2669
2670 if (byte == 0)
2671 cpu->cd.sh.sr |= SH_SR_T;
2672 else
2673 cpu->cd.sh.sr &= ~SH_SR_T;
2674 }
2675
2676
2677 /*
2678 * prom_emul:
2679 */
2680 X(prom_emul)
2681 {
2682 uint32_t old_pc;
2683 SYNCH_PC;
2684 old_pc = cpu->pc;
2685
2686 switch (cpu->machine->machine_type) {
2687 case MACHINE_DREAMCAST:
2688 dreamcast_emul(cpu);
2689 break;
2690 case MACHINE_LANDISK:
2691 sh_ipl_g_emul(cpu);
2692 break;
2693 default:
2694 fatal("SH prom_emul: unimplemented machine type.\n");
2695 exit(1);
2696 }
2697
2698 if (!cpu->running) {
2699 cpu->n_translated_instrs --;
2700 cpu->cd.sh.next_ic = &nothing_call;
2701 } else if ((uint32_t)cpu->pc != old_pc) {
2702 /* The PC value was changed by the PROM call. */
2703 quick_pc_to_pointers(cpu);
2704 }
2705 }
2706
2707
2708 /*****************************************************************************/
2709
2710
2711 X(end_of_page)
2712 {
2713 /* Update the PC: (offset 0, but on the next page) */
2714 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) <<
2715 SH_INSTR_ALIGNMENT_SHIFT);
2716 cpu->pc += (SH_IC_ENTRIES_PER_PAGE << SH_INSTR_ALIGNMENT_SHIFT);
2717
2718 /* end_of_page doesn't count as an executed instruction: */
2719 cpu->n_translated_instrs --;
2720
2721 /*
2722 * Find the new physpage and update translation pointers.
2723 *
2724 * Note: This may cause an exception, if e.g. the new page is
2725 * not accessible.
2726 */
2727 quick_pc_to_pointers(cpu);
2728
2729 /* Simple jump to the next page (if we are lucky): */
2730 if (cpu->delay_slot == NOT_DELAYED)
2731 return;
2732
2733 /*
2734 * If we were in a delay slot, and we got an exception while doing
2735 * quick_pc_to_pointers, then return. The function which called
2736 * end_of_page should handle this case.
2737 */
2738 if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
2739 return;
2740
2741 /*
2742 * Tricky situation; the delay slot is on the next virtual page.
2743 * Calling to_be_translated will translate one instruction manually,
2744 * execute it, and then discard it.
2745 */
2746 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
2747
2748 instr(to_be_translated)(cpu, cpu->cd.sh.next_ic);
2749
2750 /* The instruction in the delay slot has now executed. */
2751 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2752 cpu->delay_slot); */
2753
2754 /* Find the physpage etc of the instruction in the delay slot
2755 (or, if there was an exception, the exception handler): */
2756 quick_pc_to_pointers(cpu);
2757 }
2758
2759
2760 X(end_of_page2)
2761 {
2762 /* Synchronize PC on the _second_ instruction on the next page: */
2763 int low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page)
2764 / sizeof(struct sh_instr_call);
2765 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1)
2766 << SH_INSTR_ALIGNMENT_SHIFT);
2767 cpu->pc += (low_pc << SH_INSTR_ALIGNMENT_SHIFT);
2768
2769 /* This doesn't count as an executed instruction. */
2770 cpu->n_translated_instrs --;
2771
2772 quick_pc_to_pointers(cpu);
2773
2774 if (cpu->delay_slot == NOT_DELAYED)
2775 return;
2776
2777 fatal("end_of_page2: fatal error, we're in a delay slot\n");
2778 exit(1);
2779 }
2780
2781
2782 /*****************************************************************************/
2783
2784
2785 /*
2786 * sh_instr_to_be_translated():
2787 *
2788 * Translate an instruction word into an sh_instr_call. ic is filled in with
2789 * valid data for the translated instruction, or a "nothing" instruction if
2790 * there was a translation failure. The newly translated instruction is then
2791 * executed.
2792 */
2793 X(to_be_translated)
2794 {
2795 uint64_t addr, low_pc;
2796 uint32_t iword;
2797 unsigned char *page;
2798 unsigned char ib[4];
2799 int main_opcode, isize = cpu->cd.sh.compact? 2 : sizeof(ib);
2800 int in_crosspage_delayslot = 0, r8, r4, lo4, lo8;
2801 /* void (*samepage_function)(struct cpu *, struct sh_instr_call *); */
2802
2803 /* Figure out the (virtual) address of the instruction: */
2804 low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page)
2805 / sizeof(struct sh_instr_call);
2806
2807 /* Special case for branch with delayslot on the next page: */
2808 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
2809 /* fatal("[ delay-slot translation across page "
2810 "boundary ]\n"); */
2811 in_crosspage_delayslot = 1;
2812 }
2813
2814 addr = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1)
2815 << SH_INSTR_ALIGNMENT_SHIFT);
2816 addr += (low_pc << SH_INSTR_ALIGNMENT_SHIFT);
2817 cpu->pc = (MODE_int_t)addr;
2818 addr &= ~((1 << SH_INSTR_ALIGNMENT_SHIFT) - 1);
2819
2820 /* Read the instruction word from memory: */
2821 #ifdef MODE32
2822 page = cpu->cd.sh.host_load[(uint32_t)addr >> 12];
2823 #else
2824 {
2825 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2826 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2827 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2828 uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2829 uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2830 uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2831 DYNTRANS_L3N)) & mask3;
2832 struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.sh.l1_64[x1];
2833 struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2834 page = l3->host_load[x3];
2835 }
2836 #endif
2837
2838 if (page != NULL) {
2839 /* fatal("TRANSLATION HIT!\n"); */
2840 memcpy(ib, page + (addr & 0xfff), isize);
2841 } else {
2842 /* fatal("TRANSLATION MISS!\n"); */
2843 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2844 isize, MEM_READ, CACHE_INSTRUCTION)) {
2845 fatal("to_be_translated(): read failed: TODO\n");
2846 goto bad;
2847 }
2848 }
2849
2850 if (cpu->cd.sh.compact) {
2851 iword = *((uint16_t *)&ib[0]);
2852 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2853 iword = LE16_TO_HOST(iword);
2854 else
2855 iword = BE16_TO_HOST(iword);
2856 main_opcode = iword >> 12;
2857 r8 = (iword >> 8) & 0xf;
2858 r4 = (iword >> 4) & 0xf;
2859 lo8 = iword & 0xff;
2860 lo4 = iword & 0xf;
2861 } else {
2862 iword = *((uint32_t *)&ib[0]);
2863 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2864 iword = LE32_TO_HOST(iword);
2865 else
2866 iword = BE32_TO_HOST(iword);
2867 main_opcode = -1; /* TODO */
2868 fatal("SH5/SH64 isn't implemented yet. Sorry.\n");
2869 goto bad;
2870 }
2871
2872
2873 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2874 #include "cpu_dyntrans.c"
2875 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
2876
2877
2878 /*
2879 * Translate the instruction:
2880 */
2881
2882 /* Default args. for many instructions: */
2883 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
2884 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
2885
2886 switch (main_opcode) {
2887
2888 case 0x0:
2889 if (lo4 == 0x4) {
2890 /* MOV.B Rm,@(R0,Rn) */
2891 ic->f = instr(mov_b_rm_r0_rn);
2892 } else if (lo4 == 0x5) {
2893 /* MOV.W Rm,@(R0,Rn) */
2894 ic->f = instr(mov_w_rm_r0_rn);
2895 } else if (lo4 == 0x6) {
2896 /* MOV.L Rm,@(R0,Rn) */
2897 ic->f = instr(mov_l_rm_r0_rn);
2898 } else if (lo4 == 0x7) {
2899 /* MUL.L Rm,Rn */
2900 ic->f = instr(mul_l_rm_rn);
2901 } else if (iword == 0x000b) {
2902 if (cpu->machine->show_trace_tree)
2903 ic->f = instr(rts_trace);
2904 else
2905 ic->f = instr(rts);
2906 } else if (lo4 == 0xc) {
2907 /* MOV.B @(R0,Rm),Rn */
2908 ic->f = instr(mov_b_r0_rm_rn);
2909 } else if (lo4 == 0xd) {
2910 /* MOV.W @(R0,Rm),Rn */
2911 ic->f = instr(mov_w_r0_rm_rn);
2912 } else if (lo4 == 0xe) {
2913 /* MOV.L @(R0,Rm),Rn */
2914 ic->f = instr(mov_l_r0_rm_rn);
2915 } else if (iword == 0x0008) {
2916 /* CLRT */
2917 ic->f = instr(clrt);
2918 } else if (iword == 0x0018) {
2919 /* SETT */
2920 ic->f = instr(sett);
2921 } else if (iword == 0x0019) {
2922 /* DIV0U */
2923 ic->f = instr(div0u);
2924 } else if (iword == 0x001b) {
2925 /* SLEEP */
2926 ic->f = instr(sleep);
2927 } else if (iword == 0x0028) {
2928 /* CLRMAC */
2929 ic->f = instr(clrmac);
2930 } else if (iword == 0x002b) {
2931 /* RTE */
2932 ic->f = instr(rte);
2933 } else if (iword == 0x0038) {
2934 /* LDTLB */
2935 ic->f = instr(ldtlb);
2936 } else if (iword == 0x0048) {
2937 /* CLRS */
2938 ic->f = instr(clrs);
2939 } else if (iword == 0x0058) {
2940 /* SETS */
2941 ic->f = instr(sets);
2942 } else if ((lo8 & 0x8f) == 0x82) {
2943 /* STC Rm_BANK, Rn */
2944 ic->f = instr(copy_privileged_register);
2945 ic->arg[0] = (size_t)&cpu->cd.sh.r_bank[(lo8 >> 4) & 7];
2946 } else if (iword == SH_INVALID_INSTR) {
2947 /* PROM emulation (GXemul specific) */
2948 ic->f = instr(prom_emul);
2949 } else {
2950 switch (lo8) {
2951 case 0x02: /* STC SR,Rn */
2952 ic->f = instr(copy_privileged_register);
2953 ic->arg[0] = (size_t)&cpu->cd.sh.sr;
2954 break;
2955 case 0x03: /* BSRF Rn */
2956 ic->f = instr(bsrf_rn);
2957 ic->arg[0] = (int32_t) (addr &
2958 ((SH_IC_ENTRIES_PER_PAGE-1)
2959 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
2960 /* arg[1] is Rn */
2961 break;
2962 case 0x09: /* NOP */
2963 ic->f = instr(nop);
2964 if (iword & 0x0f00) {
2965 fatal("Unimplemented NOP variant?\n");
2966 goto bad;
2967 }
2968 break;
2969 case 0x0a: /* STS MACH,Rn */
2970 ic->f = instr(mov_rm_rn);
2971 ic->arg[0] = (size_t)&cpu->cd.sh.mach;
2972 break;
2973 case 0x12: /* STC GBR,Rn */
2974 ic->f = instr(mov_rm_rn);
2975 ic->arg[0] = (size_t)&cpu->cd.sh.gbr;
2976 break;
2977 case 0x1a: /* STS MACL,Rn */
2978 ic->f = instr(mov_rm_rn);
2979 ic->arg[0] = (size_t)&cpu->cd.sh.macl;
2980 break;
2981 case 0x22: /* STC VBR,Rn */
2982 ic->f = instr(copy_privileged_register);
2983 ic->arg[0] = (size_t)&cpu->cd.sh.vbr;
2984 break;
2985 case 0x23: /* BRAF Rn */
2986 ic->f = instr(braf_rn);
2987 ic->arg[0] = (int32_t) (addr &
2988 ((SH_IC_ENTRIES_PER_PAGE-1)
2989 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
2990 /* arg[1] is Rn */
2991 break;
2992 case 0x29: /* MOVT Rn */
2993 ic->f = instr(movt_rn);
2994 break;
2995 case 0x2a: /* STS PR,Rn */
2996 ic->f = instr(mov_rm_rn);
2997 ic->arg[0] = (size_t)&cpu->cd.sh.pr;
2998 break;
2999 case 0x32: /* STC SSR,Rn */
3000 ic->f = instr(copy_privileged_register);
3001 ic->arg[0] = (size_t)&cpu->cd.sh.ssr;
3002 break;
3003 case 0x42: /* STC SPC,Rn */
3004 ic->f = instr(copy_privileged_register);
3005 ic->arg[0] = (size_t)&cpu->cd.sh.spc;
3006 break;
3007 case 0x5a: /* STS FPUL,Rn */
3008 ic->f = instr(copy_fp_register);
3009 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3010 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3011 break;
3012 case 0x6a: /* STS FPSCR,Rn */
3013 ic->f = instr(copy_fp_register);
3014 ic->arg[0] = (size_t)&cpu->cd.sh.fpscr;
3015 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3016 break;
3017 case 0x83: /* PREF @Rn */
3018 ic->f = instr(pref_rn);
3019 break;
3020 case 0x93: /* OCBI @Rn */
3021 /* Treat as nop for now: */
3022 /* TODO: Implement this. */
3023 ic->f = instr(nop);
3024 break;
3025 case 0xa3: /* OCBP @Rn */
3026 /* Treat as nop for now: */
3027 /* TODO: Implement this. */
3028 ic->f = instr(nop);
3029 break;
3030 case 0xb3: /* OCBWB @Rn */
3031 /* Treat as nop for now: */
3032 /* TODO: Implement this. */
3033 ic->f = instr(nop);
3034 break;
3035 case 0xc3: /* MOVCA.L R0,@Rn */
3036 /* Treat as nop for now: */
3037 /* TODO: Implement this. */
3038 ic->f = instr(nop);
3039 break;
3040 case 0xfa: /* STC DBR,Rn */
3041 ic->f = instr(copy_privileged_register);
3042 ic->arg[0] = (size_t)&cpu->cd.sh.dbr;
3043 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3044 break;
3045 default:fatal("Unimplemented opcode 0x%x,0x%03x\n",
3046 main_opcode, iword & 0xfff);
3047 goto bad;
3048 }
3049 }
3050 break;
3051
3052 case 0x1:
3053 ic->f = instr(mov_l_rm_disp_rn);
3054 ic->arg[1] = r8 + (lo4 << 4);
3055 break;
3056
3057 case 0x2:
3058 switch (lo4) {
3059 case 0x0: /* MOV.B Rm,@Rn */
3060 ic->f = instr(mov_b_store_rm_rn);
3061 break;
3062 case 0x1: /* MOV.W Rm,@Rn */
3063 ic->f = instr(mov_w_store_rm_rn);
3064 break;
3065 case 0x2: /* MOV.L Rm,@Rn */
3066 ic->f = instr(mov_l_store_rm_rn);
3067 break;
3068 case 0x4: /* MOV.B Rm,@-Rn */
3069 ic->f = instr(mov_b_rm_predec_rn);
3070 break;
3071 case 0x5: /* MOV.W Rm,@-Rn */
3072 ic->f = instr(mov_w_rm_predec_rn);
3073 break;
3074 case 0x6: /* MOV.L Rm,@-Rn */
3075 ic->f = instr(mov_l_rm_predec_rn);
3076 break;
3077 case 0x7: /* DIV0S Rm,Rn */
3078 ic->f = instr(div0s_rm_rn);
3079 break;
3080 case 0x8: /* TST Rm,Rn */
3081 ic->f = instr(tst_rm_rn);
3082 break;
3083 case 0x9: /* AND Rm,Rn */
3084 ic->f = instr(and_rm_rn);
3085 break;
3086 case 0xa: /* XOR Rm,Rn */
3087 ic->f = instr(xor_rm_rn);
3088 break;
3089 case 0xb: /* OR Rm,Rn */
3090 ic->f = instr(or_rm_rn);
3091 break;
3092 case 0xc: /* CMP/STR Rm,Rn */
3093 ic->f = instr(cmp_str_rm_rn);
3094 break;
3095 case 0xd: /* XTRCT Rm,Rn */
3096 ic->f = instr(xtrct_rm_rn);
3097 break;
3098 case 0xe: /* MULU.W Rm,Rn */
3099 ic->f = instr(mulu_w_rm_rn);
3100 break;
3101 case 0xf: /* MULS.W Rm,Rn */
3102 ic->f = instr(muls_w_rm_rn);
3103 break;
3104 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3105 main_opcode, lo4);
3106 goto bad;
3107 }
3108 break;
3109
3110 case 0x3:
3111 switch (lo4) {
3112 case 0x0: /* CMP/EQ Rm,Rn */
3113 ic->f = instr(cmpeq_rm_rn);
3114 break;
3115 case 0x2: /* CMP/HS Rm,Rn */
3116 ic->f = instr(cmphs_rm_rn);
3117 break;
3118 case 0x3: /* CMP/GE Rm,Rn */
3119 ic->f = instr(cmpge_rm_rn);
3120 break;
3121 case 0x4: /* DIV1 Rm,Rn */
3122 ic->f = instr(div1_rm_rn);
3123 break;
3124 case 0x5: /* DMULU.L Rm,Rn */
3125 ic->f = instr(dmulu_l_rm_rn);
3126 break;
3127 case 0x6: /* CMP/HI Rm,Rn */
3128 ic->f = instr(cmphi_rm_rn);
3129 break;
3130 case 0x7: /* CMP/GT Rm,Rn */
3131 ic->f = instr(cmpgt_rm_rn);
3132 break;
3133 case 0x8: /* SUB Rm,Rn */
3134 ic->f = instr(sub_rm_rn);
3135 break;
3136 case 0xa: /* SUBC Rm,Rn */
3137 ic->f = instr(subc_rm_rn);
3138 break;
3139 case 0xc: /* ADD Rm,Rn */
3140 ic->f = instr(add_rm_rn);
3141 break;
3142 case 0xd: /* DMULS.L Rm,Rn */
3143 ic->f = instr(dmuls_l_rm_rn);
3144 break;
3145 case 0xe: /* ADDC Rm,Rn */
3146 ic->f = instr(addc_rm_rn);
3147 break;
3148 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3149 main_opcode, lo4);
3150 goto bad;
3151 }
3152 break;
3153
3154 case 0x4:
3155 if (lo4 == 0xc) {
3156 ic->f = instr(shad);
3157 } else if (lo4 == 0xd) {
3158 ic->f = instr(shld);
3159 } else if ((lo8 & 0x8f) == 0x83) {
3160 /* STC.L Rm_BANK,@-Rn */
3161 ic->f = instr(stc_l_rm_predec_rn_md);
3162 ic->arg[0] = (size_t)&cpu->cd.sh.r_bank[
3163 (lo8 >> 4) & 7]; /* m */
3164 } else if ((lo8 & 0x8f) == 0x87) {
3165 /* LDC.L @Rm+,Rn_BANK */
3166 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3167 ic->arg[0] = (size_t)&cpu->cd.sh.r_bank[(lo8 >> 4) & 7];
3168 } else if ((lo8 & 0x8f) == 0x8e) {
3169 /* LDC Rm, Rn_BANK */
3170 ic->f = instr(copy_privileged_register);
3171 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8];
3172 ic->arg[1] = (size_t)&cpu->cd.sh.r_bank[(lo8 >> 4) & 7];
3173 } else {
3174 switch (lo8) {
3175 case 0x00: /* SHLL Rn */
3176 ic->f = instr(shll_rn);
3177 break;
3178 case 0x01: /* SHLR Rn */
3179 ic->f = instr(shlr_rn);
3180 break;
3181 case 0x02: /* STS.L MACH,@-Rn */
3182 ic->f = instr(mov_l_rm_predec_rn);
3183 ic->arg[0] = (size_t)&cpu->cd.sh.mach;
3184 break;
3185 case 0x03: /* STC.L SR,@-Rn */
3186 ic->f = instr(stc_l_rm_predec_rn_md);
3187 ic->arg[0] = (size_t)&cpu->cd.sh.sr;
3188 break;
3189 case 0x04: /* ROTL Rn */
3190 ic->f = instr(rotl_rn);
3191 break;
3192 case 0x05: /* ROTR Rn */
3193 ic->f = instr(rotr_rn);
3194 break;
3195 case 0x06: /* LDS.L @Rm+,MACH */
3196 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3197 ic->arg[0] = (size_t)&cpu->cd.sh.mach;
3198 break;
3199 case 0x07: /* LDC.L @Rm+,SR */
3200 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3201 ic->arg[0] = (size_t)&cpu->cd.sh.sr;
3202 break;
3203 case 0x08: /* SHLL2 Rn */
3204 ic->f = instr(shll2_rn);
3205 break;
3206 case 0x09: /* SHLR2 Rn */
3207 ic->f = instr(shlr2_rn);
3208 break;
3209 case 0x0b: /* JSR @Rn */
3210 if (cpu->machine->show_trace_tree)
3211 ic->f = instr(jsr_rn_trace);
3212 else
3213 ic->f = instr(jsr_rn);
3214 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3215 ic->arg[1] = (addr & 0xffe) + 4;
3216 break;
3217 case 0x0e: /* LDC Rm,SR */
3218 ic->f = instr(ldc_rm_sr);
3219 break;
3220 case 0x10: /* DT Rn */
3221 ic->f = instr(dt_rn);
3222 break;
3223 case 0x11: /* CMP/PZ Rn */
3224 ic->f = instr(cmppz_rn);
3225 break;
3226 case 0x12: /* STS.L MACL,@-Rn */
3227 ic->f = instr(mov_l_rm_predec_rn);
3228 ic->arg[0] = (size_t)&cpu->cd.sh.macl;
3229 break;
3230 case 0x13: /* STC.L GBR,@-Rn */
3231 ic->f = instr(mov_l_rm_predec_rn);
3232 ic->arg[0] = (size_t)&cpu->cd.sh.gbr;
3233 break;
3234 case 0x15: /* CMP/PL Rn */
3235 ic->f = instr(cmppl_rn);
3236 break;
3237 case 0x16: /* LDS.L @Rm+,MACL */
3238 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3239 ic->arg[0] = (size_t)&cpu->cd.sh.macl;
3240 break;
3241 case 0x17: /* LDC.L @Rm+,GBR */
3242 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3243 ic->arg[0] = (size_t)&cpu->cd.sh.gbr;
3244 break;
3245 case 0x18: /* SHLL8 Rn */
3246 ic->f = instr(shll8_rn);
3247 break;
3248 case 0x19: /* SHLR8 Rn */
3249 ic->f = instr(shlr8_rn);
3250 break;
3251 case 0x1b: /* TAS.B @Rn */
3252 ic->f = instr(tas_b_rn);
3253 break;
3254 case 0x1e: /* LDC Rm,GBR */
3255 ic->f = instr(mov_rm_rn);
3256 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3257 ic->arg[1] = (size_t)&cpu->cd.sh.gbr;
3258 break;
3259 case 0x20: /* SHAL Rn */
3260 ic->f = instr(shll_rn); /* NOTE: shll */
3261 break;
3262 case 0x21: /* SHAR Rn */
3263 ic->f = instr(shar_rn);
3264 break;
3265 case 0x22: /* STS.L PR,@-Rn */
3266 ic->f = instr(mov_l_rm_predec_rn);
3267 ic->arg[0] = (size_t)&cpu->cd.sh.pr; /* m */
3268 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3269 break;
3270 case 0x23: /* STC.L VBR,@-Rn */
3271 ic->f = instr(stc_l_rm_predec_rn_md);
3272 ic->arg[0] = (size_t)&cpu->cd.sh.vbr;
3273 break;
3274 case 0x24: /* ROTCL Rn */
3275 ic->f = instr(rotcl_rn);
3276 break;
3277 case 0x25: /* ROTCR Rn */
3278 ic->f = instr(rotcr_rn);
3279 break;
3280 case 0x26: /* LDS.L @Rm+,PR */
3281 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3282 ic->arg[0] = (size_t)&cpu->cd.sh.pr;
3283 break;
3284 case 0x27: /* LDC.L @Rm+,VBR */
3285 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3286 ic->arg[0] = (size_t)&cpu->cd.sh.vbr;
3287 break;
3288 case 0x28: /* SHLL16 Rn */
3289 ic->f = instr(shll16_rn);
3290 break;
3291 case 0x29: /* SHLR16 Rn */
3292 ic->f = instr(shlr16_rn);
3293 break;
3294 case 0x2a: /* LDS Rm,PR */
3295 ic->f = instr(mov_rm_rn);
3296 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3297 ic->arg[1] = (size_t)&cpu->cd.sh.pr;
3298 break;
3299 case 0x2b: /* JMP @Rn */
3300 if (cpu->machine->show_trace_tree)
3301 ic->f = instr(jmp_rn_trace);
3302 else
3303 ic->f = instr(jmp_rn);
3304 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3305 ic->arg[1] = (addr & 0xffe) + 4;
3306 break;
3307 case 0x2e: /* LDC Rm,VBR */
3308 ic->f = instr(copy_privileged_register);
3309 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3310 ic->arg[1] = (size_t)&cpu->cd.sh.vbr;
3311 break;
3312 case 0x33: /* STC.L SSR,@-Rn */
3313 ic->f = instr(stc_l_rm_predec_rn_md);
3314 ic->arg[0] = (size_t)&cpu->cd.sh.ssr;
3315 break;
3316 case 0x37: /* LDC.L @Rm+,SSR */
3317 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3318 ic->arg[0] = (size_t)&cpu->cd.sh.ssr;
3319 break;
3320 case 0x3e: /* LDC rm,SSR */
3321 ic->f = instr(copy_privileged_register);
3322 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3323 ic->arg[1] = (size_t)&cpu->cd.sh.ssr;
3324 break;
3325 case 0x43: /* STC.L SPC,@-Rn */
3326 ic->f = instr(stc_l_rm_predec_rn_md);
3327 ic->arg[0] = (size_t)&cpu->cd.sh.spc;
3328 break;
3329 case 0x47: /* LDC.L @Rm+,SPC */
3330 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3331 ic->arg[0] = (size_t)&cpu->cd.sh.spc;
3332 break;
3333 case 0x4e: /* LDC rm,SPC */
3334 ic->f = instr(copy_privileged_register);
3335 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3336 ic->arg[1] = (size_t)&cpu->cd.sh.spc;
3337 break;
3338 case 0x52: /* STS.L FPUL,@-Rn */
3339 ic->f = instr(mov_l_rm_predec_rn);
3340 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3341 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3342 break;
3343 case 0x56: /* LDS.L @Rm+,FPUL */
3344 ic->f = instr(mov_l_arg1_postinc_to_arg0_fp);
3345 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3346 break;
3347 case 0x5a: /* LDS Rm,FPUL */
3348 ic->f = instr(copy_fp_register);
3349 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3350 ic->arg[1] = (size_t)&cpu->cd.sh.fpul;
3351 break;
3352 case 0x62: /* STS.L FPSCR,@-Rn */
3353 ic->f = instr(mov_l_rm_predec_rn);
3354 ic->arg[0] = (size_t)&cpu->cd.sh.fpscr;
3355 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3356 break;
3357 case 0x66: /* LDS.L @Rm+,FPSCR */
3358 /* Note: Loading into FPSCR is a specia
3359 case (need to call sh_update_fpsrc()). */
3360 ic->f = instr(mov_l_arg1_postinc_to_arg0_fp);
3361 ic->arg[0] = (size_t)&cpu->cd.sh.fpscr;
3362 break;
3363 case 0x6a: /* LDS Rm,FPSCR */
3364 ic->f = instr(lds_rm_fpscr);
3365 /* arg 1 = R8 = Rm */
3366 break;
3367 case 0xfa: /* LDC Rm,DBR */
3368 ic->f = instr(copy_privileged_register);
3369 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8];
3370 ic->arg[1] = (size_t)&cpu->cd.sh.dbr;
3371 break;
3372 default:fatal("Unimplemented opcode 0x%x,0x%02x\n",
3373 main_opcode, lo8);
3374 goto bad;
3375 }
3376 }
3377 break;
3378
3379 case 0x5:
3380 ic->f = instr(mov_l_disp_rm_rn);
3381 ic->arg[0] = r4 + (lo4 << 4);
3382 break;
3383
3384 case 0x6:
3385 switch (lo4) {
3386 case 0x0: /* MOV.B @Rm,Rn */
3387 ic->f = instr(load_b_rm_rn);
3388 break;
3389 case 0x1: /* MOV.W @Rm,Rn */
3390 ic->f = instr(load_w_rm_rn);
3391 break;
3392 case 0x2: /* MOV.L @Rm,Rn */
3393 ic->f = instr(load_l_rm_rn);
3394 break;
3395 case 0x3: /* MOV Rm,Rn */
3396 ic->f = instr(mov_rm_rn);
3397 break;
3398 case 0x4: /* MOV.B @Rm+,Rn */
3399 ic->f = instr(mov_b_arg1_postinc_to_arg0);
3400 /* Note: Order */
3401 ic->arg[1] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3402 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3403 break;
3404 case 0x5: /* MOV.W @Rm+,Rn */
3405 ic->f = instr(mov_w_arg1_postinc_to_arg0);
3406 /* Note: Order */
3407 ic->arg[1] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3408 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3409 break;
3410 case 0x6: /* MOV.L @Rm+,Rn */
3411 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3412 /* Note: Order */
3413 ic->arg[1] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3414 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3415 break;
3416 case 0x7: /* NOT Rm,Rn */
3417 ic->f = instr(not_rm_rn);
3418 break;
3419 case 0x8: /* SWAP.B Rm,Rn */
3420 ic->f = instr(swap_b_rm_rn);
3421 break;
3422 case 0x9: /* SWAP.W Rm,Rn */
3423 ic->f = instr(swap_w_rm_rn);
3424 break;
3425 case 0xa: /* NEGC Rm,Rn */
3426 ic->f = instr(negc_rm_rn);
3427 break;
3428 case 0xb: /* NEG Rm,Rn */
3429 ic->f = instr(neg_rm_rn);
3430 break;
3431 case 0xc: /* EXTU.B Rm,Rn */
3432 ic->f = instr(extu_b_rm_rn);
3433 break;
3434 case 0xd: /* EXTU.W Rm,Rn */
3435 ic->f = instr(extu_w_rm_rn);
3436 break;
3437 case 0xe: /* EXTS.B Rm,Rn */
3438 ic->f = instr(exts_b_rm_rn);
3439 break;
3440 case 0xf: /* EXTS.W Rm,Rn */
3441 ic->f = instr(exts_w_rm_rn);
3442 break;
3443 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3444 main_opcode, lo4);
3445 goto bad;
3446 }
3447 break;
3448
3449 case 0x7: /* ADD #imm,Rn */
3450 ic->f = instr(add_imm_rn);
3451 ic->arg[0] = (int8_t)lo8;
3452 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3453 break;
3454
3455 case 0x8:
3456 /* Displacement from beginning of page = default arg 0. */
3457 ic->arg[0] = (int8_t)lo8 * 2 +
3458 (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3459 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
3460 switch (r8) {
3461 case 0x0: /* MOV.B R0,@(disp,Rn) */
3462 ic->f = instr(mov_b_r0_disp_rn);
3463 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3464 ic->arg[1] = lo4;
3465 break;
3466 case 0x1: /* MOV.W R0,@(disp,Rn) */
3467 ic->f = instr(mov_w_r0_disp_rn);
3468 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3469 ic->arg[1] = lo4 * 2;
3470 break;
3471 case 0x4: /* MOV.B @(disp,Rn),R0 */
3472 ic->f = instr(mov_b_disp_rn_r0);
3473 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3474 ic->arg[1] = lo4;
3475 break;
3476 case 0x5: /* MOV.W @(disp,Rn),R0 */
3477 ic->f = instr(mov_w_disp_rn_r0);
3478 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3479 ic->arg[1] = lo4 * 2;
3480 break;
3481 case 0x8: /* CMP/EQ #imm,R0 */
3482 ic->f = instr(cmpeq_imm_r0);
3483 ic->arg[0] = (int8_t)lo8;
3484 break;
3485 case 0x9: /* BT (disp,PC) */
3486 ic->f = instr(bt);
3487 break;
3488 case 0xb: /* BF (disp,PC) */
3489 ic->f = instr(bf);
3490 break;
3491 case 0xd: /* BT/S (disp,PC) */
3492 ic->f = instr(bt_s);
3493 break;
3494 case 0xf: /* BF/S (disp,PC) */
3495 ic->f = instr(bf_s);
3496 break;
3497 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3498 main_opcode, r8);
3499 goto bad;
3500 }
3501 break;
3502
3503 case 0x9: /* MOV.W @(disp,PC),Rn */
3504 ic->f = instr(mov_w_disp_pc_rn);
3505 ic->arg[0] = lo8 * 2 + (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3506 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
3507 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3508 break;
3509
3510 case 0xa: /* BRA disp */
3511 case 0xb: /* BSR disp */
3512 ic->f = main_opcode == 0xa? instr(bra) : instr(bsr);
3513 ic->arg[0] = (int32_t) ( (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3514 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4 +
3515 (((int32_t)(int16_t)((iword & 0xfff) << 4)) >> 3) );
3516 break;
3517
3518 case 0xc:
3519 switch (r8) {
3520 case 0x0:
3521 ic->f = instr(mov_b_r0_disp_gbr);
3522 ic->arg[1] = lo8;
3523 break;
3524 case 0x1:
3525 ic->f = instr(mov_w_r0_disp_gbr);
3526 ic->arg[1] = lo8 << 1;
3527 break;
3528 case 0x2:
3529 ic->f = instr(mov_l_r0_disp_gbr);
3530 ic->arg[1] = lo8 << 2;
3531 break;
3532 case 0x3:
3533 ic->f = instr(trapa);
3534 ic->arg[0] = lo8 << 2;
3535 break;
3536 case 0x4:
3537 ic->f = instr(mov_b_disp_gbr_r0);
3538 ic->arg[1] = lo8;
3539 break;
3540 case 0x5:
3541 ic->f = instr(mov_w_disp_gbr_r0);
3542 ic->arg[1] = lo8 << 1;
3543 break;
3544 case 0x6:
3545 ic->f = instr(mov_l_disp_gbr_r0);
3546 ic->arg[1] = lo8 << 2;
3547 break;
3548 case 0x7: /* MOVA @(disp,pc),R0 */
3549 ic->f = instr(mova_r0);
3550 ic->arg[0] = lo8 * 4 + (addr &
3551 ((SH_IC_ENTRIES_PER_PAGE-1)
3552 << SH_INSTR_ALIGNMENT_SHIFT) & ~3) + 4;
3553 break;
3554 case 0x8: /* TST #imm,R0 */
3555 ic->f = instr(tst_imm_r0);
3556 ic->arg[0] = lo8;
3557 break;
3558 case 0x9: /* AND #imm,R0 */
3559 ic->f = instr(and_imm_r0);
3560 ic->arg[0] = lo8;
3561 break;
3562 case 0xa: /* XOR #imm,R0 */
3563 ic->f = instr(xor_imm_r0);
3564 ic->arg[0] = lo8;
3565 break;
3566 case 0xb: /* OR #imm,R0 */
3567 ic->f = instr(or_imm_r0);
3568 ic->arg[0] = lo8;
3569 break;
3570 case 0xd: /* AND.B #imm,@(R0,GBR) */
3571 ic->f = instr(and_b_imm_r0_gbr);
3572 ic->arg[0] = lo8;
3573 break;
3574 case 0xe: /* XOR.B #imm,@(R0,GBR) */
3575 ic->f = instr(xor_b_imm_r0_gbr);
3576 ic->arg[0] = lo8;
3577 break;
3578 case 0xf: /* OR.B #imm,@(R0,GBR) */
3579 ic->f = instr(or_b_imm_r0_gbr);
3580 ic->arg[0] = lo8;
3581 break;
3582 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3583 main_opcode, r8);
3584 goto bad;
3585 }
3586 break;
3587
3588 case 0xd: /* MOV.L @(disp,PC),Rn */
3589 ic->f = instr(mov_l_disp_pc_rn);
3590 ic->arg[0] = lo8 * 4 + (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3591 << SH_INSTR_ALIGNMENT_SHIFT) & ~3) + 4;
3592 break;
3593
3594 case 0xe: /* MOV #imm,Rn */
3595 ic->f = instr(mov_imm_rn);
3596 ic->arg[0] = (int8_t)lo8;
3597 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3598 break;
3599
3600 case 0xf:
3601 if (lo4 == 0x0) {
3602 /* FADD FRm,FRn */
3603 ic->f = instr(fadd_frm_frn);
3604 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3605 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3606 } else if (lo4 == 0x1) {
3607 /* FSUB FRm,FRn */
3608 ic->f = instr(fsub_frm_frn);
3609 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3610 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3611 } else if (lo4 == 0x2) {
3612 /* FMUL FRm,FRn */
3613 ic->f = instr(fmul_frm_frn);
3614 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3615 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3616 } else if (lo4 == 0x3) {
3617 /* FDIV FRm,FRn */
3618 ic->f = instr(fdiv_frm_frn);
3619 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3620 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3621 } else if (lo4 == 0x4) {
3622 /* FCMP/EQ FRm,FRn */
3623 ic->f = instr(fcmp_eq_frm_frn);
3624 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3625 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3626 } else if (lo4 == 0x5) {
3627 /* FCMP/GT FRm,FRn */
3628 ic->f = instr(fcmp_gt_frm_frn);
3629 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3630 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3631 } else if (lo4 == 0x6) {
3632 /* FMOV @(R0,Rm),FRn */
3633 ic->f = instr(fmov_r0_rm_frn);
3634 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3635 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3636 } else if (lo4 == 0x7) {
3637 /* FMOV FRm,@(R0,Rn) */
3638 ic->f = instr(fmov_frm_r0_rn);
3639 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; /* m */
3640 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3641 } else if (lo4 == 0x8) {
3642 /* FMOV @Rm,FRn */
3643 ic->f = instr(fmov_rm_frn);
3644 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3645 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3646 } else if (lo4 == 0x9) {
3647 /* FMOV @Rm+,FRn */
3648 ic->f = instr(fmov_rm_postinc_frn);
3649 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3650 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3651 } else if (lo4 == 0xa) {
3652 /* FMOV FRm,@Rn */
3653 ic->f = instr(fmov_frm_rn);
3654 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; /* m */
3655 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3656 } else if (lo4 == 0xb) {
3657 /* FMOV FRm,@-Rn */
3658 ic->f = instr(fmov_frm_predec_rn);
3659 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; /* m */
3660 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3661 } else if (lo4 == 0xc) {
3662 /* FMOV FRm,FRn */
3663 ic->f = instr(fmov_frm_frn);
3664 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3665 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3666 } else if (lo8 == 0x0d) {
3667 /* FSTS FPUL,FRn */
3668 ic->f = instr(copy_fp_register);
3669 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3670 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3671 } else if (lo8 == 0x1d) {
3672 /* FLDS FRn,FPUL */
3673 ic->f = instr(copy_fp_register);
3674 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3675 ic->arg[1] = (size_t)&cpu->cd.sh.fpul;
3676 } else if (lo8 == 0x2d) {
3677 /* FLOAT FPUL,FRn */
3678 ic->f = instr(float_fpul_frn);
3679 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3680 } else if (lo8 == 0x3d) {
3681 /* FTRC FRm,FPUL */
3682 ic->f = instr(ftrc_frm_fpul);
3683 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3684 } else if (lo8 == 0x4d) {
3685 /* FNEG FRn */
3686 ic->f = instr(fneg_frn);
3687 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3688 } else if (lo8 == 0x5d) {
3689 /* FABS FRn */
3690 ic->f = instr(fabs_frn);
3691 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3692 } else if (lo8 == 0x6d) {
3693 /* FSQRT FRn */
3694 ic->f = instr(fsqrt_frn);
3695 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3696 } else if (lo8 == 0x8d) {
3697 /* FLDI0 FRn */
3698 ic->f = instr(fldi_frn);
3699 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3700 ic->arg[1] = 0x00000000;
3701 } else if (lo8 == 0x9d) {
3702 /* FLDI1 FRn */
3703 ic->f = instr(fldi_frn);
3704 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3705 ic->arg[1] = 0x3f800000;
3706 } else if ((iword & 0x01ff) == 0x00ad) {
3707 /* FCNVSD FPUL,DRn */
3708 ic->f = instr(fcnvsd_fpul_drn);
3709 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3710 } else if ((iword & 0x01ff) == 0x00bd) {
3711 /* FCNVDS DRm,FPUL */
3712 ic->f = instr(fcnvds_drm_fpul);
3713 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3714 } else if ((iword & 0x01ff) == 0x00fd) {
3715 /* FSCA FPUL,DRn */
3716 ic->f = instr(fsca_fpul_drn);
3717 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3718 } else if (iword == 0xf3fd) {
3719 /* FSCHG */
3720 ic->f = instr(fschg);
3721 } else if (iword == 0xfbfd) {
3722 /* FRCHG */
3723 ic->f = instr(frchg);
3724 } else if ((iword & 0xf3ff) == 0xf1fd) {
3725 /* FTRV XMTRX, FVn */
3726 ic->f = instr(ftrv_xmtrx_fvn);
3727 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8 & 0xc];
3728 } else if (lo4 == 0xe) {
3729 /* FMAC FR0,FRm,FRn */
3730 ic->f = instr(fmac_fr0_frm_frn);
3731 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3732 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3733 } else {
3734 fatal("Unimplemented opcode 0x%x,0x%02x\n",
3735 main_opcode, lo8);
3736 goto bad;
3737 }
3738 break;
3739
3740 default:fatal("Unimplemented main opcode 0x%x\n", main_opcode);
3741 goto bad;
3742 }
3743
3744
3745 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3746 #include "cpu_dyntrans.c"
3747 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
3748 }
3749

  ViewVC Help
Powered by ViewVC 1.1.26