1 /* rx.c --- opcode semantics for stand-alone RX simulator.
3 Copyright (C) 2008-2014 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 */
104 "RXO_sat", /* sat(d) */
107 "RXO_fadd", /* d op= s */
116 "RXO_bset", /* d |= (1<<s) */
117 "RXO_bclr", /* d &= ~(1<<s) */
118 "RXO_btst", /* s & (1<<s2) */
119 "RXO_bnot", /* d ^= (1<<s) */
120 "RXO_bmcc", /* d<s> = cond(s2) */
122 "RXO_clrpsw", /* flag index in d */
123 "RXO_setpsw", /* flag index in d */
124 "RXO_mvtipl", /* new IPL in s */
128 "RXO_rtd", /* undocumented */
130 "RXO_dbt", /* undocumented */
131 "RXO_int", /* vector id in s */
135 "RXO_sccnd", /* d = cond(s) ? 1 : 0 */
138 static const char * optype_names
[] = {
140 "#Imm", /* #addend */
142 "[Rn]", /* [Rn + addend] */
145 " cc ", /* eq, gtu, etc */
146 "Flag", /* [UIOSZC] */
147 "RbRi" /* [Rb + scale * Ri] */
150 #define N_RXO (sizeof(id_names)/sizeof(id_names[0]))
151 #define N_RXT (sizeof(optype_names)/sizeof(optype_names[0]))
154 static unsigned long long benchmark_start_cycle
;
155 static unsigned long long benchmark_end_cycle
;
157 static int op_cache
[N_RXT
][N_RXT
][N_RXT
];
158 static int op_cache_rev
[N_MAP
];
159 static int op_cache_idx
= 0;
162 op_lookup (int a
, int b
, int c
)
164 if (op_cache
[a
][b
][c
])
165 return op_cache
[a
][b
][c
];
167 if (op_cache_idx
>= N_MAP
)
169 printf("op_cache_idx exceeds %d\n", N_MAP
);
172 op_cache
[a
][b
][c
] = op_cache_idx
;
173 op_cache_rev
[op_cache_idx
] = (a
<<8) | (b
<<4) | c
;
178 op_cache_string (int map
)
181 static char cb
[5][20];
184 map
= op_cache_rev
[map
];
189 sprintf(cb
[ci
], "%s %s %s", optype_names
[a
], optype_names
[b
], optype_names
[c
]);
193 static unsigned long long cycles_per_id
[N_RXO
][N_MAP
];
194 static unsigned long long times_per_id
[N_RXO
][N_MAP
];
195 static unsigned long long memory_stalls
;
196 static unsigned long long register_stalls
;
197 static unsigned long long branch_stalls
;
198 static unsigned long long branch_alignment_stalls
;
199 static unsigned long long fast_returns
;
201 static unsigned long times_per_pair
[N_RXO
][N_MAP
][N_RXO
][N_MAP
];
202 static int prev_opcode_id
= RXO_unknown
;
209 #endif /* CYCLE_STATS */
212 #ifdef CYCLE_ACCURATE
214 static int new_rt
= -1;
216 /* Number of cycles to add if an insn spans an 8-byte boundary. */
217 static int branch_alignment_penalty
= 0;
221 static int running_benchmark
= 1;
223 #define tprintf if (trace && running_benchmark) printf
225 jmp_buf decode_jmp_buf
;
226 unsigned int rx_cycles
= 0;
228 #ifdef CYCLE_ACCURATE
229 /* If nonzero, memory was read at some point and cycle latency might
231 static int memory_source
= 0;
232 /* If nonzero, memory was written and extra cycles might be
234 static int memory_dest
= 0;
237 cycles (int throughput
)
239 tprintf("%d cycles\n", throughput
);
240 regs
.cycle_count
+= throughput
;
243 /* Number of execution (E) cycles the op uses. For memory sources, we
244 include the load micro-op stall as two extra E cycles. */
245 #define E(c) cycles (memory_source ? c + 2 : c)
246 #define E1 cycles (1)
247 #define E2 cycles (2)
248 #define EBIT cycles (memory_source ? 2 : 1)
250 /* Check to see if a read latency must be applied for a given register. */
254 tprintf("register %d load stall\n", r); \
255 regs.cycle_count ++; \
256 STATS(register_stalls ++); \
263 tprintf ("Rt now %d\n", r); \
268 lsb_count (unsigned long v
, int is_signed
)
271 if (is_signed
&& (v
& 0x80000000U
))
272 v
= (unsigned long)(long)(-v
);
273 for (i
=31; i
>=0; i
--)
276 /* v is 0..31, we want 1=1-2, 2=3-4, 3=5-6, etc. */
284 divu_cycles(unsigned long num
, unsigned long den
)
286 int nb
= lsb_count (num
, 0);
287 int db
= lsb_count (den
, 0);
299 div_cycles(long num
, long den
)
301 int nb
= lsb_count ((unsigned long)num
, 1);
302 int db
= lsb_count ((unsigned long)den
, 1);
313 #else /* !CYCLE_ACCURATE */
323 #define divu_cycles(n,d)
324 #define div_cycles(n,d)
326 #endif /* else CYCLE_ACCURATE */
328 static int size2bytes
[] = {
329 4, 1, 1, 1, 2, 2, 2, 3, 4
336 #define rx_abort() _rx_abort(__FILE__, __LINE__)
338 _rx_abort (const char *file
, int line
)
340 if (strrchr (file
, '/'))
341 file
= strrchr (file
, '/') + 1;
342 fprintf(stderr
, "abort at %s:%d\n", file
, line
);
346 static unsigned char *get_byte_base
;
347 static RX_Opcode_Decoded
**decode_cache_base
;
348 static SI get_byte_page
;
354 decode_cache_base
= 0;
359 maybe_get_mem_page (SI tpc
)
361 if (((tpc
^ get_byte_page
) & NONPAGE_MASK
) || enable_counting
)
363 get_byte_page
= tpc
& NONPAGE_MASK
;
364 get_byte_base
= rx_mem_ptr (get_byte_page
, MPA_READING
) - get_byte_page
;
365 decode_cache_base
= rx_mem_decode_cache (get_byte_page
) - get_byte_page
;
369 /* This gets called a *lot* so optimize it. */
371 rx_get_byte (void *vdata
)
373 RX_Data
*rx_data
= (RX_Data
*)vdata
;
374 SI tpc
= rx_data
->dpc
;
376 /* See load.c for an explanation of this. */
380 maybe_get_mem_page (tpc
);
383 return get_byte_base
[tpc
];
387 get_op (const RX_Opcode_Decoded
*rd
, int i
)
389 const RX_Opcode_Operand
*o
= rd
->op
+ i
;
394 case RX_Operand_None
:
397 case RX_Operand_Immediate
: /* #addend */
400 case RX_Operand_Register
: /* Rn */
402 rv
= get_reg (o
->reg
);
405 case RX_Operand_Predec
: /* [-Rn] */
406 put_reg (o
->reg
, get_reg (o
->reg
) - size2bytes
[o
->size
]);
408 case RX_Operand_Postinc
: /* [Rn+] */
409 case RX_Operand_Indirect
: /* [Rn + addend] */
410 case RX_Operand_TwoReg
: /* [Rn + scale * R2] */
411 #ifdef CYCLE_ACCURATE
413 if (o
->type
== RX_Operand_TwoReg
)
416 if (regs
.m2m
== M2M_BOTH
)
418 tprintf("src memory stall\n");
429 if (o
->type
== RX_Operand_TwoReg
)
430 addr
= get_reg (o
->reg
) * size2bytes
[rd
->size
] + get_reg (rd
->op
[2].reg
);
432 addr
= get_reg (o
->reg
) + o
->addend
;
439 case RX_Byte
: /* undefined extension */
442 rv
= mem_get_qi (addr
);
445 case RX_Word
: /* undefined extension */
448 rv
= mem_get_hi (addr
);
452 rv
= mem_get_psi (addr
);
456 rv
= mem_get_si (addr
);
460 if (o
->type
== RX_Operand_Postinc
)
461 put_reg (o
->reg
, get_reg (o
->reg
) + size2bytes
[o
->size
]);
465 case RX_Operand_Condition
: /* eq, gtu, etc */
466 return condition_true (o
->reg
);
468 case RX_Operand_Flag
: /* [UIOSZC] */
469 return (regs
.r_psw
& (1 << o
->reg
)) ? 1 : 0;
472 /* if we've gotten here, we need to clip/extend the value according
479 case RX_Byte
: /* undefined extension */
480 rv
|= 0xdeadbe00; /* keep them honest */
488 rv
= sign_ext (rv
, 8);
491 case RX_Word
: /* undefined extension */
492 rv
|= 0xdead0000; /* keep them honest */
500 rv
= sign_ext (rv
, 16);
514 put_op (const RX_Opcode_Decoded
*rd
, int i
, int v
)
516 const RX_Opcode_Operand
*o
= rd
->op
+ i
;
522 if (o
->type
!= RX_Operand_Register
)
526 case RX_Byte
: /* undefined extension */
527 v
|= 0xdeadbe00; /* keep them honest */
538 case RX_Word
: /* undefined extension */
539 v
|= 0xdead0000; /* keep them honest */
547 v
= sign_ext (v
, 16);
560 case RX_Operand_None
:
561 /* Opcodes like TST and CMP use this. */
564 case RX_Operand_Immediate
: /* #addend */
565 case RX_Operand_Condition
: /* eq, gtu, etc */
568 case RX_Operand_Register
: /* Rn */
573 case RX_Operand_Predec
: /* [-Rn] */
574 put_reg (o
->reg
, get_reg (o
->reg
) - size2bytes
[o
->size
]);
576 case RX_Operand_Postinc
: /* [Rn+] */
577 case RX_Operand_Indirect
: /* [Rn + addend] */
578 case RX_Operand_TwoReg
: /* [Rn + scale * R2] */
580 #ifdef CYCLE_ACCURATE
581 if (regs
.m2m
== M2M_BOTH
)
583 tprintf("dst memory stall\n");
593 if (o
->type
== RX_Operand_TwoReg
)
594 addr
= get_reg (o
->reg
) * size2bytes
[rd
->size
] + get_reg (rd
->op
[2].reg
);
596 addr
= get_reg (o
->reg
) + o
->addend
;
603 case RX_Byte
: /* undefined extension */
606 mem_put_qi (addr
, v
);
609 case RX_Word
: /* undefined extension */
612 mem_put_hi (addr
, v
);
616 mem_put_psi (addr
, v
);
620 mem_put_si (addr
, v
);
624 if (o
->type
== RX_Operand_Postinc
)
625 put_reg (o
->reg
, get_reg (o
->reg
) + size2bytes
[o
->size
]);
629 case RX_Operand_Flag
: /* [UIOSZC] */
631 regs
.r_psw
|= (1 << o
->reg
);
633 regs
.r_psw
&= ~(1 << o
->reg
);
638 #define PD(x) put_op (opcode, 0, x)
639 #define PS(x) put_op (opcode, 1, x)
640 #define PS2(x) put_op (opcode, 2, x)
641 #define GD() get_op (opcode, 0)
642 #define GS() get_op (opcode, 1)
643 #define GS2() get_op (opcode, 2)
644 #define DSZ() size2bytes[opcode->op[0].size]
645 #define SSZ() size2bytes[opcode->op[0].size]
646 #define S2SZ() size2bytes[opcode->op[0].size]
648 /* "Universal" sources. */
649 #define US1() ((opcode->op[2].type == RX_Operand_None) ? GD() : GS())
650 #define US2() ((opcode->op[2].type == RX_Operand_None) ? GS() : GS2())
655 int rsp
= get_reg (sp
);
658 mem_put_si (rsp
, val
);
661 /* Just like the above, but tag the memory as "pushed pc" so if anyone
662 tries to write to it, it will cause an error. */
666 int rsp
= get_reg (sp
);
669 mem_put_si (rsp
, val
);
670 mem_set_content_range (rsp
, rsp
+3, MC_PUSHED_PC
);
677 int rsp
= get_reg (sp
);
678 rv
= mem_get_si (rsp
);
688 int rsp
= get_reg (sp
);
689 if (mem_get_content_type (rsp
) != MC_PUSHED_PC
)
690 execution_error (SIM_ERR_CORRUPT_STACK
, rsp
);
691 rv
= mem_get_si (rsp
);
692 mem_set_content_range (rsp
, rsp
+3, MC_UNINIT
);
698 #define MATH_OP(vop,c) \
702 ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
703 tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
704 ma = sign_ext (uma, DSZ() * 8); \
705 mb = sign_ext (umb, DSZ() * 8); \
706 sll = (long long) ma vop (long long) mb vop c; \
707 tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
708 set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
713 #define LOGIC_OP(vop) \
718 tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
724 #define SHIFT_OP(val, type, count, OP, carry_mask) \
729 tprintf("%lld " #OP " %d\n", val, count); \
730 for (i = 0; i < count; i ++) \
732 c = val & carry_mask; \
735 set_oszc (val, 4, c); \
761 fop_fadd (fp_t s1
, fp_t s2
, fp_t
*d
)
763 *d
= rxfp_add (s1
, s2
);
768 fop_fmul (fp_t s1
, fp_t s2
, fp_t
*d
)
770 *d
= rxfp_mul (s1
, s2
);
775 fop_fdiv (fp_t s1
, fp_t s2
, fp_t
*d
)
777 *d
= rxfp_div (s1
, s2
);
782 fop_fsub (fp_t s1
, fp_t s2
, fp_t
*d
)
784 *d
= rxfp_sub (s1
, s2
);
788 #define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
789 #define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
792 return do_fp_exception (opcode_pc)
794 #define FLOAT_OP(func) \
801 do_store = fop_##func (fa, fb, &fc); \
802 tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
807 if ((fc & 0x80000000UL) != 0) \
809 if ((fc & 0x7fffffffUL) == 0) \
811 set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
814 #define carry (FLAG_C ? 1 : 0)
820 } exception_info
[] = {
821 { 0xFFFFFFD0UL
, "priviledged opcode", SIGILL
},
822 { 0xFFFFFFD4UL
, "access violation", SIGSEGV
},
823 { 0xFFFFFFDCUL
, "undefined opcode", SIGILL
},
824 { 0xFFFFFFE4UL
, "floating point", SIGFPE
}
826 #define EX_PRIVILEDGED 0
828 #define EX_UNDEFINED 2
829 #define EX_FLOATING 3
830 #define EXCEPTION(n) \
831 return generate_exception (n, opcode_pc)
833 #define PRIVILEDGED() \
835 EXCEPTION (EX_PRIVILEDGED)
838 generate_exception (unsigned long type
, SI opcode_pc
)
840 SI old_psw
, old_pc
, new_pc
;
842 new_pc
= mem_get_si (exception_info
[type
].vaddr
);
843 /* 0x00020000 is the value used to initialise the known
844 exception vectors (see rx.ld), but it is a reserved
845 area of memory so do not try to access it, and if the
846 value has not been changed by the program then the
847 vector has not been installed. */
848 if (new_pc
== 0 || new_pc
== 0x00020000)
851 return RX_MAKE_STOPPED (exception_info
[type
].signal
);
853 fprintf(stderr
, "Unhandled %s exception at pc = %#lx\n",
854 exception_info
[type
].str
, (unsigned long) opcode_pc
);
855 if (type
== EX_FLOATING
)
857 int mask
= FPPENDING ();
858 fprintf (stderr
, "Pending FP exceptions:");
859 if (mask
& FPSWBITS_FV
)
860 fprintf(stderr
, " Invalid");
861 if (mask
& FPSWBITS_FO
)
862 fprintf(stderr
, " Overflow");
863 if (mask
& FPSWBITS_FZ
)
864 fprintf(stderr
, " Division-by-zero");
865 if (mask
& FPSWBITS_FU
)
866 fprintf(stderr
, " Underflow");
867 if (mask
& FPSWBITS_FX
)
868 fprintf(stderr
, " Inexact");
869 if (mask
& FPSWBITS_CE
)
870 fprintf(stderr
, " Unimplemented");
871 fprintf(stderr
, "\n");
873 return RX_MAKE_EXITED (1);
876 tprintf ("Triggering %s exception\n", exception_info
[type
].str
);
878 old_psw
= regs
.r_psw
;
879 regs
.r_psw
&= ~ (FLAGBIT_I
| FLAGBIT_U
| FLAGBIT_PM
);
884 return RX_MAKE_STEPPED ();
888 generate_access_exception (void)
892 rv
= generate_exception (EX_ACCESS
, regs
.r_pc
);
894 longjmp (decode_jmp_buf
, rv
);
898 do_fp_exception (unsigned long opcode_pc
)
901 EXCEPTION (EX_FLOATING
);
902 return RX_MAKE_STEPPED ();
906 op_is_memory (const RX_Opcode_Decoded
*rd
, int i
)
908 switch (rd
->op
[i
].type
)
910 case RX_Operand_Predec
:
911 case RX_Operand_Postinc
:
912 case RX_Operand_Indirect
:
918 #define OM(i) op_is_memory (opcode, i)
920 #define DO_RETURN(x) { longjmp (decode_jmp_buf, x); }
925 unsigned int uma
=0, umb
=0;
928 unsigned long long ll
;
930 unsigned long opcode_pc
;
932 const RX_Opcode_Decoded
*opcode
;
934 unsigned long long prev_cycle_count
;
936 #ifdef CYCLE_ACCURATE
941 prev_cycle_count
= regs
.cycle_count
;
944 #ifdef CYCLE_ACCURATE
951 maybe_get_mem_page (regs
.r_pc
);
953 opcode_pc
= regs
.r_pc
;
955 /* Note that we don't word-swap this point, there's no point. */
956 if (decode_cache_base
[opcode_pc
] == NULL
)
958 RX_Opcode_Decoded
*opcode_w
;
959 rx_data
.dpc
= opcode_pc
;
960 opcode_w
= decode_cache_base
[opcode_pc
] = calloc (1, sizeof (RX_Opcode_Decoded
));
961 opcode_size
= rx_decode_opcode (opcode_pc
, opcode_w
,
962 rx_get_byte
, &rx_data
);
967 opcode
= decode_cache_base
[opcode_pc
];
968 opcode_size
= opcode
->n_bytes
;
971 #ifdef CYCLE_ACCURATE
972 if (branch_alignment_penalty
)
974 if ((regs
.r_pc
^ (regs
.r_pc
+ opcode_size
- 1)) & ~7)
976 tprintf("1 cycle branch alignment penalty\n");
977 cycles (branch_alignment_penalty
);
979 branch_alignment_stalls
++;
982 branch_alignment_penalty
= 0;
986 regs
.r_pc
+= opcode_size
;
988 rx_flagmask
= opcode
->flags_s
;
989 rx_flagand
= ~(int)opcode
->flags_0
;
990 rx_flagor
= opcode
->flags_1
;
996 tprintf("|%lld| = ", sll
);
999 tprintf("%lld\n", sll
);
1020 if (opcode
->op
[0].type
== RX_Operand_Register
)
1032 if (opcode
->op
[0].type
== RX_Operand_Register
)
1047 if (opcode
->op
[0].type
== RX_Operand_Register
)
1057 if (opcode
->op
[1].type
== RX_Operand_None
|| GS())
1059 #ifdef CYCLE_ACCURATE
1060 SI old_pc
= regs
.r_pc
;
1064 #ifdef CYCLE_ACCURATE
1065 delta
= regs
.r_pc
- old_pc
;
1066 if (delta
>= 0 && delta
< 16
1069 tprintf("near forward branch bonus\n");
1075 branch_alignment_penalty
= 1;
1082 #ifdef CYCLE_ACCURATE
1089 if (opcode
->op
[1].type
== RX_Operand_None
|| GS())
1092 regs
.r_pc
= opcode_pc
+ delta
;
1093 #ifdef CYCLE_ACCURATE
1094 /* Note: specs say 3, chip says 2. */
1095 if (delta
>= 0 && delta
< 16
1098 tprintf("near forward branch bonus\n");
1104 branch_alignment_penalty
= 1;
1111 #ifdef CYCLE_ACCURATE
1119 int old_psw
= regs
.r_psw
;
1121 DO_RETURN (RX_MAKE_HIT_BREAK ());
1122 if (regs
.r_intb
== 0)
1124 tprintf("BREAK hit, no vector table.\n");
1125 DO_RETURN (RX_MAKE_EXITED(1));
1127 regs
.r_psw
&= ~(FLAGBIT_I
| FLAGBIT_U
| FLAGBIT_PM
);
1130 regs
.r_pc
= mem_get_si (regs
.r_intb
);
1138 if (opcode
->op
[0].type
== RX_Operand_Register
)
1150 if (opcode
->op
[1].type
== RX_Operand_Register
)
1154 umb
= ma
& (1 << mb
);
1155 set_zc (! umb
, umb
);
1160 v
= 1 << opcode
->op
[0].reg
;
1169 case RXO_div
: /* d = d / s */
1172 tprintf("%d / %d = ", mb
, ma
);
1173 if (ma
== 0 || (ma
== -1 && (unsigned int) mb
== 0x80000000))
1176 set_flags (FLAGBIT_O
, FLAGBIT_O
);
1183 set_flags (FLAGBIT_O
, 0);
1185 div_cycles (mb
, ma
);
1189 case RXO_divu
: /* d = d / s */
1192 tprintf("%u / %u = ", umb
, uma
);
1196 set_flags (FLAGBIT_O
, FLAGBIT_O
);
1203 set_flags (FLAGBIT_O
, 0);
1205 divu_cycles (umb
, uma
);
1212 sll
= (long long)ma
* (long long)mb
;
1213 tprintf("%d * %d = %lld\n", ma
, mb
, sll
);
1214 put_reg (opcode
->op
[0].reg
, sll
);
1215 put_reg (opcode
->op
[0].reg
+ 1, sll
>> 32);
1222 ll
= (long long)uma
* (long long)umb
;
1223 tprintf("%#x * %#x = %#llx\n", uma
, umb
, ll
);
1224 put_reg (opcode
->op
[0].reg
, ll
);
1225 put_reg (opcode
->op
[0].reg
+ 1, ll
>> 32);
1255 regs
.r_psw
= regs
.r_bpsw
;
1256 regs
.r_pc
= regs
.r_bpc
;
1257 #ifdef CYCLE_ACCURATE
1258 regs
.fast_return
= 0;
1271 mb
= rxfp_ftoi (ma
, FPRM_ZERO
);
1274 tprintf("(int) %g = %d\n", int2float(ma
), mb
);
1283 int rc
= rx_syscall (regs
.r
[5]);
1284 if (! RX_STEPPED (rc
))
1289 int old_psw
= regs
.r_psw
;
1290 regs
.r_psw
&= ~(FLAGBIT_I
| FLAGBIT_U
| FLAGBIT_PM
);
1293 regs
.r_pc
= mem_get_si (regs
.r_intb
+ 4 * v
);
1301 mb
= rxfp_itof (ma
, regs
.r_fpsw
);
1303 tprintf("(float) %d = %x\n", ma
, mb
);
1312 #ifdef CYCLE_ACCURATE
1317 #ifdef CYCLE_ACCURATE
1318 regs
.link_register
= regs
.r_pc
;
1320 pushpc (get_reg (pc
));
1321 if (opcode
->id
== RXO_jsrrel
)
1323 #ifdef CYCLE_ACCURATE
1324 delta
= v
- regs
.r_pc
;
1327 #ifdef CYCLE_ACCURATE
1328 /* Note: docs say 3, chip says 2 */
1329 if (delta
>= 0 && delta
< 16)
1331 tprintf ("near forward jsr bonus\n");
1336 branch_alignment_penalty
= 1;
1339 regs
.fast_return
= 1;
1345 ll
= (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
1347 put_reg64 (acc64
, ll
+ regs
.r_acc
);
1352 ll
= (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
1354 put_reg64 (acc64
, ll
+ regs
.r_acc
);
1381 if (opcode
->op
[1].type
== RX_Operand_Register
1382 && opcode
->op
[1].reg
== 17 /* PC */)
1384 /* Special case. We want the address of the insn, not the
1385 address of the next insn. */
1389 if (opcode
->op
[0].type
== RX_Operand_Register
1390 && opcode
->op
[0].reg
== 16 /* PSW */)
1392 /* Special case, LDC and POPC can't ever modify PM. */
1393 int pm
= regs
.r_psw
& FLAGBIT_PM
;
1398 v
&= ~ (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1404 /* various things can't be changed in user mode. */
1405 if (opcode
->op
[0].type
== RX_Operand_Register
)
1406 if (opcode
->op
[0].reg
== 32)
1408 v
&= ~ (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1409 v
|= regs
.r_psw
& (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1411 if (opcode
->op
[0].reg
== 34 /* ISP */
1412 || opcode
->op
[0].reg
== 37 /* BPSW */
1413 || opcode
->op
[0].reg
== 39 /* INTB */
1414 || opcode
->op
[0].reg
== 38 /* VCT */)
1415 /* These are ignored. */
1425 #ifdef CYCLE_ACCURATE
1426 if ((opcode
->op
[0].type
== RX_Operand_Predec
1427 && opcode
->op
[1].type
== RX_Operand_Register
)
1428 || (opcode
->op
[0].type
== RX_Operand_Postinc
1429 && opcode
->op
[1].type
== RX_Operand_Register
))
1431 /* Special case: push reg doesn't cause a memory stall. */
1433 tprintf("push special case\n");
1452 ll
= (unsigned long long) US1() * (unsigned long long) v
;
1459 ll
= (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v
>> 16);
1461 put_reg64 (acc64
, ll
);
1467 ll
= (long long)(signed short)(GS()) * (long long)(signed short)(v
);
1469 put_reg64 (acc64
, ll
);
1474 PD (get_reg (acchi
));
1479 PD (get_reg (acclo
));
1484 PD (get_reg (accmi
));
1489 put_reg (acchi
, GS ());
1494 put_reg (acclo
, GS ());
1499 regs
.r_psw
&= ~ FLAGBITS_IPL
;
1500 regs
.r_psw
|= (GS () << FLAGSHIFT_IPL
) & FLAGBITS_IPL
;
1515 /* POPM cannot pop R0 (sp). */
1516 if (opcode
->op
[1].reg
== 0 || opcode
->op
[2].reg
== 0)
1517 EXCEPTION (EX_UNDEFINED
);
1518 if (opcode
->op
[1].reg
>= opcode
->op
[2].reg
)
1520 regs
.r_pc
= opcode_pc
;
1521 DO_RETURN (RX_MAKE_STOPPED (SIGILL
));
1523 for (v
= opcode
->op
[1].reg
; v
<= opcode
->op
[2].reg
; v
++)
1527 put_reg (v
, pop ());
1532 /* PUSHM cannot push R0 (sp). */
1533 if (opcode
->op
[1].reg
== 0 || opcode
->op
[2].reg
== 0)
1534 EXCEPTION (EX_UNDEFINED
);
1535 if (opcode
->op
[1].reg
>= opcode
->op
[2].reg
)
1537 regs
.r_pc
= opcode_pc
;
1538 return RX_MAKE_STOPPED (SIGILL
);
1540 for (v
= opcode
->op
[2].reg
; v
>= opcode
->op
[1].reg
; v
--)
1545 cycles (opcode
->op
[2].reg
- opcode
->op
[1].reg
+ 1);
1549 ll
= get_reg64 (acc64
) << GS ();
1550 ll
+= 0x80000000ULL
;
1551 if ((signed long long)ll
> (signed long long)0x00007fff00000000ULL
)
1552 ll
= 0x00007fff00000000ULL
;
1553 else if ((signed long long)ll
< (signed long long)0xffff800000000000ULL
)
1554 ll
= 0xffff800000000000ULL
;
1556 ll
&= 0xffffffff00000000ULL
;
1557 put_reg64 (acc64
, ll
);
1563 regs
.r_pc
= poppc ();
1564 regs
.r_psw
= poppc ();
1566 regs
.r_psw
|= FLAGBIT_U
;
1567 #ifdef CYCLE_ACCURATE
1568 regs
.fast_return
= 0;
1575 umb
= (((uma
>> 24) & 0xff)
1576 | ((uma
>> 8) & 0xff00)
1577 | ((uma
<< 8) & 0xff0000)
1578 | ((uma
<< 24) & 0xff000000UL
));
1585 umb
= (((uma
>> 8) & 0x00ff00ff)
1586 | ((uma
<< 8) & 0xff00ff00UL
));
1594 #ifdef CYCLE_ACCURATE
1598 while (regs
.r
[3] != 0)
1602 switch (opcode
->size
)
1605 ma
= mem_get_si (regs
.r
[1]);
1606 mb
= mem_get_si (regs
.r
[2]);
1611 ma
= sign_ext (mem_get_hi (regs
.r
[1]), 16);
1612 mb
= sign_ext (mem_get_hi (regs
.r
[2]), 16);
1617 ma
= sign_ext (mem_get_qi (regs
.r
[1]), 8);
1618 mb
= sign_ext (mem_get_qi (regs
.r
[2]), 8);
1625 /* We do the multiply as a signed value. */
1626 sll
= (long long)ma
* (long long)mb
;
1627 tprintf(" %016llx = %d * %d\n", sll
, ma
, mb
);
1628 /* but we do the sum as unsigned, while sign extending the operands. */
1629 tmp
= regs
.r
[4] + (sll
& 0xffffffffUL
);
1630 regs
.r
[4] = tmp
& 0xffffffffUL
;
1633 tmp
+= regs
.r
[5] + (sll
& 0xffffffffUL
);
1634 regs
.r
[5] = tmp
& 0xffffffffUL
;
1637 tmp
+= regs
.r
[6] + (sll
& 0xffffffffUL
);
1638 regs
.r
[6] = tmp
& 0xffffffffUL
;
1639 tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
1640 (unsigned long) regs
.r
[6],
1641 (unsigned long) regs
.r
[5],
1642 (unsigned long) regs
.r
[4]);
1646 if (regs
.r
[6] & 0x00008000)
1647 regs
.r
[6] |= 0xffff0000UL
;
1649 regs
.r
[6] &= 0x0000ffff;
1650 ma
= (regs
.r
[6] & 0x80000000UL
) ? FLAGBIT_S
: 0;
1651 if (regs
.r
[6] != 0 && regs
.r
[6] != 0xffffffffUL
)
1652 set_flags (FLAGBIT_O
|FLAGBIT_S
, ma
| FLAGBIT_O
);
1654 set_flags (FLAGBIT_O
|FLAGBIT_S
, ma
);
1655 #ifdef CYCLE_ACCURATE
1656 switch (opcode
->size
)
1659 cycles (6 + 4 * tx
);
1662 cycles (6 + 5 * (tx
/ 2) + 4 * (tx
% 2));
1665 cycles (6 + 7 * (tx
/ 4) + 4 * (tx
% 4));
1675 ma
= v
& 0x80000000UL
;
1687 uma
|= (carry
? 0x80000000UL
: 0);
1688 set_szc (uma
, 4, mb
);
1698 uma
= (uma
<< mb
) | (uma
>> (32-mb
));
1701 set_szc (uma
, 4, mb
);
1711 uma
= (uma
>> mb
) | (uma
<< (32-mb
));
1712 mb
= uma
& 0x80000000;
1714 set_szc (uma
, 4, mb
);
1722 mb
= rxfp_ftoi (ma
, regs
.r_fpsw
);
1725 tprintf("(int) %g = %d\n", int2float(ma
), mb
);
1732 #ifdef CYCLE_ACCURATE
1735 regs
.r_pc
= poppc ();
1736 #ifdef CYCLE_ACCURATE
1737 /* Note: specs say 5, chip says 3. */
1738 if (regs
.fast_return
&& regs
.link_register
== regs
.r_pc
)
1743 tprintf("fast return bonus\n");
1747 regs
.fast_return
= 0;
1748 branch_alignment_penalty
= 1;
1754 if (opcode
->op
[2].type
== RX_Operand_Register
)
1757 /* RTSD cannot pop R0 (sp). */
1758 put_reg (0, get_reg (0) + GS() - (opcode
->op
[0].reg
-opcode
->op
[2].reg
+1)*4);
1759 if (opcode
->op
[2].reg
== 0)
1760 EXCEPTION (EX_UNDEFINED
);
1761 #ifdef CYCLE_ACCURATE
1762 tx
= opcode
->op
[0].reg
- opcode
->op
[2].reg
+ 1;
1764 for (i
= opcode
->op
[2].reg
; i
<= opcode
->op
[0].reg
; i
++)
1767 put_reg (i
, pop ());
1772 #ifdef CYCLE_ACCURATE
1775 put_reg (0, get_reg (0) + GS());
1777 put_reg (pc
, poppc());
1778 #ifdef CYCLE_ACCURATE
1779 if (regs
.fast_return
&& regs
.link_register
== regs
.r_pc
)
1781 tprintf("fast return bonus\n");
1785 cycles (tx
< 3 ? 3 : tx
+ 1);
1789 cycles (tx
< 5 ? 5 : tx
+ 1);
1791 regs
.fast_return
= 0;
1792 branch_alignment_penalty
= 1;
1797 if (FLAG_O
&& FLAG_S
)
1799 else if (FLAG_O
&& ! FLAG_S
)
1805 if (FLAG_O
&& ! FLAG_S
)
1808 put_reg (5, 0x7fffffff);
1809 put_reg (4, 0xffffffff);
1811 else if (FLAG_O
&& FLAG_S
)
1813 put_reg (6, 0xffffffff);
1814 put_reg (5, 0x80000000);
1821 MATH_OP (-, ! carry
);
1833 #ifdef CYCLE_ACCURATE
1836 while (regs
.r
[3] != 0)
1838 uma
= mem_get_qi (regs
.r
[1] ++);
1839 umb
= mem_get_qi (regs
.r
[2] ++);
1841 if (uma
!= umb
|| uma
== 0)
1847 set_zc (0, ((int)uma
- (int)umb
) >= 0);
1848 cycles (2 + 4 * (tx
/ 4) + 4 * (tx
% 4));
1852 v
= 1 << opcode
->op
[0].reg
;
1863 #ifdef CYCLE_ACCURATE
1868 uma
= mem_get_qi (regs
.r
[2] --);
1869 mem_put_qi (regs
.r
[1]--, uma
);
1872 #ifdef CYCLE_ACCURATE
1874 cycles (6 + 3 * (tx
/ 4) + 3 * (tx
% 4));
1876 cycles (2 + 3 * (tx
% 4));
1882 #ifdef CYCLE_ACCURATE
1887 uma
= mem_get_qi (regs
.r
[2] ++);
1888 mem_put_qi (regs
.r
[1]++, uma
);
1891 cycles (2 + 3 * (int)(tx
/ 4) + 3 * (tx
% 4));
1895 #ifdef CYCLE_ACCURATE
1898 while (regs
.r
[3] != 0)
1900 uma
= mem_get_qi (regs
.r
[2] ++);
1901 mem_put_qi (regs
.r
[1]++, uma
);
1906 cycles (2 + 3 * (int)(tx
/ 4) + 3 * (tx
% 4));
1909 case RXO_shar
: /* d = ma >> mb */
1910 SHIFT_OP (sll
, int, mb
, >>=, 1);
1914 case RXO_shll
: /* d = ma << mb */
1915 SHIFT_OP (ll
, int, mb
, <<=, 0x80000000UL
);
1919 case RXO_shlr
: /* d = ma >> mb */
1920 SHIFT_OP (ll
, unsigned int, mb
, >>=, 1);
1926 #ifdef CYCLE_ACCURATE
1929 switch (opcode
->size
)
1932 while (regs
.r
[3] != 0)
1934 mem_put_si (regs
.r
[1], regs
.r
[2]);
1941 while (regs
.r
[3] != 0)
1943 mem_put_hi (regs
.r
[1], regs
.r
[2]);
1947 cycles (2 + (int)(tx
/ 2) + tx
% 2);
1950 while (regs
.r
[3] != 0)
1952 mem_put_qi (regs
.r
[1], regs
.r
[2]);
1956 cycles (2 + (int)(tx
/ 4) + tx
% 4);
1971 regs
.r_psw
|= FLAGBIT_I
;
1972 DO_RETURN (RX_MAKE_STOPPED(0));
1980 #ifdef CYCLE_ACCURATE
1988 switch (opcode
->size
)
1992 while (regs
.r
[3] != 0)
1995 umb
= mem_get_si (get_reg (1));
1997 #ifdef CYCLE_ACCURATE
2003 #ifdef CYCLE_ACCURATE
2004 cycles (3 + 3 * tx
);
2008 uma
= get_reg (2) & 0xffff;
2009 while (regs
.r
[3] != 0)
2012 umb
= mem_get_hi (get_reg (1));
2014 #ifdef CYCLE_ACCURATE
2020 #ifdef CYCLE_ACCURATE
2021 cycles (3 + 3 * (tx
/ 2) + 3 * (tx
% 2));
2025 uma
= get_reg (2) & 0xff;
2026 while (regs
.r
[3] != 0)
2029 umb
= mem_get_qi (regs
.r
[1]);
2031 #ifdef CYCLE_ACCURATE
2037 #ifdef CYCLE_ACCURATE
2038 cycles (3 + 3 * (tx
/ 4) + 3 * (tx
% 4));
2047 set_zc (0, ((int)uma
- (int)umb
) >= 0);
2052 #ifdef CYCLE_ACCURATE
2057 switch (opcode
->size
)
2061 while (regs
.r
[3] != 0)
2064 umb
= mem_get_si (get_reg (1));
2066 #ifdef CYCLE_ACCURATE
2072 #ifdef CYCLE_ACCURATE
2073 cycles (3 + 3 * tx
);
2077 uma
= get_reg (2) & 0xffff;
2078 while (regs
.r
[3] != 0)
2081 umb
= mem_get_hi (get_reg (1));
2083 #ifdef CYCLE_ACCURATE
2089 #ifdef CYCLE_ACCURATE
2090 cycles (3 + 3 * (tx
/ 2) + 3 * (tx
% 2));
2094 uma
= get_reg (2) & 0xff;
2095 while (regs
.r
[3] != 0)
2098 umb
= mem_get_qi (regs
.r
[1]);
2100 #ifdef CYCLE_ACCURATE
2106 #ifdef CYCLE_ACCURATE
2107 cycles (3 + 3 * (tx
/ 4) + 3 * (tx
% 4));
2116 set_zc (0, ((int)uma
- (int)umb
) >= 0);
2121 regs
.r_psw
|= FLAGBIT_I
;
2122 DO_RETURN (RX_MAKE_STOPPED(0));
2125 #ifdef CYCLE_ACCURATE
2128 v
= GS (); /* This is the memory operand, if any. */
2129 PS (GD ()); /* and this may change the address register. */
2132 #ifdef CYCLE_ACCURATE
2133 /* all M cycles happen during xchg's cycles. */
2144 EXCEPTION (EX_UNDEFINED
);
2147 #ifdef CYCLE_ACCURATE
2150 regs
.m2m
|= M2M_SRC
;
2152 regs
.m2m
|= M2M_DST
;
2159 if (prev_cycle_count
== regs
.cycle_count
)
2161 printf("Cycle count not updated! id %s\n", id_names
[opcode
->id
]);
2167 if (running_benchmark
)
2169 int omap
= op_lookup (opcode
->op
[0].type
, opcode
->op
[1].type
, opcode
->op
[2].type
);
2172 cycles_per_id
[opcode
->id
][omap
] += regs
.cycle_count
- prev_cycle_count
;
2173 times_per_id
[opcode
->id
][omap
] ++;
2175 times_per_pair
[prev_opcode_id
][po0
][opcode
->id
][omap
] ++;
2177 prev_opcode_id
= opcode
->id
;
2182 return RX_MAKE_STEPPED ();
2187 reset_pipeline_stats (void)
2189 memset (cycles_per_id
, 0, sizeof(cycles_per_id
));
2190 memset (times_per_id
, 0, sizeof(times_per_id
));
2192 register_stalls
= 0;
2194 branch_alignment_stalls
= 0;
2196 memset (times_per_pair
, 0, sizeof(times_per_pair
));
2197 running_benchmark
= 1;
2199 benchmark_start_cycle
= regs
.cycle_count
;
2203 halt_pipeline_stats (void)
2205 running_benchmark
= 0;
2206 benchmark_end_cycle
= regs
.cycle_count
;
2211 pipeline_stats (void)
2218 #ifdef CYCLE_ACCURATE
2221 printf ("cycles: %llu\n", regs
.cycle_count
);
2225 printf ("cycles: %13s\n", comma (regs
.cycle_count
));
2229 if (benchmark_start_cycle
)
2230 printf ("bmark: %13s\n", comma (benchmark_end_cycle
- benchmark_start_cycle
));
2233 for (i
= 0; i
< N_RXO
; i
++)
2234 for (o1
= 0; o1
< N_MAP
; o1
++)
2235 if (times_per_id
[i
][o1
])
2236 printf("%13s %13s %7.2f %s %s\n",
2237 comma (cycles_per_id
[i
][o1
]),
2238 comma (times_per_id
[i
][o1
]),
2239 (double)cycles_per_id
[i
][o1
] / times_per_id
[i
][o1
],
2240 op_cache_string(o1
),
2244 for (p
= 0; p
< N_RXO
; p
++)
2245 for (p1
= 0; p1
< N_MAP
; p1
++)
2246 for (i
= 0; i
< N_RXO
; i
++)
2247 for (o1
= 0; o1
< N_MAP
; o1
++)
2248 if (times_per_pair
[p
][p1
][i
][o1
])
2250 printf("%13s %s %-9s -> %s %s\n",
2251 comma (times_per_pair
[p
][p1
][i
][o1
]),
2252 op_cache_string(p1
),
2254 op_cache_string(o1
),
2259 printf("%13s memory stalls\n", comma (memory_stalls
));
2260 printf("%13s register stalls\n", comma (register_stalls
));
2261 printf("%13s branches taken (non-return)\n", comma (branch_stalls
));
2262 printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls
));
2263 printf("%13s fast returns\n", comma (fast_returns
));
This page took 0.097956 seconds and 4 git commands to generate.