]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/rx/rx.c
Update copyright notices to add year 2010.
[thirdparty/binutils-gdb.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 }