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

Legend:
Removed from v.20  
changed lines
  Added in v.40

  ViewVC Help
Powered by ViewVC 1.1.26