cpu_sh_instr.cc Source File

Back to the index.

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

Generated on Tue Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17