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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.22  
changed lines
  Added in v.34

  ViewVC Help
Powered by ViewVC 1.1.26