arm: Support pac_key_* register operand for MRS/MSR in Armv8.1-M Mainline
[binutils-gdb.git] / sim / rx / rx.c
blob57a7d5e74f843e60f8d539d17aea96dddfcfd1b8
1 /* rx.c --- opcode semantics for stand-alone RX simulator.
3 Copyright (C) 2008-2024 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
6 This file is part of the GNU simulators.
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.
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.
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/>. */
21 /* This must come before any other includes. */
22 #include "defs.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <signal.h>
28 #include "libiberty.h"
30 #include "opcode/rx.h"
31 #include "cpu.h"
32 #include "mem.h"
33 #include "syscalls.h"
34 #include "fpu.h"
35 #include "err.h"
36 #include "misc.h"
38 #ifdef WITH_PROFILE
39 static const char * const id_names[] = {
40 "RXO_unknown",
41 "RXO_mov", /* d = s (signed) */
42 "RXO_movbi", /* d = [s,s2] (signed) */
43 "RXO_movbir", /* [s,s2] = d (signed) */
44 "RXO_pushm", /* s..s2 */
45 "RXO_popm", /* s..s2 */
46 "RXO_xchg", /* s <-> d */
47 "RXO_stcc", /* d = s if cond(s2) */
48 "RXO_rtsd", /* rtsd, 1=imm, 2-0 = reg if reg type */
50 /* These are all either d OP= s or, if s2 is set, d = s OP s2. Note
51 that d may be "None". */
52 "RXO_and",
53 "RXO_or",
54 "RXO_xor",
55 "RXO_add",
56 "RXO_sub",
57 "RXO_mul",
58 "RXO_div",
59 "RXO_divu",
60 "RXO_shll",
61 "RXO_shar",
62 "RXO_shlr",
64 "RXO_adc", /* d = d + s + carry */
65 "RXO_sbb", /* d = d - s - ~carry */
66 "RXO_abs", /* d = |s| */
67 "RXO_max", /* d = max(d,s) */
68 "RXO_min", /* d = min(d,s) */
69 "RXO_emul", /* d:64 = d:32 * s */
70 "RXO_emulu", /* d:64 = d:32 * s (unsigned) */
72 "RXO_rolc", /* d <<= 1 through carry */
73 "RXO_rorc", /* d >>= 1 through carry*/
74 "RXO_rotl", /* d <<= #s without carry */
75 "RXO_rotr", /* d >>= #s without carry*/
76 "RXO_revw", /* d = revw(s) */
77 "RXO_revl", /* d = revl(s) */
78 "RXO_branch", /* pc = d if cond(s) */
79 "RXO_branchrel",/* pc += d if cond(s) */
80 "RXO_jsr", /* pc = d */
81 "RXO_jsrrel", /* pc += d */
82 "RXO_rts",
83 "RXO_nop",
84 "RXO_nop2",
85 "RXO_nop3",
86 "RXO_nop4",
87 "RXO_nop5",
88 "RXO_nop6",
89 "RXO_nop7",
91 "RXO_scmpu",
92 "RXO_smovu",
93 "RXO_smovb",
94 "RXO_suntil",
95 "RXO_swhile",
96 "RXO_smovf",
97 "RXO_sstr",
99 "RXO_rmpa",
100 "RXO_mulhi",
101 "RXO_mullo",
102 "RXO_machi",
103 "RXO_maclo",
104 "RXO_mvtachi",
105 "RXO_mvtaclo",
106 "RXO_mvfachi",
107 "RXO_mvfacmi",
108 "RXO_mvfaclo",
109 "RXO_racw",
111 "RXO_sat", /* sat(d) */
112 "RXO_satr",
114 "RXO_fadd", /* d op= s */
115 "RXO_fcmp",
116 "RXO_fsub",
117 "RXO_ftoi",
118 "RXO_fmul",
119 "RXO_fdiv",
120 "RXO_round",
121 "RXO_itof",
123 "RXO_bset", /* d |= (1<<s) */
124 "RXO_bclr", /* d &= ~(1<<s) */
125 "RXO_btst", /* s & (1<<s2) */
126 "RXO_bnot", /* d ^= (1<<s) */
127 "RXO_bmcc", /* d<s> = cond(s2) */
129 "RXO_clrpsw", /* flag index in d */
130 "RXO_setpsw", /* flag index in d */
131 "RXO_mvtipl", /* new IPL in s */
133 "RXO_rtfi",
134 "RXO_rte",
135 "RXO_rtd", /* undocumented */
136 "RXO_brk",
137 "RXO_dbt", /* undocumented */
138 "RXO_int", /* vector id in s */
139 "RXO_stop",
140 "RXO_wait",
142 "RXO_sccnd", /* d = cond(s) ? 1 : 0 */
145 static const char * const optype_names[] = {
146 " - ",
147 "#Imm", /* #addend */
148 " Rn ", /* Rn */
149 "[Rn]", /* [Rn + addend] */
150 "Ps++", /* [Rn+] */
151 "--Pr", /* [-Rn] */
152 " cc ", /* eq, gtu, etc */
153 "Flag", /* [UIOSZC] */
154 "RbRi" /* [Rb + scale * Ri] */
157 #define N_RXO ARRAY_SIZE (id_names)
158 #define N_RXT ARRAY_SIZE (optype_names)
159 #define N_MAP 90
161 static unsigned long long benchmark_start_cycle;
162 static unsigned long long benchmark_end_cycle;
164 static int op_cache[N_RXT][N_RXT][N_RXT];
165 static int op_cache_rev[N_MAP];
166 static int op_cache_idx = 0;
168 static int
169 op_lookup (int a, int b, int c)
171 if (op_cache[a][b][c])
172 return op_cache[a][b][c];
173 op_cache_idx ++;
174 if (op_cache_idx >= N_MAP)
176 printf("op_cache_idx exceeds %d\n", N_MAP);
177 exit(1);
179 op_cache[a][b][c] = op_cache_idx;
180 op_cache_rev[op_cache_idx] = (a<<8) | (b<<4) | c;
181 return op_cache_idx;
184 static char *
185 op_cache_string (int map)
187 static int ci;
188 static char cb[5][20];
189 int a, b, c;
191 map = op_cache_rev[map];
192 a = (map >> 8) & 15;
193 b = (map >> 4) & 15;
194 c = (map >> 0) & 15;
195 ci = (ci + 1) % 5;
196 sprintf(cb[ci], "%s %s %s", optype_names[a], optype_names[b], optype_names[c]);
197 return cb[ci];
200 static unsigned long long cycles_per_id[N_RXO][N_MAP];
201 static unsigned long long times_per_id[N_RXO][N_MAP];
202 static unsigned long long memory_stalls;
203 static unsigned long long register_stalls;
204 static unsigned long long branch_stalls;
205 static unsigned long long branch_alignment_stalls;
206 static unsigned long long fast_returns;
208 static unsigned long times_per_pair[N_RXO][N_MAP][N_RXO][N_MAP];
209 static int prev_opcode_id = RXO_unknown;
210 static int po0;
212 #define STATS(x) x
214 #else
215 #define STATS(x)
216 #endif /* WITH_PROFILE */
219 #ifdef CYCLE_ACCURATE
221 static int new_rt = -1;
223 /* Number of cycles to add if an insn spans an 8-byte boundary. */
224 static int branch_alignment_penalty = 0;
226 #endif
228 static int running_benchmark = 1;
230 #define tprintf if (trace && running_benchmark) printf
232 jmp_buf decode_jmp_buf;
233 unsigned int rx_cycles = 0;
235 #ifdef CYCLE_ACCURATE
236 /* If nonzero, memory was read at some point and cycle latency might
237 take effect. */
238 static int memory_source = 0;
239 /* If nonzero, memory was written and extra cycles might be
240 needed. */
241 static int memory_dest = 0;
243 static void
244 cycles (int throughput)
246 tprintf("%d cycles\n", throughput);
247 regs.cycle_count += throughput;
250 /* Number of execution (E) cycles the op uses. For memory sources, we
251 include the load micro-op stall as two extra E cycles. */
252 #define E(c) cycles (memory_source ? c + 2 : c)
253 #define E1 cycles (1)
254 #define E2 cycles (2)
255 #define EBIT cycles (memory_source ? 2 : 1)
257 /* Check to see if a read latency must be applied for a given register. */
258 #define RL(r) \
259 if (regs.rt == r ) \
261 tprintf("register %d load stall\n", r); \
262 regs.cycle_count ++; \
263 STATS(register_stalls ++); \
264 regs.rt = -1; \
267 #define RLD(r) \
268 if (memory_source) \
270 tprintf ("Rt now %d\n", r); \
271 new_rt = r; \
274 static int
275 lsb_count (unsigned long v, int is_signed)
277 int i, lsb;
278 if (is_signed && (v & 0x80000000U))
279 v = (unsigned long)(long)(-v);
280 for (i=31; i>=0; i--)
281 if (v & (1 << i))
283 /* v is 0..31, we want 1=1-2, 2=3-4, 3=5-6, etc. */
284 lsb = (i + 2) / 2;
285 return lsb;
287 return 0;
290 static int
291 divu_cycles(unsigned long num, unsigned long den)
293 int nb = lsb_count (num, 0);
294 int db = lsb_count (den, 0);
295 int rv;
297 if (nb < db)
298 rv = 2;
299 else
300 rv = 3 + nb - db;
301 E (rv);
302 return rv;
305 static int
306 div_cycles(long num, long den)
308 int nb = lsb_count ((unsigned long)num, 1);
309 int db = lsb_count ((unsigned long)den, 1);
310 int rv;
312 if (nb < db)
313 rv = 3;
314 else
315 rv = 5 + nb - db;
316 E (rv);
317 return rv;
320 #else /* !CYCLE_ACCURATE */
322 #define cycles(t)
323 #define E(c)
324 #define E1
325 #define E2
326 #define EBIT
327 #define RL(r)
328 #define RLD(r)
330 #define divu_cycles(n,d)
331 #define div_cycles(n,d)
333 #endif /* else CYCLE_ACCURATE */
335 static const int size2bytes[] = {
336 4, 1, 1, 1, 2, 2, 2, 3, 4
339 typedef struct {
340 unsigned long dpc;
341 } RX_Data;
343 #define rx_abort() _rx_abort(__FILE__, __LINE__)
344 static void ATTRIBUTE_NORETURN
345 _rx_abort (const char *file, int line)
347 if (strrchr (file, '/'))
348 file = strrchr (file, '/') + 1;
349 fprintf(stderr, "abort at %s:%d\n", file, line);
350 abort();
353 static unsigned char *get_byte_base;
354 static RX_Opcode_Decoded **decode_cache_base;
355 static SI get_byte_page;
357 void
358 reset_decoder (void)
360 get_byte_base = 0;
361 decode_cache_base = 0;
362 get_byte_page = 0;
365 static inline void
366 maybe_get_mem_page (SI tpc)
368 if (((tpc ^ get_byte_page) & NONPAGE_MASK) || enable_counting)
370 get_byte_page = tpc & NONPAGE_MASK;
371 get_byte_base = rx_mem_ptr (get_byte_page, MPA_READING) - get_byte_page;
372 decode_cache_base = rx_mem_decode_cache (get_byte_page) - get_byte_page;
376 /* This gets called a *lot* so optimize it. */
377 static int
378 rx_get_byte (void *vdata)
380 RX_Data *rx_data = (RX_Data *)vdata;
381 SI tpc = rx_data->dpc;
383 /* See load.c for an explanation of this. */
384 if (rx_big_endian)
385 tpc ^= 3;
387 maybe_get_mem_page (tpc);
389 rx_data->dpc ++;
390 return get_byte_base [tpc];
393 static int
394 get_op (const RX_Opcode_Decoded *rd, int i)
396 const RX_Opcode_Operand *o = rd->op + i;
397 int addr, rv = 0;
399 switch (o->type)
401 case RX_Operand_None:
402 rx_abort ();
404 case RX_Operand_Immediate: /* #addend */
405 return o->addend;
407 case RX_Operand_Register: /* Rn */
408 RL (o->reg);
409 rv = get_reg (o->reg);
410 break;
412 case RX_Operand_Predec: /* [-Rn] */
413 put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
414 ATTRIBUTE_FALLTHROUGH;
415 case RX_Operand_Postinc: /* [Rn+] */
416 case RX_Operand_Zero_Indirect: /* [Rn + 0] */
417 case RX_Operand_Indirect: /* [Rn + addend] */
418 case RX_Operand_TwoReg: /* [Rn + scale * R2] */
419 #ifdef CYCLE_ACCURATE
420 RL (o->reg);
421 if (o->type == RX_Operand_TwoReg)
422 RL (rd->op[2].reg);
423 regs.rt = -1;
424 if (regs.m2m == M2M_BOTH)
426 tprintf("src memory stall\n");
427 #ifdef WITH_PROFILE
428 memory_stalls ++;
429 #endif
430 regs.cycle_count ++;
431 regs.m2m = 0;
434 memory_source = 1;
435 #endif
437 if (o->type == RX_Operand_TwoReg)
438 addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
439 else
440 addr = get_reg (o->reg) + o->addend;
442 switch (o->size)
444 default:
445 case RX_AnySize:
446 rx_abort ();
448 case RX_Byte: /* undefined extension */
449 case RX_UByte:
450 case RX_SByte:
451 rv = mem_get_qi (addr);
452 break;
454 case RX_Word: /* undefined extension */
455 case RX_UWord:
456 case RX_SWord:
457 rv = mem_get_hi (addr);
458 break;
460 case RX_3Byte:
461 rv = mem_get_psi (addr);
462 break;
464 case RX_Long:
465 rv = mem_get_si (addr);
466 break;
469 if (o->type == RX_Operand_Postinc)
470 put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
472 break;
474 case RX_Operand_Condition: /* eq, gtu, etc */
475 return condition_true (o->reg);
477 case RX_Operand_Flag: /* [UIOSZC] */
478 return (regs.r_psw & (1 << o->reg)) ? 1 : 0;
481 /* if we've gotten here, we need to clip/extend the value according
482 to the size. */
483 switch (o->size)
485 default:
486 case RX_AnySize:
487 rx_abort ();
489 case RX_Byte: /* undefined extension */
490 rv |= 0xdeadbe00; /* keep them honest */
491 break;
493 case RX_UByte:
494 rv &= 0xff;
495 break;
497 case RX_SByte:
498 rv = sign_ext (rv, 8);
499 break;
501 case RX_Word: /* undefined extension */
502 rv |= 0xdead0000; /* keep them honest */
503 break;
505 case RX_UWord:
506 rv &= 0xffff;
507 break;
509 case RX_SWord:
510 rv = sign_ext (rv, 16);
511 break;
513 case RX_3Byte:
514 rv &= 0xffffff;
515 break;
517 case RX_Long:
518 break;
520 return rv;
523 static void
524 put_op (const RX_Opcode_Decoded *rd, int i, int v)
526 const RX_Opcode_Operand *o = rd->op + i;
527 int addr;
529 switch (o->size)
531 default:
532 case RX_AnySize:
533 if (o->type != RX_Operand_Register)
534 rx_abort ();
535 break;
537 case RX_Byte: /* undefined extension */
538 v |= 0xdeadbe00; /* keep them honest */
539 break;
541 case RX_UByte:
542 v &= 0xff;
543 break;
545 case RX_SByte:
546 v = sign_ext (v, 8);
547 break;
549 case RX_Word: /* undefined extension */
550 v |= 0xdead0000; /* keep them honest */
551 break;
553 case RX_UWord:
554 v &= 0xffff;
555 break;
557 case RX_SWord:
558 v = sign_ext (v, 16);
559 break;
561 case RX_3Byte:
562 v &= 0xffffff;
563 break;
565 case RX_Long:
566 break;
569 switch (o->type)
571 case RX_Operand_None:
572 /* Opcodes like TST and CMP use this. */
573 break;
575 case RX_Operand_Immediate: /* #addend */
576 case RX_Operand_Condition: /* eq, gtu, etc */
577 rx_abort ();
579 case RX_Operand_Register: /* Rn */
580 put_reg (o->reg, v);
581 RLD (o->reg);
582 break;
584 case RX_Operand_Predec: /* [-Rn] */
585 put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
586 ATTRIBUTE_FALLTHROUGH;
587 case RX_Operand_Postinc: /* [Rn+] */
588 case RX_Operand_Zero_Indirect: /* [Rn + 0] */
589 case RX_Operand_Indirect: /* [Rn + addend] */
590 case RX_Operand_TwoReg: /* [Rn + scale * R2] */
592 #ifdef CYCLE_ACCURATE
593 if (regs.m2m == M2M_BOTH)
595 tprintf("dst memory stall\n");
596 regs.cycle_count ++;
597 #ifdef WITH_PROFILE
598 memory_stalls ++;
599 #endif
600 regs.m2m = 0;
602 memory_dest = 1;
603 #endif
605 if (o->type == RX_Operand_TwoReg)
606 addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
607 else
608 addr = get_reg (o->reg) + o->addend;
610 switch (o->size)
612 default:
613 case RX_AnySize:
614 rx_abort ();
616 case RX_Byte: /* undefined extension */
617 case RX_UByte:
618 case RX_SByte:
619 mem_put_qi (addr, v);
620 break;
622 case RX_Word: /* undefined extension */
623 case RX_UWord:
624 case RX_SWord:
625 mem_put_hi (addr, v);
626 break;
628 case RX_3Byte:
629 mem_put_psi (addr, v);
630 break;
632 case RX_Long:
633 mem_put_si (addr, v);
634 break;
637 if (o->type == RX_Operand_Postinc)
638 put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
640 break;
642 case RX_Operand_Flag: /* [UIOSZC] */
643 if (v)
644 regs.r_psw |= (1 << o->reg);
645 else
646 regs.r_psw &= ~(1 << o->reg);
647 break;
651 #define PD(x) put_op (opcode, 0, x)
652 #define PS(x) put_op (opcode, 1, x)
653 #define PS2(x) put_op (opcode, 2, x)
654 #define GD() get_op (opcode, 0)
655 #define GS() get_op (opcode, 1)
656 #define GS2() get_op (opcode, 2)
657 #define DSZ() size2bytes[opcode->op[0].size]
658 #define SSZ() size2bytes[opcode->op[0].size]
659 #define S2SZ() size2bytes[opcode->op[0].size]
661 /* "Universal" sources. */
662 #define US1() ((opcode->op[2].type == RX_Operand_None) ? GD() : GS())
663 #define US2() ((opcode->op[2].type == RX_Operand_None) ? GS() : GS2())
665 static void
666 push(int val)
668 int rsp = get_reg (sp);
669 rsp -= 4;
670 put_reg (sp, rsp);
671 mem_put_si (rsp, val);
674 /* Just like the above, but tag the memory as "pushed pc" so if anyone
675 tries to write to it, it will cause an error. */
676 static void
677 pushpc(int val)
679 int rsp = get_reg (sp);
680 rsp -= 4;
681 put_reg (sp, rsp);
682 mem_put_si (rsp, val);
683 mem_set_content_range (rsp, rsp+3, MC_PUSHED_PC);
686 static int
687 pop (void)
689 int rv;
690 int rsp = get_reg (sp);
691 rv = mem_get_si (rsp);
692 rsp += 4;
693 put_reg (sp, rsp);
694 return rv;
697 static int
698 poppc (void)
700 int rv;
701 int rsp = get_reg (sp);
702 if (mem_get_content_type (rsp) != MC_PUSHED_PC)
703 execution_error (SIM_ERR_CORRUPT_STACK, rsp);
704 rv = mem_get_si (rsp);
705 mem_set_content_range (rsp, rsp+3, MC_UNINIT);
706 rsp += 4;
707 put_reg (sp, rsp);
708 return rv;
711 #define MATH_OP(vop,c) \
713 umb = US2(); \
714 uma = US1(); \
715 ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
716 tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
717 ma = sign_ext (uma, DSZ() * 8); \
718 mb = sign_ext (umb, DSZ() * 8); \
719 sll = (long long) ma vop (long long) mb vop c; \
720 tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
721 set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
722 PD (sll); \
723 E (1); \
726 #define LOGIC_OP(vop) \
728 mb = US2(); \
729 ma = US1(); \
730 v = ma vop mb; \
731 tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
732 set_sz (v, DSZ()); \
733 PD(v); \
734 E (1); \
737 #define SHIFT_OP(val, type, count, OP, carry_mask) \
739 int i, c=0; \
740 count = US2(); \
741 val = (type)US1(); \
742 tprintf("%lld " #OP " %d\n", val, count); \
743 for (i = 0; i < count; i ++) \
745 c = val & carry_mask; \
746 val OP 1; \
748 set_oszc (val, 4, c); \
749 PD (val); \
752 typedef union {
753 int i;
754 float f;
755 } FloatInt;
757 ATTRIBUTE_UNUSED
758 static inline int
759 float2int (float f)
761 FloatInt fi;
762 fi.f = f;
763 return fi.i;
766 static inline float
767 int2float (int i)
769 FloatInt fi;
770 fi.i = i;
771 return fi.f;
774 static int
775 fop_fadd (fp_t s1, fp_t s2, fp_t *d)
777 *d = rxfp_add (s1, s2);
778 return 1;
781 static int
782 fop_fmul (fp_t s1, fp_t s2, fp_t *d)
784 *d = rxfp_mul (s1, s2);
785 return 1;
788 static int
789 fop_fdiv (fp_t s1, fp_t s2, fp_t *d)
791 *d = rxfp_div (s1, s2);
792 return 1;
795 static int
796 fop_fsub (fp_t s1, fp_t s2, fp_t *d)
798 *d = rxfp_sub (s1, s2);
799 return 1;
802 #define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
803 #define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
804 #define FPCHECK() \
805 if (FPPENDING()) \
806 return do_fp_exception (opcode_pc)
808 #define FLOAT_OP(func) \
810 int do_store; \
811 fp_t fa, fb, fc; \
812 FPCLEAR(); \
813 fb = GS (); \
814 fa = GD (); \
815 do_store = fop_##func (fa, fb, &fc); \
816 tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
817 FPCHECK(); \
818 if (do_store) \
819 PD (fc); \
820 mb = 0; \
821 if ((fc & 0x80000000UL) != 0) \
822 mb |= FLAGBIT_S; \
823 if ((fc & 0x7fffffffUL) == 0) \
824 mb |= FLAGBIT_Z; \
825 set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
828 #define carry (FLAG_C ? 1 : 0)
830 static struct {
831 unsigned long vaddr;
832 const char *str;
833 int signal;
834 } exception_info[] = {
835 { 0xFFFFFFD0UL, "priviledged opcode", SIGILL },
836 { 0xFFFFFFD4UL, "access violation", SIGSEGV },
837 { 0xFFFFFFDCUL, "undefined opcode", SIGILL },
838 { 0xFFFFFFE4UL, "floating point", SIGFPE }
840 #define EX_PRIVILEDGED 0
841 #define EX_ACCESS 1
842 #define EX_UNDEFINED 2
843 #define EX_FLOATING 3
844 #define EXCEPTION(n) \
845 return generate_exception (n, opcode_pc)
847 #define PRIVILEDGED() \
848 if (FLAG_PM) \
849 EXCEPTION (EX_PRIVILEDGED)
851 static int
852 generate_exception (unsigned long type, SI opcode_pc)
854 SI old_psw, old_pc, new_pc;
856 new_pc = mem_get_si (exception_info[type].vaddr);
857 /* 0x00020000 is the value used to initialise the known
858 exception vectors (see rx.ld), but it is a reserved
859 area of memory so do not try to access it, and if the
860 value has not been changed by the program then the
861 vector has not been installed. */
862 if (new_pc == 0 || new_pc == 0x00020000)
864 if (rx_in_gdb)
865 return RX_MAKE_STOPPED (exception_info[type].signal);
867 fprintf(stderr, "Unhandled %s exception at pc = %#lx\n",
868 exception_info[type].str, (unsigned long) opcode_pc);
869 if (type == EX_FLOATING)
871 int mask = FPPENDING ();
872 fprintf (stderr, "Pending FP exceptions:");
873 if (mask & FPSWBITS_FV)
874 fprintf(stderr, " Invalid");
875 if (mask & FPSWBITS_FO)
876 fprintf(stderr, " Overflow");
877 if (mask & FPSWBITS_FZ)
878 fprintf(stderr, " Division-by-zero");
879 if (mask & FPSWBITS_FU)
880 fprintf(stderr, " Underflow");
881 if (mask & FPSWBITS_FX)
882 fprintf(stderr, " Inexact");
883 if (mask & FPSWBITS_CE)
884 fprintf(stderr, " Unimplemented");
885 fprintf(stderr, "\n");
887 return RX_MAKE_EXITED (1);
890 tprintf ("Triggering %s exception\n", exception_info[type].str);
892 old_psw = regs.r_psw;
893 regs.r_psw &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
894 old_pc = opcode_pc;
895 regs.r_pc = new_pc;
896 pushpc (old_psw);
897 pushpc (old_pc);
898 return RX_MAKE_STEPPED ();
901 void
902 generate_access_exception (void)
904 int rv;
906 rv = generate_exception (EX_ACCESS, regs.r_pc);
907 if (RX_EXITED (rv))
908 longjmp (decode_jmp_buf, rv);
911 static int
912 do_fp_exception (unsigned long opcode_pc)
914 while (FPPENDING())
915 EXCEPTION (EX_FLOATING);
916 return RX_MAKE_STEPPED ();
919 static int
920 op_is_memory (const RX_Opcode_Decoded *rd, int i)
922 switch (rd->op[i].type)
924 case RX_Operand_Predec:
925 case RX_Operand_Postinc:
926 case RX_Operand_Indirect:
927 return 1;
928 default:
929 return 0;
932 #define OM(i) op_is_memory (opcode, i)
934 #define DO_RETURN(x) { longjmp (decode_jmp_buf, x); }
937 decode_opcode (void)
939 unsigned int uma=0, umb=0;
940 int ma=0, mb=0;
941 int opcode_size, v;
942 unsigned long long ll;
943 long long sll;
944 unsigned long opcode_pc;
945 RX_Data rx_data;
946 const RX_Opcode_Decoded *opcode;
947 #ifdef WITH_PROFILE
948 unsigned long long prev_cycle_count;
949 #endif
950 #ifdef CYCLE_ACCURATE
951 unsigned int tx;
952 #endif
954 #ifdef WITH_PROFILE
955 prev_cycle_count = regs.cycle_count;
956 #endif
958 #ifdef CYCLE_ACCURATE
959 memory_source = 0;
960 memory_dest = 0;
961 #endif
963 rx_cycles ++;
965 maybe_get_mem_page (regs.r_pc);
967 opcode_pc = regs.r_pc;
969 /* Note that we don't word-swap this point, there's no point. */
970 if (decode_cache_base[opcode_pc] == NULL)
972 RX_Opcode_Decoded *opcode_w;
973 rx_data.dpc = opcode_pc;
974 opcode_w = decode_cache_base[opcode_pc] = calloc (1, sizeof (RX_Opcode_Decoded));
975 opcode_size = rx_decode_opcode (opcode_pc, opcode_w,
976 rx_get_byte, &rx_data);
977 opcode = opcode_w;
979 else
981 opcode = decode_cache_base[opcode_pc];
982 opcode_size = opcode->n_bytes;
985 #ifdef CYCLE_ACCURATE
986 if (branch_alignment_penalty)
988 if ((regs.r_pc ^ (regs.r_pc + opcode_size - 1)) & ~7)
990 tprintf("1 cycle branch alignment penalty\n");
991 cycles (branch_alignment_penalty);
992 #ifdef WITH_PROFILE
993 branch_alignment_stalls ++;
994 #endif
996 branch_alignment_penalty = 0;
998 #endif
1000 regs.r_pc += opcode_size;
1002 rx_flagmask = opcode->flags_s;
1003 rx_flagand = ~(int)opcode->flags_0;
1004 rx_flagor = opcode->flags_1;
1006 switch (opcode->id)
1008 case RXO_abs:
1009 sll = GS ();
1010 tprintf("|%lld| = ", sll);
1011 if (sll < 0)
1012 sll = -sll;
1013 tprintf("%lld\n", sll);
1014 PD (sll);
1015 set_osz (sll, 4);
1016 E (1);
1017 break;
1019 case RXO_adc:
1020 MATH_OP (+,carry);
1021 break;
1023 case RXO_add:
1024 MATH_OP (+,0);
1025 break;
1027 case RXO_and:
1028 LOGIC_OP (&);
1029 break;
1031 case RXO_bclr:
1032 ma = GD ();
1033 mb = GS ();
1034 if (opcode->op[0].type == RX_Operand_Register)
1035 mb &= 0x1f;
1036 else
1037 mb &= 0x07;
1038 ma &= ~(1 << mb);
1039 PD (ma);
1040 EBIT;
1041 break;
1043 case RXO_bmcc:
1044 ma = GD ();
1045 mb = GS ();
1046 if (opcode->op[0].type == RX_Operand_Register)
1047 mb &= 0x1f;
1048 else
1049 mb &= 0x07;
1050 if (GS2 ())
1051 ma |= (1 << mb);
1052 else
1053 ma &= ~(1 << mb);
1054 PD (ma);
1055 EBIT;
1056 break;
1058 case RXO_bnot:
1059 ma = GD ();
1060 mb = GS ();
1061 if (opcode->op[0].type == RX_Operand_Register)
1062 mb &= 0x1f;
1063 else
1064 mb &= 0x07;
1065 ma ^= (1 << mb);
1066 PD (ma);
1067 EBIT;
1068 break;
1070 case RXO_branch:
1071 if (opcode->op[1].type == RX_Operand_None || GS())
1073 #ifdef CYCLE_ACCURATE
1074 SI old_pc = regs.r_pc;
1075 int delta;
1076 #endif
1077 regs.r_pc = GD();
1078 #ifdef CYCLE_ACCURATE
1079 delta = regs.r_pc - old_pc;
1080 if (delta >= 0 && delta < 16
1081 && opcode_size > 1)
1083 tprintf("near forward branch bonus\n");
1084 cycles (2);
1086 else
1088 cycles (3);
1089 branch_alignment_penalty = 1;
1091 #ifdef WITH_PROFILE
1092 branch_stalls ++;
1093 #endif
1094 #endif
1096 #ifdef CYCLE_ACCURATE
1097 else
1098 cycles (1);
1099 #endif
1100 break;
1102 case RXO_branchrel:
1103 if (opcode->op[1].type == RX_Operand_None || GS())
1105 int delta = GD();
1106 regs.r_pc = opcode_pc + delta;
1107 #ifdef CYCLE_ACCURATE
1108 /* Note: specs say 3, chip says 2. */
1109 if (delta >= 0 && delta < 16
1110 && opcode_size > 1)
1112 tprintf("near forward branch bonus\n");
1113 cycles (2);
1115 else
1117 cycles (3);
1118 branch_alignment_penalty = 1;
1120 #ifdef WITH_PROFILE
1121 branch_stalls ++;
1122 #endif
1123 #endif
1125 #ifdef CYCLE_ACCURATE
1126 else
1127 cycles (1);
1128 #endif
1129 break;
1131 case RXO_brk:
1133 int old_psw = regs.r_psw;
1134 if (rx_in_gdb)
1135 DO_RETURN (RX_MAKE_HIT_BREAK ());
1136 if (regs.r_intb == 0)
1138 tprintf("BREAK hit, no vector table.\n");
1139 DO_RETURN (RX_MAKE_EXITED(1));
1141 regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
1142 pushpc (old_psw);
1143 pushpc (regs.r_pc);
1144 regs.r_pc = mem_get_si (regs.r_intb);
1145 cycles(6);
1147 break;
1149 case RXO_bset:
1150 ma = GD ();
1151 mb = GS ();
1152 if (opcode->op[0].type == RX_Operand_Register)
1153 mb &= 0x1f;
1154 else
1155 mb &= 0x07;
1156 ma |= (1 << mb);
1157 PD (ma);
1158 EBIT;
1159 break;
1161 case RXO_btst:
1162 ma = GS ();
1163 mb = GS2 ();
1164 if (opcode->op[1].type == RX_Operand_Register)
1165 mb &= 0x1f;
1166 else
1167 mb &= 0x07;
1168 umb = ma & (1 << mb);
1169 set_zc (! umb, umb);
1170 EBIT;
1171 break;
1173 case RXO_clrpsw:
1174 v = 1 << opcode->op[0].reg;
1175 if (FLAG_PM
1176 && (v == FLAGBIT_I
1177 || v == FLAGBIT_U))
1178 break;
1179 regs.r_psw &= ~v;
1180 cycles (1);
1181 break;
1183 case RXO_div: /* d = d / s */
1184 ma = GS();
1185 mb = GD();
1186 tprintf("%d / %d = ", mb, ma);
1187 if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
1189 tprintf("#NAN\n");
1190 set_flags (FLAGBIT_O, FLAGBIT_O);
1191 cycles (3);
1193 else
1195 v = mb/ma;
1196 tprintf("%d\n", v);
1197 set_flags (FLAGBIT_O, 0);
1198 PD (v);
1199 div_cycles (mb, ma);
1201 break;
1203 case RXO_divu: /* d = d / s */
1204 uma = GS();
1205 umb = GD();
1206 tprintf("%u / %u = ", umb, uma);
1207 if (uma == 0)
1209 tprintf("#NAN\n");
1210 set_flags (FLAGBIT_O, FLAGBIT_O);
1211 cycles (2);
1213 else
1215 v = umb / uma;
1216 tprintf("%u\n", v);
1217 set_flags (FLAGBIT_O, 0);
1218 PD (v);
1219 divu_cycles (umb, uma);
1221 break;
1223 case RXO_emul:
1224 ma = GD ();
1225 mb = GS ();
1226 sll = (long long)ma * (long long)mb;
1227 tprintf("%d * %d = %lld\n", ma, mb, sll);
1228 put_reg (opcode->op[0].reg, sll);
1229 put_reg (opcode->op[0].reg + 1, sll >> 32);
1231 break;
1233 case RXO_emulu:
1234 uma = GD ();
1235 umb = GS ();
1236 ll = (long long)uma * (long long)umb;
1237 tprintf("%#x * %#x = %#llx\n", uma, umb, ll);
1238 put_reg (opcode->op[0].reg, ll);
1239 put_reg (opcode->op[0].reg + 1, ll >> 32);
1241 break;
1243 case RXO_fadd:
1244 FLOAT_OP (fadd);
1245 E (4);
1246 break;
1248 case RXO_fcmp:
1249 ma = GD();
1250 mb = GS();
1251 FPCLEAR ();
1252 rxfp_cmp (ma, mb);
1253 FPCHECK ();
1254 E (1);
1255 break;
1257 case RXO_fdiv:
1258 FLOAT_OP (fdiv);
1259 E (16);
1260 break;
1262 case RXO_fmul:
1263 FLOAT_OP (fmul);
1264 E (3);
1265 break;
1267 case RXO_rtfi:
1268 PRIVILEDGED ();
1269 regs.r_psw = regs.r_bpsw;
1270 regs.r_pc = regs.r_bpc;
1271 #ifdef CYCLE_ACCURATE
1272 regs.fast_return = 0;
1273 cycles(3);
1274 #endif
1275 break;
1277 case RXO_fsub:
1278 FLOAT_OP (fsub);
1279 E (4);
1280 break;
1282 case RXO_ftoi:
1283 ma = GS ();
1284 FPCLEAR ();
1285 mb = rxfp_ftoi (ma, FPRM_ZERO);
1286 FPCHECK ();
1287 PD (mb);
1288 tprintf("(int) %g = %d\n", int2float(ma), mb);
1289 set_sz (mb, 4);
1290 E (2);
1291 break;
1293 case RXO_int:
1294 v = GS ();
1295 if (v == 255)
1297 int rc = rx_syscall (regs.r[5]);
1298 if (! RX_STEPPED (rc))
1299 DO_RETURN (rc);
1301 else
1303 int old_psw = regs.r_psw;
1304 regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
1305 pushpc (old_psw);
1306 pushpc (regs.r_pc);
1307 regs.r_pc = mem_get_si (regs.r_intb + 4 * v);
1309 cycles (6);
1310 break;
1312 case RXO_itof:
1313 ma = GS ();
1314 FPCLEAR ();
1315 mb = rxfp_itof (ma, regs.r_fpsw);
1316 FPCHECK ();
1317 tprintf("(float) %d = %x\n", ma, mb);
1318 PD (mb);
1319 set_sz (ma, 4);
1320 E (2);
1321 break;
1323 case RXO_jsr:
1324 case RXO_jsrrel:
1326 #ifdef CYCLE_ACCURATE
1327 int delta;
1328 regs.m2m = 0;
1329 #endif
1330 v = GD ();
1331 #ifdef CYCLE_ACCURATE
1332 regs.link_register = regs.r_pc;
1333 #endif
1334 pushpc (get_reg (pc));
1335 if (opcode->id == RXO_jsrrel)
1336 v += regs.r_pc;
1337 #ifdef CYCLE_ACCURATE
1338 delta = v - regs.r_pc;
1339 #endif
1340 put_reg (pc, v);
1341 #ifdef CYCLE_ACCURATE
1342 /* Note: docs say 3, chip says 2 */
1343 if (delta >= 0 && delta < 16)
1345 tprintf ("near forward jsr bonus\n");
1346 cycles (2);
1348 else
1350 branch_alignment_penalty = 1;
1351 cycles (3);
1353 regs.fast_return = 1;
1354 #endif
1356 break;
1358 case RXO_machi:
1359 ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
1360 ll <<= 16;
1361 put_reg64 (acc64, ll + regs.r_acc);
1363 break;
1365 case RXO_maclo:
1366 ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
1367 ll <<= 16;
1368 put_reg64 (acc64, ll + regs.r_acc);
1370 break;
1372 case RXO_max:
1373 mb = GS();
1374 ma = GD();
1375 if (ma > mb)
1376 PD (ma);
1377 else
1378 PD (mb);
1379 E (1);
1380 break;
1382 case RXO_min:
1383 mb = GS();
1384 ma = GD();
1385 if (ma < mb)
1386 PD (ma);
1387 else
1388 PD (mb);
1389 E (1);
1390 break;
1392 case RXO_mov:
1393 v = GS ();
1395 if (opcode->op[1].type == RX_Operand_Register
1396 && opcode->op[1].reg == 17 /* PC */)
1398 /* Special case. We want the address of the insn, not the
1399 address of the next insn. */
1400 v = opcode_pc;
1403 if (opcode->op[0].type == RX_Operand_Register
1404 && opcode->op[0].reg == 16 /* PSW */)
1406 /* Special case, LDC and POPC can't ever modify PM. */
1407 int pm = regs.r_psw & FLAGBIT_PM;
1408 v &= ~ FLAGBIT_PM;
1409 v |= pm;
1410 if (pm)
1412 v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1413 v |= pm;
1416 if (FLAG_PM)
1418 /* various things can't be changed in user mode. */
1419 if (opcode->op[0].type == RX_Operand_Register)
1420 if (opcode->op[0].reg == 32)
1422 v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1423 v |= regs.r_psw & (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1425 if (opcode->op[0].reg == 34 /* ISP */
1426 || opcode->op[0].reg == 37 /* BPSW */
1427 || opcode->op[0].reg == 39 /* INTB */
1428 || opcode->op[0].reg == 38 /* VCT */)
1429 /* These are ignored. */
1430 break;
1432 if (OM(0) && OM(1))
1433 cycles (2);
1434 else
1435 cycles (1);
1437 PD (v);
1439 #ifdef CYCLE_ACCURATE
1440 if ((opcode->op[0].type == RX_Operand_Predec
1441 && opcode->op[1].type == RX_Operand_Register)
1442 || (opcode->op[0].type == RX_Operand_Postinc
1443 && opcode->op[1].type == RX_Operand_Register))
1445 /* Special case: push reg doesn't cause a memory stall. */
1446 memory_dest = 0;
1447 tprintf("push special case\n");
1449 #endif
1451 set_sz (v, DSZ());
1452 break;
1454 case RXO_movbi:
1455 PD (GS ());
1456 cycles (1);
1457 break;
1459 case RXO_movbir:
1460 PS (GD ());
1461 cycles (1);
1462 break;
1464 case RXO_mul:
1465 v = US2 ();
1466 ll = (unsigned long long) US1() * (unsigned long long) v;
1467 PD(ll);
1468 E (1);
1469 break;
1471 case RXO_mulhi:
1472 v = GS2 ();
1473 ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v >> 16);
1474 ll <<= 16;
1475 put_reg64 (acc64, ll);
1477 break;
1479 case RXO_mullo:
1480 v = GS2 ();
1481 ll = (long long)(signed short)(GS()) * (long long)(signed short)(v);
1482 ll <<= 16;
1483 put_reg64 (acc64, ll);
1485 break;
1487 case RXO_mvfachi:
1488 PD (get_reg (acchi));
1490 break;
1492 case RXO_mvfaclo:
1493 PD (get_reg (acclo));
1495 break;
1497 case RXO_mvfacmi:
1498 PD (get_reg (accmi));
1500 break;
1502 case RXO_mvtachi:
1503 put_reg (acchi, GS ());
1505 break;
1507 case RXO_mvtaclo:
1508 put_reg (acclo, GS ());
1510 break;
1512 case RXO_mvtipl:
1513 regs.r_psw &= ~ FLAGBITS_IPL;
1514 regs.r_psw |= (GS () << FLAGSHIFT_IPL) & FLAGBITS_IPL;
1516 break;
1518 case RXO_nop:
1519 case RXO_nop2:
1520 case RXO_nop3:
1521 case RXO_nop4:
1522 case RXO_nop5:
1523 case RXO_nop6:
1524 case RXO_nop7:
1526 break;
1528 case RXO_or:
1529 LOGIC_OP (|);
1530 break;
1532 case RXO_popm:
1533 /* POPM cannot pop R0 (sp). */
1534 if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
1535 EXCEPTION (EX_UNDEFINED);
1536 if (opcode->op[1].reg >= opcode->op[2].reg)
1538 regs.r_pc = opcode_pc;
1539 DO_RETURN (RX_MAKE_STOPPED (SIGILL));
1541 for (v = opcode->op[1].reg; v <= opcode->op[2].reg; v++)
1543 cycles (1);
1544 RLD (v);
1545 put_reg (v, pop ());
1547 break;
1549 case RXO_pushm:
1550 /* PUSHM cannot push R0 (sp). */
1551 if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
1552 EXCEPTION (EX_UNDEFINED);
1553 if (opcode->op[1].reg >= opcode->op[2].reg)
1555 regs.r_pc = opcode_pc;
1556 return RX_MAKE_STOPPED (SIGILL);
1558 for (v = opcode->op[2].reg; v >= opcode->op[1].reg; v--)
1560 RL (v);
1561 push (get_reg (v));
1563 cycles (opcode->op[2].reg - opcode->op[1].reg + 1);
1564 break;
1566 case RXO_racw:
1567 ll = get_reg64 (acc64) << GS ();
1568 ll += 0x80000000ULL;
1569 if ((signed long long)ll > (signed long long)0x00007fff00000000ULL)
1570 ll = 0x00007fff00000000ULL;
1571 else if ((signed long long)ll < (signed long long)0xffff800000000000ULL)
1572 ll = 0xffff800000000000ULL;
1573 else
1574 ll &= 0xffffffff00000000ULL;
1575 put_reg64 (acc64, ll);
1577 break;
1579 case RXO_rte:
1580 PRIVILEDGED ();
1581 regs.r_pc = poppc ();
1582 regs.r_psw = poppc ();
1583 if (FLAG_PM)
1584 regs.r_psw |= FLAGBIT_U;
1585 #ifdef CYCLE_ACCURATE
1586 regs.fast_return = 0;
1587 cycles (6);
1588 #endif
1589 break;
1591 case RXO_revl:
1592 uma = GS ();
1593 umb = (((uma >> 24) & 0xff)
1594 | ((uma >> 8) & 0xff00)
1595 | ((uma << 8) & 0xff0000)
1596 | ((uma << 24) & 0xff000000UL));
1597 PD (umb);
1599 break;
1601 case RXO_revw:
1602 uma = GS ();
1603 umb = (((uma >> 8) & 0x00ff00ff)
1604 | ((uma << 8) & 0xff00ff00UL));
1605 PD (umb);
1607 break;
1609 case RXO_rmpa:
1610 RL(4);
1611 RL(5);
1612 #ifdef CYCLE_ACCURATE
1613 tx = regs.r[3];
1614 #endif
1616 while (regs.r[3] != 0)
1618 long long tmp;
1620 switch (opcode->size)
1622 case RX_Long:
1623 ma = mem_get_si (regs.r[1]);
1624 mb = mem_get_si (regs.r[2]);
1625 regs.r[1] += 4;
1626 regs.r[2] += 4;
1627 break;
1628 case RX_Word:
1629 ma = sign_ext (mem_get_hi (regs.r[1]), 16);
1630 mb = sign_ext (mem_get_hi (regs.r[2]), 16);
1631 regs.r[1] += 2;
1632 regs.r[2] += 2;
1633 break;
1634 case RX_Byte:
1635 ma = sign_ext (mem_get_qi (regs.r[1]), 8);
1636 mb = sign_ext (mem_get_qi (regs.r[2]), 8);
1637 regs.r[1] += 1;
1638 regs.r[2] += 1;
1639 break;
1640 default:
1641 abort ();
1643 /* We do the multiply as a signed value. */
1644 sll = (long long)ma * (long long)mb;
1645 tprintf(" %016llx = %d * %d\n", sll, ma, mb);
1646 /* but we do the sum as unsigned, while sign extending the operands. */
1647 tmp = regs.r[4] + (sll & 0xffffffffUL);
1648 regs.r[4] = tmp & 0xffffffffUL;
1649 tmp >>= 32;
1650 sll >>= 32;
1651 tmp += regs.r[5] + (sll & 0xffffffffUL);
1652 regs.r[5] = tmp & 0xffffffffUL;
1653 tmp >>= 32;
1654 sll >>= 32;
1655 tmp += regs.r[6] + (sll & 0xffffffffUL);
1656 regs.r[6] = tmp & 0xffffffffUL;
1657 tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
1658 (unsigned long) regs.r[6],
1659 (unsigned long) regs.r[5],
1660 (unsigned long) regs.r[4]);
1662 regs.r[3] --;
1664 if (regs.r[6] & 0x00008000)
1665 regs.r[6] |= 0xffff0000UL;
1666 else
1667 regs.r[6] &= 0x0000ffff;
1668 ma = (regs.r[6] & 0x80000000UL) ? FLAGBIT_S : 0;
1669 if (regs.r[6] != 0 && regs.r[6] != 0xffffffffUL)
1670 set_flags (FLAGBIT_O|FLAGBIT_S, ma | FLAGBIT_O);
1671 else
1672 set_flags (FLAGBIT_O|FLAGBIT_S, ma);
1673 #ifdef CYCLE_ACCURATE
1674 switch (opcode->size)
1676 case RX_Long:
1677 cycles (6 + 4 * tx);
1678 break;
1679 case RX_Word:
1680 cycles (6 + 5 * (tx / 2) + 4 * (tx % 2));
1681 break;
1682 case RX_Byte:
1683 cycles (6 + 7 * (tx / 4) + 4 * (tx % 4));
1684 break;
1685 default:
1686 abort ();
1688 #endif
1689 break;
1691 case RXO_rolc:
1692 v = GD ();
1693 ma = v & 0x80000000UL;
1694 v <<= 1;
1695 v |= carry;
1696 set_szc (v, 4, ma);
1697 PD (v);
1699 break;
1701 case RXO_rorc:
1702 uma = GD ();
1703 mb = uma & 1;
1704 uma >>= 1;
1705 uma |= (carry ? 0x80000000UL : 0);
1706 set_szc (uma, 4, mb);
1707 PD (uma);
1709 break;
1711 case RXO_rotl:
1712 mb = GS ();
1713 uma = GD ();
1714 if (mb)
1716 uma = (uma << mb) | (uma >> (32-mb));
1717 mb = uma & 1;
1719 set_szc (uma, 4, mb);
1720 PD (uma);
1722 break;
1724 case RXO_rotr:
1725 mb = GS ();
1726 uma = GD ();
1727 if (mb)
1729 uma = (uma >> mb) | (uma << (32-mb));
1730 mb = uma & 0x80000000;
1732 set_szc (uma, 4, mb);
1733 PD (uma);
1735 break;
1737 case RXO_round:
1738 ma = GS ();
1739 FPCLEAR ();
1740 mb = rxfp_ftoi (ma, regs.r_fpsw);
1741 FPCHECK ();
1742 PD (mb);
1743 tprintf("(int) %g = %d\n", int2float(ma), mb);
1744 set_sz (mb, 4);
1745 E (2);
1746 break;
1748 case RXO_rts:
1750 #ifdef CYCLE_ACCURATE
1751 int cyc = 5;
1752 #endif
1753 regs.r_pc = poppc ();
1754 #ifdef CYCLE_ACCURATE
1755 /* Note: specs say 5, chip says 3. */
1756 if (regs.fast_return && regs.link_register == regs.r_pc)
1758 #ifdef WITH_PROFILE
1759 fast_returns ++;
1760 #endif
1761 tprintf("fast return bonus\n");
1762 cyc -= 2;
1764 cycles (cyc);
1765 regs.fast_return = 0;
1766 branch_alignment_penalty = 1;
1767 #endif
1769 break;
1771 case RXO_rtsd:
1772 if (opcode->op[2].type == RX_Operand_Register)
1774 int i;
1775 /* RTSD cannot pop R0 (sp). */
1776 put_reg (0, get_reg (0) + GS() - (opcode->op[0].reg-opcode->op[2].reg+1)*4);
1777 if (opcode->op[2].reg == 0)
1778 EXCEPTION (EX_UNDEFINED);
1779 #ifdef CYCLE_ACCURATE
1780 tx = opcode->op[0].reg - opcode->op[2].reg + 1;
1781 #endif
1782 for (i = opcode->op[2].reg; i <= opcode->op[0].reg; i ++)
1784 RLD (i);
1785 put_reg (i, pop ());
1788 else
1790 #ifdef CYCLE_ACCURATE
1791 tx = 0;
1792 #endif
1793 put_reg (0, get_reg (0) + GS());
1795 put_reg (pc, poppc());
1796 #ifdef CYCLE_ACCURATE
1797 if (regs.fast_return && regs.link_register == regs.r_pc)
1799 tprintf("fast return bonus\n");
1800 #ifdef WITH_PROFILE
1801 fast_returns ++;
1802 #endif
1803 cycles (tx < 3 ? 3 : tx + 1);
1805 else
1807 cycles (tx < 5 ? 5 : tx + 1);
1809 regs.fast_return = 0;
1810 branch_alignment_penalty = 1;
1811 #endif
1812 break;
1814 case RXO_sat:
1815 if (FLAG_O && FLAG_S)
1816 PD (0x7fffffffUL);
1817 else if (FLAG_O && ! FLAG_S)
1818 PD (0x80000000UL);
1820 break;
1822 case RXO_satr:
1823 if (FLAG_O && ! FLAG_S)
1825 put_reg (6, 0x0);
1826 put_reg (5, 0x7fffffff);
1827 put_reg (4, 0xffffffff);
1829 else if (FLAG_O && FLAG_S)
1831 put_reg (6, 0xffffffff);
1832 put_reg (5, 0x80000000);
1833 put_reg (4, 0x0);
1836 break;
1838 case RXO_sbb:
1839 MATH_OP (-, ! carry);
1840 break;
1842 case RXO_sccnd:
1843 if (GS())
1844 PD (1);
1845 else
1846 PD (0);
1848 break;
1850 case RXO_scmpu:
1851 #ifdef CYCLE_ACCURATE
1852 tx = regs.r[3];
1853 #endif
1854 while (regs.r[3] != 0)
1856 uma = mem_get_qi (regs.r[1] ++);
1857 umb = mem_get_qi (regs.r[2] ++);
1858 regs.r[3] --;
1859 if (uma != umb || uma == 0)
1860 break;
1862 if (uma == umb)
1863 set_zc (1, 1);
1864 else
1865 set_zc (0, ((int)uma - (int)umb) >= 0);
1866 cycles (2 + 4 * (tx / 4) + 4 * (tx % 4));
1867 break;
1869 case RXO_setpsw:
1870 v = 1 << opcode->op[0].reg;
1871 if (FLAG_PM
1872 && (v == FLAGBIT_I
1873 || v == FLAGBIT_U))
1874 break;
1875 regs.r_psw |= v;
1876 cycles (1);
1877 break;
1879 case RXO_smovb:
1880 RL (3);
1881 #ifdef CYCLE_ACCURATE
1882 tx = regs.r[3];
1883 #endif
1884 while (regs.r[3])
1886 uma = mem_get_qi (regs.r[2] --);
1887 mem_put_qi (regs.r[1]--, uma);
1888 regs.r[3] --;
1890 #ifdef CYCLE_ACCURATE
1891 if (tx > 3)
1892 cycles (6 + 3 * (tx / 4) + 3 * (tx % 4));
1893 else
1894 cycles (2 + 3 * (tx % 4));
1895 #endif
1896 break;
1898 case RXO_smovf:
1899 RL (3);
1900 #ifdef CYCLE_ACCURATE
1901 tx = regs.r[3];
1902 #endif
1903 while (regs.r[3])
1905 uma = mem_get_qi (regs.r[2] ++);
1906 mem_put_qi (regs.r[1]++, uma);
1907 regs.r[3] --;
1909 cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
1910 break;
1912 case RXO_smovu:
1913 #ifdef CYCLE_ACCURATE
1914 tx = regs.r[3];
1915 #endif
1916 while (regs.r[3] != 0)
1918 uma = mem_get_qi (regs.r[2] ++);
1919 mem_put_qi (regs.r[1]++, uma);
1920 regs.r[3] --;
1921 if (uma == 0)
1922 break;
1924 cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
1925 break;
1927 case RXO_shar: /* d = ma >> mb */
1928 SHIFT_OP (sll, int, mb, >>=, 1);
1929 E (1);
1930 break;
1932 case RXO_shll: /* d = ma << mb */
1933 SHIFT_OP (ll, int, mb, <<=, 0x80000000UL);
1934 E (1);
1935 break;
1937 case RXO_shlr: /* d = ma >> mb */
1938 SHIFT_OP (ll, unsigned int, mb, >>=, 1);
1939 E (1);
1940 break;
1942 case RXO_sstr:
1943 RL (3);
1944 #ifdef CYCLE_ACCURATE
1945 tx = regs.r[3];
1946 #endif
1947 switch (opcode->size)
1949 case RX_Long:
1950 while (regs.r[3] != 0)
1952 mem_put_si (regs.r[1], regs.r[2]);
1953 regs.r[1] += 4;
1954 regs.r[3] --;
1956 cycles (2 + tx);
1957 break;
1958 case RX_Word:
1959 while (regs.r[3] != 0)
1961 mem_put_hi (regs.r[1], regs.r[2]);
1962 regs.r[1] += 2;
1963 regs.r[3] --;
1965 cycles (2 + (int)(tx / 2) + tx % 2);
1966 break;
1967 case RX_Byte:
1968 while (regs.r[3] != 0)
1970 mem_put_qi (regs.r[1], regs.r[2]);
1971 regs.r[1] ++;
1972 regs.r[3] --;
1974 cycles (2 + (int)(tx / 4) + tx % 4);
1975 break;
1976 default:
1977 abort ();
1979 break;
1981 case RXO_stcc:
1982 if (GS2())
1983 PD (GS ());
1985 break;
1987 case RXO_stop:
1988 PRIVILEDGED ();
1989 regs.r_psw |= FLAGBIT_I;
1990 DO_RETURN (RX_MAKE_STOPPED(0));
1992 case RXO_sub:
1993 MATH_OP (-, 0);
1994 break;
1996 case RXO_suntil:
1997 RL(3);
1998 #ifdef CYCLE_ACCURATE
1999 tx = 0;
2000 #endif
2001 if (regs.r[3] == 0)
2003 cycles (3);
2004 break;
2006 switch (opcode->size)
2008 case RX_Long:
2009 uma = get_reg (2);
2010 while (regs.r[3] != 0)
2012 regs.r[3] --;
2013 umb = mem_get_si (get_reg (1));
2014 regs.r[1] += 4;
2015 #ifdef CYCLE_ACCURATE
2016 tx ++;
2017 #endif
2018 if (umb == uma)
2019 break;
2021 #ifdef CYCLE_ACCURATE
2022 cycles (3 + 3 * tx);
2023 #endif
2024 break;
2025 case RX_Word:
2026 uma = get_reg (2) & 0xffff;
2027 while (regs.r[3] != 0)
2029 regs.r[3] --;
2030 umb = mem_get_hi (get_reg (1));
2031 regs.r[1] += 2;
2032 #ifdef CYCLE_ACCURATE
2033 tx ++;
2034 #endif
2035 if (umb == uma)
2036 break;
2038 #ifdef CYCLE_ACCURATE
2039 cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
2040 #endif
2041 break;
2042 case RX_Byte:
2043 uma = get_reg (2) & 0xff;
2044 while (regs.r[3] != 0)
2046 regs.r[3] --;
2047 umb = mem_get_qi (regs.r[1]);
2048 regs.r[1] += 1;
2049 #ifdef CYCLE_ACCURATE
2050 tx ++;
2051 #endif
2052 if (umb == uma)
2053 break;
2055 #ifdef CYCLE_ACCURATE
2056 cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
2057 #endif
2058 break;
2059 default:
2060 abort();
2062 if (uma == umb)
2063 set_zc (1, 1);
2064 else
2065 set_zc (0, ((int)uma - (int)umb) >= 0);
2066 break;
2068 case RXO_swhile:
2069 RL(3);
2070 #ifdef CYCLE_ACCURATE
2071 tx = 0;
2072 #endif
2073 if (regs.r[3] == 0)
2074 break;
2075 switch (opcode->size)
2077 case RX_Long:
2078 uma = get_reg (2);
2079 while (regs.r[3] != 0)
2081 regs.r[3] --;
2082 umb = mem_get_si (get_reg (1));
2083 regs.r[1] += 4;
2084 #ifdef CYCLE_ACCURATE
2085 tx ++;
2086 #endif
2087 if (umb != uma)
2088 break;
2090 #ifdef CYCLE_ACCURATE
2091 cycles (3 + 3 * tx);
2092 #endif
2093 break;
2094 case RX_Word:
2095 uma = get_reg (2) & 0xffff;
2096 while (regs.r[3] != 0)
2098 regs.r[3] --;
2099 umb = mem_get_hi (get_reg (1));
2100 regs.r[1] += 2;
2101 #ifdef CYCLE_ACCURATE
2102 tx ++;
2103 #endif
2104 if (umb != uma)
2105 break;
2107 #ifdef CYCLE_ACCURATE
2108 cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
2109 #endif
2110 break;
2111 case RX_Byte:
2112 uma = get_reg (2) & 0xff;
2113 while (regs.r[3] != 0)
2115 regs.r[3] --;
2116 umb = mem_get_qi (regs.r[1]);
2117 regs.r[1] += 1;
2118 #ifdef CYCLE_ACCURATE
2119 tx ++;
2120 #endif
2121 if (umb != uma)
2122 break;
2124 #ifdef CYCLE_ACCURATE
2125 cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
2126 #endif
2127 break;
2128 default:
2129 abort();
2131 if (uma == umb)
2132 set_zc (1, 1);
2133 else
2134 set_zc (0, ((int)uma - (int)umb) >= 0);
2135 break;
2137 case RXO_wait:
2138 PRIVILEDGED ();
2139 regs.r_psw |= FLAGBIT_I;
2140 DO_RETURN (RX_MAKE_STOPPED(0));
2142 case RXO_xchg:
2143 #ifdef CYCLE_ACCURATE
2144 regs.m2m = 0;
2145 #endif
2146 v = GS (); /* This is the memory operand, if any. */
2147 PS (GD ()); /* and this may change the address register. */
2148 PD (v);
2150 #ifdef CYCLE_ACCURATE
2151 /* all M cycles happen during xchg's cycles. */
2152 memory_dest = 0;
2153 memory_source = 0;
2154 #endif
2155 break;
2157 case RXO_xor:
2158 LOGIC_OP (^);
2159 break;
2161 default:
2162 EXCEPTION (EX_UNDEFINED);
2165 #ifdef CYCLE_ACCURATE
2166 regs.m2m = 0;
2167 if (memory_source)
2168 regs.m2m |= M2M_SRC;
2169 if (memory_dest)
2170 regs.m2m |= M2M_DST;
2172 regs.rt = new_rt;
2173 new_rt = -1;
2174 #endif
2176 #ifdef WITH_PROFILE
2177 if (prev_cycle_count == regs.cycle_count)
2179 printf("Cycle count not updated! id %s\n", id_names[opcode->id]);
2180 abort ();
2182 #endif
2184 #ifdef WITH_PROFILE
2185 if (running_benchmark)
2187 int omap = op_lookup (opcode->op[0].type, opcode->op[1].type, opcode->op[2].type);
2190 cycles_per_id[opcode->id][omap] += regs.cycle_count - prev_cycle_count;
2191 times_per_id[opcode->id][omap] ++;
2193 times_per_pair[prev_opcode_id][po0][opcode->id][omap] ++;
2195 prev_opcode_id = opcode->id;
2196 po0 = omap;
2198 #endif
2200 return RX_MAKE_STEPPED ();
2203 #ifdef WITH_PROFILE
2204 void
2205 reset_pipeline_stats (void)
2207 memset (cycles_per_id, 0, sizeof(cycles_per_id));
2208 memset (times_per_id, 0, sizeof(times_per_id));
2209 memory_stalls = 0;
2210 register_stalls = 0;
2211 branch_stalls = 0;
2212 branch_alignment_stalls = 0;
2213 fast_returns = 0;
2214 memset (times_per_pair, 0, sizeof(times_per_pair));
2215 running_benchmark = 1;
2217 benchmark_start_cycle = regs.cycle_count;
2220 void
2221 halt_pipeline_stats (void)
2223 running_benchmark = 0;
2224 benchmark_end_cycle = regs.cycle_count;
2226 #endif
2228 void
2229 pipeline_stats (void)
2231 #ifdef WITH_PROFILE
2232 int i, o1;
2233 int p, p1;
2234 #endif
2236 #ifdef CYCLE_ACCURATE
2237 if (verbose == 1)
2239 printf ("cycles: %llu\n", regs.cycle_count);
2240 return;
2243 printf ("cycles: %13s\n", comma (regs.cycle_count));
2244 #endif
2246 #ifdef WITH_PROFILE
2247 if (benchmark_start_cycle)
2248 printf ("bmark: %13s\n", comma (benchmark_end_cycle - benchmark_start_cycle));
2250 printf("\n");
2251 for (i = 0; i < N_RXO; i++)
2252 for (o1 = 0; o1 < N_MAP; o1 ++)
2253 if (times_per_id[i][o1])
2254 printf("%13s %13s %7.2f %s %s\n",
2255 comma (cycles_per_id[i][o1]),
2256 comma (times_per_id[i][o1]),
2257 (double)cycles_per_id[i][o1] / times_per_id[i][o1],
2258 op_cache_string(o1),
2259 id_names[i]+4);
2261 printf("\n");
2262 for (p = 0; p < N_RXO; p ++)
2263 for (p1 = 0; p1 < N_MAP; p1 ++)
2264 for (i = 0; i < N_RXO; i ++)
2265 for (o1 = 0; o1 < N_MAP; o1 ++)
2266 if (times_per_pair[p][p1][i][o1])
2268 printf("%13s %s %-9s -> %s %s\n",
2269 comma (times_per_pair[p][p1][i][o1]),
2270 op_cache_string(p1),
2271 id_names[p]+4,
2272 op_cache_string(o1),
2273 id_names[i]+4);
2276 printf("\n");
2277 printf("%13s memory stalls\n", comma (memory_stalls));
2278 printf("%13s register stalls\n", comma (register_stalls));
2279 printf("%13s branches taken (non-return)\n", comma (branch_stalls));
2280 printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls));
2281 printf("%13s fast returns\n", comma (fast_returns));
2282 #endif