82b92b5167d3abe0b63382f669329265ee6e6c24
1 /* rx.c --- opcode semantics for stand-alone RX simulator.
3 Copyright (C) 2008-2017 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/>. */
27 #include "opcode/rx.h"
36 static const char * id_names
[] = {
38 "RXO_mov", /* d = s (signed) */
39 "RXO_movbi", /* d = [s,s2] (signed) */
40 "RXO_movbir", /* [s,s2] = d (signed) */
41 "RXO_pushm", /* s..s2 */
42 "RXO_popm", /* s..s2 */
43 "RXO_xchg", /* s <-> d */
44 "RXO_stcc", /* d = s if cond(s2) */
45 "RXO_rtsd", /* rtsd, 1=imm, 2-0 = reg if reg type */
47 /* These are all either d OP= s or, if s2 is set, d = s OP s2. Note
48 that d may be "None". */
61 "RXO_adc", /* d = d + s + carry */
62 "RXO_sbb", /* d = d - s - ~carry */
63 "RXO_abs", /* d = |s| */
64 "RXO_max", /* d = max(d,s) */
65 "RXO_min", /* d = min(d,s) */
66 "RXO_emul", /* d:64 = d:32 * s */
67 "RXO_emulu", /* d:64 = d:32 * s (unsigned) */
69 "RXO_rolc", /* d <<= 1 through carry */
70 "RXO_rorc", /* d >>= 1 through carry*/
71 "RXO_rotl", /* d <<= #s without carry */
72 "RXO_rotr", /* d >>= #s without carry*/
73 "RXO_revw", /* d = revw(s) */
74 "RXO_revl", /* d = revl(s) */
75 "RXO_branch", /* pc = d if cond(s) */
76 "RXO_branchrel",/* pc += d if cond(s) */
77 "RXO_jsr", /* pc = d */
78 "RXO_jsrrel", /* pc += d */
108 "RXO_sat", /* sat(d) */
111 "RXO_fadd", /* d op= s */
120 "RXO_bset", /* d |= (1<<s) */
121 "RXO_bclr", /* d &= ~(1<<s) */
122 "RXO_btst", /* s & (1<<s2) */
123 "RXO_bnot", /* d ^= (1<<s) */
124 "RXO_bmcc", /* d<s> = cond(s2) */
126 "RXO_clrpsw", /* flag index in d */
127 "RXO_setpsw", /* flag index in d */
128 "RXO_mvtipl", /* new IPL in s */
132 "RXO_rtd", /* undocumented */
134 "RXO_dbt", /* undocumented */
135 "RXO_int", /* vector id in s */
139 "RXO_sccnd", /* d = cond(s) ? 1 : 0 */
142 static const char * optype_names
[] = {
144 "#Imm", /* #addend */
146 "[Rn]", /* [Rn + addend] */
149 " cc ", /* eq, gtu, etc */
150 "Flag", /* [UIOSZC] */
151 "RbRi" /* [Rb + scale * Ri] */
154 #define N_RXO (sizeof(id_names)/sizeof(id_names[0]))
155 #define N_RXT (sizeof(optype_names)/sizeof(optype_names[0]))
158 static unsigned long long benchmark_start_cycle
;
159 static unsigned long long benchmark_end_cycle
;
161 static int op_cache
[N_RXT
][N_RXT
][N_RXT
];
162 static int op_cache_rev
[N_MAP
];
163 static int op_cache_idx
= 0;
166 op_lookup (int a
, int b
, int c
)
168 if (op_cache
[a
][b
][c
])
169 return op_cache
[a
][b
][c
];
171 if (op_cache_idx
>= N_MAP
)
173 printf("op_cache_idx exceeds %d\n", N_MAP
);
176 op_cache
[a
][b
][c
] = op_cache_idx
;
177 op_cache_rev
[op_cache_idx
] = (a
<<8) | (b
<<4) | c
;
182 op_cache_string (int map
)
185 static char cb
[5][20];
188 map
= op_cache_rev
[map
];
193 sprintf(cb
[ci
], "%s %s %s", optype_names
[a
], optype_names
[b
], optype_names
[c
]);
197 static unsigned long long cycles_per_id
[N_RXO
][N_MAP
];
198 static unsigned long long times_per_id
[N_RXO
][N_MAP
];
199 static unsigned long long memory_stalls
;
200 static unsigned long long register_stalls
;
201 static unsigned long long branch_stalls
;
202 static unsigned long long branch_alignment_stalls
;
203 static unsigned long long fast_returns
;
205 static unsigned long times_per_pair
[N_RXO
][N_MAP
][N_RXO
][N_MAP
];
206 static int prev_opcode_id
= RXO_unknown
;
213 #endif /* CYCLE_STATS */
216 #ifdef CYCLE_ACCURATE
218 static int new_rt
= -1;
220 /* Number of cycles to add if an insn spans an 8-byte boundary. */
221 static int branch_alignment_penalty
= 0;
225 static int running_benchmark
= 1;
227 #define tprintf if (trace && running_benchmark) printf
229 jmp_buf decode_jmp_buf
;
230 unsigned int rx_cycles
= 0;
232 #ifdef CYCLE_ACCURATE
233 /* If nonzero, memory was read at some point and cycle latency might
235 static int memory_source
= 0;
236 /* If nonzero, memory was written and extra cycles might be
238 static int memory_dest
= 0;
241 cycles (int throughput
)
243 tprintf("%d cycles\n", throughput
);
244 regs
.cycle_count
+= throughput
;
247 /* Number of execution (E) cycles the op uses. For memory sources, we
248 include the load micro-op stall as two extra E cycles. */
249 #define E(c) cycles (memory_source ? c + 2 : c)
250 #define E1 cycles (1)
251 #define E2 cycles (2)
252 #define EBIT cycles (memory_source ? 2 : 1)
254 /* Check to see if a read latency must be applied for a given register. */
258 tprintf("register %d load stall\n", r); \
259 regs.cycle_count ++; \
260 STATS(register_stalls ++); \
267 tprintf ("Rt now %d\n", r); \
272 lsb_count (unsigned long v
, int is_signed
)
275 if (is_signed
&& (v
& 0x80000000U
))
276 v
= (unsigned long)(long)(-v
);
277 for (i
=31; i
>=0; i
--)
280 /* v is 0..31, we want 1=1-2, 2=3-4, 3=5-6, etc. */
288 divu_cycles(unsigned long num
, unsigned long den
)
290 int nb
= lsb_count (num
, 0);
291 int db
= lsb_count (den
, 0);
303 div_cycles(long num
, long den
)
305 int nb
= lsb_count ((unsigned long)num
, 1);
306 int db
= lsb_count ((unsigned long)den
, 1);
317 #else /* !CYCLE_ACCURATE */
327 #define divu_cycles(n,d)
328 #define div_cycles(n,d)
330 #endif /* else CYCLE_ACCURATE */
332 static int size2bytes
[] = {
333 4, 1, 1, 1, 2, 2, 2, 3, 4
340 #define rx_abort() _rx_abort(__FILE__, __LINE__)
342 _rx_abort (const char *file
, int line
)
344 if (strrchr (file
, '/'))
345 file
= strrchr (file
, '/') + 1;
346 fprintf(stderr
, "abort at %s:%d\n", file
, line
);
350 static unsigned char *get_byte_base
;
351 static RX_Opcode_Decoded
**decode_cache_base
;
352 static SI get_byte_page
;
358 decode_cache_base
= 0;
363 maybe_get_mem_page (SI tpc
)
365 if (((tpc
^ get_byte_page
) & NONPAGE_MASK
) || enable_counting
)
367 get_byte_page
= tpc
& NONPAGE_MASK
;
368 get_byte_base
= rx_mem_ptr (get_byte_page
, MPA_READING
) - get_byte_page
;
369 decode_cache_base
= rx_mem_decode_cache (get_byte_page
) - get_byte_page
;
373 /* This gets called a *lot* so optimize it. */
375 rx_get_byte (void *vdata
)
377 RX_Data
*rx_data
= (RX_Data
*)vdata
;
378 SI tpc
= rx_data
->dpc
;
380 /* See load.c for an explanation of this. */
384 maybe_get_mem_page (tpc
);
387 return get_byte_base
[tpc
];
391 get_op (const RX_Opcode_Decoded
*rd
, int i
)
393 const RX_Opcode_Operand
*o
= rd
->op
+ i
;
398 case RX_Operand_None
:
401 case RX_Operand_Immediate
: /* #addend */
404 case RX_Operand_Register
: /* Rn */
406 rv
= get_reg (o
->reg
);
409 case RX_Operand_Predec
: /* [-Rn] */
410 put_reg (o
->reg
, get_reg (o
->reg
) - size2bytes
[o
->size
]);
412 case RX_Operand_Postinc
: /* [Rn+] */
413 case RX_Operand_Zero_Indirect
: /* [Rn + 0] */
414 case RX_Operand_Indirect
: /* [Rn + addend] */
415 case RX_Operand_TwoReg
: /* [Rn + scale * R2] */
416 #ifdef CYCLE_ACCURATE
418 if (o
->type
== RX_Operand_TwoReg
)
421 if (regs
.m2m
== M2M_BOTH
)
423 tprintf("src memory stall\n");
434 if (o
->type
== RX_Operand_TwoReg
)
435 addr
= get_reg (o
->reg
) * size2bytes
[rd
->size
] + get_reg (rd
->op
[2].reg
);
437 addr
= get_reg (o
->reg
) + o
->addend
;
445 case RX_Byte
: /* undefined extension */
448 rv
= mem_get_qi (addr
);
451 case RX_Word
: /* undefined extension */
454 rv
= mem_get_hi (addr
);
458 rv
= mem_get_psi (addr
);
462 rv
= mem_get_si (addr
);
466 if (o
->type
== RX_Operand_Postinc
)
467 put_reg (o
->reg
, get_reg (o
->reg
) + size2bytes
[o
->size
]);
471 case RX_Operand_Condition
: /* eq, gtu, etc */
472 return condition_true (o
->reg
);
474 case RX_Operand_Flag
: /* [UIOSZC] */
475 return (regs
.r_psw
& (1 << o
->reg
)) ? 1 : 0;
478 /* if we've gotten here, we need to clip/extend the value according
486 case RX_Byte
: /* undefined extension */
487 rv
|= 0xdeadbe00; /* keep them honest */
495 rv
= sign_ext (rv
, 8);
498 case RX_Word
: /* undefined extension */
499 rv
|= 0xdead0000; /* keep them honest */
507 rv
= sign_ext (rv
, 16);
521 put_op (const RX_Opcode_Decoded
*rd
, int i
, int v
)
523 const RX_Opcode_Operand
*o
= rd
->op
+ i
;
530 if (o
->type
!= RX_Operand_Register
)
534 case RX_Byte
: /* undefined extension */
535 v
|= 0xdeadbe00; /* keep them honest */
546 case RX_Word
: /* undefined extension */
547 v
|= 0xdead0000; /* keep them honest */
555 v
= sign_ext (v
, 16);
568 case RX_Operand_None
:
569 /* Opcodes like TST and CMP use this. */
572 case RX_Operand_Immediate
: /* #addend */
573 case RX_Operand_Condition
: /* eq, gtu, etc */
576 case RX_Operand_Register
: /* Rn */
581 case RX_Operand_Predec
: /* [-Rn] */
582 put_reg (o
->reg
, get_reg (o
->reg
) - size2bytes
[o
->size
]);
584 case RX_Operand_Postinc
: /* [Rn+] */
585 case RX_Operand_Zero_Indirect
: /* [Rn + 0] */
586 case RX_Operand_Indirect
: /* [Rn + addend] */
587 case RX_Operand_TwoReg
: /* [Rn + scale * R2] */
589 #ifdef CYCLE_ACCURATE
590 if (regs
.m2m
== M2M_BOTH
)
592 tprintf("dst memory stall\n");
602 if (o
->type
== RX_Operand_TwoReg
)
603 addr
= get_reg (o
->reg
) * size2bytes
[rd
->size
] + get_reg (rd
->op
[2].reg
);
605 addr
= get_reg (o
->reg
) + o
->addend
;
613 case RX_Byte
: /* undefined extension */
616 mem_put_qi (addr
, v
);
619 case RX_Word
: /* undefined extension */
622 mem_put_hi (addr
, v
);
626 mem_put_psi (addr
, v
);
630 mem_put_si (addr
, v
);
634 if (o
->type
== RX_Operand_Postinc
)
635 put_reg (o
->reg
, get_reg (o
->reg
) + size2bytes
[o
->size
]);
639 case RX_Operand_Flag
: /* [UIOSZC] */
641 regs
.r_psw
|= (1 << o
->reg
);
643 regs
.r_psw
&= ~(1 << o
->reg
);
648 #define PD(x) put_op (opcode, 0, x)
649 #define PS(x) put_op (opcode, 1, x)
650 #define PS2(x) put_op (opcode, 2, x)
651 #define GD() get_op (opcode, 0)
652 #define GS() get_op (opcode, 1)
653 #define GS2() get_op (opcode, 2)
654 #define DSZ() size2bytes[opcode->op[0].size]
655 #define SSZ() size2bytes[opcode->op[0].size]
656 #define S2SZ() size2bytes[opcode->op[0].size]
658 /* "Universal" sources. */
659 #define US1() ((opcode->op[2].type == RX_Operand_None) ? GD() : GS())
660 #define US2() ((opcode->op[2].type == RX_Operand_None) ? GS() : GS2())
665 int rsp
= get_reg (sp
);
668 mem_put_si (rsp
, val
);
671 /* Just like the above, but tag the memory as "pushed pc" so if anyone
672 tries to write to it, it will cause an error. */
676 int rsp
= get_reg (sp
);
679 mem_put_si (rsp
, val
);
680 mem_set_content_range (rsp
, rsp
+3, MC_PUSHED_PC
);
687 int rsp
= get_reg (sp
);
688 rv
= mem_get_si (rsp
);
698 int rsp
= get_reg (sp
);
699 if (mem_get_content_type (rsp
) != MC_PUSHED_PC
)
700 execution_error (SIM_ERR_CORRUPT_STACK
, rsp
);
701 rv
= mem_get_si (rsp
);
702 mem_set_content_range (rsp
, rsp
+3, MC_UNINIT
);
708 #define MATH_OP(vop,c) \
712 ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
713 tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
714 ma = sign_ext (uma, DSZ() * 8); \
715 mb = sign_ext (umb, DSZ() * 8); \
716 sll = (long long) ma vop (long long) mb vop c; \
717 tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
718 set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
723 #define LOGIC_OP(vop) \
728 tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
734 #define SHIFT_OP(val, type, count, OP, carry_mask) \
739 tprintf("%lld " #OP " %d\n", val, count); \
740 for (i = 0; i < count; i ++) \
742 c = val & carry_mask; \
745 set_oszc (val, 4, c); \
771 fop_fadd (fp_t s1
, fp_t s2
, fp_t
*d
)
773 *d
= rxfp_add (s1
, s2
);
778 fop_fmul (fp_t s1
, fp_t s2
, fp_t
*d
)
780 *d
= rxfp_mul (s1
, s2
);
785 fop_fdiv (fp_t s1
, fp_t s2
, fp_t
*d
)
787 *d
= rxfp_div (s1
, s2
);
792 fop_fsub (fp_t s1
, fp_t s2
, fp_t
*d
)
794 *d
= rxfp_sub (s1
, s2
);
798 #define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
799 #define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
802 return do_fp_exception (opcode_pc)
804 #define FLOAT_OP(func) \
811 do_store = fop_##func (fa, fb, &fc); \
812 tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
817 if ((fc & 0x80000000UL) != 0) \
819 if ((fc & 0x7fffffffUL) == 0) \
821 set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
824 #define carry (FLAG_C ? 1 : 0)
830 } exception_info
[] = {
831 { 0xFFFFFFD0UL
, "priviledged opcode", SIGILL
},
832 { 0xFFFFFFD4UL
, "access violation", SIGSEGV
},
833 { 0xFFFFFFDCUL
, "undefined opcode", SIGILL
},
834 { 0xFFFFFFE4UL
, "floating point", SIGFPE
}
836 #define EX_PRIVILEDGED 0
838 #define EX_UNDEFINED 2
839 #define EX_FLOATING 3
840 #define EXCEPTION(n) \
841 return generate_exception (n, opcode_pc)
843 #define PRIVILEDGED() \
845 EXCEPTION (EX_PRIVILEDGED)
848 generate_exception (unsigned long type
, SI opcode_pc
)
850 SI old_psw
, old_pc
, new_pc
;
852 new_pc
= mem_get_si (exception_info
[type
].vaddr
);
853 /* 0x00020000 is the value used to initialise the known
854 exception vectors (see rx.ld), but it is a reserved
855 area of memory so do not try to access it, and if the
856 value has not been changed by the program then the
857 vector has not been installed. */
858 if (new_pc
== 0 || new_pc
== 0x00020000)
861 return RX_MAKE_STOPPED (exception_info
[type
].signal
);
863 fprintf(stderr
, "Unhandled %s exception at pc = %#lx\n",
864 exception_info
[type
].str
, (unsigned long) opcode_pc
);
865 if (type
== EX_FLOATING
)
867 int mask
= FPPENDING ();
868 fprintf (stderr
, "Pending FP exceptions:");
869 if (mask
& FPSWBITS_FV
)
870 fprintf(stderr
, " Invalid");
871 if (mask
& FPSWBITS_FO
)
872 fprintf(stderr
, " Overflow");
873 if (mask
& FPSWBITS_FZ
)
874 fprintf(stderr
, " Division-by-zero");
875 if (mask
& FPSWBITS_FU
)
876 fprintf(stderr
, " Underflow");
877 if (mask
& FPSWBITS_FX
)
878 fprintf(stderr
, " Inexact");
879 if (mask
& FPSWBITS_CE
)
880 fprintf(stderr
, " Unimplemented");
881 fprintf(stderr
, "\n");
883 return RX_MAKE_EXITED (1);
886 tprintf ("Triggering %s exception\n", exception_info
[type
].str
);
888 old_psw
= regs
.r_psw
;
889 regs
.r_psw
&= ~ (FLAGBIT_I
| FLAGBIT_U
| FLAGBIT_PM
);
894 return RX_MAKE_STEPPED ();
898 generate_access_exception (void)
902 rv
= generate_exception (EX_ACCESS
, regs
.r_pc
);
904 longjmp (decode_jmp_buf
, rv
);
908 do_fp_exception (unsigned long opcode_pc
)
911 EXCEPTION (EX_FLOATING
);
912 return RX_MAKE_STEPPED ();
916 op_is_memory (const RX_Opcode_Decoded
*rd
, int i
)
918 switch (rd
->op
[i
].type
)
920 case RX_Operand_Predec
:
921 case RX_Operand_Postinc
:
922 case RX_Operand_Indirect
:
928 #define OM(i) op_is_memory (opcode, i)
930 #define DO_RETURN(x) { longjmp (decode_jmp_buf, x); }
935 unsigned int uma
=0, umb
=0;
938 unsigned long long ll
;
940 unsigned long opcode_pc
;
942 const RX_Opcode_Decoded
*opcode
;
944 unsigned long long prev_cycle_count
;
946 #ifdef CYCLE_ACCURATE
951 prev_cycle_count
= regs
.cycle_count
;
954 #ifdef CYCLE_ACCURATE
961 maybe_get_mem_page (regs
.r_pc
);
963 opcode_pc
= regs
.r_pc
;
965 /* Note that we don't word-swap this point, there's no point. */
966 if (decode_cache_base
[opcode_pc
] == NULL
)
968 RX_Opcode_Decoded
*opcode_w
;
969 rx_data
.dpc
= opcode_pc
;
970 opcode_w
= decode_cache_base
[opcode_pc
] = calloc (1, sizeof (RX_Opcode_Decoded
));
971 opcode_size
= rx_decode_opcode (opcode_pc
, opcode_w
,
972 rx_get_byte
, &rx_data
);
977 opcode
= decode_cache_base
[opcode_pc
];
978 opcode_size
= opcode
->n_bytes
;
981 #ifdef CYCLE_ACCURATE
982 if (branch_alignment_penalty
)
984 if ((regs
.r_pc
^ (regs
.r_pc
+ opcode_size
- 1)) & ~7)
986 tprintf("1 cycle branch alignment penalty\n");
987 cycles (branch_alignment_penalty
);
989 branch_alignment_stalls
++;
992 branch_alignment_penalty
= 0;
996 regs
.r_pc
+= opcode_size
;
998 rx_flagmask
= opcode
->flags_s
;
999 rx_flagand
= ~(int)opcode
->flags_0
;
1000 rx_flagor
= opcode
->flags_1
;
1006 tprintf("|%lld| = ", sll
);
1009 tprintf("%lld\n", sll
);
1030 if (opcode
->op
[0].type
== RX_Operand_Register
)
1042 if (opcode
->op
[0].type
== RX_Operand_Register
)
1057 if (opcode
->op
[0].type
== RX_Operand_Register
)
1067 if (opcode
->op
[1].type
== RX_Operand_None
|| GS())
1069 #ifdef CYCLE_ACCURATE
1070 SI old_pc
= regs
.r_pc
;
1074 #ifdef CYCLE_ACCURATE
1075 delta
= regs
.r_pc
- old_pc
;
1076 if (delta
>= 0 && delta
< 16
1079 tprintf("near forward branch bonus\n");
1085 branch_alignment_penalty
= 1;
1092 #ifdef CYCLE_ACCURATE
1099 if (opcode
->op
[1].type
== RX_Operand_None
|| GS())
1102 regs
.r_pc
= opcode_pc
+ delta
;
1103 #ifdef CYCLE_ACCURATE
1104 /* Note: specs say 3, chip says 2. */
1105 if (delta
>= 0 && delta
< 16
1108 tprintf("near forward branch bonus\n");
1114 branch_alignment_penalty
= 1;
1121 #ifdef CYCLE_ACCURATE
1129 int old_psw
= regs
.r_psw
;
1131 DO_RETURN (RX_MAKE_HIT_BREAK ());
1132 if (regs
.r_intb
== 0)
1134 tprintf("BREAK hit, no vector table.\n");
1135 DO_RETURN (RX_MAKE_EXITED(1));
1137 regs
.r_psw
&= ~(FLAGBIT_I
| FLAGBIT_U
| FLAGBIT_PM
);
1140 regs
.r_pc
= mem_get_si (regs
.r_intb
);
1148 if (opcode
->op
[0].type
== RX_Operand_Register
)
1160 if (opcode
->op
[1].type
== RX_Operand_Register
)
1164 umb
= ma
& (1 << mb
);
1165 set_zc (! umb
, umb
);
1170 v
= 1 << opcode
->op
[0].reg
;
1179 case RXO_div
: /* d = d / s */
1182 tprintf("%d / %d = ", mb
, ma
);
1183 if (ma
== 0 || (ma
== -1 && (unsigned int) mb
== 0x80000000))
1186 set_flags (FLAGBIT_O
, FLAGBIT_O
);
1193 set_flags (FLAGBIT_O
, 0);
1195 div_cycles (mb
, ma
);
1199 case RXO_divu
: /* d = d / s */
1202 tprintf("%u / %u = ", umb
, uma
);
1206 set_flags (FLAGBIT_O
, FLAGBIT_O
);
1213 set_flags (FLAGBIT_O
, 0);
1215 divu_cycles (umb
, uma
);
1222 sll
= (long long)ma
* (long long)mb
;
1223 tprintf("%d * %d = %lld\n", ma
, mb
, sll
);
1224 put_reg (opcode
->op
[0].reg
, sll
);
1225 put_reg (opcode
->op
[0].reg
+ 1, sll
>> 32);
1232 ll
= (long long)uma
* (long long)umb
;
1233 tprintf("%#x * %#x = %#llx\n", uma
, umb
, ll
);
1234 put_reg (opcode
->op
[0].reg
, ll
);
1235 put_reg (opcode
->op
[0].reg
+ 1, ll
>> 32);
1265 regs
.r_psw
= regs
.r_bpsw
;
1266 regs
.r_pc
= regs
.r_bpc
;
1267 #ifdef CYCLE_ACCURATE
1268 regs
.fast_return
= 0;
1281 mb
= rxfp_ftoi (ma
, FPRM_ZERO
);
1284 tprintf("(int) %g = %d\n", int2float(ma
), mb
);
1293 int rc
= rx_syscall (regs
.r
[5]);
1294 if (! RX_STEPPED (rc
))
1299 int old_psw
= regs
.r_psw
;
1300 regs
.r_psw
&= ~(FLAGBIT_I
| FLAGBIT_U
| FLAGBIT_PM
);
1303 regs
.r_pc
= mem_get_si (regs
.r_intb
+ 4 * v
);
1311 mb
= rxfp_itof (ma
, regs
.r_fpsw
);
1313 tprintf("(float) %d = %x\n", ma
, mb
);
1322 #ifdef CYCLE_ACCURATE
1327 #ifdef CYCLE_ACCURATE
1328 regs
.link_register
= regs
.r_pc
;
1330 pushpc (get_reg (pc
));
1331 if (opcode
->id
== RXO_jsrrel
)
1333 #ifdef CYCLE_ACCURATE
1334 delta
= v
- regs
.r_pc
;
1337 #ifdef CYCLE_ACCURATE
1338 /* Note: docs say 3, chip says 2 */
1339 if (delta
>= 0 && delta
< 16)
1341 tprintf ("near forward jsr bonus\n");
1346 branch_alignment_penalty
= 1;
1349 regs
.fast_return
= 1;
1355 ll
= (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
1357 put_reg64 (acc64
, ll
+ regs
.r_acc
);
1362 ll
= (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
1364 put_reg64 (acc64
, ll
+ regs
.r_acc
);
1391 if (opcode
->op
[1].type
== RX_Operand_Register
1392 && opcode
->op
[1].reg
== 17 /* PC */)
1394 /* Special case. We want the address of the insn, not the
1395 address of the next insn. */
1399 if (opcode
->op
[0].type
== RX_Operand_Register
1400 && opcode
->op
[0].reg
== 16 /* PSW */)
1402 /* Special case, LDC and POPC can't ever modify PM. */
1403 int pm
= regs
.r_psw
& FLAGBIT_PM
;
1408 v
&= ~ (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1414 /* various things can't be changed in user mode. */
1415 if (opcode
->op
[0].type
== RX_Operand_Register
)
1416 if (opcode
->op
[0].reg
== 32)
1418 v
&= ~ (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1419 v
|= regs
.r_psw
& (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1421 if (opcode
->op
[0].reg
== 34 /* ISP */
1422 || opcode
->op
[0].reg
== 37 /* BPSW */
1423 || opcode
->op
[0].reg
== 39 /* INTB */
1424 || opcode
->op
[0].reg
== 38 /* VCT */)
1425 /* These are ignored. */
1435 #ifdef CYCLE_ACCURATE
1436 if ((opcode
->op
[0].type
== RX_Operand_Predec
1437 && opcode
->op
[1].type
== RX_Operand_Register
)
1438 || (opcode
->op
[0].type
== RX_Operand_Postinc
1439 && opcode
->op
[1].type
== RX_Operand_Register
))
1441 /* Special case: push reg doesn't cause a memory stall. */
1443 tprintf("push special case\n");
1462 ll
= (unsigned long long) US1() * (unsigned long long) v
;
1469 ll
= (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v
>> 16);
1471 put_reg64 (acc64
, ll
);
1477 ll
= (long long)(signed short)(GS()) * (long long)(signed short)(v
);
1479 put_reg64 (acc64
, ll
);
1484 PD (get_reg (acchi
));
1489 PD (get_reg (acclo
));
1494 PD (get_reg (accmi
));
1499 put_reg (acchi
, GS ());
1504 put_reg (acclo
, GS ());
1509 regs
.r_psw
&= ~ FLAGBITS_IPL
;
1510 regs
.r_psw
|= (GS () << FLAGSHIFT_IPL
) & FLAGBITS_IPL
;
1529 /* POPM cannot pop R0 (sp). */
1530 if (opcode
->op
[1].reg
== 0 || opcode
->op
[2].reg
== 0)
1531 EXCEPTION (EX_UNDEFINED
);
1532 if (opcode
->op
[1].reg
>= opcode
->op
[2].reg
)
1534 regs
.r_pc
= opcode_pc
;
1535 DO_RETURN (RX_MAKE_STOPPED (SIGILL
));
1537 for (v
= opcode
->op
[1].reg
; v
<= opcode
->op
[2].reg
; v
++)
1541 put_reg (v
, pop ());
1546 /* PUSHM cannot push R0 (sp). */
1547 if (opcode
->op
[1].reg
== 0 || opcode
->op
[2].reg
== 0)
1548 EXCEPTION (EX_UNDEFINED
);
1549 if (opcode
->op
[1].reg
>= opcode
->op
[2].reg
)
1551 regs
.r_pc
= opcode_pc
;
1552 return RX_MAKE_STOPPED (SIGILL
);
1554 for (v
= opcode
->op
[2].reg
; v
>= opcode
->op
[1].reg
; v
--)
1559 cycles (opcode
->op
[2].reg
- opcode
->op
[1].reg
+ 1);
1563 ll
= get_reg64 (acc64
) << GS ();
1564 ll
+= 0x80000000ULL
;
1565 if ((signed long long)ll
> (signed long long)0x00007fff00000000ULL
)
1566 ll
= 0x00007fff00000000ULL
;
1567 else if ((signed long long)ll
< (signed long long)0xffff800000000000ULL
)
1568 ll
= 0xffff800000000000ULL
;
1570 ll
&= 0xffffffff00000000ULL
;
1571 put_reg64 (acc64
, ll
);
1577 regs
.r_pc
= poppc ();
1578 regs
.r_psw
= poppc ();
1580 regs
.r_psw
|= FLAGBIT_U
;
1581 #ifdef CYCLE_ACCURATE
1582 regs
.fast_return
= 0;
1589 umb
= (((uma
>> 24) & 0xff)
1590 | ((uma
>> 8) & 0xff00)
1591 | ((uma
<< 8) & 0xff0000)
1592 | ((uma
<< 24) & 0xff000000UL
));
1599 umb
= (((uma
>> 8) & 0x00ff00ff)
1600 | ((uma
<< 8) & 0xff00ff00UL
));
1608 #ifdef CYCLE_ACCURATE
1612 while (regs
.r
[3] != 0)
1616 switch (opcode
->size
)
1619 ma
= mem_get_si (regs
.r
[1]);
1620 mb
= mem_get_si (regs
.r
[2]);
1625 ma
= sign_ext (mem_get_hi (regs
.r
[1]), 16);
1626 mb
= sign_ext (mem_get_hi (regs
.r
[2]), 16);
1631 ma
= sign_ext (mem_get_qi (regs
.r
[1]), 8);
1632 mb
= sign_ext (mem_get_qi (regs
.r
[2]), 8);
1639 /* We do the multiply as a signed value. */
1640 sll
= (long long)ma
* (long long)mb
;
1641 tprintf(" %016llx = %d * %d\n", sll
, ma
, mb
);
1642 /* but we do the sum as unsigned, while sign extending the operands. */
1643 tmp
= regs
.r
[4] + (sll
& 0xffffffffUL
);
1644 regs
.r
[4] = tmp
& 0xffffffffUL
;
1647 tmp
+= regs
.r
[5] + (sll
& 0xffffffffUL
);
1648 regs
.r
[5] = tmp
& 0xffffffffUL
;
1651 tmp
+= regs
.r
[6] + (sll
& 0xffffffffUL
);
1652 regs
.r
[6] = tmp
& 0xffffffffUL
;
1653 tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
1654 (unsigned long) regs
.r
[6],
1655 (unsigned long) regs
.r
[5],
1656 (unsigned long) regs
.r
[4]);
1660 if (regs
.r
[6] & 0x00008000)
1661 regs
.r
[6] |= 0xffff0000UL
;
1663 regs
.r
[6] &= 0x0000ffff;
1664 ma
= (regs
.r
[6] & 0x80000000UL
) ? FLAGBIT_S
: 0;
1665 if (regs
.r
[6] != 0 && regs
.r
[6] != 0xffffffffUL
)
1666 set_flags (FLAGBIT_O
|FLAGBIT_S
, ma
| FLAGBIT_O
);
1668 set_flags (FLAGBIT_O
|FLAGBIT_S
, ma
);
1669 #ifdef CYCLE_ACCURATE
1670 switch (opcode
->size
)
1673 cycles (6 + 4 * tx
);
1676 cycles (6 + 5 * (tx
/ 2) + 4 * (tx
% 2));
1679 cycles (6 + 7 * (tx
/ 4) + 4 * (tx
% 4));
1689 ma
= v
& 0x80000000UL
;
1701 uma
|= (carry
? 0x80000000UL
: 0);
1702 set_szc (uma
, 4, mb
);
1712 uma
= (uma
<< mb
) | (uma
>> (32-mb
));
1715 set_szc (uma
, 4, mb
);
1725 uma
= (uma
>> mb
) | (uma
<< (32-mb
));
1726 mb
= uma
& 0x80000000;
1728 set_szc (uma
, 4, mb
);
1736 mb
= rxfp_ftoi (ma
, regs
.r_fpsw
);
1739 tprintf("(int) %g = %d\n", int2float(ma
), mb
);
1746 #ifdef CYCLE_ACCURATE
1749 regs
.r_pc
= poppc ();
1750 #ifdef CYCLE_ACCURATE
1751 /* Note: specs say 5, chip says 3. */
1752 if (regs
.fast_return
&& regs
.link_register
== regs
.r_pc
)
1757 tprintf("fast return bonus\n");
1761 regs
.fast_return
= 0;
1762 branch_alignment_penalty
= 1;
1768 if (opcode
->op
[2].type
== RX_Operand_Register
)
1771 /* RTSD cannot pop R0 (sp). */
1772 put_reg (0, get_reg (0) + GS() - (opcode
->op
[0].reg
-opcode
->op
[2].reg
+1)*4);
1773 if (opcode
->op
[2].reg
== 0)
1774 EXCEPTION (EX_UNDEFINED
);
1775 #ifdef CYCLE_ACCURATE
1776 tx
= opcode
->op
[0].reg
- opcode
->op
[2].reg
+ 1;
1778 for (i
= opcode
->op
[2].reg
; i
<= opcode
->op
[0].reg
; i
++)
1781 put_reg (i
, pop ());
1786 #ifdef CYCLE_ACCURATE
1789 put_reg (0, get_reg (0) + GS());
1791 put_reg (pc
, poppc());
1792 #ifdef CYCLE_ACCURATE
1793 if (regs
.fast_return
&& regs
.link_register
== regs
.r_pc
)
1795 tprintf("fast return bonus\n");
1799 cycles (tx
< 3 ? 3 : tx
+ 1);
1803 cycles (tx
< 5 ? 5 : tx
+ 1);
1805 regs
.fast_return
= 0;
1806 branch_alignment_penalty
= 1;
1811 if (FLAG_O
&& FLAG_S
)
1813 else if (FLAG_O
&& ! FLAG_S
)
1819 if (FLAG_O
&& ! FLAG_S
)
1822 put_reg (5, 0x7fffffff);
1823 put_reg (4, 0xffffffff);
1825 else if (FLAG_O
&& FLAG_S
)
1827 put_reg (6, 0xffffffff);
1828 put_reg (5, 0x80000000);
1835 MATH_OP (-, ! carry
);
1847 #ifdef CYCLE_ACCURATE
1850 while (regs
.r
[3] != 0)
1852 uma
= mem_get_qi (regs
.r
[1] ++);
1853 umb
= mem_get_qi (regs
.r
[2] ++);
1855 if (uma
!= umb
|| uma
== 0)
1861 set_zc (0, ((int)uma
- (int)umb
) >= 0);
1862 cycles (2 + 4 * (tx
/ 4) + 4 * (tx
% 4));
1866 v
= 1 << opcode
->op
[0].reg
;
1877 #ifdef CYCLE_ACCURATE
1882 uma
= mem_get_qi (regs
.r
[2] --);
1883 mem_put_qi (regs
.r
[1]--, uma
);
1886 #ifdef CYCLE_ACCURATE
1888 cycles (6 + 3 * (tx
/ 4) + 3 * (tx
% 4));
1890 cycles (2 + 3 * (tx
% 4));
1896 #ifdef CYCLE_ACCURATE
1901 uma
= mem_get_qi (regs
.r
[2] ++);
1902 mem_put_qi (regs
.r
[1]++, uma
);
1905 cycles (2 + 3 * (int)(tx
/ 4) + 3 * (tx
% 4));
1909 #ifdef CYCLE_ACCURATE
1912 while (regs
.r
[3] != 0)
1914 uma
= mem_get_qi (regs
.r
[2] ++);
1915 mem_put_qi (regs
.r
[1]++, uma
);
1920 cycles (2 + 3 * (int)(tx
/ 4) + 3 * (tx
% 4));
1923 case RXO_shar
: /* d = ma >> mb */
1924 SHIFT_OP (sll
, int, mb
, >>=, 1);
1928 case RXO_shll
: /* d = ma << mb */
1929 SHIFT_OP (ll
, int, mb
, <<=, 0x80000000UL
);
1933 case RXO_shlr
: /* d = ma >> mb */
1934 SHIFT_OP (ll
, unsigned int, mb
, >>=, 1);
1940 #ifdef CYCLE_ACCURATE
1943 switch (opcode
->size
)
1946 while (regs
.r
[3] != 0)
1948 mem_put_si (regs
.r
[1], regs
.r
[2]);
1955 while (regs
.r
[3] != 0)
1957 mem_put_hi (regs
.r
[1], regs
.r
[2]);
1961 cycles (2 + (int)(tx
/ 2) + tx
% 2);
1964 while (regs
.r
[3] != 0)
1966 mem_put_qi (regs
.r
[1], regs
.r
[2]);
1970 cycles (2 + (int)(tx
/ 4) + tx
% 4);
1985 regs
.r_psw
|= FLAGBIT_I
;
1986 DO_RETURN (RX_MAKE_STOPPED(0));
1994 #ifdef CYCLE_ACCURATE
2002 switch (opcode
->size
)
2006 while (regs
.r
[3] != 0)
2009 umb
= mem_get_si (get_reg (1));
2011 #ifdef CYCLE_ACCURATE
2017 #ifdef CYCLE_ACCURATE
2018 cycles (3 + 3 * tx
);
2022 uma
= get_reg (2) & 0xffff;
2023 while (regs
.r
[3] != 0)
2026 umb
= mem_get_hi (get_reg (1));
2028 #ifdef CYCLE_ACCURATE
2034 #ifdef CYCLE_ACCURATE
2035 cycles (3 + 3 * (tx
/ 2) + 3 * (tx
% 2));
2039 uma
= get_reg (2) & 0xff;
2040 while (regs
.r
[3] != 0)
2043 umb
= mem_get_qi (regs
.r
[1]);
2045 #ifdef CYCLE_ACCURATE
2051 #ifdef CYCLE_ACCURATE
2052 cycles (3 + 3 * (tx
/ 4) + 3 * (tx
% 4));
2061 set_zc (0, ((int)uma
- (int)umb
) >= 0);
2066 #ifdef CYCLE_ACCURATE
2071 switch (opcode
->size
)
2075 while (regs
.r
[3] != 0)
2078 umb
= mem_get_si (get_reg (1));
2080 #ifdef CYCLE_ACCURATE
2086 #ifdef CYCLE_ACCURATE
2087 cycles (3 + 3 * tx
);
2091 uma
= get_reg (2) & 0xffff;
2092 while (regs
.r
[3] != 0)
2095 umb
= mem_get_hi (get_reg (1));
2097 #ifdef CYCLE_ACCURATE
2103 #ifdef CYCLE_ACCURATE
2104 cycles (3 + 3 * (tx
/ 2) + 3 * (tx
% 2));
2108 uma
= get_reg (2) & 0xff;
2109 while (regs
.r
[3] != 0)
2112 umb
= mem_get_qi (regs
.r
[1]);
2114 #ifdef CYCLE_ACCURATE
2120 #ifdef CYCLE_ACCURATE
2121 cycles (3 + 3 * (tx
/ 4) + 3 * (tx
% 4));
2130 set_zc (0, ((int)uma
- (int)umb
) >= 0);
2135 regs
.r_psw
|= FLAGBIT_I
;
2136 DO_RETURN (RX_MAKE_STOPPED(0));
2139 #ifdef CYCLE_ACCURATE
2142 v
= GS (); /* This is the memory operand, if any. */
2143 PS (GD ()); /* and this may change the address register. */
2146 #ifdef CYCLE_ACCURATE
2147 /* all M cycles happen during xchg's cycles. */
2158 EXCEPTION (EX_UNDEFINED
);
2161 #ifdef CYCLE_ACCURATE
2164 regs
.m2m
|= M2M_SRC
;
2166 regs
.m2m
|= M2M_DST
;
2173 if (prev_cycle_count
== regs
.cycle_count
)
2175 printf("Cycle count not updated! id %s\n", id_names
[opcode
->id
]);
2181 if (running_benchmark
)
2183 int omap
= op_lookup (opcode
->op
[0].type
, opcode
->op
[1].type
, opcode
->op
[2].type
);
2186 cycles_per_id
[opcode
->id
][omap
] += regs
.cycle_count
- prev_cycle_count
;
2187 times_per_id
[opcode
->id
][omap
] ++;
2189 times_per_pair
[prev_opcode_id
][po0
][opcode
->id
][omap
] ++;
2191 prev_opcode_id
= opcode
->id
;
2196 return RX_MAKE_STEPPED ();
2201 reset_pipeline_stats (void)
2203 memset (cycles_per_id
, 0, sizeof(cycles_per_id
));
2204 memset (times_per_id
, 0, sizeof(times_per_id
));
2206 register_stalls
= 0;
2208 branch_alignment_stalls
= 0;
2210 memset (times_per_pair
, 0, sizeof(times_per_pair
));
2211 running_benchmark
= 1;
2213 benchmark_start_cycle
= regs
.cycle_count
;
2217 halt_pipeline_stats (void)
2219 running_benchmark
= 0;
2220 benchmark_end_cycle
= regs
.cycle_count
;
2225 pipeline_stats (void)
2232 #ifdef CYCLE_ACCURATE
2235 printf ("cycles: %llu\n", regs
.cycle_count
);
2239 printf ("cycles: %13s\n", comma (regs
.cycle_count
));
2243 if (benchmark_start_cycle
)
2244 printf ("bmark: %13s\n", comma (benchmark_end_cycle
- benchmark_start_cycle
));
2247 for (i
= 0; i
< N_RXO
; i
++)
2248 for (o1
= 0; o1
< N_MAP
; o1
++)
2249 if (times_per_id
[i
][o1
])
2250 printf("%13s %13s %7.2f %s %s\n",
2251 comma (cycles_per_id
[i
][o1
]),
2252 comma (times_per_id
[i
][o1
]),
2253 (double)cycles_per_id
[i
][o1
] / times_per_id
[i
][o1
],
2254 op_cache_string(o1
),
2258 for (p
= 0; p
< N_RXO
; p
++)
2259 for (p1
= 0; p1
< N_MAP
; p1
++)
2260 for (i
= 0; i
< N_RXO
; i
++)
2261 for (o1
= 0; o1
< N_MAP
; o1
++)
2262 if (times_per_pair
[p
][p1
][i
][o1
])
2264 printf("%13s %s %-9s -> %s %s\n",
2265 comma (times_per_pair
[p
][p1
][i
][o1
]),
2266 op_cache_string(p1
),
2268 op_cache_string(o1
),
2273 printf("%13s memory stalls\n", comma (memory_stalls
));
2274 printf("%13s register stalls\n", comma (register_stalls
));
2275 printf("%13s branches taken (non-return)\n", comma (branch_stalls
));
2276 printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls
));
2277 printf("%13s fast returns\n", comma (fast_returns
));
This page took 0.162944 seconds and 4 git commands to generate.