/[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 36 - (show annotations)
Mon Oct 8 16:21:34 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 93822 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1497 2007/03/18 03:41:36 debug Exp $
20070224	Minor update to the initialization of the ns16550 in
		machine_walnut.c, to allow that machine type to boot with the
		new interrupt system (although it is still a dummy machine).
		Adding a wdc at 0x14000000 to machine_landisk.c, and fixing
		the SCIF serial interrupts of the SH4 cpu enough to get
		NetBSD/landisk booting from a disk image :-)  Adding a
		preliminary install instruction skeleton to guestoses.html.
20070306	Adding SH-IPL+G PROM emulation, and also passing the "end"
		symbol in r5 on bootup, for Landisk emulation. This is enough
		to get OpenBSD/landisk to install :)  Adding a preliminary
		install instruction skeleton to the documentation. SuperH
		emulation is still shaky, though :-/
20070307	Fixed a strangeness in memory_sh.c (read/write was never
		returned for any page). (Unknown whether this fixes any actual
		problems, though.)
20070308	dev_ram.c fix: invalidate code translations on writes to
		RAM, emulated as separate devices. Linux/dreamcast gets
		further in the boot process than before, but still bugs out
		in userland.
		Fixing bugs in the "stc.l gbr,@-rN" and "ldc.l @rN+,gbr" SuperH 
		instructions (they should NOT check the MD bit), allowing the
		Linux/dreamcast Live CD to reach userland correctly :-)
20070310	Changing the cpu name "Alpha" in src/useremul.c to "21364" to
		unbreak userland syscall emulation of FreeBSD/Alpha binaries.
20070314	Applying a patch from Michael Yaroslavtsev which fixes the
		previous Linux lib64 patch to the configure script.
20070315	Adding a (dummy) sun4v machine type, and SPARC T1 cpu type.
20070316	Creating a new directory, src/disk, and moving diskimage.c
		to it. Separating out bootblock loading stuff from emul.c into
		new files in src/disk.
		Adding some more SPARC registers.
20070318	Preparing/testing for a minirelease, 0.4.4.1.

==============  RELEASE 0.4.4.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.51 2007/03/08 19:04:09 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 reg(ic->arg[0]) = data;
822 }
823 X(mov_l_arg1_postinc_to_arg0_fp)
824 {
825 uint32_t addr = reg(ic->arg[1]);
826 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
827 uint32_t data;
828
829 FLOATING_POINT_AVAILABLE_CHECK;
830
831 if (p != NULL) {
832 data = p[(addr & 0xfff) >> 2];
833 } else {
834 SYNCH_PC;
835 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
836 sizeof(data), MEM_READ, CACHE_DATA)) {
837 /* Exception. */
838 return;
839 }
840 }
841 /* The load was ok: */
842 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
843 data = LE32_TO_HOST(data);
844 else
845 data = BE32_TO_HOST(data);
846 reg(ic->arg[1]) = addr + sizeof(data);
847
848 if (ic->arg[0] == (size_t)cpu->cd.sh.fpscr)
849 sh_update_fpscr(cpu, data);
850 else
851 reg(ic->arg[0]) = data;
852 }
853 X(mov_b_r0_rm_rn)
854 {
855 uint32_t addr = reg(ic->arg[0]) + cpu->cd.sh.r[0];
856 int8_t *p = (int8_t *) cpu->cd.sh.host_load[addr >> 12];
857 int8_t data;
858
859 if (p != NULL) {
860 data = p[addr & 0xfff];
861 } else {
862 SYNCH_PC;
863 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
864 sizeof(data), MEM_READ, CACHE_DATA)) {
865 /* Exception. */
866 return;
867 }
868 }
869
870 reg(ic->arg[1]) = data;
871 }
872 X(mov_w_r0_rm_rn)
873 {
874 uint32_t addr = reg(ic->arg[0]) + cpu->cd.sh.r[0];
875 int16_t *p = (int16_t *) cpu->cd.sh.host_load[addr >> 12];
876 int16_t data;
877
878 if (p != NULL) {
879 data = p[(addr & 0xfff) >> 1];
880 } else {
881 SYNCH_PC;
882 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
883 sizeof(data), MEM_READ, CACHE_DATA)) {
884 /* Exception. */
885 return;
886 }
887 }
888
889 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
890 data = LE16_TO_HOST(data);
891 else
892 data = BE16_TO_HOST(data);
893 reg(ic->arg[1]) = data;
894 }
895 X(mov_l_r0_rm_rn)
896 {
897 uint32_t addr = reg(ic->arg[0]) + cpu->cd.sh.r[0];
898 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
899 uint32_t data;
900
901 if (p != NULL) {
902 data = p[(addr & 0xfff) >> 2];
903 } else {
904 SYNCH_PC;
905 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
906 sizeof(data), MEM_READ, CACHE_DATA)) {
907 /* Exception. */
908 return;
909 }
910 }
911
912 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
913 data = LE32_TO_HOST(data);
914 else
915 data = BE32_TO_HOST(data);
916 reg(ic->arg[1]) = data;
917 }
918 X(mov_l_disp_rm_rn)
919 {
920 uint32_t addr = cpu->cd.sh.r[ic->arg[0] & 0xf] +
921 ((ic->arg[0] >> 4) << 2);
922 uint32_t *p = (uint32_t *) cpu->cd.sh.host_load[addr >> 12];
923 uint32_t data;
924
925 if (p != NULL) {
926 data = p[(addr & 0xfff) >> 2];
927 } else {
928 SYNCH_PC;
929 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
930 sizeof(data), MEM_READ, CACHE_DATA)) {
931 /* Exception. */
932 return;
933 }
934 }
935
936 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
937 data = LE32_TO_HOST(data);
938 else
939 data = BE32_TO_HOST(data);
940 reg(ic->arg[1]) = data;
941 }
942 X(mov_b_disp_rn_r0)
943 {
944 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
945 uint8_t *p = (uint8_t *) cpu->cd.sh.host_load[addr >> 12];
946 uint8_t data;
947
948 if (p != NULL) {
949 data = p[addr & 0xfff];
950 } else {
951 SYNCH_PC;
952 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
953 sizeof(data), MEM_READ, CACHE_DATA)) {
954 /* Exception. */
955 return;
956 }
957 }
958
959 cpu->cd.sh.r[0] = (int8_t) data;
960 }
961 X(mov_w_disp_rn_r0)
962 {
963 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
964 uint16_t *p = (uint16_t *) cpu->cd.sh.host_load[addr >> 12];
965 uint16_t data;
966
967 if (p != NULL) {
968 data = p[(addr & 0xfff) >> 1];
969 } else {
970 SYNCH_PC;
971 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
972 sizeof(data), MEM_READ, CACHE_DATA)) {
973 /* Exception. */
974 return;
975 }
976 }
977
978 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
979 data = LE16_TO_HOST(data);
980 else
981 data = BE16_TO_HOST(data);
982 cpu->cd.sh.r[0] = (int16_t) data;
983 }
984
985
986 /*
987 * mov_b_store_rm_rn: Store Rm to address Rn (8-bit).
988 * mov_w_store_rm_rn: Store Rm to address Rn (16-bit).
989 * mov_l_store_rm_rn: Store Rm to address Rn (32-bit).
990 * fmov_frm_rn: Store FRm to address Rn.
991 * fmov_frm_r0_rn: Store FRm to address R0 + Rn.
992 * fmov_frm_predec_rn: Store FRm to address Rn - 4 (or 8), update Rn.
993 * mov_b_rm_r0_rn: Store Rm to address Rn + R0 (8-bit).
994 * mov_w_rm_r0_rn: Store Rm to address Rn + R0 (16-bit).
995 * mov_l_rm_r0_rn: Store Rm to address Rn + R0 (32-bit).
996 * mov_b_r0_disp_gbr: Store R0 to address disp + GBR (8-bit).
997 * mov_w_r0_disp_gbr: Store R0 to address disp + GBR (16-bit).
998 * mov_l_r0_disp_gbr: Store R0 to address disp + GBR (32-bit).
999 * mov_l_rm_disp_rn: Store Rm to address disp + Rn.
1000 * mov_b_r0_disp_rn: Store R0 to address disp + Rn (8-bit).
1001 * mov_w_r0_disp_rn: Store R0 to address disp + Rn (16-bit).
1002 *
1003 * arg[0] = ptr to rm
1004 * arg[1] = ptr to rn (or Rn+(disp<<4) for mov_l_rm_disp_rn)
1005 * (or disp for mov_*_r0_disp_gbr)
1006 */
1007 X(mov_b_store_rm_rn)
1008 {
1009 uint32_t addr = reg(ic->arg[1]);
1010 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
1011 uint8_t data = reg(ic->arg[0]);
1012
1013 if (p != NULL) {
1014 p[addr & 0xfff] = data;
1015 } else {
1016 SYNCH_PC;
1017 if (!cpu->memory_rw(cpu, cpu->mem, addr, &data,
1018 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1019 /* Exception. */
1020 return;
1021 }
1022 }
1023 }
1024 X(mov_w_store_rm_rn)
1025 {
1026 uint32_t addr = reg(ic->arg[1]);
1027 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1028 uint16_t data = reg(ic->arg[0]);
1029
1030 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1031 data = LE16_TO_HOST(data);
1032 else
1033 data = BE16_TO_HOST(data);
1034
1035 if (p != NULL) {
1036 p[(addr & 0xfff) >> 1] = data;
1037 } else {
1038 SYNCH_PC;
1039 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1040 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1041 /* Exception. */
1042 return;
1043 }
1044 }
1045 }
1046 X(mov_l_store_rm_rn)
1047 {
1048 uint32_t addr = reg(ic->arg[1]);
1049 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1050 uint32_t data = reg(ic->arg[0]);
1051
1052 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1053 data = LE32_TO_HOST(data);
1054 else
1055 data = BE32_TO_HOST(data);
1056
1057 if (p != NULL) {
1058 p[(addr & 0xfff) >> 2] = data;
1059 } else {
1060 SYNCH_PC;
1061 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1062 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1063 /* Exception. */
1064 return;
1065 }
1066 }
1067 }
1068 X(fmov_frm_rn)
1069 {
1070 uint32_t addr = reg(ic->arg[1]);
1071 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1072 uint32_t data = reg(ic->arg[0]);
1073
1074 FLOATING_POINT_AVAILABLE_CHECK;
1075
1076 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1077 fatal("fmov_frm_rn: sz=1 (register pair): TODO\n");
1078 exit(1);
1079 }
1080
1081 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1082 data = LE32_TO_HOST(data);
1083 else
1084 data = BE32_TO_HOST(data);
1085
1086 if (p != NULL) {
1087 p[(addr & 0xfff) >> 2] = data;
1088 } else {
1089 SYNCH_PC;
1090 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1091 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1092 /* Exception. */
1093 return;
1094 }
1095 }
1096 }
1097 X(fmov_frm_r0_rn)
1098 {
1099 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1100 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1101 uint32_t data = reg(ic->arg[0]);
1102
1103 FLOATING_POINT_AVAILABLE_CHECK;
1104
1105 if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1106 fatal("fmov_frm_r0_rn: sz=1 (register pair): TODO\n");
1107 exit(1);
1108 }
1109
1110 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1111 data = LE32_TO_HOST(data);
1112 else
1113 data = BE32_TO_HOST(data);
1114
1115 if (p != NULL) {
1116 p[(addr & 0xfff) >> 2] = data;
1117 } else {
1118 SYNCH_PC;
1119 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1120 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1121 /* Exception. */
1122 return;
1123 }
1124 }
1125 }
1126 X(fmov_frm_predec_rn)
1127 {
1128 int d = cpu->cd.sh.fpscr & SH_FPSCR_SZ? 1 : 0;
1129 uint32_t data, addr = reg(ic->arg[1]) - (d? 8 : 4);
1130 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1131 size_t r0 = ic->arg[0];
1132
1133 if (d) {
1134 /* xd instead of dr? */
1135 int ofs0 = (r0 - (size_t)&cpu->cd.sh.fr[0]) / sizeof(uint32_t);
1136 if (ofs0 & 1)
1137 r0 = (size_t)&cpu->cd.sh.xf[ofs0 & ~1];
1138 }
1139
1140 data = reg(r0);
1141
1142 FLOATING_POINT_AVAILABLE_CHECK;
1143
1144 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1145 data = LE32_TO_HOST(data);
1146 else
1147 data = BE32_TO_HOST(data);
1148
1149 if (p != NULL) {
1150 p[(addr & 0xfff) >> 2] = data;
1151 } else {
1152 SYNCH_PC;
1153 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1154 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1155 /* Exception. */
1156 return;
1157 }
1158 }
1159
1160 if (d) {
1161 /* Store second single-precision floating point word: */
1162 data = reg(r0 + 4);
1163 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1164 data = LE32_TO_HOST(data);
1165 else
1166 data = BE32_TO_HOST(data);
1167 SYNCH_PC;
1168 if (!cpu->memory_rw(cpu, cpu->mem, addr + 4, (unsigned
1169 char *)&data, sizeof(data), MEM_WRITE, CACHE_DATA))
1170 return;
1171 }
1172
1173 reg(ic->arg[1]) = addr;
1174 }
1175 X(mov_b_rm_r0_rn)
1176 {
1177 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1178 int8_t *p = (int8_t *) cpu->cd.sh.host_store[addr >> 12];
1179 int8_t data = reg(ic->arg[0]);
1180 if (p != NULL) {
1181 p[addr & 0xfff] = data;
1182 } else {
1183 SYNCH_PC;
1184 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1185 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1186 /* Exception. */
1187 return;
1188 }
1189 }
1190 }
1191 X(mov_w_rm_r0_rn)
1192 {
1193 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1194 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1195 uint16_t data = reg(ic->arg[0]);
1196
1197 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1198 data = LE16_TO_HOST(data);
1199 else
1200 data = BE16_TO_HOST(data);
1201
1202 if (p != NULL) {
1203 p[(addr & 0xfff) >> 1] = data;
1204 } else {
1205 SYNCH_PC;
1206 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1207 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1208 /* Exception. */
1209 return;
1210 }
1211 }
1212 }
1213 X(mov_l_rm_r0_rn)
1214 {
1215 uint32_t addr = reg(ic->arg[1]) + cpu->cd.sh.r[0];
1216 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1217 uint32_t data = reg(ic->arg[0]);
1218
1219 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1220 data = LE32_TO_HOST(data);
1221 else
1222 data = BE32_TO_HOST(data);
1223
1224 if (p != NULL) {
1225 p[(addr & 0xfff) >> 2] = data;
1226 } else {
1227 SYNCH_PC;
1228 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1229 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1230 /* Exception. */
1231 return;
1232 }
1233 }
1234 }
1235 X(mov_b_r0_disp_gbr)
1236 {
1237 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
1238 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
1239 uint8_t data = cpu->cd.sh.r[0];
1240 if (p != NULL) {
1241 p[addr & 0xfff] = data;
1242 } else {
1243 SYNCH_PC;
1244 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1245 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1246 /* Exception. */
1247 return;
1248 }
1249 }
1250 }
1251 X(mov_w_r0_disp_gbr)
1252 {
1253 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
1254 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1255 uint16_t data = cpu->cd.sh.r[0];
1256
1257 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1258 data = LE16_TO_HOST(data);
1259 else
1260 data = BE16_TO_HOST(data);
1261
1262 if (p != NULL) {
1263 p[(addr & 0xfff) >> 1] = data;
1264 } else {
1265 SYNCH_PC;
1266 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1267 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1268 /* Exception. */
1269 return;
1270 }
1271 }
1272 }
1273 X(mov_l_r0_disp_gbr)
1274 {
1275 uint32_t addr = cpu->cd.sh.gbr + ic->arg[1];
1276 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1277 uint32_t data = cpu->cd.sh.r[0];
1278
1279 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1280 data = LE32_TO_HOST(data);
1281 else
1282 data = BE32_TO_HOST(data);
1283
1284 if (p != NULL) {
1285 p[(addr & 0xfff) >> 2] = data;
1286 } else {
1287 SYNCH_PC;
1288 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1289 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1290 /* Exception. */
1291 return;
1292 }
1293 }
1294 }
1295 X(mov_l_rm_disp_rn)
1296 {
1297 uint32_t addr = cpu->cd.sh.r[ic->arg[1] & 0xf] +
1298 ((ic->arg[1] >> 4) << 2);
1299 uint32_t *p = (uint32_t *) cpu->cd.sh.host_store[addr >> 12];
1300 uint32_t data = reg(ic->arg[0]);
1301
1302 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1303 data = LE32_TO_HOST(data);
1304 else
1305 data = BE32_TO_HOST(data);
1306
1307 if (p != NULL) {
1308 p[(addr & 0xfff) >> 2] = data;
1309 } else {
1310 SYNCH_PC;
1311 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1312 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1313 /* Exception. */
1314 return;
1315 }
1316 }
1317 }
1318 X(mov_b_r0_disp_rn)
1319 {
1320 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
1321 uint8_t *p = (uint8_t *) cpu->cd.sh.host_store[addr >> 12];
1322 uint8_t data = cpu->cd.sh.r[0];
1323
1324 if (p != NULL) {
1325 p[addr & 0xfff] = data;
1326 } else {
1327 SYNCH_PC;
1328 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1329 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1330 /* Exception. */
1331 return;
1332 }
1333 }
1334 }
1335 X(mov_w_r0_disp_rn)
1336 {
1337 uint32_t addr = reg(ic->arg[0]) + ic->arg[1];
1338 uint16_t *p = (uint16_t *) cpu->cd.sh.host_store[addr >> 12];
1339 uint16_t data = cpu->cd.sh.r[0];
1340
1341 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1342 data = LE16_TO_HOST(data);
1343 else
1344 data = BE16_TO_HOST(data);
1345
1346 if (p != NULL) {
1347 p[(addr & 0xfff) >> 1] = data;
1348 } else {
1349 SYNCH_PC;
1350 if (!cpu->memory_rw(cpu, cpu->mem, addr, (unsigned char *)&data,
1351 sizeof(data), MEM_WRITE, CACHE_DATA)) {
1352 /* Exception. */
1353 return;
1354 }
1355 }
1356 }
1357
1358
1359 /*
1360 * add_rm_rn: rn = rn + rm
1361 * addc_rm_rn: rn = rn + rm + t
1362 * and_rm_rn: rn = rn & rm
1363 * xor_rm_rn: rn = rn ^ rm
1364 * or_rm_rn: rn = rn | rm
1365 * sub_rm_rn: rn = rn - rm
1366 * subc_rm_rn: rn = rn - rm - t; t = borrow
1367 * tst_rm_rn: t = ((rm & rn) == 0)
1368 * xtrct_rm_rn: rn = (rn >> 16) | (rm << 16)
1369 *
1370 * arg[0] = ptr to rm
1371 * arg[1] = ptr to rn
1372 */
1373 X(add_rm_rn) { reg(ic->arg[1]) += reg(ic->arg[0]); }
1374 X(addc_rm_rn)
1375 {
1376 uint64_t res = reg(ic->arg[1]);
1377 res += (uint64_t) reg(ic->arg[0]);
1378 if (cpu->cd.sh.sr & SH_SR_T)
1379 res ++;
1380 if ((res >> 32) & 1)
1381 cpu->cd.sh.sr |= SH_SR_T;
1382 else
1383 cpu->cd.sh.sr &= ~SH_SR_T;
1384 reg(ic->arg[1]) = (uint32_t) res;
1385 }
1386 X(and_rm_rn) { reg(ic->arg[1]) &= reg(ic->arg[0]); }
1387 X(xor_rm_rn) { reg(ic->arg[1]) ^= reg(ic->arg[0]); }
1388 X(or_rm_rn) { reg(ic->arg[1]) |= reg(ic->arg[0]); }
1389 X(sub_rm_rn) { reg(ic->arg[1]) -= reg(ic->arg[0]); }
1390 X(subc_rm_rn)
1391 {
1392 uint64_t res = reg(ic->arg[1]);
1393 res -= (uint64_t) reg(ic->arg[0]);
1394 if (cpu->cd.sh.sr & SH_SR_T)
1395 res --;
1396 if ((res >> 32) & 1)
1397 cpu->cd.sh.sr |= SH_SR_T;
1398 else
1399 cpu->cd.sh.sr &= ~SH_SR_T;
1400 reg(ic->arg[1]) = (uint32_t) res;
1401 }
1402 X(tst_rm_rn)
1403 {
1404 if (reg(ic->arg[1]) & reg(ic->arg[0]))
1405 cpu->cd.sh.sr &= ~SH_SR_T;
1406 else
1407 cpu->cd.sh.sr |= SH_SR_T;
1408 }
1409 X(xtrct_rm_rn)
1410 {
1411 uint32_t rn = reg(ic->arg[1]), rm = reg(ic->arg[0]);
1412 reg(ic->arg[1]) = (rn >> 16) | (rm << 16);
1413 }
1414
1415
1416 /*
1417 * div0u: Division step 0; prepare for unsigned division.
1418 * div0s_rm_rn: Division step 0; prepare for signed division.
1419 * div1_rm_rn: Division step 1.
1420 *
1421 * arg[0] = ptr to rm
1422 * arg[1] = ptr to rn
1423 */
1424 X(div0u)
1425 {
1426 cpu->cd.sh.sr &= ~(SH_SR_Q | SH_SR_M | SH_SR_T);
1427 }
1428 X(div0s_rm_rn)
1429 {
1430 int q = reg(ic->arg[1]) >> 31, m = reg(ic->arg[0]) >> 31;
1431 cpu->cd.sh.sr &= ~(SH_SR_Q | SH_SR_M | SH_SR_T);
1432 if (q)
1433 cpu->cd.sh.sr |= SH_SR_Q;
1434 if (m)
1435 cpu->cd.sh.sr |= SH_SR_M;
1436 if (m ^ q)
1437 cpu->cd.sh.sr |= SH_SR_T;
1438 }
1439 X(div1_rm_rn)
1440 {
1441 uint32_t q, old_q = (cpu->cd.sh.sr & SH_SR_Q)? 1 : 0;
1442 uint32_t m = (cpu->cd.sh.sr & SH_SR_M)? 1 : 0;
1443 uint32_t t = (cpu->cd.sh.sr & SH_SR_T)? 1 : 0;
1444 uint32_t op1 = reg(ic->arg[0]), op2 = reg(ic->arg[1]);
1445 uint64_t op2_64;
1446
1447 q = op2 >> 31;
1448 op2_64 = (uint32_t) ((op2 << 1) + t);
1449 if (old_q == m)
1450 op2_64 -= (uint64_t)op1;
1451 else
1452 op2_64 += (uint64_t)op1;
1453 q ^= m ^ ((op2_64 >> 32) & 1);
1454 t = 1 - (q ^ m);
1455 cpu->cd.sh.sr &= ~(SH_SR_Q | SH_SR_T);
1456 if (q)
1457 cpu->cd.sh.sr |= SH_SR_Q;
1458 if (t)
1459 cpu->cd.sh.sr |= SH_SR_T;
1460 reg(ic->arg[1]) = (uint32_t) op2_64;
1461 }
1462
1463
1464 /*
1465 * mul_l_rm_rn: MACL = Rm * Rn (32-bit)
1466 * muls_w_rm_rn: MACL = Rm * Rn (signed 16-bit * 16-bit ==> 32-bit)
1467 * mulu_w_rm_rn: MACL = Rm * Rn (unsigned 16-bit * 16-bit ==> 32-bit)
1468 * dmuls_l_rm_rn: MACH:MACL = Rm * Rn (signed, 64-bit result)
1469 * dmulu_l_rm_rn: MACH:MACL = Rm * Rn (unsigned, 64-bit result)
1470 *
1471 * arg[0] = ptr to rm
1472 * arg[1] = ptr to rn
1473 */
1474 X(mul_l_rm_rn)
1475 {
1476 cpu->cd.sh.macl = reg(ic->arg[0]) * reg(ic->arg[1]);
1477 }
1478 X(muls_w_rm_rn)
1479 {
1480 cpu->cd.sh.macl = (int32_t)(int16_t)reg(ic->arg[0]) *
1481 (int32_t)(int16_t)reg(ic->arg[1]);
1482 }
1483 X(mulu_w_rm_rn)
1484 {
1485 cpu->cd.sh.macl = (int32_t)(uint16_t)reg(ic->arg[0]) *
1486 (int32_t)(uint16_t)reg(ic->arg[1]);
1487 }
1488 X(dmuls_l_rm_rn)
1489 {
1490 uint64_t rm = (int32_t)reg(ic->arg[0]), rn = (int32_t)reg(ic->arg[1]);
1491 uint64_t res = rm * rn;
1492 cpu->cd.sh.mach = (uint32_t) (res >> 32);
1493 cpu->cd.sh.macl = (uint32_t) res;
1494 }
1495 X(dmulu_l_rm_rn)
1496 {
1497 uint64_t rm = reg(ic->arg[0]), rn = reg(ic->arg[1]), res;
1498 res = rm * rn;
1499 cpu->cd.sh.mach = (uint32_t) (res >> 32);
1500 cpu->cd.sh.macl = (uint32_t) res;
1501 }
1502
1503
1504 /*
1505 * cmpeq_imm_r0: rn == int8_t immediate
1506 * cmpeq_rm_rn: rn == rm
1507 * cmphs_rm_rn: rn >= rm, unsigned
1508 * cmpge_rm_rn: rn >= rm, signed
1509 * cmphi_rm_rn: rn > rm, unsigned
1510 * cmpgt_rm_rn: rn > rm, signed
1511 * cmppz_rn: rn >= 0, signed
1512 * cmppl_rn: rn > 0, signed
1513 * cmp_str_rm_rn: t=1 if any bytes in rm and rn match, 0 otherwise
1514 *
1515 * arg[0] = ptr to rm (or imm, for cmpeq_imm_r0)
1516 * arg[1] = ptr to rn
1517 */
1518 X(cmpeq_imm_r0)
1519 {
1520 if (cpu->cd.sh.r[0] == (uint32_t)ic->arg[0])
1521 cpu->cd.sh.sr |= SH_SR_T;
1522 else
1523 cpu->cd.sh.sr &= ~SH_SR_T;
1524 }
1525 X(cmpeq_rm_rn)
1526 {
1527 if (reg(ic->arg[1]) == reg(ic->arg[0]))
1528 cpu->cd.sh.sr |= SH_SR_T;
1529 else
1530 cpu->cd.sh.sr &= ~SH_SR_T;
1531 }
1532 X(cmphs_rm_rn)
1533 {
1534 if (reg(ic->arg[1]) >= reg(ic->arg[0]))
1535 cpu->cd.sh.sr |= SH_SR_T;
1536 else
1537 cpu->cd.sh.sr &= ~SH_SR_T;
1538 }
1539 X(cmpge_rm_rn)
1540 {
1541 if ((int32_t)reg(ic->arg[1]) >= (int32_t)reg(ic->arg[0]))
1542 cpu->cd.sh.sr |= SH_SR_T;
1543 else
1544 cpu->cd.sh.sr &= ~SH_SR_T;
1545 }
1546 X(cmphi_rm_rn)
1547 {
1548 if (reg(ic->arg[1]) > reg(ic->arg[0]))
1549 cpu->cd.sh.sr |= SH_SR_T;
1550 else
1551 cpu->cd.sh.sr &= ~SH_SR_T;
1552 }
1553 X(cmpgt_rm_rn)
1554 {
1555 if ((int32_t)reg(ic->arg[1]) > (int32_t)reg(ic->arg[0]))
1556 cpu->cd.sh.sr |= SH_SR_T;
1557 else
1558 cpu->cd.sh.sr &= ~SH_SR_T;
1559 }
1560 X(cmppz_rn)
1561 {
1562 if ((int32_t)reg(ic->arg[1]) >= 0)
1563 cpu->cd.sh.sr |= SH_SR_T;
1564 else
1565 cpu->cd.sh.sr &= ~SH_SR_T;
1566 }
1567 X(cmppl_rn)
1568 {
1569 if ((int32_t)reg(ic->arg[1]) > 0)
1570 cpu->cd.sh.sr |= SH_SR_T;
1571 else
1572 cpu->cd.sh.sr &= ~SH_SR_T;
1573 }
1574 X(cmp_str_rm_rn)
1575 {
1576 uint32_t r0 = reg(ic->arg[0]), r1 = reg(ic->arg[1]);
1577 int t = 0;
1578 if ((r0 & 0xff000000) == (r1 & 0xff000000))
1579 t = 1;
1580 else if ((r0 & 0xff0000) == (r1 & 0xff0000))
1581 t = 1;
1582 else if ((r0 & 0xff00) == (r1 & 0xff00))
1583 t = 1;
1584 else if ((r0 & 0xff) == (r1 & 0xff))
1585 t = 1;
1586 if (t)
1587 cpu->cd.sh.sr |= SH_SR_T;
1588 else
1589 cpu->cd.sh.sr &= ~SH_SR_T;
1590 }
1591
1592
1593 /*
1594 * shll_rn: Shift rn left by 1 (t = bit that was shifted out)
1595 * shlr_rn: Shift rn right by 1 (t = bit that was shifted out)
1596 * rotl_rn: Shift rn left by 1 (t = bit that was shifted out)
1597 * rotr_rn: Shift rn right by 1 (t = bit that was shifted out)
1598 * shar_rn: Shift rn right arithmetically by 1 (t = bit that was shifted out)
1599 * shllX_rn: Shift rn left logically by X bits
1600 * shlrX_rn: Shift rn right logically by X bits
1601 * rotcl_rn: Rotate rn left via the t bit
1602 * rotcr_rn: Rotate rn right via the t bit
1603 * dt_rn: Decrease rn; t = (rn == 0)
1604 *
1605 * arg[1] = ptr to rn
1606 */
1607 X(shll_rn)
1608 {
1609 uint32_t rn = reg(ic->arg[1]);
1610 if (rn >> 31)
1611 cpu->cd.sh.sr |= SH_SR_T;
1612 else
1613 cpu->cd.sh.sr &= ~SH_SR_T;
1614 reg(ic->arg[1]) = rn << 1;
1615 }
1616 X(shlr_rn)
1617 {
1618 uint32_t rn = reg(ic->arg[1]);
1619 if (rn & 1)
1620 cpu->cd.sh.sr |= SH_SR_T;
1621 else
1622 cpu->cd.sh.sr &= ~SH_SR_T;
1623 reg(ic->arg[1]) = rn >> 1;
1624 }
1625 X(rotl_rn)
1626 {
1627 uint32_t rn = reg(ic->arg[1]);
1628 if (rn >> 31)
1629 cpu->cd.sh.sr |= SH_SR_T;
1630 else
1631 cpu->cd.sh.sr &= ~SH_SR_T;
1632 reg(ic->arg[1]) = (rn << 1) | (rn >> 31);
1633 }
1634 X(rotr_rn)
1635 {
1636 uint32_t rn = reg(ic->arg[1]);
1637 if (rn & 1)
1638 cpu->cd.sh.sr |= SH_SR_T;
1639 else
1640 cpu->cd.sh.sr &= ~SH_SR_T;
1641 reg(ic->arg[1]) = (rn >> 1) | (rn << 31);
1642 }
1643 X(shar_rn)
1644 {
1645 int32_t rn = reg(ic->arg[1]);
1646 if (rn & 1)
1647 cpu->cd.sh.sr |= SH_SR_T;
1648 else
1649 cpu->cd.sh.sr &= ~SH_SR_T;
1650 reg(ic->arg[1]) = rn >> 1;
1651 }
1652 X(rotcl_rn)
1653 {
1654 uint32_t rn = reg(ic->arg[1]), top;
1655 top = rn & 0x80000000;
1656 rn <<= 1;
1657 if (cpu->cd.sh.sr & SH_SR_T)
1658 rn ++;
1659 if (top)
1660 cpu->cd.sh.sr |= SH_SR_T;
1661 else
1662 cpu->cd.sh.sr &= ~SH_SR_T;
1663 reg(ic->arg[1]) = rn;
1664 }
1665 X(rotcr_rn)
1666 {
1667 uint32_t rn = reg(ic->arg[1]), bottom;
1668 bottom = rn & 1;
1669 rn >>= 1;
1670 if (cpu->cd.sh.sr & SH_SR_T)
1671 rn |= 0x80000000;
1672 if (bottom)
1673 cpu->cd.sh.sr |= SH_SR_T;
1674 else
1675 cpu->cd.sh.sr &= ~SH_SR_T;
1676 reg(ic->arg[1]) = rn;
1677 }
1678 X(dt_rn)
1679 {
1680 uint32_t rn = reg(ic->arg[1]) - 1;
1681 if (rn == 0)
1682 cpu->cd.sh.sr |= SH_SR_T;
1683 else
1684 cpu->cd.sh.sr &= ~SH_SR_T;
1685 reg(ic->arg[1]) = rn;
1686 }
1687 X(shll2_rn) { reg(ic->arg[1]) <<= 2; }
1688 X(shll8_rn) { reg(ic->arg[1]) <<= 8; }
1689 X(shll16_rn) { reg(ic->arg[1]) <<= 16; }
1690 X(shlr2_rn) { reg(ic->arg[1]) >>= 2; }
1691 X(shlr8_rn) { reg(ic->arg[1]) >>= 8; }
1692 X(shlr16_rn) { reg(ic->arg[1]) >>= 16; }
1693
1694
1695 /*
1696 * shad: Shift Rn arithmetic left/right, as indicated by Rm. Result in Rn.
1697 * shld: Shift Rn logically left/right, as indicated by Rm. Result in Rn.
1698 *
1699 * arg[0] = ptr to rm
1700 * arg[1] = ptr to rn
1701 */
1702 X(shad)
1703 {
1704 int32_t rn = reg(ic->arg[1]);
1705 int32_t rm = reg(ic->arg[0]);
1706 int sa = rm & 0x1f;
1707
1708 if (rm >= 0)
1709 rn <<= sa;
1710 else if (sa != 0)
1711 rn >>= (32 - sa);
1712 else if (rn < 0)
1713 rn = -1;
1714 else
1715 rn = 0;
1716
1717 reg(ic->arg[1]) = rn;
1718 }
1719 X(shld)
1720 {
1721 uint32_t rn = reg(ic->arg[1]);
1722 int32_t rm = reg(ic->arg[0]);
1723 int sa = rm & 0x1f;
1724
1725 if (rm >= 0)
1726 rn <<= sa;
1727 else if (sa != 0)
1728 rn >>= (32 - sa);
1729 else
1730 rn = 0;
1731
1732 reg(ic->arg[1]) = rn;
1733 }
1734
1735
1736 /*
1737 * bra: Branch using PC relative immediace displacement (with delay-slot)
1738 * bsr: Like bra, but also sets PR to the return address
1739 * braf: Like bra, but using a register instead of an immediate
1740 * bsrf: Like braf, but also sets PR to the return address
1741 *
1742 * arg[0] = immediate offset relative to start of page
1743 * arg[1] = ptr to Rn (for braf/bsrf)
1744 */
1745 X(bra)
1746 {
1747 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1748 SH_INSTR_ALIGNMENT_SHIFT);
1749 target += ic->arg[0];
1750 cpu->delay_slot = TO_BE_DELAYED;
1751 ic[1].f(cpu, ic+1);
1752 cpu->n_translated_instrs ++;
1753 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1754 cpu->pc = target;
1755 cpu->delay_slot = NOT_DELAYED;
1756 quick_pc_to_pointers(cpu);
1757 } else
1758 cpu->delay_slot = NOT_DELAYED;
1759 }
1760 X(bsr)
1761 {
1762 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1763 SH_INSTR_ALIGNMENT_SHIFT);
1764 uint32_t old_pc;
1765 SYNCH_PC;
1766 old_pc = cpu->pc;
1767 target += ic->arg[0];
1768 cpu->delay_slot = TO_BE_DELAYED;
1769 ic[1].f(cpu, ic+1);
1770 cpu->n_translated_instrs ++;
1771 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1772 cpu->cd.sh.pr = old_pc + 4;
1773 cpu->pc = target;
1774 cpu->delay_slot = NOT_DELAYED;
1775 quick_pc_to_pointers(cpu);
1776 } else
1777 cpu->delay_slot = NOT_DELAYED;
1778 }
1779 X(braf_rn)
1780 {
1781 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1782 SH_INSTR_ALIGNMENT_SHIFT);
1783 target += ic->arg[0] + reg(ic->arg[1]);
1784 cpu->delay_slot = TO_BE_DELAYED;
1785 ic[1].f(cpu, ic+1);
1786 cpu->n_translated_instrs ++;
1787 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1788 cpu->pc = target;
1789 cpu->delay_slot = NOT_DELAYED;
1790 quick_pc_to_pointers(cpu);
1791 } else
1792 cpu->delay_slot = NOT_DELAYED;
1793 }
1794 X(bsrf_rn)
1795 {
1796 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1797 SH_INSTR_ALIGNMENT_SHIFT);
1798 uint32_t old_pc;
1799 SYNCH_PC;
1800 old_pc = cpu->pc;
1801 target += ic->arg[0] + reg(ic->arg[1]);
1802 cpu->delay_slot = TO_BE_DELAYED;
1803 ic[1].f(cpu, ic+1);
1804 cpu->n_translated_instrs ++;
1805 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1806 cpu->cd.sh.pr = old_pc + 4;
1807 cpu->pc = target;
1808 cpu->delay_slot = NOT_DELAYED;
1809 quick_pc_to_pointers(cpu);
1810 } else
1811 cpu->delay_slot = NOT_DELAYED;
1812 }
1813
1814
1815 /*
1816 * bt: Branch if true
1817 * bf: Branch if false
1818 * bt/s: Branch if true (with delay-slot)
1819 * bf/s: Branch if false (with delay-slot)
1820 *
1821 * arg[0] = immediate offset relative to start of page
1822 */
1823 X(bt)
1824 {
1825 if (cpu->cd.sh.sr & SH_SR_T) {
1826 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1827 SH_INSTR_ALIGNMENT_SHIFT);
1828 cpu->pc += ic->arg[0];
1829 quick_pc_to_pointers(cpu);
1830 }
1831 }
1832 X(bf)
1833 {
1834 if (!(cpu->cd.sh.sr & SH_SR_T)) {
1835 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1836 SH_INSTR_ALIGNMENT_SHIFT);
1837 cpu->pc += ic->arg[0];
1838 quick_pc_to_pointers(cpu);
1839 }
1840 }
1841 X(bt_s)
1842 {
1843 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1844 SH_INSTR_ALIGNMENT_SHIFT);
1845 int cond = cpu->cd.sh.sr & SH_SR_T;
1846 target += ic->arg[0];
1847 cpu->delay_slot = TO_BE_DELAYED;
1848 ic[1].f(cpu, ic+1);
1849 cpu->n_translated_instrs ++;
1850 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1851 cpu->delay_slot = NOT_DELAYED;
1852 if (cond) {
1853 cpu->pc = target;
1854 quick_pc_to_pointers(cpu);
1855 } else
1856 cpu->cd.sh.next_ic ++;
1857 } else
1858 cpu->delay_slot = NOT_DELAYED;
1859 }
1860 X(bf_s)
1861 {
1862 MODE_int_t target = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1863 SH_INSTR_ALIGNMENT_SHIFT);
1864 int cond = !(cpu->cd.sh.sr & SH_SR_T);
1865 target += ic->arg[0];
1866 cpu->delay_slot = TO_BE_DELAYED;
1867 ic[1].f(cpu, ic+1);
1868 cpu->n_translated_instrs ++;
1869 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1870 cpu->delay_slot = NOT_DELAYED;
1871 if (cond) {
1872 cpu->pc = target;
1873 quick_pc_to_pointers(cpu);
1874 } else
1875 cpu->cd.sh.next_ic ++;
1876 } else
1877 cpu->delay_slot = NOT_DELAYED;
1878 }
1879
1880
1881 /*
1882 * jmp_rn: Jump to Rn
1883 * jsr_rn: Jump to Rn, store return address in PR.
1884 *
1885 * arg[0] = ptr to rn
1886 */
1887 X(jmp_rn)
1888 {
1889 MODE_int_t target = reg(ic->arg[0]);
1890 cpu->delay_slot = TO_BE_DELAYED;
1891 ic[1].f(cpu, ic+1);
1892 cpu->n_translated_instrs ++;
1893 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1894 cpu->pc = target;
1895 cpu->delay_slot = NOT_DELAYED;
1896 quick_pc_to_pointers(cpu);
1897 } else
1898 cpu->delay_slot = NOT_DELAYED;
1899 }
1900 X(jmp_rn_trace)
1901 {
1902 MODE_int_t target = reg(ic->arg[0]);
1903 cpu->delay_slot = TO_BE_DELAYED;
1904 ic[1].f(cpu, ic+1);
1905 cpu->n_translated_instrs ++;
1906 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1907 cpu->pc = target;
1908 #if 0
1909 /* NOTE: Jmp works like both a return, and a subroutine
1910 call. */
1911 cpu_functioncall_trace_return(cpu);
1912 cpu_functioncall_trace(cpu, cpu->pc);
1913 #endif
1914 cpu->delay_slot = NOT_DELAYED;
1915 quick_pc_to_pointers(cpu);
1916 } else
1917 cpu->delay_slot = NOT_DELAYED;
1918 }
1919 X(jsr_rn)
1920 {
1921 MODE_int_t target = reg(ic->arg[0]), retaddr;
1922 cpu->delay_slot = TO_BE_DELAYED;
1923 retaddr = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1924 SH_INSTR_ALIGNMENT_SHIFT);
1925 ic[1].f(cpu, ic+1);
1926 cpu->n_translated_instrs ++;
1927 cpu->cd.sh.pr = retaddr + (int32_t)ic->arg[1];
1928 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1929 cpu->pc = target;
1930 cpu->delay_slot = NOT_DELAYED;
1931 quick_pc_to_pointers(cpu);
1932 } else
1933 cpu->delay_slot = NOT_DELAYED;
1934 }
1935 X(jsr_rn_trace)
1936 {
1937 MODE_int_t target = reg(ic->arg[0]), retaddr;
1938 cpu->delay_slot = TO_BE_DELAYED;
1939 retaddr = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1) <<
1940 SH_INSTR_ALIGNMENT_SHIFT);
1941 ic[1].f(cpu, ic+1);
1942 cpu->n_translated_instrs ++;
1943 cpu->cd.sh.pr = retaddr + (int32_t)ic->arg[1];
1944 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1945 cpu->pc = target;
1946 cpu_functioncall_trace(cpu, cpu->pc);
1947 cpu->delay_slot = NOT_DELAYED;
1948 quick_pc_to_pointers(cpu);
1949 } else
1950 cpu->delay_slot = NOT_DELAYED;
1951 }
1952
1953
1954 /*
1955 * rts: Jump to PR.
1956 */
1957 X(rts)
1958 {
1959 MODE_int_t target = cpu->cd.sh.pr;
1960 cpu->delay_slot = TO_BE_DELAYED;
1961 ic[1].f(cpu, ic+1);
1962 cpu->n_translated_instrs ++;
1963 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1964 cpu->pc = target;
1965 cpu->delay_slot = NOT_DELAYED;
1966 quick_pc_to_pointers(cpu);
1967 } else
1968 cpu->delay_slot = NOT_DELAYED;
1969 }
1970 X(rts_trace)
1971 {
1972 MODE_int_t target = cpu->cd.sh.pr;
1973 cpu->delay_slot = TO_BE_DELAYED;
1974 ic[1].f(cpu, ic+1);
1975 cpu->n_translated_instrs ++;
1976 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1977 cpu->pc = target;
1978 cpu_functioncall_trace_return(cpu);
1979 cpu->delay_slot = NOT_DELAYED;
1980 quick_pc_to_pointers(cpu);
1981 } else
1982 cpu->delay_slot = NOT_DELAYED;
1983 }
1984
1985
1986 /*
1987 * sts_mach_rn: Store MACH into Rn
1988 * sts_macl_rn: Store MACL into Rn
1989 * sts_pr_rn: Store PR into Rn
1990 *
1991 * arg[1] = ptr to rn
1992 */
1993 X(sts_mach_rn) { reg(ic->arg[1]) = cpu->cd.sh.mach; }
1994 X(sts_macl_rn) { reg(ic->arg[1]) = cpu->cd.sh.macl; }
1995 X(sts_pr_rn) { reg(ic->arg[1]) = cpu->cd.sh.pr; }
1996
1997
1998 /*
1999 * rte: Return from exception.
2000 */
2001 X(rte)
2002 {
2003 RES_INST_IF_NOT_MD;
2004
2005 cpu->delay_slot = TO_BE_DELAYED;
2006 ic[1].f(cpu, ic+1);
2007 cpu->n_translated_instrs ++;
2008 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
2009 cpu->pc = cpu->cd.sh.spc;
2010 cpu->delay_slot = NOT_DELAYED;
2011 sh_update_sr(cpu, cpu->cd.sh.ssr);
2012 quick_pc_to_pointers(cpu);
2013 } else
2014 cpu->delay_slot = NOT_DELAYED;
2015 }
2016
2017
2018 /*
2019 * ldtlb: Load UTLB entry.
2020 */
2021 X(ldtlb)
2022 {
2023 uint32_t old_hi, old_lo;
2024 int urc = (cpu->cd.sh.mmucr & SH4_MMUCR_URC_MASK)
2025 >> SH4_MMUCR_URC_SHIFT;
2026
2027 RES_INST_IF_NOT_MD;
2028
2029 old_hi = cpu->cd.sh.utlb_hi[urc];
2030 old_lo = cpu->cd.sh.utlb_lo[urc];
2031
2032 cpu->cd.sh.utlb_hi[urc] = cpu->cd.sh.pteh;
2033 cpu->cd.sh.utlb_lo[urc] = cpu->cd.sh.ptel;
2034
2035 /* Invalidate the old mapping, if it belonged to the same ASID: */
2036 if ((old_hi & SH4_PTEH_ASID_MASK) ==
2037 (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK)) {
2038 if ((old_lo & SH4_PTEL_SZ_MASK) == SH4_PTEL_SZ_4K)
2039 cpu->invalidate_translation_caches(cpu,
2040 old_hi & 0xfffff000, INVALIDATE_VADDR);
2041 else
2042 cpu->invalidate_translation_caches(cpu,
2043 old_hi & 0xfffff000, INVALIDATE_ALL);
2044 }
2045 }
2046
2047
2048 /*
2049 * copy_privileged_register: Copy normal into privileged register, or vice
2050 * versa, after checking the MD status bit.
2051 *
2052 * arg[0] = ptr to source register
2053 * arg[1] = ptr to destination register
2054 */
2055 X(copy_privileged_register)
2056 {
2057 RES_INST_IF_NOT_MD;
2058 reg(ic->arg[1]) = reg(ic->arg[0]);
2059 }
2060
2061
2062 /*
2063 * ldc_rm_sr: Copy Rm into SR, after checking the MD status bit.
2064 *
2065 * arg[1] = ptr to rm
2066 */
2067 X(ldc_rm_sr)
2068 {
2069 RES_INST_IF_NOT_MD;
2070 sh_update_sr(cpu, reg(ic->arg[1]));
2071 }
2072
2073
2074 /*
2075 * trapa: Immediate trap.
2076 *
2077 * arg[0] = imm << 2
2078 */
2079 X(trapa)
2080 {
2081 SYNCH_PC;
2082
2083 if (cpu->delay_slot) {
2084 sh_exception(cpu, EXPEVT_SLOT_INST, 0, 0);
2085 return;
2086 }
2087
2088 cpu->cd.sh.tra = ic->arg[0];
2089 sh_exception(cpu, EXPEVT_TRAPA, 0, 0);
2090 }
2091
2092
2093 /*
2094 * copy_fp_register: Copy a register into another, with FP avail check.
2095 * lds_rm_fpscr: Copy Rm into FPSCR.
2096 *
2097 * arg[0] = ptr to source
2098 * arg[1] = ptr to destination
2099 */
2100 X(copy_fp_register)
2101 {
2102 FLOATING_POINT_AVAILABLE_CHECK;
2103 reg(ic->arg[1]) = reg(ic->arg[0]);
2104 }
2105 X(lds_rm_fpscr)
2106 {
2107 FLOATING_POINT_AVAILABLE_CHECK;
2108 sh_update_fpscr(cpu, reg(ic->arg[1]));
2109 }
2110
2111
2112 /*
2113 * fmov_frm_frn: Copy one floating-point register (or pair) to another.
2114 *
2115 * arg[0] = ptr to source float register or pair
2116 * arg[1] = ptr to destination float register or pair
2117 */
2118 X(fmov_frm_frn)
2119 {
2120 size_t r0, r1;
2121 int ofs0, ofs1;
2122
2123 FLOATING_POINT_AVAILABLE_CHECK;
2124
2125 /* Simplest case, single-precision: */
2126 if (!(cpu->cd.sh.fpscr & SH_FPSCR_SZ)) {
2127 reg(ic->arg[1]) = reg(ic->arg[0]);
2128 return;
2129 }
2130
2131 /* Double-precision: */
2132 r0 = ic->arg[0]; r1 = ic->arg[1];
2133 ofs0 = (r0 - (size_t)&cpu->cd.sh.fr[0]) / sizeof(uint32_t);
2134 ofs1 = (r1 - (size_t)&cpu->cd.sh.fr[0]) / sizeof(uint32_t);
2135 if (ofs0 & 1)
2136 r0 = (size_t)&cpu->cd.sh.xf[ofs0 & ~1];
2137 if (ofs1 & 1)
2138 r1 = (size_t)&cpu->cd.sh.xf[ofs1 & ~1];
2139
2140 reg(r1) = reg(r0);
2141 reg(r1 + 4) = reg(r0 + 4);
2142 }
2143
2144
2145 /*
2146 * float_fpul_frn: Load FPUL into float register.
2147 *
2148 * arg[0] = ptr to float register, or float register pair
2149 */
2150 X(float_fpul_frn)
2151 {
2152 int32_t fpul = cpu->cd.sh.fpul;
2153
2154 FLOATING_POINT_AVAILABLE_CHECK;
2155
2156 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2157 /* Double-precision, using a pair of registers: */
2158 uint64_t ieee = ieee_store_float_value(fpul, IEEE_FMT_D, 0);
2159 reg(ic->arg[0]) = (uint32_t) (ieee >> 32);
2160 reg(ic->arg[0] + sizeof(uint32_t)) = (uint32_t) ieee;
2161 } else {
2162 /* Single-precision: */
2163 uint32_t ieee = ieee_store_float_value(fpul, IEEE_FMT_S, 0);
2164 reg(ic->arg[0]) = (uint32_t) ieee;
2165 }
2166 }
2167
2168
2169 /*
2170 * ftrc_frm_fpul: Truncate a float register into FPUL.
2171 *
2172 * arg[0] = ptr to float register, or float register pair
2173 */
2174 X(ftrc_frm_fpul)
2175 {
2176 struct ieee_float_value op1;
2177
2178 FLOATING_POINT_AVAILABLE_CHECK;
2179
2180 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2181 /* Double-precision, using a pair of registers: */
2182 int64_t r1 = ((uint64_t)reg(ic->arg[0]) << 32) +
2183 reg(ic->arg[0] + sizeof(uint32_t));
2184 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2185 cpu->cd.sh.fpul = (int32_t) op1.f;
2186 } else {
2187 /* Single-precision: */
2188 ieee_interpret_float_value(reg(ic->arg[0]), &op1, IEEE_FMT_S);
2189 cpu->cd.sh.fpul = (int32_t) op1.f;
2190 }
2191 }
2192
2193
2194 /*
2195 * fsca_fpul_drn: Sinus/cosinus approximation.
2196 *
2197 * Note: This is an interesting instruction. It is not included in the SH4
2198 * manual. Some googling indicated that this might be an SH4X instruction.
2199 * On the other hand, it is used by Dreamcast code (and the Dreamcast has an
2200 * SH4), and a cvs comment for gdb said that this is an SH4 instruction, not
2201 * an SH4A instruction. Well well...
2202 *
2203 * arg[0] = ptr to single-precision float register pair
2204 */
2205 X(fsca_fpul_drn)
2206 {
2207 double fpul = ((double) (int32_t)cpu->cd.sh.fpul) / 32768.0;
2208
2209 FLOATING_POINT_AVAILABLE_CHECK;
2210
2211 reg(ic->arg[0]) = ieee_store_float_value(sin(fpul), IEEE_FMT_S, 0);
2212 reg(ic->arg[0] + sizeof(uint32_t)) =
2213 ieee_store_float_value(cos(fpul), IEEE_FMT_S, 0);
2214 }
2215
2216
2217 /*
2218 * ftrv_xmtrx_fvn: Matrix * vector ==> vector
2219 *
2220 * arg[0] = ptr to FVn
2221 */
2222 X(ftrv_xmtrx_fvn)
2223 {
2224 int i;
2225 struct ieee_float_value xmtrx[16], frn[4];
2226 double frnp0 = 0.0, frnp1 = 0.0, frnp2 = 0.0, frnp3 = 0.0;
2227
2228 ieee_interpret_float_value(reg(ic->arg[0] + 0), &frn[0], IEEE_FMT_S);
2229 ieee_interpret_float_value(reg(ic->arg[0] + 4), &frn[1], IEEE_FMT_S);
2230 ieee_interpret_float_value(reg(ic->arg[0] + 8), &frn[2], IEEE_FMT_S);
2231 ieee_interpret_float_value(reg(ic->arg[0] + 12), &frn[3], IEEE_FMT_S);
2232
2233 for (i=0; i<16; i++)
2234 ieee_interpret_float_value(cpu->cd.sh.xf[i],
2235 &xmtrx[i], IEEE_FMT_S);
2236
2237 for (i=0; i<4; i++)
2238 frnp0 += xmtrx[i*4].f * frn[i].f;
2239
2240 for (i=0; i<4; i++)
2241 frnp1 += xmtrx[i*4 + 1].f * frn[i].f;
2242
2243 for (i=0; i<4; i++)
2244 frnp2 += xmtrx[i*4 + 2].f * frn[i].f;
2245
2246 for (i=0; i<4; i++)
2247 frnp3 += xmtrx[i*4 + 3].f * frn[i].f;
2248
2249 reg(ic->arg[0] + 0) = ieee_store_float_value(frnp0, IEEE_FMT_S, 0);
2250 reg(ic->arg[0] + 4) = ieee_store_float_value(frnp1, IEEE_FMT_S, 0);
2251 reg(ic->arg[0] + 8) = ieee_store_float_value(frnp2, IEEE_FMT_S, 0);
2252 reg(ic->arg[0] + 12) = ieee_store_float_value(frnp3, IEEE_FMT_S, 0);
2253 }
2254
2255
2256 /*
2257 * fldi: Load immediate (0.0 or 1.0) into floating point register.
2258 * fneg: Negate a floating point register
2259 * fabs: Get the absolute value of a floating point register
2260 * fsqrt: Calculate square root
2261 *
2262 * arg[0] = ptr to fp register
2263 * arg[1] = (uint32_t) immediate value (for fldi)
2264 */
2265 X(fldi_frn)
2266 {
2267 FLOATING_POINT_AVAILABLE_CHECK;
2268 reg(ic->arg[0]) = ic->arg[1];
2269 }
2270 X(fneg_frn)
2271 {
2272 FLOATING_POINT_AVAILABLE_CHECK;
2273 /* Note: This also works for double-precision. */
2274 reg(ic->arg[0]) ^= 0x80000000;
2275 }
2276 X(fabs_frn)
2277 {
2278 FLOATING_POINT_AVAILABLE_CHECK;
2279 /* Note: This also works for double-precision. */
2280 reg(ic->arg[0]) &= 0x7fffffff;
2281 }
2282 X(fsqrt_frn)
2283 {
2284 struct ieee_float_value op1;
2285
2286 FLOATING_POINT_AVAILABLE_CHECK;
2287
2288 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2289 /* Double-precision: */
2290 int64_t r1, ieee;
2291 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2292 ((uint64_t)reg(ic->arg[0]) << 32);
2293 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2294 ieee = ieee_store_float_value(sqrt(op1.f), IEEE_FMT_D, 0);
2295 reg(ic->arg[0]) = (uint32_t) (ieee >> 32);
2296 reg(ic->arg[0] + sizeof(uint32_t)) = (uint32_t) ieee;
2297 } else {
2298 /* Single-precision: */
2299 int32_t ieee, r1 = reg(ic->arg[0]);
2300 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2301 ieee = ieee_store_float_value(sqrt(op1.f), IEEE_FMT_S, 0);
2302 reg(ic->arg[0]) = ieee;
2303 }
2304 }
2305
2306
2307 /*
2308 * fadd_frm_frn: Floating point addition.
2309 * fsub_frm_frn: Floating point subtraction.
2310 * fmul_frm_frn: Floating point multiplication.
2311 * fdiv_frm_frn: Floating point division.
2312 * fmac_fr0_frm_frn: Multiply-and-accumulate.
2313 * fcmp_eq_frm_frn: Floating point greater-than comparison.
2314 * fcmp_gt_frm_frn: Floating point greater-than comparison.
2315 *
2316 * arg[0] = ptr to float register FRm
2317 * arg[1] = ptr to float register FRn
2318 */
2319 X(fadd_frm_frn)
2320 {
2321 struct ieee_float_value op1, op2;
2322
2323 FLOATING_POINT_AVAILABLE_CHECK;
2324
2325 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2326 /* Double-precision, using a pair of registers: */
2327 int64_t r1, r2, ieee;
2328 double result;
2329
2330 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2331 ((uint64_t)reg(ic->arg[0]) << 32);
2332 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2333 ((uint64_t)reg(ic->arg[1]) << 32);
2334 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2335 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2336
2337 result = op2.f + op1.f;
2338 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2339 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2340 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2341 } else {
2342 /* Single-precision: */
2343 uint32_t r1, r2, ieee;
2344 double result;
2345
2346 r1 = reg(ic->arg[0]);
2347 r2 = reg(ic->arg[1]);
2348 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2349 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2350
2351 result = op2.f + op1.f;
2352 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2353 reg(ic->arg[1]) = (uint32_t) ieee;
2354 }
2355 }
2356 X(fsub_frm_frn)
2357 {
2358 struct ieee_float_value op1, op2;
2359
2360 FLOATING_POINT_AVAILABLE_CHECK;
2361
2362 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2363 /* Double-precision, using a pair of registers: */
2364 int64_t r1, r2, ieee;
2365 double result;
2366 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2367 ((uint64_t)reg(ic->arg[0]) << 32);
2368 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2369 ((uint64_t)reg(ic->arg[1]) << 32);
2370 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2371 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2372 result = op2.f - op1.f;
2373 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2374 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2375 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2376 } else {
2377 /* Single-precision: */
2378 uint32_t r1, r2, ieee;
2379 double result;
2380 r1 = reg(ic->arg[0]);
2381 r2 = reg(ic->arg[1]);
2382 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2383 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2384 result = op2.f - op1.f;
2385 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2386 reg(ic->arg[1]) = (uint32_t) ieee;
2387 }
2388 }
2389 X(fmul_frm_frn)
2390 {
2391 struct ieee_float_value op1, op2;
2392
2393 FLOATING_POINT_AVAILABLE_CHECK;
2394
2395 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2396 /* Double-precision, using a pair of registers: */
2397 int64_t r1, r2, ieee;
2398 double result;
2399
2400 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2401 ((uint64_t)reg(ic->arg[0]) << 32);
2402 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2403 ((uint64_t)reg(ic->arg[1]) << 32);
2404 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2405 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2406
2407 result = op2.f * op1.f;
2408 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2409 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2410 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2411 } else {
2412 /* Single-precision: */
2413 uint32_t r1, r2, ieee;
2414 double result;
2415
2416 r1 = reg(ic->arg[0]);
2417 r2 = reg(ic->arg[1]);
2418 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2419 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2420
2421 result = op2.f * op1.f;
2422 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2423 reg(ic->arg[1]) = (uint32_t) ieee;
2424 }
2425 }
2426 X(fdiv_frm_frn)
2427 {
2428 struct ieee_float_value op1, op2;
2429
2430 FLOATING_POINT_AVAILABLE_CHECK;
2431
2432 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2433 /* Double-precision, using a pair of registers: */
2434 int64_t r1, r2, ieee;
2435 double result;
2436
2437 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2438 ((uint64_t)reg(ic->arg[0]) << 32);
2439 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2440 ((uint64_t)reg(ic->arg[1]) << 32);
2441 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2442 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2443
2444 if (op1.f != 0.0)
2445 result = op2.f / op1.f;
2446 else
2447 result = 0.0;
2448
2449 ieee = ieee_store_float_value(result, IEEE_FMT_D, 0);
2450
2451 reg(ic->arg[1]) = (uint32_t) (ieee >> 32);
2452 reg(ic->arg[1] + sizeof(uint32_t)) = (uint32_t) ieee;
2453 } else {
2454 /* Single-precision: */
2455 uint32_t r1, r2, ieee;
2456 double result;
2457
2458 r1 = reg(ic->arg[0]);
2459 r2 = reg(ic->arg[1]);
2460 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2461 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2462
2463 if (op1.f != 0.0)
2464 result = op2.f / op1.f;
2465 else
2466 result = 0.0;
2467
2468 ieee = ieee_store_float_value(result, IEEE_FMT_S, 0);
2469
2470 reg(ic->arg[1]) = (uint32_t) ieee;
2471 }
2472 }
2473 X(fmac_fr0_frm_frn)
2474 {
2475 struct ieee_float_value op1, op2, op0;
2476 int32_t r1, r2, fr0 = cpu->cd.sh.fr[0], ieee;
2477
2478 FLOATING_POINT_AVAILABLE_CHECK;
2479
2480 r1 = reg(ic->arg[0]), r2 = reg(ic->arg[1]);
2481 ieee_interpret_float_value(fr0, &op0, IEEE_FMT_S);
2482 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2483 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2484 ieee = ieee_store_float_value(op0.f * op1.f + op2.f, IEEE_FMT_S, 0);
2485 reg(ic->arg[1]) = ieee;
2486 }
2487 X(fcmp_eq_frm_frn)
2488 {
2489 struct ieee_float_value op1, op2;
2490
2491 FLOATING_POINT_AVAILABLE_CHECK;
2492
2493 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2494 /* Double-precision, using a pair of registers: */
2495 int64_t r1, r2;
2496 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2497 ((uint64_t)reg(ic->arg[0]) << 32);
2498 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2499 ((uint64_t)reg(ic->arg[1]) << 32);
2500 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2501 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2502 } else {
2503 /* Single-precision: */
2504 uint32_t r1 = reg(ic->arg[0]), r2 = reg(ic->arg[1]);
2505 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2506 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2507 }
2508
2509 if (op2.f == op1.f)
2510 cpu->cd.sh.sr |= SH_SR_T;
2511 else
2512 cpu->cd.sh.sr &= ~SH_SR_T;
2513 }
2514 X(fcmp_gt_frm_frn)
2515 {
2516 struct ieee_float_value op1, op2;
2517
2518 FLOATING_POINT_AVAILABLE_CHECK;
2519
2520 if (cpu->cd.sh.fpscr & SH_FPSCR_PR) {
2521 /* Double-precision, using a pair of registers: */
2522 int64_t r1, r2;
2523 r1 = reg(ic->arg[0] + sizeof(uint32_t)) +
2524 ((uint64_t)reg(ic->arg[0]) << 32);
2525 r2 = reg(ic->arg[1] + sizeof(uint32_t)) +
2526 ((uint64_t)reg(ic->arg[1]) << 32);
2527 ieee_interpret_float_value(r1, &op1, IEEE_FMT_D);
2528 ieee_interpret_float_value(r2, &op2, IEEE_FMT_D);
2529 } else {
2530 /* Single-precision: */
2531 uint32_t r1 = reg(ic->arg[0]), r2 = reg(ic->arg[1]);
2532 ieee_interpret_float_value(r1, &op1, IEEE_FMT_S);
2533 ieee_interpret_float_value(r2, &op2, IEEE_FMT_S);
2534 }
2535
2536 if (op2.f > op1.f)
2537 cpu->cd.sh.sr |= SH_SR_T;
2538 else
2539 cpu->cd.sh.sr &= ~SH_SR_T;
2540 }
2541
2542
2543 /*
2544 * frchg: Change floating-point register banks.
2545 * fschg: Change floating-point register size.
2546 */
2547 X(frchg)
2548 {
2549 FLOATING_POINT_AVAILABLE_CHECK;
2550 sh_update_fpscr(cpu, cpu->cd.sh.fpscr ^ SH_FPSCR_FR);
2551 }
2552 X(fschg)
2553 {
2554 FLOATING_POINT_AVAILABLE_CHECK;
2555 sh_update_fpscr(cpu, cpu->cd.sh.fpscr ^ SH_FPSCR_SZ);
2556 }
2557
2558
2559 /*
2560 * pref_rn: Prefetch.
2561 *
2562 * arg[1] = ptr to Rn
2563 */
2564 X(pref_rn)
2565 {
2566 uint32_t addr = reg(ic->arg[1]), extaddr;
2567 int sq_nr, ofs;
2568
2569 if (addr < 0xe0000000 || addr >= 0xe4000000)
2570 return;
2571
2572 /* Send Store Queue contents to external memory: */
2573 extaddr = addr & 0x03ffffe0;
2574 sq_nr = addr & 0x20? 1 : 0;
2575
2576 if (cpu->cd.sh.mmucr & SH4_MMUCR_AT) {
2577 fatal("Store Queue to external memory, when "
2578 "MMU enabled: TODO\n");
2579 exit(1);
2580 }
2581
2582 if (sq_nr == 0)
2583 extaddr |= (((cpu->cd.sh.qacr0 >> 2) & 7) << 26);
2584 else
2585 extaddr |= (((cpu->cd.sh.qacr1 >> 2) & 7) << 26);
2586
2587 /* fatal("extaddr = 0x%08x\n", extaddr); */
2588
2589 SYNCH_PC;
2590 for (ofs = 0; ofs < 32; ofs += sizeof(uint32_t)) {
2591 uint32_t word;
2592 cpu->memory_rw(cpu, cpu->mem, 0xe0000000 + ofs
2593 + sq_nr * 0x20, (unsigned char *)
2594 &word, sizeof(word), MEM_READ, PHYSICAL);
2595 cpu->memory_rw(cpu, cpu->mem, extaddr+ofs, (unsigned char *)
2596 &word, sizeof(word), MEM_WRITE, PHYSICAL);
2597 }
2598 }
2599
2600
2601 /*
2602 * tas_b_rn: Test-and-Set.
2603 *
2604 * arg[1] = ptr to Rn
2605 */
2606 X(tas_b_rn)
2607 {
2608 uint32_t addr = reg(ic->arg[1]);
2609 uint8_t byte, newbyte;
2610
2611 SYNCH_PC;
2612
2613 if (!cpu->memory_rw(cpu, cpu->mem, addr, &byte, 1, MEM_READ,
2614 CACHE_DATA)) {
2615 /* Exception. */
2616 return;
2617 }
2618
2619 newbyte = byte | 0x80;
2620
2621 if (!cpu->memory_rw(cpu, cpu->mem, addr, &newbyte, 1, MEM_WRITE,
2622 CACHE_DATA)) {
2623 /* Exception. */
2624 return;
2625 }
2626
2627 if (byte == 0)
2628 cpu->cd.sh.sr |= SH_SR_T;
2629 else
2630 cpu->cd.sh.sr &= ~SH_SR_T;
2631 }
2632
2633
2634 /*
2635 * prom_emul:
2636 */
2637 X(prom_emul)
2638 {
2639 uint32_t old_pc;
2640 SYNCH_PC;
2641 old_pc = cpu->pc;
2642
2643 switch (cpu->machine->machine_type) {
2644 case MACHINE_DREAMCAST:
2645 dreamcast_emul(cpu);
2646 break;
2647 case MACHINE_LANDISK:
2648 sh_ipl_g_emul(cpu);
2649 break;
2650 default:
2651 fatal("SH prom_emul: unimplemented machine type.\n");
2652 exit(1);
2653 }
2654
2655 if (!cpu->running) {
2656 cpu->n_translated_instrs --;
2657 cpu->cd.sh.next_ic = &nothing_call;
2658 } else if ((uint32_t)cpu->pc != old_pc) {
2659 /* The PC value was changed by the PROM call. */
2660 quick_pc_to_pointers(cpu);
2661 }
2662 }
2663
2664
2665 /*****************************************************************************/
2666
2667
2668 X(end_of_page)
2669 {
2670 /* Update the PC: (offset 0, but on the next page) */
2671 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1) <<
2672 SH_INSTR_ALIGNMENT_SHIFT);
2673 cpu->pc += (SH_IC_ENTRIES_PER_PAGE << SH_INSTR_ALIGNMENT_SHIFT);
2674
2675 /* end_of_page doesn't count as an executed instruction: */
2676 cpu->n_translated_instrs --;
2677
2678 /*
2679 * Find the new physpage and update translation pointers.
2680 *
2681 * Note: This may cause an exception, if e.g. the new page is
2682 * not accessible.
2683 */
2684 quick_pc_to_pointers(cpu);
2685
2686 /* Simple jump to the next page (if we are lucky): */
2687 if (cpu->delay_slot == NOT_DELAYED)
2688 return;
2689
2690 /*
2691 * If we were in a delay slot, and we got an exception while doing
2692 * quick_pc_to_pointers, then return. The function which called
2693 * end_of_page should handle this case.
2694 */
2695 if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
2696 return;
2697
2698 /*
2699 * Tricky situation; the delay slot is on the next virtual page.
2700 * Calling to_be_translated will translate one instruction manually,
2701 * execute it, and then discard it.
2702 */
2703 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
2704
2705 instr(to_be_translated)(cpu, cpu->cd.sh.next_ic);
2706
2707 /* The instruction in the delay slot has now executed. */
2708 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2709 cpu->delay_slot); */
2710
2711 /* Find the physpage etc of the instruction in the delay slot
2712 (or, if there was an exception, the exception handler): */
2713 quick_pc_to_pointers(cpu);
2714 }
2715
2716
2717 X(end_of_page2)
2718 {
2719 /* Synchronize PC on the _second_ instruction on the next page: */
2720 int low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page)
2721 / sizeof(struct sh_instr_call);
2722 cpu->pc &= ~((SH_IC_ENTRIES_PER_PAGE-1)
2723 << SH_INSTR_ALIGNMENT_SHIFT);
2724 cpu->pc += (low_pc << SH_INSTR_ALIGNMENT_SHIFT);
2725
2726 /* This doesn't count as an executed instruction. */
2727 cpu->n_translated_instrs --;
2728
2729 quick_pc_to_pointers(cpu);
2730
2731 if (cpu->delay_slot == NOT_DELAYED)
2732 return;
2733
2734 fatal("end_of_page2: fatal error, we're in a delay slot\n");
2735 exit(1);
2736 }
2737
2738
2739 /*****************************************************************************/
2740
2741
2742 /*
2743 * sh_instr_to_be_translated():
2744 *
2745 * Translate an instruction word into an sh_instr_call. ic is filled in with
2746 * valid data for the translated instruction, or a "nothing" instruction if
2747 * there was a translation failure. The newly translated instruction is then
2748 * executed.
2749 */
2750 X(to_be_translated)
2751 {
2752 uint64_t addr, low_pc;
2753 uint32_t iword;
2754 unsigned char *page;
2755 unsigned char ib[4];
2756 int main_opcode, isize = cpu->cd.sh.compact? 2 : sizeof(ib);
2757 int in_crosspage_delayslot = 0, r8, r4, lo4, lo8;
2758 /* void (*samepage_function)(struct cpu *, struct sh_instr_call *); */
2759
2760 /* Figure out the (virtual) address of the instruction: */
2761 low_pc = ((size_t)ic - (size_t)cpu->cd.sh.cur_ic_page)
2762 / sizeof(struct sh_instr_call);
2763
2764 /* Special case for branch with delayslot on the next page: */
2765 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
2766 /* fatal("[ delay-slot translation across page "
2767 "boundary ]\n"); */
2768 in_crosspage_delayslot = 1;
2769 }
2770
2771 addr = cpu->pc & ~((SH_IC_ENTRIES_PER_PAGE-1)
2772 << SH_INSTR_ALIGNMENT_SHIFT);
2773 addr += (low_pc << SH_INSTR_ALIGNMENT_SHIFT);
2774 cpu->pc = (MODE_int_t)addr;
2775 addr &= ~((1 << SH_INSTR_ALIGNMENT_SHIFT) - 1);
2776
2777 /* Read the instruction word from memory: */
2778 #ifdef MODE32
2779 page = cpu->cd.sh.host_load[(uint32_t)addr >> 12];
2780 #else
2781 {
2782 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2783 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2784 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2785 uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2786 uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2787 uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2788 DYNTRANS_L3N)) & mask3;
2789 struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.sh.l1_64[x1];
2790 struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2791 page = l3->host_load[x3];
2792 }
2793 #endif
2794
2795 if (page != NULL) {
2796 /* fatal("TRANSLATION HIT!\n"); */
2797 memcpy(ib, page + (addr & 0xfff), isize);
2798 } else {
2799 /* fatal("TRANSLATION MISS!\n"); */
2800 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2801 isize, MEM_READ, CACHE_INSTRUCTION)) {
2802 fatal("to_be_translated(): read failed: TODO\n");
2803 goto bad;
2804 }
2805 }
2806
2807 if (cpu->cd.sh.compact) {
2808 iword = *((uint16_t *)&ib[0]);
2809 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2810 iword = LE16_TO_HOST(iword);
2811 else
2812 iword = BE16_TO_HOST(iword);
2813 main_opcode = iword >> 12;
2814 r8 = (iword >> 8) & 0xf;
2815 r4 = (iword >> 4) & 0xf;
2816 lo8 = iword & 0xff;
2817 lo4 = iword & 0xf;
2818 } else {
2819 iword = *((uint32_t *)&ib[0]);
2820 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2821 iword = LE32_TO_HOST(iword);
2822 else
2823 iword = BE32_TO_HOST(iword);
2824 main_opcode = -1; /* TODO */
2825 fatal("SH5/SH64 isn't implemented yet. Sorry.\n");
2826 goto bad;
2827 }
2828
2829
2830 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2831 #include "cpu_dyntrans.c"
2832 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
2833
2834
2835 /*
2836 * Translate the instruction:
2837 */
2838
2839 /* Default args. for many instructions: */
2840 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
2841 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
2842
2843 switch (main_opcode) {
2844
2845 case 0x0:
2846 if (lo4 == 0x4) {
2847 /* MOV.B Rm,@(R0,Rn) */
2848 ic->f = instr(mov_b_rm_r0_rn);
2849 } else if (lo4 == 0x5) {
2850 /* MOV.W Rm,@(R0,Rn) */
2851 ic->f = instr(mov_w_rm_r0_rn);
2852 } else if (lo4 == 0x6) {
2853 /* MOV.L Rm,@(R0,Rn) */
2854 ic->f = instr(mov_l_rm_r0_rn);
2855 } else if (lo4 == 0x7) {
2856 /* MUL.L Rm,Rn */
2857 ic->f = instr(mul_l_rm_rn);
2858 } else if (iword == 0x000b) {
2859 if (cpu->machine->show_trace_tree)
2860 ic->f = instr(rts_trace);
2861 else
2862 ic->f = instr(rts);
2863 } else if (lo4 == 0xc) {
2864 /* MOV.B @(R0,Rm),Rn */
2865 ic->f = instr(mov_b_r0_rm_rn);
2866 } else if (lo4 == 0xd) {
2867 /* MOV.W @(R0,Rm),Rn */
2868 ic->f = instr(mov_w_r0_rm_rn);
2869 } else if (lo4 == 0xe) {
2870 /* MOV.L @(R0,Rm),Rn */
2871 ic->f = instr(mov_l_r0_rm_rn);
2872 } else if (iword == 0x0008) {
2873 /* CLRT */
2874 ic->f = instr(clrt);
2875 } else if (iword == 0x0018) {
2876 /* SETT */
2877 ic->f = instr(sett);
2878 } else if (iword == 0x0019) {
2879 /* DIV0U */
2880 ic->f = instr(div0u);
2881 } else if (iword == 0x001b) {
2882 /* SLEEP */
2883 ic->f = instr(sleep);
2884 } else if (iword == 0x0028) {
2885 /* CLRMAC */
2886 ic->f = instr(clrmac);
2887 } else if (iword == 0x002b) {
2888 /* RTE */
2889 ic->f = instr(rte);
2890 } else if (iword == 0x0038) {
2891 /* LDTLB */
2892 ic->f = instr(ldtlb);
2893 } else if (iword == 0x0048) {
2894 /* CLRS */
2895 ic->f = instr(clrs);
2896 } else if (iword == 0x0058) {
2897 /* SETS */
2898 ic->f = instr(sets);
2899 } else if ((lo8 & 0x8f) == 0x82) {
2900 /* STC Rm_BANK, Rn */
2901 ic->f = instr(copy_privileged_register);
2902 ic->arg[0] = (size_t)&cpu->cd.sh.r_bank[(lo8 >> 4) & 7];
2903 } else if (iword == SH_INVALID_INSTR) {
2904 /* PROM emulation (GXemul specific) */
2905 ic->f = instr(prom_emul);
2906 } else {
2907 switch (lo8) {
2908 case 0x02: /* STC SR,Rn */
2909 ic->f = instr(copy_privileged_register);
2910 ic->arg[0] = (size_t)&cpu->cd.sh.sr;
2911 break;
2912 case 0x03: /* BSRF Rn */
2913 ic->f = instr(bsrf_rn);
2914 ic->arg[0] = (int32_t) (addr &
2915 ((SH_IC_ENTRIES_PER_PAGE-1)
2916 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
2917 /* arg[1] is Rn */
2918 break;
2919 case 0x09: /* NOP */
2920 ic->f = instr(nop);
2921 if (iword & 0x0f00) {
2922 fatal("Unimplemented NOP variant?\n");
2923 goto bad;
2924 }
2925 break;
2926 case 0x0a: /* STS MACH,Rn */
2927 ic->f = instr(sts_mach_rn);
2928 break;
2929 case 0x12: /* STC GBR,Rn */
2930 ic->f = instr(mov_rm_rn);
2931 ic->arg[0] = (size_t)&cpu->cd.sh.gbr;
2932 break;
2933 case 0x1a: /* STS MACL,Rn */
2934 ic->f = instr(sts_macl_rn);
2935 break;
2936 case 0x22: /* STC VBR,Rn */
2937 ic->f = instr(copy_privileged_register);
2938 ic->arg[0] = (size_t)&cpu->cd.sh.vbr;
2939 break;
2940 case 0x23: /* BRAF Rn */
2941 ic->f = instr(braf_rn);
2942 ic->arg[0] = (int32_t) (addr &
2943 ((SH_IC_ENTRIES_PER_PAGE-1)
2944 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
2945 /* arg[1] is Rn */
2946 break;
2947 case 0x29: /* MOVT Rn */
2948 ic->f = instr(movt_rn);
2949 break;
2950 case 0x2a: /* STS PR,Rn */
2951 ic->f = instr(sts_pr_rn);
2952 break;
2953 case 0x32: /* STC SSR,Rn */
2954 ic->f = instr(copy_privileged_register);
2955 ic->arg[0] = (size_t)&cpu->cd.sh.ssr;
2956 break;
2957 case 0x42: /* STC SPC,Rn */
2958 ic->f = instr(copy_privileged_register);
2959 ic->arg[0] = (size_t)&cpu->cd.sh.spc;
2960 break;
2961 case 0x5a: /* STS FPUL,Rn */
2962 ic->f = instr(copy_fp_register);
2963 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
2964 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
2965 break;
2966 case 0x6a: /* STS FPSCR,Rn */
2967 ic->f = instr(copy_fp_register);
2968 ic->arg[0] = (size_t)&cpu->cd.sh.fpscr;
2969 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
2970 break;
2971 case 0x83: /* PREF @Rn */
2972 ic->f = instr(pref_rn);
2973 break;
2974 case 0x93: /* OCBI @Rn */
2975 /* Treat as nop for now: */
2976 /* TODO: Implement this. */
2977 ic->f = instr(nop);
2978 break;
2979 case 0xa3: /* OCBP @Rn */
2980 /* Treat as nop for now: */
2981 /* TODO: Implement this. */
2982 ic->f = instr(nop);
2983 break;
2984 case 0xb3: /* OCBWB @Rn */
2985 /* Treat as nop for now: */
2986 /* TODO: Implement this. */
2987 ic->f = instr(nop);
2988 break;
2989 case 0xc3: /* MOVCA.L R0,@Rn */
2990 /* Treat as nop for now: */
2991 /* TODO: Implement this. */
2992 ic->f = instr(nop);
2993 break;
2994 case 0xfa: /* STC DBR,Rn */
2995 ic->f = instr(copy_privileged_register);
2996 ic->arg[0] = (size_t)&cpu->cd.sh.dbr;
2997 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
2998 break;
2999 default:fatal("Unimplemented opcode 0x%x,0x%03x\n",
3000 main_opcode, iword & 0xfff);
3001 goto bad;
3002 }
3003 }
3004 break;
3005
3006 case 0x1:
3007 ic->f = instr(mov_l_rm_disp_rn);
3008 ic->arg[1] = r8 + (lo4 << 4);
3009 break;
3010
3011 case 0x2:
3012 switch (lo4) {
3013 case 0x0: /* MOV.B Rm,@Rn */
3014 ic->f = instr(mov_b_store_rm_rn);
3015 break;
3016 case 0x1: /* MOV.W Rm,@Rn */
3017 ic->f = instr(mov_w_store_rm_rn);
3018 break;
3019 case 0x2: /* MOV.L Rm,@Rn */
3020 ic->f = instr(mov_l_store_rm_rn);
3021 break;
3022 case 0x4: /* MOV.B Rm,@-Rn */
3023 ic->f = instr(mov_b_rm_predec_rn);
3024 break;
3025 case 0x5: /* MOV.W Rm,@-Rn */
3026 ic->f = instr(mov_w_rm_predec_rn);
3027 break;
3028 case 0x6: /* MOV.L Rm,@-Rn */
3029 ic->f = instr(mov_l_rm_predec_rn);
3030 break;
3031 case 0x7: /* DIV0S Rm,Rn */
3032 ic->f = instr(div0s_rm_rn);
3033 break;
3034 case 0x8: /* TST Rm,Rn */
3035 ic->f = instr(tst_rm_rn);
3036 break;
3037 case 0x9: /* AND Rm,Rn */
3038 ic->f = instr(and_rm_rn);
3039 break;
3040 case 0xa: /* XOR Rm,Rn */
3041 ic->f = instr(xor_rm_rn);
3042 break;
3043 case 0xb: /* OR Rm,Rn */
3044 ic->f = instr(or_rm_rn);
3045 break;
3046 case 0xc: /* CMP/STR Rm,Rn */
3047 ic->f = instr(cmp_str_rm_rn);
3048 break;
3049 case 0xd: /* XTRCT Rm,Rn */
3050 ic->f = instr(xtrct_rm_rn);
3051 break;
3052 case 0xe: /* MULU.W Rm,Rn */
3053 ic->f = instr(mulu_w_rm_rn);
3054 break;
3055 case 0xf: /* MULS.W Rm,Rn */
3056 ic->f = instr(muls_w_rm_rn);
3057 break;
3058 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3059 main_opcode, lo4);
3060 goto bad;
3061 }
3062 break;
3063
3064 case 0x3:
3065 switch (lo4) {
3066 case 0x0: /* CMP/EQ Rm,Rn */
3067 ic->f = instr(cmpeq_rm_rn);
3068 break;
3069 case 0x2: /* CMP/HS Rm,Rn */
3070 ic->f = instr(cmphs_rm_rn);
3071 break;
3072 case 0x3: /* CMP/GE Rm,Rn */
3073 ic->f = instr(cmpge_rm_rn);
3074 break;
3075 case 0x4: /* DIV1 Rm,Rn */
3076 ic->f = instr(div1_rm_rn);
3077 break;
3078 case 0x5: /* DMULU.L Rm,Rn */
3079 ic->f = instr(dmulu_l_rm_rn);
3080 break;
3081 case 0x6: /* CMP/HI Rm,Rn */
3082 ic->f = instr(cmphi_rm_rn);
3083 break;
3084 case 0x7: /* CMP/GT Rm,Rn */
3085 ic->f = instr(cmpgt_rm_rn);
3086 break;
3087 case 0x8: /* SUB Rm,Rn */
3088 ic->f = instr(sub_rm_rn);
3089 break;
3090 case 0xa: /* SUBC Rm,Rn */
3091 ic->f = instr(subc_rm_rn);
3092 break;
3093 case 0xc: /* ADD Rm,Rn */
3094 ic->f = instr(add_rm_rn);
3095 break;
3096 case 0xd: /* DMULS.L Rm,Rn */
3097 ic->f = instr(dmuls_l_rm_rn);
3098 break;
3099 case 0xe: /* ADDC Rm,Rn */
3100 ic->f = instr(addc_rm_rn);
3101 break;
3102 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3103 main_opcode, lo4);
3104 goto bad;
3105 }
3106 break;
3107
3108 case 0x4:
3109 if (lo4 == 0xc) {
3110 ic->f = instr(shad);
3111 } else if (lo4 == 0xd) {
3112 ic->f = instr(shld);
3113 } else if ((lo8 & 0x8f) == 0x83) {
3114 /* STC.L Rm_BANK,@-Rn */
3115 ic->f = instr(stc_l_rm_predec_rn_md);
3116 ic->arg[0] = (size_t)&cpu->cd.sh.r_bank[
3117 (lo8 >> 4) & 7]; /* m */
3118 } else if ((lo8 & 0x8f) == 0x87) {
3119 /* LDC.L @Rm+,Rn_BANK */
3120 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3121 ic->arg[0] = (size_t)&cpu->cd.sh.r_bank[(lo8 >> 4) & 7];
3122 } else if ((lo8 & 0x8f) == 0x8e) {
3123 /* LDC Rm, Rn_BANK */
3124 ic->f = instr(copy_privileged_register);
3125 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8];
3126 ic->arg[1] = (size_t)&cpu->cd.sh.r_bank[(lo8 >> 4) & 7];
3127 } else {
3128 switch (lo8) {
3129 case 0x00: /* SHLL Rn */
3130 ic->f = instr(shll_rn);
3131 break;
3132 case 0x01: /* SHLR Rn */
3133 ic->f = instr(shlr_rn);
3134 break;
3135 case 0x02: /* STS.L MACH,@-Rn */
3136 ic->f = instr(mov_l_rm_predec_rn);
3137 ic->arg[0] = (size_t)&cpu->cd.sh.mach;
3138 break;
3139 case 0x03: /* STC.L SR,@-Rn */
3140 ic->f = instr(stc_l_rm_predec_rn_md);
3141 ic->arg[0] = (size_t)&cpu->cd.sh.sr;
3142 break;
3143 case 0x04: /* ROTL Rn */
3144 ic->f = instr(rotl_rn);
3145 break;
3146 case 0x05: /* ROTR Rn */
3147 ic->f = instr(rotr_rn);
3148 break;
3149 case 0x06: /* LDS.L @Rm+,MACH */
3150 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3151 ic->arg[0] = (size_t)&cpu->cd.sh.mach;
3152 break;
3153 case 0x07: /* LDC.L @Rm+,SR */
3154 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3155 ic->arg[0] = (size_t)&cpu->cd.sh.sr;
3156 break;
3157 case 0x08: /* SHLL2 Rn */
3158 ic->f = instr(shll2_rn);
3159 break;
3160 case 0x09: /* SHLR2 Rn */
3161 ic->f = instr(shlr2_rn);
3162 break;
3163 case 0x0b: /* JSR @Rn */
3164 if (cpu->machine->show_trace_tree)
3165 ic->f = instr(jsr_rn_trace);
3166 else
3167 ic->f = instr(jsr_rn);
3168 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3169 ic->arg[1] = (addr & 0xffe) + 4;
3170 break;
3171 case 0x0e: /* LDC Rm,SR */
3172 ic->f = instr(ldc_rm_sr);
3173 break;
3174 case 0x10: /* DT Rn */
3175 ic->f = instr(dt_rn);
3176 break;
3177 case 0x11: /* CMP/PZ Rn */
3178 ic->f = instr(cmppz_rn);
3179 break;
3180 case 0x12: /* STS.L MACL,@-Rn */
3181 ic->f = instr(mov_l_rm_predec_rn);
3182 ic->arg[0] = (size_t)&cpu->cd.sh.macl;
3183 break;
3184 case 0x13: /* STC.L GBR,@-Rn */
3185 ic->f = instr(mov_l_rm_predec_rn);
3186 ic->arg[0] = (size_t)&cpu->cd.sh.gbr;
3187 break;
3188 case 0x15: /* CMP/PL Rn */
3189 ic->f = instr(cmppl_rn);
3190 break;
3191 case 0x16: /* LDS.L @Rm+,MACL */
3192 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3193 ic->arg[0] = (size_t)&cpu->cd.sh.macl;
3194 break;
3195 case 0x17: /* LDC.L @Rm+,GBR */
3196 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3197 ic->arg[0] = (size_t)&cpu->cd.sh.gbr;
3198 break;
3199 case 0x18: /* SHLL8 Rn */
3200 ic->f = instr(shll8_rn);
3201 break;
3202 case 0x19: /* SHLR8 Rn */
3203 ic->f = instr(shlr8_rn);
3204 break;
3205 case 0x1b: /* TAS.B @Rn */
3206 ic->f = instr(tas_b_rn);
3207 break;
3208 case 0x1e: /* LDC Rm,GBR */
3209 ic->f = instr(mov_rm_rn);
3210 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3211 ic->arg[1] = (size_t)&cpu->cd.sh.gbr;
3212 break;
3213 case 0x20: /* SHAL Rn */
3214 ic->f = instr(shll_rn); /* NOTE: shll */
3215 break;
3216 case 0x21: /* SHAR Rn */
3217 ic->f = instr(shar_rn);
3218 break;
3219 case 0x22: /* STS.L PR,@-Rn */
3220 ic->f = instr(mov_l_rm_predec_rn);
3221 ic->arg[0] = (size_t)&cpu->cd.sh.pr; /* m */
3222 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3223 break;
3224 case 0x23: /* STC.L VBR,@-Rn */
3225 ic->f = instr(stc_l_rm_predec_rn_md);
3226 ic->arg[0] = (size_t)&cpu->cd.sh.vbr;
3227 break;
3228 case 0x24: /* ROTCL Rn */
3229 ic->f = instr(rotcl_rn);
3230 break;
3231 case 0x25: /* ROTCR Rn */
3232 ic->f = instr(rotcr_rn);
3233 break;
3234 case 0x26: /* LDS.L @Rm+,PR */
3235 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3236 ic->arg[0] = (size_t)&cpu->cd.sh.pr;
3237 break;
3238 case 0x27: /* LDC.L @Rm+,VBR */
3239 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3240 ic->arg[0] = (size_t)&cpu->cd.sh.vbr;
3241 break;
3242 case 0x28: /* SHLL16 Rn */
3243 ic->f = instr(shll16_rn);
3244 break;
3245 case 0x29: /* SHLR16 Rn */
3246 ic->f = instr(shlr16_rn);
3247 break;
3248 case 0x2a: /* LDS Rm,PR */
3249 ic->f = instr(mov_rm_rn);
3250 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3251 ic->arg[1] = (size_t)&cpu->cd.sh.pr;
3252 break;
3253 case 0x2b: /* JMP @Rn */
3254 if (cpu->machine->show_trace_tree)
3255 ic->f = instr(jmp_rn_trace);
3256 else
3257 ic->f = instr(jmp_rn);
3258 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3259 ic->arg[1] = (addr & 0xffe) + 4;
3260 break;
3261 case 0x2e: /* LDC Rm,VBR */
3262 ic->f = instr(copy_privileged_register);
3263 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3264 ic->arg[1] = (size_t)&cpu->cd.sh.vbr;
3265 break;
3266 case 0x33: /* STC.L SSR,@-Rn */
3267 ic->f = instr(stc_l_rm_predec_rn_md);
3268 ic->arg[0] = (size_t)&cpu->cd.sh.ssr;
3269 break;
3270 case 0x37: /* LDC.L @Rm+,SSR */
3271 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3272 ic->arg[0] = (size_t)&cpu->cd.sh.ssr;
3273 break;
3274 case 0x3e: /* LDC rm,SSR */
3275 ic->f = instr(copy_privileged_register);
3276 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3277 ic->arg[1] = (size_t)&cpu->cd.sh.ssr;
3278 break;
3279 case 0x43: /* STC.L SPC,@-Rn */
3280 ic->f = instr(stc_l_rm_predec_rn_md);
3281 ic->arg[0] = (size_t)&cpu->cd.sh.spc;
3282 break;
3283 case 0x47: /* LDC.L @Rm+,SPC */
3284 ic->f = instr(mov_l_arg1_postinc_to_arg0_md);
3285 ic->arg[0] = (size_t)&cpu->cd.sh.spc;
3286 break;
3287 case 0x4e: /* LDC rm,SPC */
3288 ic->f = instr(copy_privileged_register);
3289 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3290 ic->arg[1] = (size_t)&cpu->cd.sh.spc;
3291 break;
3292 case 0x52: /* STS.L FPUL,@-Rn */
3293 ic->f = instr(mov_l_rm_predec_rn);
3294 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3295 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3296 break;
3297 case 0x56: /* LDS.L @Rm+,FPUL */
3298 ic->f = instr(mov_l_arg1_postinc_to_arg0_fp);
3299 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3300 break;
3301 case 0x5a: /* LDS Rm,FPUL */
3302 ic->f = instr(copy_fp_register);
3303 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* m */
3304 ic->arg[1] = (size_t)&cpu->cd.sh.fpul;
3305 break;
3306 case 0x62: /* STS.L FPSCR,@-Rn */
3307 ic->f = instr(mov_l_rm_predec_rn);
3308 ic->arg[0] = (size_t)&cpu->cd.sh.fpscr;
3309 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3310 break;
3311 case 0x66: /* LDS.L @Rm+,FPSCR */
3312 ic->f = instr(mov_l_arg1_postinc_to_arg0_fp);
3313 ic->arg[0] = (size_t)&cpu->cd.sh.fpscr;
3314 break;
3315 case 0x6a: /* LDS Rm,FPSCR */
3316 ic->f = instr(lds_rm_fpscr);
3317 /* arg 1 = R8 = Rm */
3318 break;
3319 case 0xfa: /* LDC Rm,DBR */
3320 ic->f = instr(copy_privileged_register);
3321 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8];
3322 ic->arg[1] = (size_t)&cpu->cd.sh.dbr;
3323 break;
3324 default:fatal("Unimplemented opcode 0x%x,0x%02x\n",
3325 main_opcode, lo8);
3326 goto bad;
3327 }
3328 }
3329 break;
3330
3331 case 0x5:
3332 ic->f = instr(mov_l_disp_rm_rn);
3333 ic->arg[0] = r4 + (lo4 << 4);
3334 break;
3335
3336 case 0x6:
3337 switch (lo4) {
3338 case 0x0: /* MOV.B @Rm,Rn */
3339 ic->f = instr(load_b_rm_rn);
3340 break;
3341 case 0x1: /* MOV.W @Rm,Rn */
3342 ic->f = instr(load_w_rm_rn);
3343 break;
3344 case 0x2: /* MOV.L @Rm,Rn */
3345 ic->f = instr(load_l_rm_rn);
3346 break;
3347 case 0x3: /* MOV Rm,Rn */
3348 ic->f = instr(mov_rm_rn);
3349 break;
3350 case 0x4: /* MOV.B @Rm+,Rn */
3351 ic->f = instr(mov_b_arg1_postinc_to_arg0);
3352 /* Note: Order */
3353 ic->arg[1] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3354 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3355 break;
3356 case 0x5: /* MOV.W @Rm+,Rn */
3357 ic->f = instr(mov_w_arg1_postinc_to_arg0);
3358 /* Note: Order */
3359 ic->arg[1] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3360 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3361 break;
3362 case 0x6: /* MOV.L @Rm+,Rn */
3363 ic->f = instr(mov_l_arg1_postinc_to_arg0);
3364 /* Note: Order */
3365 ic->arg[1] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3366 ic->arg[0] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3367 break;
3368 case 0x7: /* NOT Rm,Rn */
3369 ic->f = instr(not_rm_rn);
3370 break;
3371 case 0x8: /* SWAP.B Rm,Rn */
3372 ic->f = instr(swap_b_rm_rn);
3373 break;
3374 case 0x9: /* SWAP.W Rm,Rn */
3375 ic->f = instr(swap_w_rm_rn);
3376 break;
3377 case 0xa: /* NEGC Rm,Rn */
3378 ic->f = instr(negc_rm_rn);
3379 break;
3380 case 0xb: /* NEG Rm,Rn */
3381 ic->f = instr(neg_rm_rn);
3382 break;
3383 case 0xc: /* EXTU.B Rm,Rn */
3384 ic->f = instr(extu_b_rm_rn);
3385 break;
3386 case 0xd: /* EXTU.W Rm,Rn */
3387 ic->f = instr(extu_w_rm_rn);
3388 break;
3389 case 0xe: /* EXTS.B Rm,Rn */
3390 ic->f = instr(exts_b_rm_rn);
3391 break;
3392 case 0xf: /* EXTS.W Rm,Rn */
3393 ic->f = instr(exts_w_rm_rn);
3394 break;
3395 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3396 main_opcode, lo4);
3397 goto bad;
3398 }
3399 break;
3400
3401 case 0x7: /* ADD #imm,Rn */
3402 ic->f = instr(add_imm_rn);
3403 ic->arg[0] = (int8_t)lo8;
3404 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3405 break;
3406
3407 case 0x8:
3408 /* Displacement from beginning of page = default arg 0. */
3409 ic->arg[0] = (int8_t)lo8 * 2 +
3410 (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3411 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
3412 switch (r8) {
3413 case 0x0: /* MOV.B R0,@(disp,Rn) */
3414 ic->f = instr(mov_b_r0_disp_rn);
3415 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3416 ic->arg[1] = lo4;
3417 break;
3418 case 0x1: /* MOV.W R0,@(disp,Rn) */
3419 ic->f = instr(mov_w_r0_disp_rn);
3420 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3421 ic->arg[1] = lo4 * 2;
3422 break;
3423 case 0x4: /* MOV.B @(disp,Rn),R0 */
3424 ic->f = instr(mov_b_disp_rn_r0);
3425 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3426 ic->arg[1] = lo4;
3427 break;
3428 case 0x5: /* MOV.W @(disp,Rn),R0 */
3429 ic->f = instr(mov_w_disp_rn_r0);
3430 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* n */
3431 ic->arg[1] = lo4 * 2;
3432 break;
3433 case 0x8: /* CMP/EQ #imm,R0 */
3434 ic->f = instr(cmpeq_imm_r0);
3435 ic->arg[0] = (int8_t)lo8;
3436 break;
3437 case 0x9: /* BT (disp,PC) */
3438 ic->f = instr(bt);
3439 break;
3440 case 0xb: /* BF (disp,PC) */
3441 ic->f = instr(bf);
3442 break;
3443 case 0xd: /* BT/S (disp,PC) */
3444 ic->f = instr(bt_s);
3445 break;
3446 case 0xf: /* BF/S (disp,PC) */
3447 ic->f = instr(bf_s);
3448 break;
3449 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3450 main_opcode, r8);
3451 goto bad;
3452 }
3453 break;
3454
3455 case 0x9: /* MOV.W @(disp,PC),Rn */
3456 ic->f = instr(mov_w_disp_pc_rn);
3457 ic->arg[0] = lo8 * 2 + (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3458 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4;
3459 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3460 break;
3461
3462 case 0xa: /* BRA disp */
3463 case 0xb: /* BSR disp */
3464 ic->f = main_opcode == 0xa? instr(bra) : instr(bsr);
3465 ic->arg[0] = (int32_t) ( (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3466 << SH_INSTR_ALIGNMENT_SHIFT) & ~1) + 4 +
3467 (((int32_t)(int16_t)((iword & 0xfff) << 4)) >> 3) );
3468 break;
3469
3470 case 0xc:
3471 switch (r8) {
3472 case 0x0:
3473 ic->f = instr(mov_b_r0_disp_gbr);
3474 ic->arg[1] = lo8;
3475 break;
3476 case 0x1:
3477 ic->f = instr(mov_w_r0_disp_gbr);
3478 ic->arg[1] = lo8 << 1;
3479 break;
3480 case 0x2:
3481 ic->f = instr(mov_l_r0_disp_gbr);
3482 ic->arg[1] = lo8 << 2;
3483 break;
3484 case 0x3:
3485 ic->f = instr(trapa);
3486 ic->arg[0] = lo8 << 2;
3487 break;
3488 case 0x4:
3489 ic->f = instr(mov_b_disp_gbr_r0);
3490 ic->arg[1] = lo8;
3491 break;
3492 case 0x5:
3493 ic->f = instr(mov_w_disp_gbr_r0);
3494 ic->arg[1] = lo8 << 1;
3495 break;
3496 case 0x6:
3497 ic->f = instr(mov_l_disp_gbr_r0);
3498 ic->arg[1] = lo8 << 2;
3499 break;
3500 case 0x7: /* MOVA @(disp,pc),R0 */
3501 ic->f = instr(mova_r0);
3502 ic->arg[0] = lo8 * 4 + (addr &
3503 ((SH_IC_ENTRIES_PER_PAGE-1)
3504 << SH_INSTR_ALIGNMENT_SHIFT) & ~3) + 4;
3505 break;
3506 case 0x8: /* TST #imm,R0 */
3507 ic->f = instr(tst_imm_r0);
3508 ic->arg[0] = lo8;
3509 break;
3510 case 0x9: /* AND #imm,R0 */
3511 ic->f = instr(and_imm_r0);
3512 ic->arg[0] = lo8;
3513 break;
3514 case 0xa: /* XOR #imm,R0 */
3515 ic->f = instr(xor_imm_r0);
3516 ic->arg[0] = lo8;
3517 break;
3518 case 0xb: /* OR #imm,R0 */
3519 ic->f = instr(or_imm_r0);
3520 ic->arg[0] = lo8;
3521 break;
3522 case 0xd: /* AND.B #imm,@(R0,GBR) */
3523 ic->f = instr(and_b_imm_r0_gbr);
3524 ic->arg[0] = lo8;
3525 break;
3526 case 0xe: /* XOR.B #imm,@(R0,GBR) */
3527 ic->f = instr(xor_b_imm_r0_gbr);
3528 ic->arg[0] = lo8;
3529 break;
3530 case 0xf: /* OR.B #imm,@(R0,GBR) */
3531 ic->f = instr(or_b_imm_r0_gbr);
3532 ic->arg[0] = lo8;
3533 break;
3534 default:fatal("Unimplemented opcode 0x%x,0x%x\n",
3535 main_opcode, r8);
3536 goto bad;
3537 }
3538 break;
3539
3540 case 0xd: /* MOV.L @(disp,PC),Rn */
3541 ic->f = instr(mov_l_disp_pc_rn);
3542 ic->arg[0] = lo8 * 4 + (addr & ((SH_IC_ENTRIES_PER_PAGE-1)
3543 << SH_INSTR_ALIGNMENT_SHIFT) & ~3) + 4;
3544 break;
3545
3546 case 0xe: /* MOV #imm,Rn */
3547 ic->f = instr(mov_imm_rn);
3548 ic->arg[0] = (int8_t)lo8;
3549 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8]; /* n */
3550 break;
3551
3552 case 0xf:
3553 if (lo4 == 0x0) {
3554 /* FADD FRm,FRn */
3555 ic->f = instr(fadd_frm_frn);
3556 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3557 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3558 } else if (lo4 == 0x1) {
3559 /* FSUB FRm,FRn */
3560 ic->f = instr(fsub_frm_frn);
3561 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3562 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3563 } else if (lo4 == 0x2) {
3564 /* FMUL FRm,FRn */
3565 ic->f = instr(fmul_frm_frn);
3566 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3567 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3568 } else if (lo4 == 0x3) {
3569 /* FDIV FRm,FRn */
3570 ic->f = instr(fdiv_frm_frn);
3571 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3572 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3573 } else if (lo4 == 0x4) {
3574 /* FCMP/EQ FRm,FRn */
3575 ic->f = instr(fcmp_eq_frm_frn);
3576 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3577 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3578 } else if (lo4 == 0x5) {
3579 /* FCMP/GT FRm,FRn */
3580 ic->f = instr(fcmp_gt_frm_frn);
3581 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3582 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3583 } else if (lo4 == 0x6) {
3584 /* FMOV @(R0,Rm),FRn */
3585 ic->f = instr(fmov_r0_rm_frn);
3586 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3587 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3588 } else if (lo4 == 0x7) {
3589 /* FMOV FRm,@(R0,Rn) */
3590 ic->f = instr(fmov_frm_r0_rn);
3591 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; /* m */
3592 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3593 } else if (lo4 == 0x8) {
3594 /* FMOV @Rm,FRn */
3595 ic->f = instr(fmov_rm_frn);
3596 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3597 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3598 } else if (lo4 == 0x9) {
3599 /* FMOV @Rm+,FRn */
3600 ic->f = instr(fmov_rm_postinc_frn);
3601 ic->arg[0] = (size_t)&cpu->cd.sh.r[r4]; /* m */
3602 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3603 } else if (lo4 == 0xa) {
3604 /* FMOV FRm,@Rn */
3605 ic->f = instr(fmov_frm_rn);
3606 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; /* m */
3607 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3608 } else if (lo4 == 0xb) {
3609 /* FMOV FRm,@-Rn */
3610 ic->f = instr(fmov_frm_predec_rn);
3611 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4]; /* m */
3612 ic->arg[1] = (size_t)&cpu->cd.sh.r[r8];
3613 } else if (lo4 == 0xc) {
3614 /* FMOV FRm,FRn */
3615 ic->f = instr(fmov_frm_frn);
3616 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3617 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3618 } else if (lo8 == 0x0d) {
3619 /* FSTS FPUL,FRn */
3620 ic->f = instr(copy_fp_register);
3621 ic->arg[0] = (size_t)&cpu->cd.sh.fpul;
3622 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3623 } else if (lo8 == 0x1d) {
3624 /* FLDS FRn,FPUL */
3625 ic->f = instr(copy_fp_register);
3626 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3627 ic->arg[1] = (size_t)&cpu->cd.sh.fpul;
3628 } else if (lo8 == 0x2d) {
3629 /* FLOAT FPUL,FRn */
3630 ic->f = instr(float_fpul_frn);
3631 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3632 } else if (lo8 == 0x3d) {
3633 /* FTRC FRm,FPUL */
3634 ic->f = instr(ftrc_frm_fpul);
3635 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3636 } else if (lo8 == 0x4d) {
3637 /* FNEG FRn */
3638 ic->f = instr(fneg_frn);
3639 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3640 } else if (lo8 == 0x5d) {
3641 /* FABS FRn */
3642 ic->f = instr(fabs_frn);
3643 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3644 } else if (lo8 == 0x6d) {
3645 /* FSQRT FRn */
3646 ic->f = instr(fsqrt_frn);
3647 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3648 } else if (lo8 == 0x8d) {
3649 /* FLDI0 FRn */
3650 ic->f = instr(fldi_frn);
3651 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3652 ic->arg[1] = 0x00000000;
3653 } else if (lo8 == 0x9d) {
3654 /* FLDI1 FRn */
3655 ic->f = instr(fldi_frn);
3656 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3657 ic->arg[1] = 0x3f800000;
3658 } else if ((iword & 0x01ff) == 0x00fd) {
3659 /* FSCA FPUL,DRn */
3660 ic->f = instr(fsca_fpul_drn);
3661 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8];
3662 } else if (iword == 0xf3fd) {
3663 /* FSCHG */
3664 ic->f = instr(fschg);
3665 } else if (iword == 0xfbfd) {
3666 /* FRCHG */
3667 ic->f = instr(frchg);
3668 } else if ((iword & 0xf3ff) == 0xf1fd) {
3669 /* FTRV XMTRX, FVn */
3670 ic->f = instr(ftrv_xmtrx_fvn);
3671 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r8 & 0xc];
3672 } else if (lo4 == 0xe) {
3673 /* FMAC FR0,FRm,FRn */
3674 ic->f = instr(fmac_fr0_frm_frn);
3675 ic->arg[0] = (size_t)&cpu->cd.sh.fr[r4];
3676 ic->arg[1] = (size_t)&cpu->cd.sh.fr[r8];
3677 } else {
3678 fatal("Unimplemented opcode 0x%x,0x%02x\n",
3679 main_opcode, lo8);
3680 goto bad;
3681 }
3682 break;
3683
3684 default:fatal("Unimplemented main opcode 0x%x\n", main_opcode);
3685 goto bad;
3686 }
3687
3688
3689 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3690 #include "cpu_dyntrans.c"
3691 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
3692 }
3693

  ViewVC Help
Powered by ViewVC 1.1.26