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