OSDN Git Service

f1ce809014df8a2b7d761cb8167059d2996303de
[pf3gnuchains/pf3gnuchains4x.git] / sim / rx / rx.c
1 /* rx.c --- opcode semantics for stand-alone RX simulator.
2
3 Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
5
6 This file is part of the GNU simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <signal.h>
25
26 #include "opcode/rx.h"
27 #include "cpu.h"
28 #include "mem.h"
29 #include "syscalls.h"
30 #include "fpu.h"
31 #include "err.h"
32
33 #define tprintf if (trace) printf
34
35 jmp_buf decode_jmp_buf;
36 unsigned int rx_cycles = 0;
37
38 static int size2bytes[] = {
39   4, 1, 1, 1, 2, 2, 2, 3, 4
40 };
41
42 typedef struct {
43   unsigned long dpc;
44 } RX_Data;
45
46 #define rx_abort() _rx_abort(__FILE__, __LINE__)
47 static void
48 _rx_abort (const char *file, int line)
49 {
50   if (strrchr (file, '/'))
51     file = strrchr (file, '/') + 1;
52   fprintf(stderr, "abort at %s:%d\n", file, line);
53   abort();
54 }
55
56 static int
57 rx_get_byte (void *vdata)
58 {
59   int saved_trace = trace;
60   unsigned char rv;
61
62   if (trace == 1)
63     trace = 0;
64
65   RX_Data *rx_data = (RX_Data *)vdata;
66   if (rx_big_endian)
67     /* See load.c for an explanation of this.  */
68     rv = mem_get_pc (rx_data->dpc ^ 3);
69   else
70     rv = mem_get_pc (rx_data->dpc);
71   rx_data->dpc ++;
72   trace = saved_trace;
73   return rv;
74 }
75
76 static int
77 get_op (RX_Opcode_Decoded *rd, int i)
78 {
79   RX_Opcode_Operand *o = rd->op + i;
80   int addr, rv = 0;
81
82   switch (o->type)
83     {
84     case RX_Operand_None:
85       rx_abort ();
86
87     case RX_Operand_Immediate:  /* #addend */
88       return o->addend;
89
90     case RX_Operand_Register:   /* Rn */
91       rv = get_reg (o->reg);
92       break;
93
94     case RX_Operand_Predec:     /* [-Rn] */
95       put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
96       /* fall through */
97     case RX_Operand_Postinc:    /* [Rn+] */
98     case RX_Operand_Indirect:   /* [Rn + addend] */
99
100       addr = get_reg (o->reg) + o->addend;
101       switch (o->size)
102         {
103         case RX_AnySize:
104           rx_abort ();
105
106         case RX_Byte: /* undefined extension */
107         case RX_UByte:
108         case RX_SByte:
109           rv = mem_get_qi (addr);
110           break;
111
112         case RX_Word: /* undefined extension */
113         case RX_UWord:
114         case RX_SWord:
115           rv = mem_get_hi (addr);
116           break;
117
118         case RX_3Byte:
119           rv = mem_get_psi (addr);
120           break;
121
122         case RX_Long:
123           rv = mem_get_si (addr);
124           break;
125         }
126
127       if (o->type == RX_Operand_Postinc)
128         put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
129
130       break;
131
132     case RX_Operand_Condition:  /* eq, gtu, etc */
133       return condition_true (o->reg);
134
135     case RX_Operand_Flag:       /* [UIOSZC] */
136       return (regs.r_psw & (1 << o->reg)) ? 1 : 0;
137     }
138
139   /* if we've gotten here, we need to clip/extend the value according
140      to the size.  */
141   switch (o->size)
142     {
143     case RX_AnySize:
144       rx_abort ();
145
146     case RX_Byte: /* undefined extension */
147       rv |= 0xdeadbe00; /* keep them honest */
148       break;
149
150     case RX_UByte:
151       rv &= 0xff;
152       break;
153
154     case RX_SByte:
155       rv = sign_ext (rv, 8);
156       break;
157
158     case RX_Word: /* undefined extension */
159       rv |= 0xdead0000; /* keep them honest */
160       break;
161
162     case RX_UWord:
163       rv &=  0xffff;
164       break;
165
166     case RX_SWord:
167       rv = sign_ext (rv, 16);
168       break;
169
170     case RX_3Byte:
171       rv &= 0xffffff;
172       break;
173
174     case RX_Long:
175       break;
176     }
177   return rv;
178 }
179
180 static void
181 put_op (RX_Opcode_Decoded *rd, int i, int v)
182 {
183   RX_Opcode_Operand *o = rd->op + i;
184   int addr;
185
186   switch (o->size)
187     {
188     case RX_AnySize:
189       if (o->type != RX_Operand_Register)
190         rx_abort ();
191       break;
192
193     case RX_Byte: /* undefined extension */
194       v |= 0xdeadbe00; /* keep them honest */
195       break;
196
197     case RX_UByte:
198       v &= 0xff;
199       break;
200
201     case RX_SByte:
202       v = sign_ext (v, 8);
203       break;
204
205     case RX_Word: /* undefined extension */
206       v |= 0xdead0000; /* keep them honest */
207       break;
208
209     case RX_UWord:
210       v &=  0xffff;
211       break;
212
213     case RX_SWord:
214       v = sign_ext (v, 16);
215       break;
216
217     case RX_3Byte:
218       v &= 0xffffff;
219       break;
220
221     case RX_Long:
222       break;
223     }
224
225   switch (o->type)
226     {
227     case RX_Operand_None:
228       /* Opcodes like TST and CMP use this.  */
229       break;
230
231     case RX_Operand_Immediate:  /* #addend */
232     case RX_Operand_Condition:  /* eq, gtu, etc */
233       rx_abort ();
234
235     case RX_Operand_Register:   /* Rn */
236       put_reg (o->reg, v);
237       break;
238
239     case RX_Operand_Predec:     /* [-Rn] */
240       put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
241       /* fall through */
242     case RX_Operand_Postinc:    /* [Rn+] */
243     case RX_Operand_Indirect:   /* [Rn + addend] */
244
245       addr = get_reg (o->reg) + o->addend;
246       switch (o->size)
247         {
248         case RX_AnySize:
249           rx_abort ();
250
251         case RX_Byte: /* undefined extension */
252         case RX_UByte:
253         case RX_SByte:
254           mem_put_qi (addr, v);
255           break;
256
257         case RX_Word: /* undefined extension */
258         case RX_UWord:
259         case RX_SWord:
260           mem_put_hi (addr, v);
261           break;
262
263         case RX_3Byte:
264           mem_put_psi (addr, v);
265           break;
266
267         case RX_Long:
268           mem_put_si (addr, v);
269           break;
270         }
271
272       if (o->type == RX_Operand_Postinc)
273         put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
274
275       break;
276
277     case RX_Operand_Flag:       /* [UIOSZC] */
278       if (v)
279         regs.r_psw |= (1 << o->reg);
280       else
281         regs.r_psw &= ~(1 << o->reg);
282       break;
283     }
284 }
285
286 #define PD(x) put_op (&opcode, 0, x)
287 #define PS(x) put_op (&opcode, 1, x)
288 #define PS2(x) put_op (&opcode, 2, x)
289 #define GD() get_op (&opcode, 0)
290 #define GS() get_op (&opcode, 1)
291 #define GS2() get_op (&opcode, 2)
292 #define DSZ() size2bytes[opcode.op[0].size]
293 #define SSZ() size2bytes[opcode.op[0].size]
294 #define S2SZ() size2bytes[opcode.op[0].size]
295
296 /* "Universal" sources.  */
297 #define US1() ((opcode.op[2].type == RX_Operand_None) ? GD() : GS())
298 #define US2() ((opcode.op[2].type == RX_Operand_None) ? GS() : GS2())
299
300 static void
301 push(int val)
302 {
303   int rsp = get_reg (sp);
304   rsp -= 4;
305   put_reg (sp, rsp);
306   mem_put_si (rsp, val);
307 }
308
309 /* Just like the above, but tag the memory as "pushed pc" so if anyone
310    tries to write to it, it will cause an error.  */
311 static void
312 pushpc(int val)
313 {
314   int rsp = get_reg (sp);
315   rsp -= 4;
316   put_reg (sp, rsp);
317   mem_put_si (rsp, val);
318   mem_set_content_range (rsp, rsp+3, MC_PUSHED_PC);
319 }
320
321 static int
322 pop()
323 {
324   int rv;
325   int rsp = get_reg (sp);
326   rv = mem_get_si (rsp);
327   rsp += 4;
328   put_reg (sp, rsp);
329   return rv;
330 }
331
332 static int
333 poppc()
334 {
335   int rv;
336   int rsp = get_reg (sp);
337   if (mem_get_content_type (rsp) != MC_PUSHED_PC)
338     execution_error (SIM_ERR_CORRUPT_STACK, rsp);
339   rv = mem_get_si (rsp);
340   mem_set_content_range (rsp, rsp+3, MC_UNINIT);
341   rsp += 4;
342   put_reg (sp, rsp);
343   return rv;
344 }
345
346 #define MATH_OP(vop,c)                          \
347 { \
348   uma = US1(); \
349   umb = US2(); \
350   ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
351   tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
352   ma = sign_ext (uma, DSZ() * 8);                                       \
353   mb = sign_ext (umb, DSZ() * 8);                                       \
354   sll = (long long) ma vop (long long) mb vop c; \
355   tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
356   set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
357   PD (sll); \
358 }
359
360 #define LOGIC_OP(vop) \
361 { \
362   ma = US1(); \
363   mb = US2(); \
364   v = ma vop mb; \
365   tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
366   set_sz (v, DSZ()); \
367   PD(v); \
368 }
369
370 #define SHIFT_OP(val, type, count, OP, carry_mask)      \
371 { \
372   int i, c=0; \
373   val = (type)US1();                            \
374   count = US2(); \
375   tprintf("%lld " #OP " %d\n", val, count); \
376   for (i = 0; i < count; i ++) \
377     { \
378       c = val & carry_mask; \
379       val OP 1; \
380     } \
381   if (count) \
382     set_oszc (val, 4, c); \
383   PD (val); \
384 }
385
386 typedef union {
387   int i;
388   float f;
389 } FloatInt;
390
391 static inline int
392 float2int (float f)
393 {
394   FloatInt fi;
395   fi.f = f;
396   return fi.i;
397 }
398
399 static inline float
400 int2float (int i)
401 {
402   FloatInt fi;
403   fi.i = i;
404   return fi.f;
405 }
406
407 static int
408 fop_fadd (fp_t s1, fp_t s2, fp_t *d)
409 {
410   *d = rxfp_add (s1, s2);
411   return 1;
412 }
413
414 static int
415 fop_fmul (fp_t s1, fp_t s2, fp_t *d)
416 {
417   *d = rxfp_mul (s1, s2);
418   return 1;
419 }
420
421 static int
422 fop_fdiv (fp_t s1, fp_t s2, fp_t *d)
423 {
424   *d = rxfp_div (s1, s2);
425   return 1;
426 }
427
428 static int
429 fop_fsub (fp_t s1, fp_t s2, fp_t *d)
430 {
431   *d = rxfp_sub (s1, s2);
432   return 1;
433 }
434
435 #define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
436 #define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
437 #define FPCHECK() \
438   if (FPPENDING()) \
439     return do_fp_exception (opcode_pc)
440
441 #define FLOAT_OP(func) \
442 { \
443   int do_store;   \
444   fp_t fa, fb, fc; \
445   FPCLEAR(); \
446   fa = GD (); \
447   fb = GS (); \
448   do_store = fop_##func (fa, fb, &fc); \
449   tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
450   FPCHECK(); \
451   if (do_store) \
452     PD (fc);    \
453   mb = 0; \
454   if ((fc & 0x80000000UL) != 0) \
455     mb |= FLAGBIT_S; \
456   if ((fc & 0x7fffffffUL) == 0)                 \
457     mb |= FLAGBIT_Z; \
458   set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
459 }
460
461 #define carry (FLAG_C ? 1 : 0)
462
463 static struct {
464   unsigned long vaddr;
465   const char *str;
466   int signal;
467 } exception_info[] = {
468   { 0xFFFFFFD0UL, "priviledged opcode", SIGILL },
469   { 0xFFFFFFD4UL, "access violation", SIGSEGV },
470   { 0xFFFFFFDCUL, "undefined opcode", SIGILL },
471   { 0xFFFFFFE4UL, "floating point", SIGFPE }
472 };
473 #define EX_PRIVILEDGED  0
474 #define EX_ACCESS       1
475 #define EX_UNDEFINED    2
476 #define EX_FLOATING     3
477 #define EXCEPTION(n)  \
478   return generate_exception (n, opcode_pc)
479
480 #define PRIVILEDGED() \
481   if (FLAG_PM) \
482     EXCEPTION (EX_PRIVILEDGED)
483
484 static int
485 generate_exception (unsigned long type, SI opcode_pc)
486 {
487   SI old_psw, old_pc, new_pc;
488
489   new_pc = mem_get_si (exception_info[type].vaddr);
490   /* 0x00020000 is the value used to initialise the known
491      exception vectors (see rx.ld), but it is a reserved
492      area of memory so do not try to access it, and if the
493      value has not been changed by the program then the
494      vector has not been installed.  */
495   if (new_pc == 0 || new_pc == 0x00020000)
496     {
497       if (rx_in_gdb)
498         return RX_MAKE_STOPPED (exception_info[type].signal);
499
500       fprintf(stderr, "Unhandled %s exception at pc = %#lx\n",
501               exception_info[type].str, (unsigned long) opcode_pc);
502       if (type == EX_FLOATING)
503         {
504           int mask = FPPENDING ();
505           fprintf (stderr, "Pending FP exceptions:");
506           if (mask & FPSWBITS_FV)
507             fprintf(stderr, " Invalid");
508           if (mask & FPSWBITS_FO)
509             fprintf(stderr, " Overflow");
510           if (mask & FPSWBITS_FZ)
511             fprintf(stderr, " Division-by-zero");
512           if (mask & FPSWBITS_FU)
513             fprintf(stderr, " Underflow");
514           if (mask & FPSWBITS_FX)
515             fprintf(stderr, " Inexact");
516           if (mask & FPSWBITS_CE)
517             fprintf(stderr, " Unimplemented");
518           fprintf(stderr, "\n");
519         }
520       return RX_MAKE_EXITED (1);
521     }
522
523   tprintf ("Triggering %s exception\n", exception_info[type].str);
524
525   old_psw = regs.r_psw;
526   regs.r_psw &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
527   old_pc = opcode_pc;
528   regs.r_pc = new_pc;
529   pushpc (old_psw);
530   pushpc (old_pc);
531   return RX_MAKE_STEPPED ();
532 }
533
534 void
535 generate_access_exception (void)
536 {
537   int rv;
538
539   rv = generate_exception (EX_ACCESS, regs.r_pc);
540   if (RX_EXITED (rv))
541     longjmp (decode_jmp_buf, rv);
542 }
543
544 static int
545 do_fp_exception (unsigned long opcode_pc)
546 {
547   while (FPPENDING())
548     EXCEPTION (EX_FLOATING);
549   return RX_MAKE_STEPPED ();
550 }
551
552 int
553 decode_opcode ()
554 {
555   unsigned int uma=0, umb=0;
556   int ma=0, mb=0;
557   int opcode_size, v;
558   unsigned long long ll;
559   long long sll;
560   unsigned long opcode_pc;
561   RX_Data rx_data;
562   RX_Opcode_Decoded opcode;
563   int rv;
564
565   if ((rv = setjmp (decode_jmp_buf)))
566     return rv;
567
568   rx_cycles ++;
569
570   rx_data.dpc = opcode_pc = regs.r_pc;
571   opcode_size = rx_decode_opcode (opcode_pc, &opcode, rx_get_byte, &rx_data);
572   regs.r_pc += opcode_size;
573
574   rx_flagmask = opcode.flags_s;
575   rx_flagand = ~(int)opcode.flags_0;
576   rx_flagor = opcode.flags_1;
577
578   switch (opcode.id)
579     {
580     case RXO_abs:
581       sll = GS ();
582       tprintf("|%lld| = ", sll);
583       if (sll < 0)
584         sll = -sll;
585       tprintf("%lld\n", sll);
586       PD (sll);
587       set_osz (sll, 4);
588       break;
589
590     case RXO_adc:
591       MATH_OP (+,carry);
592       break;
593
594     case RXO_add:
595       MATH_OP (+,0);
596       break;
597
598     case RXO_and:
599       LOGIC_OP (&);
600       break;
601
602     case RXO_bclr:
603       ma = GD ();
604       mb = GS ();
605       if (opcode.op[0].type == RX_Operand_Register)
606         mb &= 0x1f;
607       else
608         mb &= 0x07;
609       ma &= ~(1 << mb);
610       PD (ma);
611       break;
612
613     case RXO_bmcc:
614       ma = GD ();
615       mb = GS ();
616       if (opcode.op[0].type == RX_Operand_Register)
617         mb &= 0x1f;
618       else
619         mb &= 0x07;
620       if (GS2 ())
621         ma |= (1 << mb);
622       else
623         ma &= ~(1 << mb);
624       PD (ma);
625       break;
626
627     case RXO_bnot:
628       ma = GD ();
629       mb = GS ();
630       if (opcode.op[0].type == RX_Operand_Register)
631         mb &= 0x1f;
632       else
633         mb &= 0x07;
634       ma ^= (1 << mb);
635       PD (ma);
636       break;
637
638     case RXO_branch:
639       if (GS())
640         regs.r_pc = GD();
641       break;
642
643     case RXO_branchrel:
644       if (GS())
645         regs.r_pc += GD();
646       break;
647
648     case RXO_brk:
649       {
650         int old_psw = regs.r_psw;
651         if (rx_in_gdb)
652           return RX_MAKE_HIT_BREAK ();
653         if (regs.r_intb == 0)
654           {
655             tprintf("BREAK hit, no vector table.\n");
656             return RX_MAKE_EXITED(1);
657           }
658         regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
659         pushpc (old_psw);
660         pushpc (regs.r_pc);
661         regs.r_pc = mem_get_si (regs.r_intb);
662       }
663       break;
664
665     case RXO_bset:
666       ma = GD ();
667       mb = GS ();
668       if (opcode.op[0].type == RX_Operand_Register)
669         mb &= 0x1f;
670       else
671         mb &= 0x07;
672       ma |= (1 << mb);
673       PD (ma);
674       break;
675
676     case RXO_btst:
677       ma = GS ();
678       mb = GS2 ();
679       if (opcode.op[1].type == RX_Operand_Register)
680         mb &= 0x1f;
681       else
682         mb &= 0x07;
683       umb = ma & (1 << mb);
684       set_zc (! umb, umb);
685       break;
686
687     case RXO_clrpsw:
688       v = 1 << opcode.op[0].reg;
689       if (FLAG_PM
690           && (v == FLAGBIT_I
691               || v == FLAGBIT_U))
692         break;
693       regs.r_psw &= ~v;
694       break;
695
696     case RXO_div: /* d = d / s */
697       ma = GS();
698       mb = GD();
699       tprintf("%d / %d = ", mb, ma);
700       if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
701         {
702           tprintf("#NAN\n");
703           set_flags (FLAGBIT_O, FLAGBIT_O);
704         }
705       else
706         {
707           v = mb/ma;
708           tprintf("%d\n", v);
709           set_flags (FLAGBIT_O, 0);
710           PD (v);
711         }
712       break;
713
714     case RXO_divu: /* d = d / s */
715       uma = GS();
716       umb = GD();
717       tprintf("%u / %u = ", umb, uma);
718       if (uma == 0)
719         {
720           tprintf("#NAN\n");
721           set_flags (FLAGBIT_O, FLAGBIT_O);
722         }
723       else
724         {
725           v = umb / uma;
726           tprintf("%u\n", v);
727           set_flags (FLAGBIT_O, 0);
728           PD (v);
729         }
730       break;
731
732     case RXO_ediv:
733       ma = GS();
734       mb = GD();
735       tprintf("%d / %d = ", mb, ma);
736       if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
737         {
738           tprintf("#NAN\n");
739           set_flags (FLAGBIT_O, FLAGBIT_O);
740         }
741       else
742         {
743           v = mb/ma;
744           mb = mb%ma;
745           tprintf("%d, rem %d\n", v, mb);
746           set_flags (FLAGBIT_O, 0);
747           PD (v);
748           opcode.op[0].reg ++;
749           PD (mb);
750         }
751       break;
752
753     case RXO_edivu:
754       uma = GS();
755       umb = GD();
756       tprintf("%u / %u = ", umb, uma);
757       if (uma == 0)
758         {
759           tprintf("#NAN\n");
760           set_flags (FLAGBIT_O, FLAGBIT_O);
761         }
762       else
763         {
764           v = umb/uma;
765           umb = umb%uma;
766           tprintf("%u, rem %u\n", v, umb);
767           set_flags (FLAGBIT_O, 0);
768           PD (v);
769           opcode.op[0].reg ++;
770           PD (umb);
771         }
772       break;
773
774     case RXO_emul:
775       ma = GD ();
776       mb = GS ();
777       sll = (long long)ma * (long long)mb;
778       tprintf("%d * %d = %lld\n", ma, mb, sll);
779       PD (sll);
780       opcode.op[0].reg ++;
781       PD (sll >> 32);
782       break;
783
784     case RXO_emulu:
785       uma = GD ();
786       umb = GS ();
787       ll = (long long)uma * (long long)umb;
788       tprintf("%#x * %#x = %#llx\n", uma, umb, ll);
789       PD (ll);
790       opcode.op[0].reg ++;
791       PD (ll >> 32);
792       break;
793
794     case RXO_fadd:
795       FLOAT_OP (fadd);
796       break;
797
798     case RXO_fcmp:
799       ma = GD();
800       mb = GS();
801       FPCLEAR ();
802       rxfp_cmp (ma, mb);
803       FPCHECK ();
804       break;
805
806     case RXO_fdiv:
807       FLOAT_OP (fdiv);
808       break;
809
810     case RXO_fmul:
811       FLOAT_OP (fmul);
812       break;
813
814     case RXO_rtfi:
815       PRIVILEDGED ();
816       regs.r_psw = regs.r_bpsw;
817       regs.r_pc = regs.r_bpc;
818       break;
819
820     case RXO_fsub:
821       FLOAT_OP (fsub);
822       break;
823
824     case RXO_ftoi:
825       ma = GS ();
826       FPCLEAR ();
827       mb = rxfp_ftoi (ma, FPRM_ZERO);
828       FPCHECK ();
829       PD (mb);
830       tprintf("(int) %g = %d\n", int2float(ma), mb);
831       set_sz (mb, 4);
832       break;
833
834     case RXO_int:
835       v = GS ();
836       if (v == 255)
837         {
838           return rx_syscall (regs.r[5]);
839         }
840       else
841         {
842           int old_psw = regs.r_psw;
843           regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
844           pushpc (old_psw);
845           pushpc (regs.r_pc);
846           regs.r_pc = mem_get_si (regs.r_intb + 4 * v);
847         }
848       break;
849
850     case RXO_itof:
851       ma = GS ();
852       FPCLEAR ();
853       mb = rxfp_itof (ma, regs.r_fpsw);
854       FPCHECK ();
855       tprintf("(float) %d = %x\n", ma, mb);
856       PD (mb);
857       set_sz (ma, 4);
858       break;
859
860     case RXO_jsr:
861     case RXO_jsrrel:
862       v = GD ();
863       pushpc (get_reg (pc));
864       if (opcode.id == RXO_jsrrel)
865         v += regs.r_pc;
866       put_reg (pc, v);
867       break;
868
869     case RXO_machi:
870       ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
871       ll <<= 16;
872       put_reg64 (acc64, ll + regs.r_acc);
873       break;
874
875     case RXO_maclo:
876       ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
877       ll <<= 16;
878       put_reg64 (acc64, ll + regs.r_acc);
879       break;
880
881     case RXO_max:
882       ma = GD();
883       mb = GS();
884       if (ma > mb)
885         PD (ma);
886       else
887         PD (mb);
888       break;
889
890     case RXO_min:
891       ma = GD();
892       mb = GS();
893       if (ma < mb)
894         PD (ma);
895       else
896         PD (mb);
897       break;
898
899     case RXO_mov:
900       v = GS ();
901       if (opcode.op[0].type == RX_Operand_Register
902           && opcode.op[0].reg == 16 /* PSW */)
903         {
904           /* Special case, LDC and POPC can't ever modify PM.  */
905           int pm = regs.r_psw & FLAGBIT_PM;
906           v &= ~ FLAGBIT_PM;
907           v |= pm;
908           if (pm)
909             {
910               v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
911               v |= pm;
912             }
913         }
914       if (FLAG_PM)
915         {
916           /* various things can't be changed in user mode.  */
917           if (opcode.op[0].type == RX_Operand_Register)
918             if (opcode.op[0].reg == 32)
919               {
920                 v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
921                 v |= regs.r_psw & (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
922               }
923           if (opcode.op[0].reg == 34 /* ISP */
924               || opcode.op[0].reg == 37 /* BPSW */
925               || opcode.op[0].reg == 39 /* INTB */
926               || opcode.op[0].reg == 38 /* VCT */)
927             /* These are ignored.  */
928             break;
929         }
930       PD (v);
931       set_sz (v, DSZ());
932       break;
933
934     case RXO_movbi:
935       /* We cheat to save on code duplication. */
936       regs.r_temp = (get_reg (opcode.op[1].reg) * size2bytes[opcode.size]
937                      + get_reg (opcode.op[2].reg));
938       opcode.op[1].reg = r_temp_idx;
939       opcode.op[1].type = RX_Operand_Indirect;
940       opcode.op[1].addend = 0;
941       PD (GS ());
942       break;
943
944     case RXO_movbir:
945       /* We cheat to save on code duplication. */
946       regs.r_temp = (get_reg (opcode.op[1].reg) * size2bytes[opcode.size]
947                      + get_reg (opcode.op[2].reg));
948       opcode.op[1].reg = r_temp_idx;
949       opcode.op[1].type = RX_Operand_Indirect;
950       opcode.op[1].addend = 0;
951       PS (GD ());
952       break;
953
954     case RXO_mul:
955       ll = (unsigned long long) US1() * (unsigned long long) US2();
956       PD(ll);
957       break;
958
959     case RXO_mulhi:
960       ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
961       ll <<= 16;
962       put_reg64 (acc64, ll);
963       break;
964
965     case RXO_mullo:
966       ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
967       ll <<= 16;
968       put_reg64 (acc64, ll);
969       break;
970
971     case RXO_mvfachi:
972       PD (get_reg (acchi));
973       break;
974
975     case RXO_mvfaclo:
976       PD (get_reg (acclo));
977       break;
978
979     case RXO_mvfacmi:
980       PD (get_reg (accmi));
981       break;
982
983     case RXO_mvtachi:
984       put_reg (acchi, GS ());
985       break;
986
987     case RXO_mvtaclo:
988       put_reg (acclo, GS ());
989       break;
990
991     case RXO_mvtipl:
992       regs.r_psw &= ~ FLAGBITS_IPL;
993       regs.r_psw |= (GS () << FLAGSHIFT_IPL) & FLAGBITS_IPL;
994       break;
995
996     case RXO_nop:
997       break;
998
999     case RXO_or:
1000       LOGIC_OP (|);
1001       break;
1002
1003     case RXO_popm:
1004       /* POPM cannot pop R0 (sp).  */
1005       if (opcode.op[1].reg == 0 || opcode.op[2].reg == 0)
1006         EXCEPTION (EX_UNDEFINED);
1007       if (opcode.op[1].reg >= opcode.op[2].reg)
1008         {
1009           regs.r_pc = opcode_pc;
1010           return RX_MAKE_STOPPED (SIGILL);
1011         }
1012       for (v = opcode.op[1].reg; v <= opcode.op[2].reg; v++)
1013         put_reg (v, pop ());
1014       break;
1015
1016     case RXO_pusha:
1017       push (get_reg (opcode.op[1].reg) + opcode.op[1].addend);
1018       break;
1019
1020     case RXO_pushm:
1021       /* PUSHM cannot push R0 (sp).  */
1022       if (opcode.op[1].reg == 0 || opcode.op[2].reg == 0)
1023         EXCEPTION (EX_UNDEFINED);
1024       if (opcode.op[1].reg >= opcode.op[2].reg)
1025         {
1026           regs.r_pc = opcode_pc;
1027           return RX_MAKE_STOPPED (SIGILL);
1028         }
1029       for (v = opcode.op[2].reg; v >= opcode.op[1].reg; v--)
1030         push (get_reg (v));
1031       break;
1032
1033     case RXO_racw:
1034       ll = get_reg64 (acc64) << GS ();
1035       ll += 0x80000000ULL;
1036       if ((signed long long)ll > (signed long long)0x00007fff00000000ULL)
1037         ll = 0x00007fff00000000ULL;
1038       else if ((signed long long)ll < (signed long long)0xffff800000000000ULL)
1039         ll = 0xffff800000000000ULL;
1040       else
1041         ll &= 0xffffffff00000000ULL;
1042       put_reg64 (acc64, ll);
1043       break;
1044
1045     case RXO_rte:
1046       PRIVILEDGED ();
1047       regs.r_pc = poppc ();
1048       regs.r_psw = poppc ();
1049       if (FLAG_PM)
1050         regs.r_psw |= FLAGBIT_U;
1051       break;
1052
1053     case RXO_revl:
1054       uma = GS ();
1055       umb = (((uma >> 24) & 0xff)
1056              | ((uma >> 8) & 0xff00)
1057              | ((uma << 8) & 0xff0000)
1058              | ((uma << 24) & 0xff000000UL));
1059       PD (umb);
1060       break;
1061
1062     case RXO_revw:
1063       uma = GS ();
1064       umb = (((uma >> 8) & 0x00ff00ff)
1065              | ((uma << 8) & 0xff00ff00UL));
1066       PD (umb);
1067       break;
1068
1069     case RXO_rmpa:
1070       while (regs.r[3] != 0)
1071         {
1072           long long tmp;
1073
1074           switch (opcode.size)
1075             {
1076             case RX_Long:
1077               ma = mem_get_si (regs.r[1]);
1078               mb = mem_get_si (regs.r[2]);
1079               regs.r[1] += 4;
1080               regs.r[2] += 4;
1081               break;
1082             case RX_Word:
1083               ma = sign_ext (mem_get_hi (regs.r[1]), 16);
1084               mb = sign_ext (mem_get_hi (regs.r[2]), 16);
1085               regs.r[1] += 2;
1086               regs.r[2] += 2;
1087               break;
1088             case RX_Byte:
1089               ma = sign_ext (mem_get_qi (regs.r[1]), 8);
1090               mb = sign_ext (mem_get_qi (regs.r[2]), 8);
1091               regs.r[1] += 1;
1092               regs.r[2] += 1;
1093               break;
1094             default:
1095               abort ();
1096             }
1097           /* We do the multiply as a signed value.  */
1098           sll = (long long)ma * (long long)mb;
1099           tprintf("        %016llx = %d * %d\n", sll, ma, mb);
1100           /* but we do the sum as unsigned, while sign extending the operands.  */
1101           tmp = regs.r[4] + (sll & 0xffffffffUL);
1102           regs.r[4] = tmp & 0xffffffffUL;
1103           tmp >>= 32;
1104           sll >>= 32;
1105           tmp += regs.r[5] + (sll & 0xffffffffUL);
1106           regs.r[5] = tmp & 0xffffffffUL;
1107           tmp >>= 32;
1108           sll >>= 32;
1109           tmp += regs.r[6] + (sll & 0xffffffffUL);
1110           regs.r[6] = tmp & 0xffffffffUL;
1111           tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
1112                   (unsigned long) regs.r[6],
1113                   (unsigned long) regs.r[5],
1114                   (unsigned long) regs.r[4]);
1115
1116           regs.r[3] --;
1117         }
1118       if (regs.r[6] & 0x00008000)
1119         regs.r[6] |= 0xffff0000UL;
1120       else
1121         regs.r[6] &= 0x0000ffff;
1122       ma = (regs.r[6] & 0x80000000UL) ? FLAGBIT_S : 0;
1123       if (regs.r[6] != 0 && regs.r[6] != 0xffffffffUL)
1124         set_flags (FLAGBIT_O|FLAGBIT_S, ma | FLAGBIT_O);
1125       else
1126         set_flags (FLAGBIT_O|FLAGBIT_S, ma);
1127       break;
1128
1129     case RXO_rolc:
1130       v = GD ();
1131       ma = v & 0x80000000UL;
1132       v <<= 1;
1133       v |= carry;
1134       set_szc (v, 4, ma);
1135       PD (v);
1136       break;
1137
1138     case RXO_rorc:
1139       uma = GD ();
1140       mb = uma & 1;
1141       uma >>= 1;
1142       uma |= (carry ? 0x80000000UL : 0);
1143       set_szc (uma, 4, mb);
1144       PD (uma);
1145       break;
1146
1147     case RXO_rotl:
1148       mb = GS ();
1149       uma = GD ();
1150       if (mb)
1151         {
1152           uma = (uma << mb) | (uma >> (32-mb));
1153           mb = uma & 1;
1154         }
1155       set_szc (uma, 4, mb);
1156       PD (uma);
1157       break;
1158
1159     case RXO_rotr:
1160       mb = GS ();
1161       uma = GD ();
1162       if (mb)
1163         {
1164           uma = (uma >> mb) | (uma << (32-mb));
1165           mb = uma & 0x80000000;
1166         }
1167       set_szc (uma, 4, mb);
1168       PD (uma);
1169       break;
1170
1171     case RXO_round:
1172       ma = GS ();
1173       FPCLEAR ();
1174       mb = rxfp_ftoi (ma, regs.r_fpsw);
1175       FPCHECK ();
1176       PD (mb);
1177       tprintf("(int) %g = %d\n", int2float(ma), mb);
1178       set_sz (mb, 4);
1179       break;
1180
1181     case RXO_rts:
1182       regs.r_pc = poppc ();
1183       break;
1184
1185     case RXO_rtsd:
1186       if (opcode.op[2].type == RX_Operand_Register)
1187         {
1188           int i;
1189           /* RTSD cannot pop R0 (sp).  */
1190           put_reg (0, get_reg (0) + GS() - (opcode.op[0].reg-opcode.op[2].reg+1)*4);
1191           if (opcode.op[2].reg == 0)
1192             EXCEPTION (EX_UNDEFINED);
1193           for (i = opcode.op[2].reg; i <= opcode.op[0].reg; i ++)
1194             put_reg (i, pop ());
1195         }
1196       else
1197         put_reg (0, get_reg (0) + GS());
1198       put_reg (pc, poppc ());
1199       break;
1200
1201     case RXO_sat:
1202       if (FLAG_O && FLAG_S)
1203         PD (0x7fffffffUL);
1204       else if (FLAG_O && ! FLAG_S)
1205         PD (0x80000000UL);
1206       break;
1207
1208     case RXO_sbb:
1209       MATH_OP (-, ! carry);
1210       break;
1211
1212     case RXO_sccnd:
1213       if (GS())
1214         PD (1);
1215       else
1216         PD (0);
1217       break;
1218
1219     case RXO_scmpu:
1220       while (regs.r[3] != 0)
1221         {
1222           uma = mem_get_qi (regs.r[1] ++);
1223           umb = mem_get_qi (regs.r[2] ++);
1224           regs.r[3] --;
1225           if (uma != umb || uma == 0)
1226             break;
1227         }
1228       if (uma == umb)
1229         set_zc (1, 1);
1230       else
1231         set_zc (0, ((int)uma - (int)umb) >= 0);
1232       break;
1233
1234     case RXO_setpsw:
1235       v = 1 << opcode.op[0].reg;
1236       if (FLAG_PM
1237           && (v == FLAGBIT_I
1238               || v == FLAGBIT_U))
1239         break;
1240       regs.r_psw |= v;
1241       break;
1242
1243     case RXO_smovb:
1244       while (regs.r[3])
1245         {
1246           uma = mem_get_qi (regs.r[2] --);
1247           mem_put_qi (regs.r[1]--, uma);
1248           regs.r[3] --;
1249         }
1250       break;
1251
1252     case RXO_smovf:
1253       while (regs.r[3])
1254         {
1255           uma = mem_get_qi (regs.r[2] ++);
1256           mem_put_qi (regs.r[1]++, uma);
1257           regs.r[3] --;
1258         }
1259       break;
1260
1261     case RXO_smovu:
1262       while (regs.r[3] != 0)
1263         {
1264           uma = mem_get_qi (regs.r[2] ++);
1265           mem_put_qi (regs.r[1]++, uma);
1266           regs.r[3] --;
1267           if (uma == 0)
1268             break;
1269         }
1270       break;
1271
1272     case RXO_shar: /* d = ma >> mb */
1273       SHIFT_OP (sll, int, mb, >>=, 1);
1274       break;
1275
1276     case RXO_shll: /* d = ma << mb */
1277       SHIFT_OP (ll, int, mb, <<=, 0x80000000UL);
1278       break;
1279
1280     case RXO_shlr: /* d = ma >> mb */
1281       SHIFT_OP (ll, unsigned int, mb, >>=, 1);
1282       break;
1283
1284     case RXO_sstr:
1285       switch (opcode.size)
1286         {
1287         case RX_Long:
1288           while (regs.r[3] != 0)
1289             {
1290               mem_put_si (regs.r[1], regs.r[2]);
1291               regs.r[1] += 4;
1292               regs.r[3] --;
1293             }
1294           break;
1295         case RX_Word:
1296           while (regs.r[3] != 0)
1297             {
1298               mem_put_hi (regs.r[1], regs.r[2]);
1299               regs.r[1] += 2;
1300               regs.r[3] --;
1301             }
1302           break;
1303         case RX_Byte:
1304           while (regs.r[3] != 0)
1305             {
1306               mem_put_qi (regs.r[1], regs.r[2]);
1307               regs.r[1] ++;
1308               regs.r[3] --;
1309             }
1310           break;
1311         default:
1312           abort ();
1313         }
1314       break;
1315
1316     case RXO_stcc:
1317       if (GS2())
1318         PD (GS ());
1319       break;
1320
1321     case RXO_stop:
1322       PRIVILEDGED ();
1323       regs.r_psw |= FLAGBIT_I;
1324       return RX_MAKE_STOPPED(0);
1325
1326     case RXO_sub:
1327       MATH_OP (-, 0);
1328       break;
1329
1330     case RXO_suntil:
1331       if (regs.r[3] == 0)
1332         break;
1333       switch (opcode.size)
1334         {
1335         case RX_Long:
1336           uma = get_reg (2);
1337           while (regs.r[3] != 0)
1338             {
1339               regs.r[3] --;
1340               umb = mem_get_si (get_reg (1));
1341               regs.r[1] += 4;
1342               if (umb == uma)
1343                 break;
1344             }
1345           break;
1346         case RX_Word:
1347           uma = get_reg (2) & 0xffff;
1348           while (regs.r[3] != 0)
1349             {
1350               regs.r[3] --;
1351               umb = mem_get_hi (get_reg (1));
1352               regs.r[1] += 2;
1353               if (umb == uma)
1354                 break;
1355             }
1356           break;
1357         case RX_Byte:
1358           uma = get_reg (2) & 0xff;
1359           while (regs.r[3] != 0)
1360             {
1361               regs.r[3] --;
1362               umb = mem_get_qi (regs.r[1]);
1363               regs.r[1] += 1;
1364               if (umb == uma)
1365                 break;
1366             }
1367           break;
1368         default:
1369           abort();
1370         }
1371       if (uma == umb)
1372         set_zc (1, 1);
1373       else
1374         set_zc (0, ((int)uma - (int)umb) >= 0);
1375       break;
1376
1377     case RXO_swhile:
1378       if (regs.r[3] == 0)
1379         break;
1380       switch (opcode.size)
1381         {
1382         case RX_Long:
1383           uma = get_reg (2);
1384           while (regs.r[3] != 0)
1385             {
1386               regs.r[3] --;
1387               umb = mem_get_si (get_reg (1));
1388               regs.r[1] += 4;
1389               if (umb != uma)
1390                 break;
1391             }
1392           break;
1393         case RX_Word:
1394           uma = get_reg (2) & 0xffff;
1395           while (regs.r[3] != 0)
1396             {
1397               regs.r[3] --;
1398               umb = mem_get_hi (get_reg (1));
1399               regs.r[1] += 2;
1400               if (umb != uma)
1401                 break;
1402             }
1403           break;
1404         case RX_Byte:
1405           uma = get_reg (2) & 0xff;
1406           while (regs.r[3] != 0)
1407             {
1408               regs.r[3] --;
1409               umb = mem_get_qi (regs.r[1]);
1410               regs.r[1] += 1;
1411               if (umb != uma)
1412                 break;
1413             }
1414           break;
1415         default:
1416           abort();
1417         }
1418       if (uma == umb)
1419         set_zc (1, 1);
1420       else
1421         set_zc (0, ((int)uma - (int)umb) >= 0);
1422       break;
1423
1424     case RXO_wait:
1425       PRIVILEDGED ();
1426       regs.r_psw |= FLAGBIT_I;
1427       return RX_MAKE_STOPPED(0);
1428
1429     case RXO_xchg:
1430       v = GS (); /* This is the memory operand, if any.  */
1431       PS (GD ()); /* and this may change the address register.  */
1432       PD (v);
1433       break;
1434
1435     case RXO_xor:
1436       LOGIC_OP (^);
1437       break;
1438
1439     default:
1440       EXCEPTION (EX_UNDEFINED);
1441     }
1442
1443   return RX_MAKE_STEPPED ();
1444 }