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

Contents of /upstream/0.4.4/src/cpus/cpu_sh_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26