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

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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26