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

Legend:
Removed from v.14  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26