[PATCH 22/57][Arm][GAS] Add support for MVE instructions: vmlaldav, vmlalv, vmlsldav...
[binutils-gdb.git] / sim / rx / rx.c
blob58c1d1ff49bc4d6c7f4cffd8be5c8724478e1351
1 /* rx.c --- opcode semantics for stand-alone RX simulator.
3 Copyright (C) 2008-2019 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 #include "config.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <signal.h>
26 #include "libiberty.h"
28 #include "opcode/rx.h"
29 #include "cpu.h"
30 #include "mem.h"
31 #include "syscalls.h"
32 #include "fpu.h"
33 #include "err.h"
34 #include "misc.h"
36 #ifdef CYCLE_STATS
37 static const char * id_names[] = {
38 "RXO_unknown",
39 "RXO_mov", /* d = s (signed) */
40 "RXO_movbi", /* d = [s,s2] (signed) */
41 "RXO_movbir", /* [s,s2] = d (signed) */
42 "RXO_pushm", /* s..s2 */
43 "RXO_popm", /* s..s2 */
44 "RXO_xchg", /* s <-> d */
45 "RXO_stcc", /* d = s if cond(s2) */
46 "RXO_rtsd", /* rtsd, 1=imm, 2-0 = reg if reg type */
48 /* These are all either d OP= s or, if s2 is set, d = s OP s2. Note
49 that d may be "None". */
50 "RXO_and",
51 "RXO_or",
52 "RXO_xor",
53 "RXO_add",
54 "RXO_sub",
55 "RXO_mul",
56 "RXO_div",
57 "RXO_divu",
58 "RXO_shll",
59 "RXO_shar",
60 "RXO_shlr",
62 "RXO_adc", /* d = d + s + carry */
63 "RXO_sbb", /* d = d - s - ~carry */
64 "RXO_abs", /* d = |s| */
65 "RXO_max", /* d = max(d,s) */
66 "RXO_min", /* d = min(d,s) */
67 "RXO_emul", /* d:64 = d:32 * s */
68 "RXO_emulu", /* d:64 = d:32 * s (unsigned) */
70 "RXO_rolc", /* d <<= 1 through carry */
71 "RXO_rorc", /* d >>= 1 through carry*/
72 "RXO_rotl", /* d <<= #s without carry */
73 "RXO_rotr", /* d >>= #s without carry*/
74 "RXO_revw", /* d = revw(s) */
75 "RXO_revl", /* d = revl(s) */
76 "RXO_branch", /* pc = d if cond(s) */
77 "RXO_branchrel",/* pc += d if cond(s) */
78 "RXO_jsr", /* pc = d */
79 "RXO_jsrrel", /* pc += d */
80 "RXO_rts",
81 "RXO_nop",
82 "RXO_nop2",
83 "RXO_nop3",
84 "RXO_nop4",
85 "RXO_nop5",
86 "RXO_nop6",
87 "RXO_nop7",
89 "RXO_scmpu",
90 "RXO_smovu",
91 "RXO_smovb",
92 "RXO_suntil",
93 "RXO_swhile",
94 "RXO_smovf",
95 "RXO_sstr",
97 "RXO_rmpa",
98 "RXO_mulhi",
99 "RXO_mullo",
100 "RXO_machi",
101 "RXO_maclo",
102 "RXO_mvtachi",
103 "RXO_mvtaclo",
104 "RXO_mvfachi",
105 "RXO_mvfacmi",
106 "RXO_mvfaclo",
107 "RXO_racw",
109 "RXO_sat", /* sat(d) */
110 "RXO_satr",
112 "RXO_fadd", /* d op= s */
113 "RXO_fcmp",
114 "RXO_fsub",
115 "RXO_ftoi",
116 "RXO_fmul",
117 "RXO_fdiv",
118 "RXO_round",
119 "RXO_itof",
121 "RXO_bset", /* d |= (1<<s) */
122 "RXO_bclr", /* d &= ~(1<<s) */
123 "RXO_btst", /* s & (1<<s2) */
124 "RXO_bnot", /* d ^= (1<<s) */
125 "RXO_bmcc", /* d<s> = cond(s2) */
127 "RXO_clrpsw", /* flag index in d */
128 "RXO_setpsw", /* flag index in d */
129 "RXO_mvtipl", /* new IPL in s */
131 "RXO_rtfi",
132 "RXO_rte",
133 "RXO_rtd", /* undocumented */
134 "RXO_brk",
135 "RXO_dbt", /* undocumented */
136 "RXO_int", /* vector id in s */
137 "RXO_stop",
138 "RXO_wait",
140 "RXO_sccnd", /* d = cond(s) ? 1 : 0 */
143 static const char * optype_names[] = {
144 " - ",
145 "#Imm", /* #addend */
146 " Rn ", /* Rn */
147 "[Rn]", /* [Rn + addend] */
148 "Ps++", /* [Rn+] */
149 "--Pr", /* [-Rn] */
150 " cc ", /* eq, gtu, etc */
151 "Flag", /* [UIOSZC] */
152 "RbRi" /* [Rb + scale * Ri] */
155 #define N_RXO ARRAY_SIZE (id_names)
156 #define N_RXT ARRAY_SIZE (optype_names)
157 #define N_MAP 90
159 static unsigned long long benchmark_start_cycle;
160 static unsigned long long benchmark_end_cycle;
162 static int op_cache[N_RXT][N_RXT][N_RXT];
163 static int op_cache_rev[N_MAP];
164 static int op_cache_idx = 0;
166 static int
167 op_lookup (int a, int b, int c)
169 if (op_cache[a][b][c])
170 return op_cache[a][b][c];
171 op_cache_idx ++;
172 if (op_cache_idx >= N_MAP)
174 printf("op_cache_idx exceeds %d\n", N_MAP);
175 exit(1);
177 op_cache[a][b][c] = op_cache_idx;
178 op_cache_rev[op_cache_idx] = (a<<8) | (b<<4) | c;
179 return op_cache_idx;
182 static char *
183 op_cache_string (int map)
185 static int ci;
186 static char cb[5][20];
187 int a, b, c;
189 map = op_cache_rev[map];
190 a = (map >> 8) & 15;
191 b = (map >> 4) & 15;
192 c = (map >> 0) & 15;
193 ci = (ci + 1) % 5;
194 sprintf(cb[ci], "%s %s %s", optype_names[a], optype_names[b], optype_names[c]);
195 return cb[ci];
198 static unsigned long long cycles_per_id[N_RXO][N_MAP];
199 static unsigned long long times_per_id[N_RXO][N_MAP];
200 static unsigned long long memory_stalls;
201 static unsigned long long register_stalls;
202 static unsigned long long branch_stalls;
203 static unsigned long long branch_alignment_stalls;
204 static unsigned long long fast_returns;
206 static unsigned long times_per_pair[N_RXO][N_MAP][N_RXO][N_MAP];
207 static int prev_opcode_id = RXO_unknown;
208 static int po0;
210 #define STATS(x) x
212 #else
213 #define STATS(x)
214 #endif /* CYCLE_STATS */
217 #ifdef CYCLE_ACCURATE
219 static int new_rt = -1;
221 /* Number of cycles to add if an insn spans an 8-byte boundary. */
222 static int branch_alignment_penalty = 0;
224 #endif
226 static int running_benchmark = 1;
228 #define tprintf if (trace && running_benchmark) printf
230 jmp_buf decode_jmp_buf;
231 unsigned int rx_cycles = 0;
233 #ifdef CYCLE_ACCURATE
234 /* If nonzero, memory was read at some point and cycle latency might
235 take effect. */
236 static int memory_source = 0;
237 /* If nonzero, memory was written and extra cycles might be
238 needed. */
239 static int memory_dest = 0;
241 static void
242 cycles (int throughput)
244 tprintf("%d cycles\n", throughput);
245 regs.cycle_count += throughput;
248 /* Number of execution (E) cycles the op uses. For memory sources, we
249 include the load micro-op stall as two extra E cycles. */
250 #define E(c) cycles (memory_source ? c + 2 : c)
251 #define E1 cycles (1)
252 #define E2 cycles (2)
253 #define EBIT cycles (memory_source ? 2 : 1)
255 /* Check to see if a read latency must be applied for a given register. */
256 #define RL(r) \
257 if (regs.rt == r ) \
259 tprintf("register %d load stall\n", r); \
260 regs.cycle_count ++; \
261 STATS(register_stalls ++); \
262 regs.rt = -1; \
265 #define RLD(r) \
266 if (memory_source) \
268 tprintf ("Rt now %d\n", r); \
269 new_rt = r; \
272 static int
273 lsb_count (unsigned long v, int is_signed)
275 int i, lsb;
276 if (is_signed && (v & 0x80000000U))
277 v = (unsigned long)(long)(-v);
278 for (i=31; i>=0; i--)
279 if (v & (1 << i))
281 /* v is 0..31, we want 1=1-2, 2=3-4, 3=5-6, etc. */
282 lsb = (i + 2) / 2;
283 return lsb;
285 return 0;
288 static int
289 divu_cycles(unsigned long num, unsigned long den)
291 int nb = lsb_count (num, 0);
292 int db = lsb_count (den, 0);
293 int rv;
295 if (nb < db)
296 rv = 2;
297 else
298 rv = 3 + nb - db;
299 E (rv);
300 return rv;
303 static int
304 div_cycles(long num, long den)
306 int nb = lsb_count ((unsigned long)num, 1);
307 int db = lsb_count ((unsigned long)den, 1);
308 int rv;
310 if (nb < db)
311 rv = 3;
312 else
313 rv = 5 + nb - db;
314 E (rv);
315 return rv;
318 #else /* !CYCLE_ACCURATE */
320 #define cycles(t)
321 #define E(c)
322 #define E1
323 #define E2
324 #define EBIT
325 #define RL(r)
326 #define RLD(r)
328 #define divu_cycles(n,d)
329 #define div_cycles(n,d)
331 #endif /* else CYCLE_ACCURATE */
333 static int size2bytes[] = {
334 4, 1, 1, 1, 2, 2, 2, 3, 4
337 typedef struct {
338 unsigned long dpc;
339 } RX_Data;
341 #define rx_abort() _rx_abort(__FILE__, __LINE__)
342 static void
343 _rx_abort (const char *file, int line)
345 if (strrchr (file, '/'))
346 file = strrchr (file, '/') + 1;
347 fprintf(stderr, "abort at %s:%d\n", file, line);
348 abort();
351 static unsigned char *get_byte_base;
352 static RX_Opcode_Decoded **decode_cache_base;
353 static SI get_byte_page;
355 void
356 reset_decoder (void)
358 get_byte_base = 0;
359 decode_cache_base = 0;
360 get_byte_page = 0;
363 static inline void
364 maybe_get_mem_page (SI tpc)
366 if (((tpc ^ get_byte_page) & NONPAGE_MASK) || enable_counting)
368 get_byte_page = tpc & NONPAGE_MASK;
369 get_byte_base = rx_mem_ptr (get_byte_page, MPA_READING) - get_byte_page;
370 decode_cache_base = rx_mem_decode_cache (get_byte_page) - get_byte_page;
374 /* This gets called a *lot* so optimize it. */
375 static int
376 rx_get_byte (void *vdata)
378 RX_Data *rx_data = (RX_Data *)vdata;
379 SI tpc = rx_data->dpc;
381 /* See load.c for an explanation of this. */
382 if (rx_big_endian)
383 tpc ^= 3;
385 maybe_get_mem_page (tpc);
387 rx_data->dpc ++;
388 return get_byte_base [tpc];
391 static int
392 get_op (const RX_Opcode_Decoded *rd, int i)
394 const RX_Opcode_Operand *o = rd->op + i;
395 int addr, rv = 0;
397 switch (o->type)
399 case RX_Operand_None:
400 rx_abort ();
402 case RX_Operand_Immediate: /* #addend */
403 return o->addend;
405 case RX_Operand_Register: /* Rn */
406 RL (o->reg);
407 rv = get_reg (o->reg);
408 break;
410 case RX_Operand_Predec: /* [-Rn] */
411 put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
412 /* fall through */
413 case RX_Operand_Postinc: /* [Rn+] */
414 case RX_Operand_Zero_Indirect: /* [Rn + 0] */
415 case RX_Operand_Indirect: /* [Rn + addend] */
416 case RX_Operand_TwoReg: /* [Rn + scale * R2] */
417 #ifdef CYCLE_ACCURATE
418 RL (o->reg);
419 if (o->type == RX_Operand_TwoReg)
420 RL (rd->op[2].reg);
421 regs.rt = -1;
422 if (regs.m2m == M2M_BOTH)
424 tprintf("src memory stall\n");
425 #ifdef CYCLE_STATS
426 memory_stalls ++;
427 #endif
428 regs.cycle_count ++;
429 regs.m2m = 0;
432 memory_source = 1;
433 #endif
435 if (o->type == RX_Operand_TwoReg)
436 addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
437 else
438 addr = get_reg (o->reg) + o->addend;
440 switch (o->size)
442 default:
443 case RX_AnySize:
444 rx_abort ();
446 case RX_Byte: /* undefined extension */
447 case RX_UByte:
448 case RX_SByte:
449 rv = mem_get_qi (addr);
450 break;
452 case RX_Word: /* undefined extension */
453 case RX_UWord:
454 case RX_SWord:
455 rv = mem_get_hi (addr);
456 break;
458 case RX_3Byte:
459 rv = mem_get_psi (addr);
460 break;
462 case RX_Long:
463 rv = mem_get_si (addr);
464 break;
467 if (o->type == RX_Operand_Postinc)
468 put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
470 break;
472 case RX_Operand_Condition: /* eq, gtu, etc */
473 return condition_true (o->reg);
475 case RX_Operand_Flag: /* [UIOSZC] */
476 return (regs.r_psw & (1 << o->reg)) ? 1 : 0;
479 /* if we've gotten here, we need to clip/extend the value according
480 to the size. */
481 switch (o->size)
483 default:
484 case RX_AnySize:
485 rx_abort ();
487 case RX_Byte: /* undefined extension */
488 rv |= 0xdeadbe00; /* keep them honest */
489 break;
491 case RX_UByte:
492 rv &= 0xff;
493 break;
495 case RX_SByte:
496 rv = sign_ext (rv, 8);
497 break;
499 case RX_Word: /* undefined extension */
500 rv |= 0xdead0000; /* keep them honest */
501 break;
503 case RX_UWord:
504 rv &= 0xffff;
505 break;
507 case RX_SWord:
508 rv = sign_ext (rv, 16);
509 break;
511 case RX_3Byte:
512 rv &= 0xffffff;
513 break;
515 case RX_Long:
516 break;
518 return rv;
521 static void
522 put_op (const RX_Opcode_Decoded *rd, int i, int v)
524 const RX_Opcode_Operand *o = rd->op + i;
525 int addr;
527 switch (o->size)
529 default:
530 case RX_AnySize:
531 if (o->type != RX_Operand_Register)
532 rx_abort ();
533 break;
535 case RX_Byte: /* undefined extension */
536 v |= 0xdeadbe00; /* keep them honest */
537 break;
539 case RX_UByte:
540 v &= 0xff;
541 break;
543 case RX_SByte:
544 v = sign_ext (v, 8);
545 break;
547 case RX_Word: /* undefined extension */
548 v |= 0xdead0000; /* keep them honest */
549 break;
551 case RX_UWord:
552 v &= 0xffff;
553 break;
555 case RX_SWord:
556 v = sign_ext (v, 16);
557 break;
559 case RX_3Byte:
560 v &= 0xffffff;
561 break;
563 case RX_Long:
564 break;
567 switch (o->type)
569 case RX_Operand_None:
570 /* Opcodes like TST and CMP use this. */
571 break;
573 case RX_Operand_Immediate: /* #addend */
574 case RX_Operand_Condition: /* eq, gtu, etc */
575 rx_abort ();
577 case RX_Operand_Register: /* Rn */
578 put_reg (o->reg, v);
579 RLD (o->reg);
580 break;
582 case RX_Operand_Predec: /* [-Rn] */
583 put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
584 /* fall through */
585 case RX_Operand_Postinc: /* [Rn+] */
586 case RX_Operand_Zero_Indirect: /* [Rn + 0] */
587 case RX_Operand_Indirect: /* [Rn + addend] */
588 case RX_Operand_TwoReg: /* [Rn + scale * R2] */
590 #ifdef CYCLE_ACCURATE
591 if (regs.m2m == M2M_BOTH)
593 tprintf("dst memory stall\n");
594 regs.cycle_count ++;
595 #ifdef CYCLE_STATS
596 memory_stalls ++;
597 #endif
598 regs.m2m = 0;
600 memory_dest = 1;
601 #endif
603 if (o->type == RX_Operand_TwoReg)
604 addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
605 else
606 addr = get_reg (o->reg) + o->addend;
608 switch (o->size)
610 default:
611 case RX_AnySize:
612 rx_abort ();
614 case RX_Byte: /* undefined extension */
615 case RX_UByte:
616 case RX_SByte:
617 mem_put_qi (addr, v);
618 break;
620 case RX_Word: /* undefined extension */
621 case RX_UWord:
622 case RX_SWord:
623 mem_put_hi (addr, v);
624 break;
626 case RX_3Byte:
627 mem_put_psi (addr, v);
628 break;
630 case RX_Long:
631 mem_put_si (addr, v);
632 break;
635 if (o->type == RX_Operand_Postinc)
636 put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
638 break;
640 case RX_Operand_Flag: /* [UIOSZC] */
641 if (v)
642 regs.r_psw |= (1 << o->reg);
643 else
644 regs.r_psw &= ~(1 << o->reg);
645 break;
649 #define PD(x) put_op (opcode, 0, x)
650 #define PS(x) put_op (opcode, 1, x)
651 #define PS2(x) put_op (opcode, 2, x)
652 #define GD() get_op (opcode, 0)
653 #define GS() get_op (opcode, 1)
654 #define GS2() get_op (opcode, 2)
655 #define DSZ() size2bytes[opcode->op[0].size]
656 #define SSZ() size2bytes[opcode->op[0].size]
657 #define S2SZ() size2bytes[opcode->op[0].size]
659 /* "Universal" sources. */
660 #define US1() ((opcode->op[2].type == RX_Operand_None) ? GD() : GS())
661 #define US2() ((opcode->op[2].type == RX_Operand_None) ? GS() : GS2())
663 static void
664 push(int val)
666 int rsp = get_reg (sp);
667 rsp -= 4;
668 put_reg (sp, rsp);
669 mem_put_si (rsp, val);
672 /* Just like the above, but tag the memory as "pushed pc" so if anyone
673 tries to write to it, it will cause an error. */
674 static void
675 pushpc(int val)
677 int rsp = get_reg (sp);
678 rsp -= 4;
679 put_reg (sp, rsp);
680 mem_put_si (rsp, val);
681 mem_set_content_range (rsp, rsp+3, MC_PUSHED_PC);
684 static int
685 pop()
687 int rv;
688 int rsp = get_reg (sp);
689 rv = mem_get_si (rsp);
690 rsp += 4;
691 put_reg (sp, rsp);
692 return rv;
695 static int
696 poppc()
698 int rv;
699 int rsp = get_reg (sp);
700 if (mem_get_content_type (rsp) != MC_PUSHED_PC)
701 execution_error (SIM_ERR_CORRUPT_STACK, rsp);
702 rv = mem_get_si (rsp);
703 mem_set_content_range (rsp, rsp+3, MC_UNINIT);
704 rsp += 4;
705 put_reg (sp, rsp);
706 return rv;
709 #define MATH_OP(vop,c) \
711 umb = US2(); \
712 uma = US1(); \
713 ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
714 tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
715 ma = sign_ext (uma, DSZ() * 8); \
716 mb = sign_ext (umb, DSZ() * 8); \
717 sll = (long long) ma vop (long long) mb vop c; \
718 tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
719 set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
720 PD (sll); \
721 E (1); \
724 #define LOGIC_OP(vop) \
726 mb = US2(); \
727 ma = US1(); \
728 v = ma vop mb; \
729 tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
730 set_sz (v, DSZ()); \
731 PD(v); \
732 E (1); \
735 #define SHIFT_OP(val, type, count, OP, carry_mask) \
737 int i, c=0; \
738 count = US2(); \
739 val = (type)US1(); \
740 tprintf("%lld " #OP " %d\n", val, count); \
741 for (i = 0; i < count; i ++) \
743 c = val & carry_mask; \
744 val OP 1; \
746 set_oszc (val, 4, c); \
747 PD (val); \
750 typedef union {
751 int i;
752 float f;
753 } FloatInt;
755 static inline int
756 float2int (float f)
758 FloatInt fi;
759 fi.f = f;
760 return fi.i;
763 static inline float
764 int2float (int i)
766 FloatInt fi;
767 fi.i = i;
768 return fi.f;
771 static int
772 fop_fadd (fp_t s1, fp_t s2, fp_t *d)
774 *d = rxfp_add (s1, s2);
775 return 1;
778 static int
779 fop_fmul (fp_t s1, fp_t s2, fp_t *d)
781 *d = rxfp_mul (s1, s2);
782 return 1;
785 static int
786 fop_fdiv (fp_t s1, fp_t s2, fp_t *d)
788 *d = rxfp_div (s1, s2);
789 return 1;
792 static int
793 fop_fsub (fp_t s1, fp_t s2, fp_t *d)
795 *d = rxfp_sub (s1, s2);
796 return 1;
799 #define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
800 #define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
801 #define FPCHECK() \
802 if (FPPENDING()) \
803 return do_fp_exception (opcode_pc)
805 #define FLOAT_OP(func) \
807 int do_store; \
808 fp_t fa, fb, fc; \
809 FPCLEAR(); \
810 fb = GS (); \
811 fa = GD (); \
812 do_store = fop_##func (fa, fb, &fc); \
813 tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
814 FPCHECK(); \
815 if (do_store) \
816 PD (fc); \
817 mb = 0; \
818 if ((fc & 0x80000000UL) != 0) \
819 mb |= FLAGBIT_S; \
820 if ((fc & 0x7fffffffUL) == 0) \
821 mb |= FLAGBIT_Z; \
822 set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
825 #define carry (FLAG_C ? 1 : 0)
827 static struct {
828 unsigned long vaddr;
829 const char *str;
830 int signal;
831 } exception_info[] = {
832 { 0xFFFFFFD0UL, "priviledged opcode", SIGILL },
833 { 0xFFFFFFD4UL, "access violation", SIGSEGV },
834 { 0xFFFFFFDCUL, "undefined opcode", SIGILL },
835 { 0xFFFFFFE4UL, "floating point", SIGFPE }
837 #define EX_PRIVILEDGED 0
838 #define EX_ACCESS 1
839 #define EX_UNDEFINED 2
840 #define EX_FLOATING 3
841 #define EXCEPTION(n) \
842 return generate_exception (n, opcode_pc)
844 #define PRIVILEDGED() \
845 if (FLAG_PM) \
846 EXCEPTION (EX_PRIVILEDGED)
848 static int
849 generate_exception (unsigned long type, SI opcode_pc)
851 SI old_psw, old_pc, new_pc;
853 new_pc = mem_get_si (exception_info[type].vaddr);
854 /* 0x00020000 is the value used to initialise the known
855 exception vectors (see rx.ld), but it is a reserved
856 area of memory so do not try to access it, and if the
857 value has not been changed by the program then the
858 vector has not been installed. */
859 if (new_pc == 0 || new_pc == 0x00020000)
861 if (rx_in_gdb)
862 return RX_MAKE_STOPPED (exception_info[type].signal);
864 fprintf(stderr, "Unhandled %s exception at pc = %#lx\n",
865 exception_info[type].str, (unsigned long) opcode_pc);
866 if (type == EX_FLOATING)
868 int mask = FPPENDING ();
869 fprintf (stderr, "Pending FP exceptions:");
870 if (mask & FPSWBITS_FV)
871 fprintf(stderr, " Invalid");
872 if (mask & FPSWBITS_FO)
873 fprintf(stderr, " Overflow");
874 if (mask & FPSWBITS_FZ)
875 fprintf(stderr, " Division-by-zero");
876 if (mask & FPSWBITS_FU)
877 fprintf(stderr, " Underflow");
878 if (mask & FPSWBITS_FX)
879 fprintf(stderr, " Inexact");
880 if (mask & FPSWBITS_CE)
881 fprintf(stderr, " Unimplemented");
882 fprintf(stderr, "\n");
884 return RX_MAKE_EXITED (1);
887 tprintf ("Triggering %s exception\n", exception_info[type].str);
889 old_psw = regs.r_psw;
890 regs.r_psw &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
891 old_pc = opcode_pc;
892 regs.r_pc = new_pc;
893 pushpc (old_psw);
894 pushpc (old_pc);
895 return RX_MAKE_STEPPED ();
898 void
899 generate_access_exception (void)
901 int rv;
903 rv = generate_exception (EX_ACCESS, regs.r_pc);
904 if (RX_EXITED (rv))
905 longjmp (decode_jmp_buf, rv);
908 static int
909 do_fp_exception (unsigned long opcode_pc)
911 while (FPPENDING())
912 EXCEPTION (EX_FLOATING);
913 return RX_MAKE_STEPPED ();
916 static int
917 op_is_memory (const RX_Opcode_Decoded *rd, int i)
919 switch (rd->op[i].type)
921 case RX_Operand_Predec:
922 case RX_Operand_Postinc:
923 case RX_Operand_Indirect:
924 return 1;
925 default:
926 return 0;
929 #define OM(i) op_is_memory (opcode, i)
931 #define DO_RETURN(x) { longjmp (decode_jmp_buf, x); }
934 decode_opcode ()
936 unsigned int uma=0, umb=0;
937 int ma=0, mb=0;
938 int opcode_size, v;
939 unsigned long long ll;
940 long long sll;
941 unsigned long opcode_pc;
942 RX_Data rx_data;
943 const RX_Opcode_Decoded *opcode;
944 #ifdef CYCLE_STATS
945 unsigned long long prev_cycle_count;
946 #endif
947 #ifdef CYCLE_ACCURATE
948 unsigned int tx;
949 #endif
951 #ifdef CYCLE_STATS
952 prev_cycle_count = regs.cycle_count;
953 #endif
955 #ifdef CYCLE_ACCURATE
956 memory_source = 0;
957 memory_dest = 0;
958 #endif
960 rx_cycles ++;
962 maybe_get_mem_page (regs.r_pc);
964 opcode_pc = regs.r_pc;
966 /* Note that we don't word-swap this point, there's no point. */
967 if (decode_cache_base[opcode_pc] == NULL)
969 RX_Opcode_Decoded *opcode_w;
970 rx_data.dpc = opcode_pc;
971 opcode_w = decode_cache_base[opcode_pc] = calloc (1, sizeof (RX_Opcode_Decoded));
972 opcode_size = rx_decode_opcode (opcode_pc, opcode_w,
973 rx_get_byte, &rx_data);
974 opcode = opcode_w;
976 else
978 opcode = decode_cache_base[opcode_pc];
979 opcode_size = opcode->n_bytes;
982 #ifdef CYCLE_ACCURATE
983 if (branch_alignment_penalty)
985 if ((regs.r_pc ^ (regs.r_pc + opcode_size - 1)) & ~7)
987 tprintf("1 cycle branch alignment penalty\n");
988 cycles (branch_alignment_penalty);
989 #ifdef CYCLE_STATS
990 branch_alignment_stalls ++;
991 #endif
993 branch_alignment_penalty = 0;
995 #endif
997 regs.r_pc += opcode_size;
999 rx_flagmask = opcode->flags_s;
1000 rx_flagand = ~(int)opcode->flags_0;
1001 rx_flagor = opcode->flags_1;
1003 switch (opcode->id)
1005 case RXO_abs:
1006 sll = GS ();
1007 tprintf("|%lld| = ", sll);
1008 if (sll < 0)
1009 sll = -sll;
1010 tprintf("%lld\n", sll);
1011 PD (sll);
1012 set_osz (sll, 4);
1013 E (1);
1014 break;
1016 case RXO_adc:
1017 MATH_OP (+,carry);
1018 break;
1020 case RXO_add:
1021 MATH_OP (+,0);
1022 break;
1024 case RXO_and:
1025 LOGIC_OP (&);
1026 break;
1028 case RXO_bclr:
1029 ma = GD ();
1030 mb = GS ();
1031 if (opcode->op[0].type == RX_Operand_Register)
1032 mb &= 0x1f;
1033 else
1034 mb &= 0x07;
1035 ma &= ~(1 << mb);
1036 PD (ma);
1037 EBIT;
1038 break;
1040 case RXO_bmcc:
1041 ma = GD ();
1042 mb = GS ();
1043 if (opcode->op[0].type == RX_Operand_Register)
1044 mb &= 0x1f;
1045 else
1046 mb &= 0x07;
1047 if (GS2 ())
1048 ma |= (1 << mb);
1049 else
1050 ma &= ~(1 << mb);
1051 PD (ma);
1052 EBIT;
1053 break;
1055 case RXO_bnot:
1056 ma = GD ();
1057 mb = GS ();
1058 if (opcode->op[0].type == RX_Operand_Register)
1059 mb &= 0x1f;
1060 else
1061 mb &= 0x07;
1062 ma ^= (1 << mb);
1063 PD (ma);
1064 EBIT;
1065 break;
1067 case RXO_branch:
1068 if (opcode->op[1].type == RX_Operand_None || GS())
1070 #ifdef CYCLE_ACCURATE
1071 SI old_pc = regs.r_pc;
1072 int delta;
1073 #endif
1074 regs.r_pc = GD();
1075 #ifdef CYCLE_ACCURATE
1076 delta = regs.r_pc - old_pc;
1077 if (delta >= 0 && delta < 16
1078 && opcode_size > 1)
1080 tprintf("near forward branch bonus\n");
1081 cycles (2);
1083 else
1085 cycles (3);
1086 branch_alignment_penalty = 1;
1088 #ifdef CYCLE_STATS
1089 branch_stalls ++;
1090 #endif
1091 #endif
1093 #ifdef CYCLE_ACCURATE
1094 else
1095 cycles (1);
1096 #endif
1097 break;
1099 case RXO_branchrel:
1100 if (opcode->op[1].type == RX_Operand_None || GS())
1102 int delta = GD();
1103 regs.r_pc = opcode_pc + delta;
1104 #ifdef CYCLE_ACCURATE
1105 /* Note: specs say 3, chip says 2. */
1106 if (delta >= 0 && delta < 16
1107 && opcode_size > 1)
1109 tprintf("near forward branch bonus\n");
1110 cycles (2);
1112 else
1114 cycles (3);
1115 branch_alignment_penalty = 1;
1117 #ifdef CYCLE_STATS
1118 branch_stalls ++;
1119 #endif
1120 #endif
1122 #ifdef CYCLE_ACCURATE
1123 else
1124 cycles (1);
1125 #endif
1126 break;
1128 case RXO_brk:
1130 int old_psw = regs.r_psw;
1131 if (rx_in_gdb)
1132 DO_RETURN (RX_MAKE_HIT_BREAK ());
1133 if (regs.r_intb == 0)
1135 tprintf("BREAK hit, no vector table.\n");
1136 DO_RETURN (RX_MAKE_EXITED(1));
1138 regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
1139 pushpc (old_psw);
1140 pushpc (regs.r_pc);
1141 regs.r_pc = mem_get_si (regs.r_intb);
1142 cycles(6);
1144 break;
1146 case RXO_bset:
1147 ma = GD ();
1148 mb = GS ();
1149 if (opcode->op[0].type == RX_Operand_Register)
1150 mb &= 0x1f;
1151 else
1152 mb &= 0x07;
1153 ma |= (1 << mb);
1154 PD (ma);
1155 EBIT;
1156 break;
1158 case RXO_btst:
1159 ma = GS ();
1160 mb = GS2 ();
1161 if (opcode->op[1].type == RX_Operand_Register)
1162 mb &= 0x1f;
1163 else
1164 mb &= 0x07;
1165 umb = ma & (1 << mb);
1166 set_zc (! umb, umb);
1167 EBIT;
1168 break;
1170 case RXO_clrpsw:
1171 v = 1 << opcode->op[0].reg;
1172 if (FLAG_PM
1173 && (v == FLAGBIT_I
1174 || v == FLAGBIT_U))
1175 break;
1176 regs.r_psw &= ~v;
1177 cycles (1);
1178 break;
1180 case RXO_div: /* d = d / s */
1181 ma = GS();
1182 mb = GD();
1183 tprintf("%d / %d = ", mb, ma);
1184 if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
1186 tprintf("#NAN\n");
1187 set_flags (FLAGBIT_O, FLAGBIT_O);
1188 cycles (3);
1190 else
1192 v = mb/ma;
1193 tprintf("%d\n", v);
1194 set_flags (FLAGBIT_O, 0);
1195 PD (v);
1196 div_cycles (mb, ma);
1198 break;
1200 case RXO_divu: /* d = d / s */
1201 uma = GS();
1202 umb = GD();
1203 tprintf("%u / %u = ", umb, uma);
1204 if (uma == 0)
1206 tprintf("#NAN\n");
1207 set_flags (FLAGBIT_O, FLAGBIT_O);
1208 cycles (2);
1210 else
1212 v = umb / uma;
1213 tprintf("%u\n", v);
1214 set_flags (FLAGBIT_O, 0);
1215 PD (v);
1216 divu_cycles (umb, uma);
1218 break;
1220 case RXO_emul:
1221 ma = GD ();
1222 mb = GS ();
1223 sll = (long long)ma * (long long)mb;
1224 tprintf("%d * %d = %lld\n", ma, mb, sll);
1225 put_reg (opcode->op[0].reg, sll);
1226 put_reg (opcode->op[0].reg + 1, sll >> 32);
1228 break;
1230 case RXO_emulu:
1231 uma = GD ();
1232 umb = GS ();
1233 ll = (long long)uma * (long long)umb;
1234 tprintf("%#x * %#x = %#llx\n", uma, umb, ll);
1235 put_reg (opcode->op[0].reg, ll);
1236 put_reg (opcode->op[0].reg + 1, ll >> 32);
1238 break;
1240 case RXO_fadd:
1241 FLOAT_OP (fadd);
1242 E (4);
1243 break;
1245 case RXO_fcmp:
1246 ma = GD();
1247 mb = GS();
1248 FPCLEAR ();
1249 rxfp_cmp (ma, mb);
1250 FPCHECK ();
1251 E (1);
1252 break;
1254 case RXO_fdiv:
1255 FLOAT_OP (fdiv);
1256 E (16);
1257 break;
1259 case RXO_fmul:
1260 FLOAT_OP (fmul);
1261 E (3);
1262 break;
1264 case RXO_rtfi:
1265 PRIVILEDGED ();
1266 regs.r_psw = regs.r_bpsw;
1267 regs.r_pc = regs.r_bpc;
1268 #ifdef CYCLE_ACCURATE
1269 regs.fast_return = 0;
1270 cycles(3);
1271 #endif
1272 break;
1274 case RXO_fsub:
1275 FLOAT_OP (fsub);
1276 E (4);
1277 break;
1279 case RXO_ftoi:
1280 ma = GS ();
1281 FPCLEAR ();
1282 mb = rxfp_ftoi (ma, FPRM_ZERO);
1283 FPCHECK ();
1284 PD (mb);
1285 tprintf("(int) %g = %d\n", int2float(ma), mb);
1286 set_sz (mb, 4);
1287 E (2);
1288 break;
1290 case RXO_int:
1291 v = GS ();
1292 if (v == 255)
1294 int rc = rx_syscall (regs.r[5]);
1295 if (! RX_STEPPED (rc))
1296 DO_RETURN (rc);
1298 else
1300 int old_psw = regs.r_psw;
1301 regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
1302 pushpc (old_psw);
1303 pushpc (regs.r_pc);
1304 regs.r_pc = mem_get_si (regs.r_intb + 4 * v);
1306 cycles (6);
1307 break;
1309 case RXO_itof:
1310 ma = GS ();
1311 FPCLEAR ();
1312 mb = rxfp_itof (ma, regs.r_fpsw);
1313 FPCHECK ();
1314 tprintf("(float) %d = %x\n", ma, mb);
1315 PD (mb);
1316 set_sz (ma, 4);
1317 E (2);
1318 break;
1320 case RXO_jsr:
1321 case RXO_jsrrel:
1323 #ifdef CYCLE_ACCURATE
1324 int delta;
1325 regs.m2m = 0;
1326 #endif
1327 v = GD ();
1328 #ifdef CYCLE_ACCURATE
1329 regs.link_register = regs.r_pc;
1330 #endif
1331 pushpc (get_reg (pc));
1332 if (opcode->id == RXO_jsrrel)
1333 v += regs.r_pc;
1334 #ifdef CYCLE_ACCURATE
1335 delta = v - regs.r_pc;
1336 #endif
1337 put_reg (pc, v);
1338 #ifdef CYCLE_ACCURATE
1339 /* Note: docs say 3, chip says 2 */
1340 if (delta >= 0 && delta < 16)
1342 tprintf ("near forward jsr bonus\n");
1343 cycles (2);
1345 else
1347 branch_alignment_penalty = 1;
1348 cycles (3);
1350 regs.fast_return = 1;
1351 #endif
1353 break;
1355 case RXO_machi:
1356 ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
1357 ll <<= 16;
1358 put_reg64 (acc64, ll + regs.r_acc);
1360 break;
1362 case RXO_maclo:
1363 ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
1364 ll <<= 16;
1365 put_reg64 (acc64, ll + regs.r_acc);
1367 break;
1369 case RXO_max:
1370 mb = GS();
1371 ma = GD();
1372 if (ma > mb)
1373 PD (ma);
1374 else
1375 PD (mb);
1376 E (1);
1377 break;
1379 case RXO_min:
1380 mb = GS();
1381 ma = GD();
1382 if (ma < mb)
1383 PD (ma);
1384 else
1385 PD (mb);
1386 E (1);
1387 break;
1389 case RXO_mov:
1390 v = GS ();
1392 if (opcode->op[1].type == RX_Operand_Register
1393 && opcode->op[1].reg == 17 /* PC */)
1395 /* Special case. We want the address of the insn, not the
1396 address of the next insn. */
1397 v = opcode_pc;
1400 if (opcode->op[0].type == RX_Operand_Register
1401 && opcode->op[0].reg == 16 /* PSW */)
1403 /* Special case, LDC and POPC can't ever modify PM. */
1404 int pm = regs.r_psw & FLAGBIT_PM;
1405 v &= ~ FLAGBIT_PM;
1406 v |= pm;
1407 if (pm)
1409 v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1410 v |= pm;
1413 if (FLAG_PM)
1415 /* various things can't be changed in user mode. */
1416 if (opcode->op[0].type == RX_Operand_Register)
1417 if (opcode->op[0].reg == 32)
1419 v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1420 v |= regs.r_psw & (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1422 if (opcode->op[0].reg == 34 /* ISP */
1423 || opcode->op[0].reg == 37 /* BPSW */
1424 || opcode->op[0].reg == 39 /* INTB */
1425 || opcode->op[0].reg == 38 /* VCT */)
1426 /* These are ignored. */
1427 break;
1429 if (OM(0) && OM(1))
1430 cycles (2);
1431 else
1432 cycles (1);
1434 PD (v);
1436 #ifdef CYCLE_ACCURATE
1437 if ((opcode->op[0].type == RX_Operand_Predec
1438 && opcode->op[1].type == RX_Operand_Register)
1439 || (opcode->op[0].type == RX_Operand_Postinc
1440 && opcode->op[1].type == RX_Operand_Register))
1442 /* Special case: push reg doesn't cause a memory stall. */
1443 memory_dest = 0;
1444 tprintf("push special case\n");
1446 #endif
1448 set_sz (v, DSZ());
1449 break;
1451 case RXO_movbi:
1452 PD (GS ());
1453 cycles (1);
1454 break;
1456 case RXO_movbir:
1457 PS (GD ());
1458 cycles (1);
1459 break;
1461 case RXO_mul:
1462 v = US2 ();
1463 ll = (unsigned long long) US1() * (unsigned long long) v;
1464 PD(ll);
1465 E (1);
1466 break;
1468 case RXO_mulhi:
1469 v = GS2 ();
1470 ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v >> 16);
1471 ll <<= 16;
1472 put_reg64 (acc64, ll);
1474 break;
1476 case RXO_mullo:
1477 v = GS2 ();
1478 ll = (long long)(signed short)(GS()) * (long long)(signed short)(v);
1479 ll <<= 16;
1480 put_reg64 (acc64, ll);
1482 break;
1484 case RXO_mvfachi:
1485 PD (get_reg (acchi));
1487 break;
1489 case RXO_mvfaclo:
1490 PD (get_reg (acclo));
1492 break;
1494 case RXO_mvfacmi:
1495 PD (get_reg (accmi));
1497 break;
1499 case RXO_mvtachi:
1500 put_reg (acchi, GS ());
1502 break;
1504 case RXO_mvtaclo:
1505 put_reg (acclo, GS ());
1507 break;
1509 case RXO_mvtipl:
1510 regs.r_psw &= ~ FLAGBITS_IPL;
1511 regs.r_psw |= (GS () << FLAGSHIFT_IPL) & FLAGBITS_IPL;
1513 break;
1515 case RXO_nop:
1516 case RXO_nop2:
1517 case RXO_nop3:
1518 case RXO_nop4:
1519 case RXO_nop5:
1520 case RXO_nop6:
1521 case RXO_nop7:
1523 break;
1525 case RXO_or:
1526 LOGIC_OP (|);
1527 break;
1529 case RXO_popm:
1530 /* POPM cannot pop R0 (sp). */
1531 if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
1532 EXCEPTION (EX_UNDEFINED);
1533 if (opcode->op[1].reg >= opcode->op[2].reg)
1535 regs.r_pc = opcode_pc;
1536 DO_RETURN (RX_MAKE_STOPPED (SIGILL));
1538 for (v = opcode->op[1].reg; v <= opcode->op[2].reg; v++)
1540 cycles (1);
1541 RLD (v);
1542 put_reg (v, pop ());
1544 break;
1546 case RXO_pushm:
1547 /* PUSHM cannot push R0 (sp). */
1548 if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
1549 EXCEPTION (EX_UNDEFINED);
1550 if (opcode->op[1].reg >= opcode->op[2].reg)
1552 regs.r_pc = opcode_pc;
1553 return RX_MAKE_STOPPED (SIGILL);
1555 for (v = opcode->op[2].reg; v >= opcode->op[1].reg; v--)
1557 RL (v);
1558 push (get_reg (v));
1560 cycles (opcode->op[2].reg - opcode->op[1].reg + 1);
1561 break;
1563 case RXO_racw:
1564 ll = get_reg64 (acc64) << GS ();
1565 ll += 0x80000000ULL;
1566 if ((signed long long)ll > (signed long long)0x00007fff00000000ULL)
1567 ll = 0x00007fff00000000ULL;
1568 else if ((signed long long)ll < (signed long long)0xffff800000000000ULL)
1569 ll = 0xffff800000000000ULL;
1570 else
1571 ll &= 0xffffffff00000000ULL;
1572 put_reg64 (acc64, ll);
1574 break;
1576 case RXO_rte:
1577 PRIVILEDGED ();
1578 regs.r_pc = poppc ();
1579 regs.r_psw = poppc ();
1580 if (FLAG_PM)
1581 regs.r_psw |= FLAGBIT_U;
1582 #ifdef CYCLE_ACCURATE
1583 regs.fast_return = 0;
1584 cycles (6);
1585 #endif
1586 break;
1588 case RXO_revl:
1589 uma = GS ();
1590 umb = (((uma >> 24) & 0xff)
1591 | ((uma >> 8) & 0xff00)
1592 | ((uma << 8) & 0xff0000)
1593 | ((uma << 24) & 0xff000000UL));
1594 PD (umb);
1596 break;
1598 case RXO_revw:
1599 uma = GS ();
1600 umb = (((uma >> 8) & 0x00ff00ff)
1601 | ((uma << 8) & 0xff00ff00UL));
1602 PD (umb);
1604 break;
1606 case RXO_rmpa:
1607 RL(4);
1608 RL(5);
1609 #ifdef CYCLE_ACCURATE
1610 tx = regs.r[3];
1611 #endif
1613 while (regs.r[3] != 0)
1615 long long tmp;
1617 switch (opcode->size)
1619 case RX_Long:
1620 ma = mem_get_si (regs.r[1]);
1621 mb = mem_get_si (regs.r[2]);
1622 regs.r[1] += 4;
1623 regs.r[2] += 4;
1624 break;
1625 case RX_Word:
1626 ma = sign_ext (mem_get_hi (regs.r[1]), 16);
1627 mb = sign_ext (mem_get_hi (regs.r[2]), 16);
1628 regs.r[1] += 2;
1629 regs.r[2] += 2;
1630 break;
1631 case RX_Byte:
1632 ma = sign_ext (mem_get_qi (regs.r[1]), 8);
1633 mb = sign_ext (mem_get_qi (regs.r[2]), 8);
1634 regs.r[1] += 1;
1635 regs.r[2] += 1;
1636 break;
1637 default:
1638 abort ();
1640 /* We do the multiply as a signed value. */
1641 sll = (long long)ma * (long long)mb;
1642 tprintf(" %016llx = %d * %d\n", sll, ma, mb);
1643 /* but we do the sum as unsigned, while sign extending the operands. */
1644 tmp = regs.r[4] + (sll & 0xffffffffUL);
1645 regs.r[4] = tmp & 0xffffffffUL;
1646 tmp >>= 32;
1647 sll >>= 32;
1648 tmp += regs.r[5] + (sll & 0xffffffffUL);
1649 regs.r[5] = tmp & 0xffffffffUL;
1650 tmp >>= 32;
1651 sll >>= 32;
1652 tmp += regs.r[6] + (sll & 0xffffffffUL);
1653 regs.r[6] = tmp & 0xffffffffUL;
1654 tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
1655 (unsigned long) regs.r[6],
1656 (unsigned long) regs.r[5],
1657 (unsigned long) regs.r[4]);
1659 regs.r[3] --;
1661 if (regs.r[6] & 0x00008000)
1662 regs.r[6] |= 0xffff0000UL;
1663 else
1664 regs.r[6] &= 0x0000ffff;
1665 ma = (regs.r[6] & 0x80000000UL) ? FLAGBIT_S : 0;
1666 if (regs.r[6] != 0 && regs.r[6] != 0xffffffffUL)
1667 set_flags (FLAGBIT_O|FLAGBIT_S, ma | FLAGBIT_O);
1668 else
1669 set_flags (FLAGBIT_O|FLAGBIT_S, ma);
1670 #ifdef CYCLE_ACCURATE
1671 switch (opcode->size)
1673 case RX_Long:
1674 cycles (6 + 4 * tx);
1675 break;
1676 case RX_Word:
1677 cycles (6 + 5 * (tx / 2) + 4 * (tx % 2));
1678 break;
1679 case RX_Byte:
1680 cycles (6 + 7 * (tx / 4) + 4 * (tx % 4));
1681 break;
1682 default:
1683 abort ();
1685 #endif
1686 break;
1688 case RXO_rolc:
1689 v = GD ();
1690 ma = v & 0x80000000UL;
1691 v <<= 1;
1692 v |= carry;
1693 set_szc (v, 4, ma);
1694 PD (v);
1696 break;
1698 case RXO_rorc:
1699 uma = GD ();
1700 mb = uma & 1;
1701 uma >>= 1;
1702 uma |= (carry ? 0x80000000UL : 0);
1703 set_szc (uma, 4, mb);
1704 PD (uma);
1706 break;
1708 case RXO_rotl:
1709 mb = GS ();
1710 uma = GD ();
1711 if (mb)
1713 uma = (uma << mb) | (uma >> (32-mb));
1714 mb = uma & 1;
1716 set_szc (uma, 4, mb);
1717 PD (uma);
1719 break;
1721 case RXO_rotr:
1722 mb = GS ();
1723 uma = GD ();
1724 if (mb)
1726 uma = (uma >> mb) | (uma << (32-mb));
1727 mb = uma & 0x80000000;
1729 set_szc (uma, 4, mb);
1730 PD (uma);
1732 break;
1734 case RXO_round:
1735 ma = GS ();
1736 FPCLEAR ();
1737 mb = rxfp_ftoi (ma, regs.r_fpsw);
1738 FPCHECK ();
1739 PD (mb);
1740 tprintf("(int) %g = %d\n", int2float(ma), mb);
1741 set_sz (mb, 4);
1742 E (2);
1743 break;
1745 case RXO_rts:
1747 #ifdef CYCLE_ACCURATE
1748 int cyc = 5;
1749 #endif
1750 regs.r_pc = poppc ();
1751 #ifdef CYCLE_ACCURATE
1752 /* Note: specs say 5, chip says 3. */
1753 if (regs.fast_return && regs.link_register == regs.r_pc)
1755 #ifdef CYCLE_STATS
1756 fast_returns ++;
1757 #endif
1758 tprintf("fast return bonus\n");
1759 cyc -= 2;
1761 cycles (cyc);
1762 regs.fast_return = 0;
1763 branch_alignment_penalty = 1;
1764 #endif
1766 break;
1768 case RXO_rtsd:
1769 if (opcode->op[2].type == RX_Operand_Register)
1771 int i;
1772 /* RTSD cannot pop R0 (sp). */
1773 put_reg (0, get_reg (0) + GS() - (opcode->op[0].reg-opcode->op[2].reg+1)*4);
1774 if (opcode->op[2].reg == 0)
1775 EXCEPTION (EX_UNDEFINED);
1776 #ifdef CYCLE_ACCURATE
1777 tx = opcode->op[0].reg - opcode->op[2].reg + 1;
1778 #endif
1779 for (i = opcode->op[2].reg; i <= opcode->op[0].reg; i ++)
1781 RLD (i);
1782 put_reg (i, pop ());
1785 else
1787 #ifdef CYCLE_ACCURATE
1788 tx = 0;
1789 #endif
1790 put_reg (0, get_reg (0) + GS());
1792 put_reg (pc, poppc());
1793 #ifdef CYCLE_ACCURATE
1794 if (regs.fast_return && regs.link_register == regs.r_pc)
1796 tprintf("fast return bonus\n");
1797 #ifdef CYCLE_STATS
1798 fast_returns ++;
1799 #endif
1800 cycles (tx < 3 ? 3 : tx + 1);
1802 else
1804 cycles (tx < 5 ? 5 : tx + 1);
1806 regs.fast_return = 0;
1807 branch_alignment_penalty = 1;
1808 #endif
1809 break;
1811 case RXO_sat:
1812 if (FLAG_O && FLAG_S)
1813 PD (0x7fffffffUL);
1814 else if (FLAG_O && ! FLAG_S)
1815 PD (0x80000000UL);
1817 break;
1819 case RXO_satr:
1820 if (FLAG_O && ! FLAG_S)
1822 put_reg (6, 0x0);
1823 put_reg (5, 0x7fffffff);
1824 put_reg (4, 0xffffffff);
1826 else if (FLAG_O && FLAG_S)
1828 put_reg (6, 0xffffffff);
1829 put_reg (5, 0x80000000);
1830 put_reg (4, 0x0);
1833 break;
1835 case RXO_sbb:
1836 MATH_OP (-, ! carry);
1837 break;
1839 case RXO_sccnd:
1840 if (GS())
1841 PD (1);
1842 else
1843 PD (0);
1845 break;
1847 case RXO_scmpu:
1848 #ifdef CYCLE_ACCURATE
1849 tx = regs.r[3];
1850 #endif
1851 while (regs.r[3] != 0)
1853 uma = mem_get_qi (regs.r[1] ++);
1854 umb = mem_get_qi (regs.r[2] ++);
1855 regs.r[3] --;
1856 if (uma != umb || uma == 0)
1857 break;
1859 if (uma == umb)
1860 set_zc (1, 1);
1861 else
1862 set_zc (0, ((int)uma - (int)umb) >= 0);
1863 cycles (2 + 4 * (tx / 4) + 4 * (tx % 4));
1864 break;
1866 case RXO_setpsw:
1867 v = 1 << opcode->op[0].reg;
1868 if (FLAG_PM
1869 && (v == FLAGBIT_I
1870 || v == FLAGBIT_U))
1871 break;
1872 regs.r_psw |= v;
1873 cycles (1);
1874 break;
1876 case RXO_smovb:
1877 RL (3);
1878 #ifdef CYCLE_ACCURATE
1879 tx = regs.r[3];
1880 #endif
1881 while (regs.r[3])
1883 uma = mem_get_qi (regs.r[2] --);
1884 mem_put_qi (regs.r[1]--, uma);
1885 regs.r[3] --;
1887 #ifdef CYCLE_ACCURATE
1888 if (tx > 3)
1889 cycles (6 + 3 * (tx / 4) + 3 * (tx % 4));
1890 else
1891 cycles (2 + 3 * (tx % 4));
1892 #endif
1893 break;
1895 case RXO_smovf:
1896 RL (3);
1897 #ifdef CYCLE_ACCURATE
1898 tx = regs.r[3];
1899 #endif
1900 while (regs.r[3])
1902 uma = mem_get_qi (regs.r[2] ++);
1903 mem_put_qi (regs.r[1]++, uma);
1904 regs.r[3] --;
1906 cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
1907 break;
1909 case RXO_smovu:
1910 #ifdef CYCLE_ACCURATE
1911 tx = regs.r[3];
1912 #endif
1913 while (regs.r[3] != 0)
1915 uma = mem_get_qi (regs.r[2] ++);
1916 mem_put_qi (regs.r[1]++, uma);
1917 regs.r[3] --;
1918 if (uma == 0)
1919 break;
1921 cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
1922 break;
1924 case RXO_shar: /* d = ma >> mb */
1925 SHIFT_OP (sll, int, mb, >>=, 1);
1926 E (1);
1927 break;
1929 case RXO_shll: /* d = ma << mb */
1930 SHIFT_OP (ll, int, mb, <<=, 0x80000000UL);
1931 E (1);
1932 break;
1934 case RXO_shlr: /* d = ma >> mb */
1935 SHIFT_OP (ll, unsigned int, mb, >>=, 1);
1936 E (1);
1937 break;
1939 case RXO_sstr:
1940 RL (3);
1941 #ifdef CYCLE_ACCURATE
1942 tx = regs.r[3];
1943 #endif
1944 switch (opcode->size)
1946 case RX_Long:
1947 while (regs.r[3] != 0)
1949 mem_put_si (regs.r[1], regs.r[2]);
1950 regs.r[1] += 4;
1951 regs.r[3] --;
1953 cycles (2 + tx);
1954 break;
1955 case RX_Word:
1956 while (regs.r[3] != 0)
1958 mem_put_hi (regs.r[1], regs.r[2]);
1959 regs.r[1] += 2;
1960 regs.r[3] --;
1962 cycles (2 + (int)(tx / 2) + tx % 2);
1963 break;
1964 case RX_Byte:
1965 while (regs.r[3] != 0)
1967 mem_put_qi (regs.r[1], regs.r[2]);
1968 regs.r[1] ++;
1969 regs.r[3] --;
1971 cycles (2 + (int)(tx / 4) + tx % 4);
1972 break;
1973 default:
1974 abort ();
1976 break;
1978 case RXO_stcc:
1979 if (GS2())
1980 PD (GS ());
1982 break;
1984 case RXO_stop:
1985 PRIVILEDGED ();
1986 regs.r_psw |= FLAGBIT_I;
1987 DO_RETURN (RX_MAKE_STOPPED(0));
1989 case RXO_sub:
1990 MATH_OP (-, 0);
1991 break;
1993 case RXO_suntil:
1994 RL(3);
1995 #ifdef CYCLE_ACCURATE
1996 tx = 0;
1997 #endif
1998 if (regs.r[3] == 0)
2000 cycles (3);
2001 break;
2003 switch (opcode->size)
2005 case RX_Long:
2006 uma = get_reg (2);
2007 while (regs.r[3] != 0)
2009 regs.r[3] --;
2010 umb = mem_get_si (get_reg (1));
2011 regs.r[1] += 4;
2012 #ifdef CYCLE_ACCURATE
2013 tx ++;
2014 #endif
2015 if (umb == uma)
2016 break;
2018 #ifdef CYCLE_ACCURATE
2019 cycles (3 + 3 * tx);
2020 #endif
2021 break;
2022 case RX_Word:
2023 uma = get_reg (2) & 0xffff;
2024 while (regs.r[3] != 0)
2026 regs.r[3] --;
2027 umb = mem_get_hi (get_reg (1));
2028 regs.r[1] += 2;
2029 #ifdef CYCLE_ACCURATE
2030 tx ++;
2031 #endif
2032 if (umb == uma)
2033 break;
2035 #ifdef CYCLE_ACCURATE
2036 cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
2037 #endif
2038 break;
2039 case RX_Byte:
2040 uma = get_reg (2) & 0xff;
2041 while (regs.r[3] != 0)
2043 regs.r[3] --;
2044 umb = mem_get_qi (regs.r[1]);
2045 regs.r[1] += 1;
2046 #ifdef CYCLE_ACCURATE
2047 tx ++;
2048 #endif
2049 if (umb == uma)
2050 break;
2052 #ifdef CYCLE_ACCURATE
2053 cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
2054 #endif
2055 break;
2056 default:
2057 abort();
2059 if (uma == umb)
2060 set_zc (1, 1);
2061 else
2062 set_zc (0, ((int)uma - (int)umb) >= 0);
2063 break;
2065 case RXO_swhile:
2066 RL(3);
2067 #ifdef CYCLE_ACCURATE
2068 tx = 0;
2069 #endif
2070 if (regs.r[3] == 0)
2071 break;
2072 switch (opcode->size)
2074 case RX_Long:
2075 uma = get_reg (2);
2076 while (regs.r[3] != 0)
2078 regs.r[3] --;
2079 umb = mem_get_si (get_reg (1));
2080 regs.r[1] += 4;
2081 #ifdef CYCLE_ACCURATE
2082 tx ++;
2083 #endif
2084 if (umb != uma)
2085 break;
2087 #ifdef CYCLE_ACCURATE
2088 cycles (3 + 3 * tx);
2089 #endif
2090 break;
2091 case RX_Word:
2092 uma = get_reg (2) & 0xffff;
2093 while (regs.r[3] != 0)
2095 regs.r[3] --;
2096 umb = mem_get_hi (get_reg (1));
2097 regs.r[1] += 2;
2098 #ifdef CYCLE_ACCURATE
2099 tx ++;
2100 #endif
2101 if (umb != uma)
2102 break;
2104 #ifdef CYCLE_ACCURATE
2105 cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
2106 #endif
2107 break;
2108 case RX_Byte:
2109 uma = get_reg (2) & 0xff;
2110 while (regs.r[3] != 0)
2112 regs.r[3] --;
2113 umb = mem_get_qi (regs.r[1]);
2114 regs.r[1] += 1;
2115 #ifdef CYCLE_ACCURATE
2116 tx ++;
2117 #endif
2118 if (umb != uma)
2119 break;
2121 #ifdef CYCLE_ACCURATE
2122 cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
2123 #endif
2124 break;
2125 default:
2126 abort();
2128 if (uma == umb)
2129 set_zc (1, 1);
2130 else
2131 set_zc (0, ((int)uma - (int)umb) >= 0);
2132 break;
2134 case RXO_wait:
2135 PRIVILEDGED ();
2136 regs.r_psw |= FLAGBIT_I;
2137 DO_RETURN (RX_MAKE_STOPPED(0));
2139 case RXO_xchg:
2140 #ifdef CYCLE_ACCURATE
2141 regs.m2m = 0;
2142 #endif
2143 v = GS (); /* This is the memory operand, if any. */
2144 PS (GD ()); /* and this may change the address register. */
2145 PD (v);
2147 #ifdef CYCLE_ACCURATE
2148 /* all M cycles happen during xchg's cycles. */
2149 memory_dest = 0;
2150 memory_source = 0;
2151 #endif
2152 break;
2154 case RXO_xor:
2155 LOGIC_OP (^);
2156 break;
2158 default:
2159 EXCEPTION (EX_UNDEFINED);
2162 #ifdef CYCLE_ACCURATE
2163 regs.m2m = 0;
2164 if (memory_source)
2165 regs.m2m |= M2M_SRC;
2166 if (memory_dest)
2167 regs.m2m |= M2M_DST;
2169 regs.rt = new_rt;
2170 new_rt = -1;
2171 #endif
2173 #ifdef CYCLE_STATS
2174 if (prev_cycle_count == regs.cycle_count)
2176 printf("Cycle count not updated! id %s\n", id_names[opcode->id]);
2177 abort ();
2179 #endif
2181 #ifdef CYCLE_STATS
2182 if (running_benchmark)
2184 int omap = op_lookup (opcode->op[0].type, opcode->op[1].type, opcode->op[2].type);
2187 cycles_per_id[opcode->id][omap] += regs.cycle_count - prev_cycle_count;
2188 times_per_id[opcode->id][omap] ++;
2190 times_per_pair[prev_opcode_id][po0][opcode->id][omap] ++;
2192 prev_opcode_id = opcode->id;
2193 po0 = omap;
2195 #endif
2197 return RX_MAKE_STEPPED ();
2200 #ifdef CYCLE_STATS
2201 void
2202 reset_pipeline_stats (void)
2204 memset (cycles_per_id, 0, sizeof(cycles_per_id));
2205 memset (times_per_id, 0, sizeof(times_per_id));
2206 memory_stalls = 0;
2207 register_stalls = 0;
2208 branch_stalls = 0;
2209 branch_alignment_stalls = 0;
2210 fast_returns = 0;
2211 memset (times_per_pair, 0, sizeof(times_per_pair));
2212 running_benchmark = 1;
2214 benchmark_start_cycle = regs.cycle_count;
2217 void
2218 halt_pipeline_stats (void)
2220 running_benchmark = 0;
2221 benchmark_end_cycle = regs.cycle_count;
2223 #endif
2225 void
2226 pipeline_stats (void)
2228 #ifdef CYCLE_STATS
2229 int i, o1;
2230 int p, p1;
2231 #endif
2233 #ifdef CYCLE_ACCURATE
2234 if (verbose == 1)
2236 printf ("cycles: %llu\n", regs.cycle_count);
2237 return;
2240 printf ("cycles: %13s\n", comma (regs.cycle_count));
2241 #endif
2243 #ifdef CYCLE_STATS
2244 if (benchmark_start_cycle)
2245 printf ("bmark: %13s\n", comma (benchmark_end_cycle - benchmark_start_cycle));
2247 printf("\n");
2248 for (i = 0; i < N_RXO; i++)
2249 for (o1 = 0; o1 < N_MAP; o1 ++)
2250 if (times_per_id[i][o1])
2251 printf("%13s %13s %7.2f %s %s\n",
2252 comma (cycles_per_id[i][o1]),
2253 comma (times_per_id[i][o1]),
2254 (double)cycles_per_id[i][o1] / times_per_id[i][o1],
2255 op_cache_string(o1),
2256 id_names[i]+4);
2258 printf("\n");
2259 for (p = 0; p < N_RXO; p ++)
2260 for (p1 = 0; p1 < N_MAP; p1 ++)
2261 for (i = 0; i < N_RXO; i ++)
2262 for (o1 = 0; o1 < N_MAP; o1 ++)
2263 if (times_per_pair[p][p1][i][o1])
2265 printf("%13s %s %-9s -> %s %s\n",
2266 comma (times_per_pair[p][p1][i][o1]),
2267 op_cache_string(p1),
2268 id_names[p]+4,
2269 op_cache_string(o1),
2270 id_names[i]+4);
2273 printf("\n");
2274 printf("%13s memory stalls\n", comma (memory_stalls));
2275 printf("%13s register stalls\n", comma (register_stalls));
2276 printf("%13s branches taken (non-return)\n", comma (branch_stalls));
2277 printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls));
2278 printf("%13s fast returns\n", comma (fast_returns));
2279 #endif