1 /* rx.c --- opcode semantics for stand-alone RX simulator.
3 Copyright (C) 2008, 2009, 2010, 2011 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; \
736 set_oszc (val, 4, c); \
762 fop_fadd (fp_t s1
, fp_t s2
, fp_t
*d
)
764 *d
= rxfp_add (s1
, s2
);
769 fop_fmul (fp_t s1
, fp_t s2
, fp_t
*d
)
771 *d
= rxfp_mul (s1
, s2
);
776 fop_fdiv (fp_t s1
, fp_t s2
, fp_t
*d
)
778 *d
= rxfp_div (s1
, s2
);
783 fop_fsub (fp_t s1
, fp_t s2
, fp_t
*d
)
785 *d
= rxfp_sub (s1
, s2
);
789 #define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
790 #define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
793 return do_fp_exception (opcode_pc)
795 #define FLOAT_OP(func) \
802 do_store = fop_##func (fa, fb, &fc); \
803 tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
808 if ((fc & 0x80000000UL) != 0) \
810 if ((fc & 0x7fffffffUL) == 0) \
812 set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
815 #define carry (FLAG_C ? 1 : 0)
821 } exception_info
[] = {
822 { 0xFFFFFFD0UL
, "priviledged opcode", SIGILL
},
823 { 0xFFFFFFD4UL
, "access violation", SIGSEGV
},
824 { 0xFFFFFFDCUL
, "undefined opcode", SIGILL
},
825 { 0xFFFFFFE4UL
, "floating point", SIGFPE
}
827 #define EX_PRIVILEDGED 0
829 #define EX_UNDEFINED 2
830 #define EX_FLOATING 3
831 #define EXCEPTION(n) \
832 return generate_exception (n, opcode_pc)
834 #define PRIVILEDGED() \
836 EXCEPTION (EX_PRIVILEDGED)
839 generate_exception (unsigned long type
, SI opcode_pc
)
841 SI old_psw
, old_pc
, new_pc
;
843 new_pc
= mem_get_si (exception_info
[type
].vaddr
);
844 /* 0x00020000 is the value used to initialise the known
845 exception vectors (see rx.ld), but it is a reserved
846 area of memory so do not try to access it, and if the
847 value has not been changed by the program then the
848 vector has not been installed. */
849 if (new_pc
== 0 || new_pc
== 0x00020000)
852 return RX_MAKE_STOPPED (exception_info
[type
].signal
);
854 fprintf(stderr
, "Unhandled %s exception at pc = %#lx\n",
855 exception_info
[type
].str
, (unsigned long) opcode_pc
);
856 if (type
== EX_FLOATING
)
858 int mask
= FPPENDING ();
859 fprintf (stderr
, "Pending FP exceptions:");
860 if (mask
& FPSWBITS_FV
)
861 fprintf(stderr
, " Invalid");
862 if (mask
& FPSWBITS_FO
)
863 fprintf(stderr
, " Overflow");
864 if (mask
& FPSWBITS_FZ
)
865 fprintf(stderr
, " Division-by-zero");
866 if (mask
& FPSWBITS_FU
)
867 fprintf(stderr
, " Underflow");
868 if (mask
& FPSWBITS_FX
)
869 fprintf(stderr
, " Inexact");
870 if (mask
& FPSWBITS_CE
)
871 fprintf(stderr
, " Unimplemented");
872 fprintf(stderr
, "\n");
874 return RX_MAKE_EXITED (1);
877 tprintf ("Triggering %s exception\n", exception_info
[type
].str
);
879 old_psw
= regs
.r_psw
;
880 regs
.r_psw
&= ~ (FLAGBIT_I
| FLAGBIT_U
| FLAGBIT_PM
);
885 return RX_MAKE_STEPPED ();
889 generate_access_exception (void)
893 rv
= generate_exception (EX_ACCESS
, regs
.r_pc
);
895 longjmp (decode_jmp_buf
, rv
);
899 do_fp_exception (unsigned long opcode_pc
)
902 EXCEPTION (EX_FLOATING
);
903 return RX_MAKE_STEPPED ();
907 op_is_memory (const RX_Opcode_Decoded
*rd
, int i
)
909 switch (rd
->op
[i
].type
)
911 case RX_Operand_Predec
:
912 case RX_Operand_Postinc
:
913 case RX_Operand_Indirect
:
919 #define OM(i) op_is_memory (opcode, i)
921 #define DO_RETURN(x) { longjmp (decode_jmp_buf, x); }
926 unsigned int uma
=0, umb
=0;
929 unsigned long long ll
;
931 unsigned long opcode_pc
;
933 const RX_Opcode_Decoded
*opcode
;
935 unsigned long long prev_cycle_count
;
937 #ifdef CYCLE_ACCURATE
942 prev_cycle_count
= regs
.cycle_count
;
945 #ifdef CYCLE_ACCURATE
952 maybe_get_mem_page (regs
.r_pc
);
954 opcode_pc
= regs
.r_pc
;
956 /* Note that we don't word-swap this point, there's no point. */
957 if (decode_cache_base
[opcode_pc
] == NULL
)
959 RX_Opcode_Decoded
*opcode_w
;
960 rx_data
.dpc
= opcode_pc
;
961 opcode_w
= decode_cache_base
[opcode_pc
] = calloc (1, sizeof (RX_Opcode_Decoded
));
962 opcode_size
= rx_decode_opcode (opcode_pc
, opcode_w
,
963 rx_get_byte
, &rx_data
);
968 opcode
= decode_cache_base
[opcode_pc
];
969 opcode_size
= opcode
->n_bytes
;
972 #ifdef CYCLE_ACCURATE
973 if (branch_alignment_penalty
)
975 if ((regs
.r_pc
^ (regs
.r_pc
+ opcode_size
- 1)) & ~7)
977 tprintf("1 cycle branch alignment penalty\n");
978 cycles (branch_alignment_penalty
);
980 branch_alignment_stalls
++;
983 branch_alignment_penalty
= 0;
987 regs
.r_pc
+= opcode_size
;
989 rx_flagmask
= opcode
->flags_s
;
990 rx_flagand
= ~(int)opcode
->flags_0
;
991 rx_flagor
= opcode
->flags_1
;
997 tprintf("|%lld| = ", sll
);
1000 tprintf("%lld\n", sll
);
1021 if (opcode
->op
[0].type
== RX_Operand_Register
)
1033 if (opcode
->op
[0].type
== RX_Operand_Register
)
1048 if (opcode
->op
[0].type
== RX_Operand_Register
)
1058 if (opcode
->op
[1].type
== RX_Operand_None
|| GS())
1060 #ifdef CYCLE_ACCURATE
1061 SI old_pc
= regs
.r_pc
;
1065 #ifdef CYCLE_ACCURATE
1066 delta
= regs
.r_pc
- old_pc
;
1067 if (delta
>= 0 && delta
< 16
1070 tprintf("near forward branch bonus\n");
1076 branch_alignment_penalty
= 1;
1083 #ifdef CYCLE_ACCURATE
1090 if (opcode
->op
[1].type
== RX_Operand_None
|| GS())
1093 regs
.r_pc
= opcode_pc
+ delta
;
1094 #ifdef CYCLE_ACCURATE
1095 /* Note: specs say 3, chip says 2. */
1096 if (delta
>= 0 && delta
< 16
1099 tprintf("near forward branch bonus\n");
1105 branch_alignment_penalty
= 1;
1112 #ifdef CYCLE_ACCURATE
1120 int old_psw
= regs
.r_psw
;
1122 DO_RETURN (RX_MAKE_HIT_BREAK ());
1123 if (regs
.r_intb
== 0)
1125 tprintf("BREAK hit, no vector table.\n");
1126 DO_RETURN (RX_MAKE_EXITED(1));
1128 regs
.r_psw
&= ~(FLAGBIT_I
| FLAGBIT_U
| FLAGBIT_PM
);
1131 regs
.r_pc
= mem_get_si (regs
.r_intb
);
1139 if (opcode
->op
[0].type
== RX_Operand_Register
)
1151 if (opcode
->op
[1].type
== RX_Operand_Register
)
1155 umb
= ma
& (1 << mb
);
1156 set_zc (! umb
, umb
);
1161 v
= 1 << opcode
->op
[0].reg
;
1170 case RXO_div
: /* d = d / s */
1173 tprintf("%d / %d = ", mb
, ma
);
1174 if (ma
== 0 || (ma
== -1 && (unsigned int) mb
== 0x80000000))
1177 set_flags (FLAGBIT_O
, FLAGBIT_O
);
1184 set_flags (FLAGBIT_O
, 0);
1186 div_cycles (mb
, ma
);
1190 case RXO_divu
: /* d = d / s */
1193 tprintf("%u / %u = ", umb
, uma
);
1197 set_flags (FLAGBIT_O
, FLAGBIT_O
);
1204 set_flags (FLAGBIT_O
, 0);
1206 divu_cycles (umb
, uma
);
1213 sll
= (long long)ma
* (long long)mb
;
1214 tprintf("%d * %d = %lld\n", ma
, mb
, sll
);
1215 put_reg (opcode
->op
[0].reg
, sll
);
1216 put_reg (opcode
->op
[0].reg
+ 1, sll
>> 32);
1223 ll
= (long long)uma
* (long long)umb
;
1224 tprintf("%#x * %#x = %#llx\n", uma
, umb
, ll
);
1225 put_reg (opcode
->op
[0].reg
, ll
);
1226 put_reg (opcode
->op
[0].reg
+ 1, ll
>> 32);
1256 regs
.r_psw
= regs
.r_bpsw
;
1257 regs
.r_pc
= regs
.r_bpc
;
1258 #ifdef CYCLE_ACCURATE
1259 regs
.fast_return
= 0;
1272 mb
= rxfp_ftoi (ma
, FPRM_ZERO
);
1275 tprintf("(int) %g = %d\n", int2float(ma
), mb
);
1284 int rc
= rx_syscall (regs
.r
[5]);
1285 if (! RX_STEPPED (rc
))
1290 int old_psw
= regs
.r_psw
;
1291 regs
.r_psw
&= ~(FLAGBIT_I
| FLAGBIT_U
| FLAGBIT_PM
);
1294 regs
.r_pc
= mem_get_si (regs
.r_intb
+ 4 * v
);
1302 mb
= rxfp_itof (ma
, regs
.r_fpsw
);
1304 tprintf("(float) %d = %x\n", ma
, mb
);
1313 #ifdef CYCLE_ACCURATE
1318 #ifdef CYCLE_ACCURATE
1319 regs
.link_register
= regs
.r_pc
;
1321 pushpc (get_reg (pc
));
1322 if (opcode
->id
== RXO_jsrrel
)
1324 #ifdef CYCLE_ACCURATE
1325 delta
= v
- regs
.r_pc
;
1328 #ifdef CYCLE_ACCURATE
1329 /* Note: docs say 3, chip says 2 */
1330 if (delta
>= 0 && delta
< 16)
1332 tprintf ("near forward jsr bonus\n");
1337 branch_alignment_penalty
= 1;
1340 regs
.fast_return
= 1;
1346 ll
= (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
1348 put_reg64 (acc64
, ll
+ regs
.r_acc
);
1353 ll
= (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
1355 put_reg64 (acc64
, ll
+ regs
.r_acc
);
1382 if (opcode
->op
[1].type
== RX_Operand_Register
1383 && opcode
->op
[1].reg
== 17 /* PC */)
1385 /* Special case. We want the address of the insn, not the
1386 address of the next insn. */
1390 if (opcode
->op
[0].type
== RX_Operand_Register
1391 && opcode
->op
[0].reg
== 16 /* PSW */)
1393 /* Special case, LDC and POPC can't ever modify PM. */
1394 int pm
= regs
.r_psw
& FLAGBIT_PM
;
1399 v
&= ~ (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1405 /* various things can't be changed in user mode. */
1406 if (opcode
->op
[0].type
== RX_Operand_Register
)
1407 if (opcode
->op
[0].reg
== 32)
1409 v
&= ~ (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1410 v
|= regs
.r_psw
& (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1412 if (opcode
->op
[0].reg
== 34 /* ISP */
1413 || opcode
->op
[0].reg
== 37 /* BPSW */
1414 || opcode
->op
[0].reg
== 39 /* INTB */
1415 || opcode
->op
[0].reg
== 38 /* VCT */)
1416 /* These are ignored. */
1426 #ifdef CYCLE_ACCURATE
1427 if ((opcode
->op
[0].type
== RX_Operand_Predec
1428 && opcode
->op
[1].type
== RX_Operand_Register
)
1429 || (opcode
->op
[0].type
== RX_Operand_Postinc
1430 && opcode
->op
[1].type
== RX_Operand_Register
))
1432 /* Special case: push reg doesn't cause a memory stall. */
1434 tprintf("push special case\n");
1453 ll
= (unsigned long long) US1() * (unsigned long long) v
;
1460 ll
= (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v
>> 16);
1462 put_reg64 (acc64
, ll
);
1468 ll
= (long long)(signed short)(GS()) * (long long)(signed short)(v
);
1470 put_reg64 (acc64
, ll
);
1475 PD (get_reg (acchi
));
1480 PD (get_reg (acclo
));
1485 PD (get_reg (accmi
));
1490 put_reg (acchi
, GS ());
1495 put_reg (acclo
, GS ());
1500 regs
.r_psw
&= ~ FLAGBITS_IPL
;
1501 regs
.r_psw
|= (GS () << FLAGSHIFT_IPL
) & FLAGBITS_IPL
;
1516 /* POPM cannot pop R0 (sp). */
1517 if (opcode
->op
[1].reg
== 0 || opcode
->op
[2].reg
== 0)
1518 EXCEPTION (EX_UNDEFINED
);
1519 if (opcode
->op
[1].reg
>= opcode
->op
[2].reg
)
1521 regs
.r_pc
= opcode_pc
;
1522 DO_RETURN (RX_MAKE_STOPPED (SIGILL
));
1524 for (v
= opcode
->op
[1].reg
; v
<= opcode
->op
[2].reg
; v
++)
1528 put_reg (v
, pop ());
1533 /* PUSHM cannot push R0 (sp). */
1534 if (opcode
->op
[1].reg
== 0 || opcode
->op
[2].reg
== 0)
1535 EXCEPTION (EX_UNDEFINED
);
1536 if (opcode
->op
[1].reg
>= opcode
->op
[2].reg
)
1538 regs
.r_pc
= opcode_pc
;
1539 return RX_MAKE_STOPPED (SIGILL
);
1541 for (v
= opcode
->op
[2].reg
; v
>= opcode
->op
[1].reg
; v
--)
1546 cycles (opcode
->op
[2].reg
- opcode
->op
[1].reg
+ 1);
1550 ll
= get_reg64 (acc64
) << GS ();
1551 ll
+= 0x80000000ULL
;
1552 if ((signed long long)ll
> (signed long long)0x00007fff00000000ULL
)
1553 ll
= 0x00007fff00000000ULL
;
1554 else if ((signed long long)ll
< (signed long long)0xffff800000000000ULL
)
1555 ll
= 0xffff800000000000ULL
;
1557 ll
&= 0xffffffff00000000ULL
;
1558 put_reg64 (acc64
, ll
);
1564 regs
.r_pc
= poppc ();
1565 regs
.r_psw
= poppc ();
1567 regs
.r_psw
|= FLAGBIT_U
;
1568 #ifdef CYCLE_ACCURATE
1569 regs
.fast_return
= 0;
1576 umb
= (((uma
>> 24) & 0xff)
1577 | ((uma
>> 8) & 0xff00)
1578 | ((uma
<< 8) & 0xff0000)
1579 | ((uma
<< 24) & 0xff000000UL
));
1586 umb
= (((uma
>> 8) & 0x00ff00ff)
1587 | ((uma
<< 8) & 0xff00ff00UL
));
1595 #ifdef CYCLE_ACCURATE
1599 while (regs
.r
[3] != 0)
1603 switch (opcode
->size
)
1606 ma
= mem_get_si (regs
.r
[1]);
1607 mb
= mem_get_si (regs
.r
[2]);
1612 ma
= sign_ext (mem_get_hi (regs
.r
[1]), 16);
1613 mb
= sign_ext (mem_get_hi (regs
.r
[2]), 16);
1618 ma
= sign_ext (mem_get_qi (regs
.r
[1]), 8);
1619 mb
= sign_ext (mem_get_qi (regs
.r
[2]), 8);
1626 /* We do the multiply as a signed value. */
1627 sll
= (long long)ma
* (long long)mb
;
1628 tprintf(" %016llx = %d * %d\n", sll
, ma
, mb
);
1629 /* but we do the sum as unsigned, while sign extending the operands. */
1630 tmp
= regs
.r
[4] + (sll
& 0xffffffffUL
);
1631 regs
.r
[4] = tmp
& 0xffffffffUL
;
1634 tmp
+= regs
.r
[5] + (sll
& 0xffffffffUL
);
1635 regs
.r
[5] = tmp
& 0xffffffffUL
;
1638 tmp
+= regs
.r
[6] + (sll
& 0xffffffffUL
);
1639 regs
.r
[6] = tmp
& 0xffffffffUL
;
1640 tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
1641 (unsigned long) regs
.r
[6],
1642 (unsigned long) regs
.r
[5],
1643 (unsigned long) regs
.r
[4]);
1647 if (regs
.r
[6] & 0x00008000)
1648 regs
.r
[6] |= 0xffff0000UL
;
1650 regs
.r
[6] &= 0x0000ffff;
1651 ma
= (regs
.r
[6] & 0x80000000UL
) ? FLAGBIT_S
: 0;
1652 if (regs
.r
[6] != 0 && regs
.r
[6] != 0xffffffffUL
)
1653 set_flags (FLAGBIT_O
|FLAGBIT_S
, ma
| FLAGBIT_O
);
1655 set_flags (FLAGBIT_O
|FLAGBIT_S
, ma
);
1656 #ifdef CYCLE_ACCURATE
1657 switch (opcode
->size
)
1660 cycles (6 + 4 * tx
);
1663 cycles (6 + 5 * (tx
/ 2) + 4 * (tx
% 2));
1666 cycles (6 + 7 * (tx
/ 4) + 4 * (tx
% 4));
1676 ma
= v
& 0x80000000UL
;
1688 uma
|= (carry
? 0x80000000UL
: 0);
1689 set_szc (uma
, 4, mb
);
1699 uma
= (uma
<< mb
) | (uma
>> (32-mb
));
1702 set_szc (uma
, 4, mb
);
1712 uma
= (uma
>> mb
) | (uma
<< (32-mb
));
1713 mb
= uma
& 0x80000000;
1715 set_szc (uma
, 4, mb
);
1723 mb
= rxfp_ftoi (ma
, regs
.r_fpsw
);
1726 tprintf("(int) %g = %d\n", int2float(ma
), mb
);
1733 #ifdef CYCLE_ACCURATE
1736 regs
.r_pc
= poppc ();
1737 #ifdef CYCLE_ACCURATE
1738 /* Note: specs say 5, chip says 3. */
1739 if (regs
.fast_return
&& regs
.link_register
== regs
.r_pc
)
1744 tprintf("fast return bonus\n");
1748 regs
.fast_return
= 0;
1749 branch_alignment_penalty
= 1;
1755 if (opcode
->op
[2].type
== RX_Operand_Register
)
1758 /* RTSD cannot pop R0 (sp). */
1759 put_reg (0, get_reg (0) + GS() - (opcode
->op
[0].reg
-opcode
->op
[2].reg
+1)*4);
1760 if (opcode
->op
[2].reg
== 0)
1761 EXCEPTION (EX_UNDEFINED
);
1762 #ifdef CYCLE_ACCURATE
1763 tx
= opcode
->op
[0].reg
- opcode
->op
[2].reg
+ 1;
1765 for (i
= opcode
->op
[2].reg
; i
<= opcode
->op
[0].reg
; i
++)
1768 put_reg (i
, pop ());
1773 #ifdef CYCLE_ACCURATE
1776 put_reg (0, get_reg (0) + GS());
1778 put_reg (pc
, poppc());
1779 #ifdef CYCLE_ACCURATE
1780 if (regs
.fast_return
&& regs
.link_register
== regs
.r_pc
)
1782 tprintf("fast return bonus\n");
1786 cycles (tx
< 3 ? 3 : tx
+ 1);
1790 cycles (tx
< 5 ? 5 : tx
+ 1);
1792 regs
.fast_return
= 0;
1793 branch_alignment_penalty
= 1;
1798 if (FLAG_O
&& FLAG_S
)
1800 else if (FLAG_O
&& ! FLAG_S
)
1806 MATH_OP (-, ! carry
);
1818 #ifdef CYCLE_ACCURATE
1821 while (regs
.r
[3] != 0)
1823 uma
= mem_get_qi (regs
.r
[1] ++);
1824 umb
= mem_get_qi (regs
.r
[2] ++);
1826 if (uma
!= umb
|| uma
== 0)
1832 set_zc (0, ((int)uma
- (int)umb
) >= 0);
1833 cycles (2 + 4 * (tx
/ 4) + 4 * (tx
% 4));
1837 v
= 1 << opcode
->op
[0].reg
;
1848 #ifdef CYCLE_ACCURATE
1853 uma
= mem_get_qi (regs
.r
[2] --);
1854 mem_put_qi (regs
.r
[1]--, uma
);
1857 #ifdef CYCLE_ACCURATE
1859 cycles (6 + 3 * (tx
/ 4) + 3 * (tx
% 4));
1861 cycles (2 + 3 * (tx
% 4));
1867 #ifdef CYCLE_ACCURATE
1872 uma
= mem_get_qi (regs
.r
[2] ++);
1873 mem_put_qi (regs
.r
[1]++, uma
);
1876 cycles (2 + 3 * (int)(tx
/ 4) + 3 * (tx
% 4));
1880 #ifdef CYCLE_ACCURATE
1883 while (regs
.r
[3] != 0)
1885 uma
= mem_get_qi (regs
.r
[2] ++);
1886 mem_put_qi (regs
.r
[1]++, uma
);
1891 cycles (2 + 3 * (int)(tx
/ 4) + 3 * (tx
% 4));
1894 case RXO_shar
: /* d = ma >> mb */
1895 SHIFT_OP (sll
, int, mb
, >>=, 1);
1899 case RXO_shll
: /* d = ma << mb */
1900 SHIFT_OP (ll
, int, mb
, <<=, 0x80000000UL
);
1904 case RXO_shlr
: /* d = ma >> mb */
1905 SHIFT_OP (ll
, unsigned int, mb
, >>=, 1);
1911 #ifdef CYCLE_ACCURATE
1914 switch (opcode
->size
)
1917 while (regs
.r
[3] != 0)
1919 mem_put_si (regs
.r
[1], regs
.r
[2]);
1926 while (regs
.r
[3] != 0)
1928 mem_put_hi (regs
.r
[1], regs
.r
[2]);
1932 cycles (2 + (int)(tx
/ 2) + tx
% 2);
1935 while (regs
.r
[3] != 0)
1937 mem_put_qi (regs
.r
[1], regs
.r
[2]);
1941 cycles (2 + (int)(tx
/ 4) + tx
% 4);
1956 regs
.r_psw
|= FLAGBIT_I
;
1957 DO_RETURN (RX_MAKE_STOPPED(0));
1965 #ifdef CYCLE_ACCURATE
1973 switch (opcode
->size
)
1977 while (regs
.r
[3] != 0)
1980 umb
= mem_get_si (get_reg (1));
1982 #ifdef CYCLE_ACCURATE
1988 #ifdef CYCLE_ACCURATE
1989 cycles (3 + 3 * tx
);
1993 uma
= get_reg (2) & 0xffff;
1994 while (regs
.r
[3] != 0)
1997 umb
= mem_get_hi (get_reg (1));
1999 #ifdef CYCLE_ACCURATE
2005 #ifdef CYCLE_ACCURATE
2006 cycles (3 + 3 * (tx
/ 2) + 3 * (tx
% 2));
2010 uma
= get_reg (2) & 0xff;
2011 while (regs
.r
[3] != 0)
2014 umb
= mem_get_qi (regs
.r
[1]);
2016 #ifdef CYCLE_ACCURATE
2022 #ifdef CYCLE_ACCURATE
2023 cycles (3 + 3 * (tx
/ 4) + 3 * (tx
% 4));
2032 set_zc (0, ((int)uma
- (int)umb
) >= 0);
2037 #ifdef CYCLE_ACCURATE
2042 switch (opcode
->size
)
2046 while (regs
.r
[3] != 0)
2049 umb
= mem_get_si (get_reg (1));
2051 #ifdef CYCLE_ACCURATE
2057 #ifdef CYCLE_ACCURATE
2058 cycles (3 + 3 * tx
);
2062 uma
= get_reg (2) & 0xffff;
2063 while (regs
.r
[3] != 0)
2066 umb
= mem_get_hi (get_reg (1));
2068 #ifdef CYCLE_ACCURATE
2074 #ifdef CYCLE_ACCURATE
2075 cycles (3 + 3 * (tx
/ 2) + 3 * (tx
% 2));
2079 uma
= get_reg (2) & 0xff;
2080 while (regs
.r
[3] != 0)
2083 umb
= mem_get_qi (regs
.r
[1]);
2085 #ifdef CYCLE_ACCURATE
2091 #ifdef CYCLE_ACCURATE
2092 cycles (3 + 3 * (tx
/ 4) + 3 * (tx
% 4));
2101 set_zc (0, ((int)uma
- (int)umb
) >= 0);
2106 regs
.r_psw
|= FLAGBIT_I
;
2107 DO_RETURN (RX_MAKE_STOPPED(0));
2110 #ifdef CYCLE_ACCURATE
2113 v
= GS (); /* This is the memory operand, if any. */
2114 PS (GD ()); /* and this may change the address register. */
2117 #ifdef CYCLE_ACCURATE
2118 /* all M cycles happen during xchg's cycles. */
2129 EXCEPTION (EX_UNDEFINED
);
2132 #ifdef CYCLE_ACCURATE
2135 regs
.m2m
|= M2M_SRC
;
2137 regs
.m2m
|= M2M_DST
;
2144 if (prev_cycle_count
== regs
.cycle_count
)
2146 printf("Cycle count not updated! id %s\n", id_names
[opcode
->id
]);
2152 if (running_benchmark
)
2154 int omap
= op_lookup (opcode
->op
[0].type
, opcode
->op
[1].type
, opcode
->op
[2].type
);
2157 cycles_per_id
[opcode
->id
][omap
] += regs
.cycle_count
- prev_cycle_count
;
2158 times_per_id
[opcode
->id
][omap
] ++;
2160 times_per_pair
[prev_opcode_id
][po0
][opcode
->id
][omap
] ++;
2162 prev_opcode_id
= opcode
->id
;
2167 return RX_MAKE_STEPPED ();
2172 reset_pipeline_stats (void)
2174 memset (cycles_per_id
, 0, sizeof(cycles_per_id
));
2175 memset (times_per_id
, 0, sizeof(times_per_id
));
2177 register_stalls
= 0;
2179 branch_alignment_stalls
= 0;
2181 memset (times_per_pair
, 0, sizeof(times_per_pair
));
2182 running_benchmark
= 1;
2184 benchmark_start_cycle
= regs
.cycle_count
;
2188 halt_pipeline_stats (void)
2190 running_benchmark
= 0;
2191 benchmark_end_cycle
= regs
.cycle_count
;
2196 pipeline_stats (void)
2203 #ifdef CYCLE_ACCURATE
2206 printf ("cycles: %llu\n", regs
.cycle_count
);
2210 printf ("cycles: %13s\n", comma (regs
.cycle_count
));
2214 if (benchmark_start_cycle
)
2215 printf ("bmark: %13s\n", comma (benchmark_end_cycle
- benchmark_start_cycle
));
2218 for (i
= 0; i
< N_RXO
; i
++)
2219 for (o1
= 0; o1
< N_MAP
; o1
++)
2220 if (times_per_id
[i
][o1
])
2221 printf("%13s %13s %7.2f %s %s\n",
2222 comma (cycles_per_id
[i
][o1
]),
2223 comma (times_per_id
[i
][o1
]),
2224 (double)cycles_per_id
[i
][o1
] / times_per_id
[i
][o1
],
2225 op_cache_string(o1
),
2229 for (p
= 0; p
< N_RXO
; p
++)
2230 for (p1
= 0; p1
< N_MAP
; p1
++)
2231 for (i
= 0; i
< N_RXO
; i
++)
2232 for (o1
= 0; o1
< N_MAP
; o1
++)
2233 if (times_per_pair
[p
][p1
][i
][o1
])
2235 printf("%13s %s %-9s -> %s %s\n",
2236 comma (times_per_pair
[p
][p1
][i
][o1
]),
2237 op_cache_string(p1
),
2239 op_cache_string(o1
),
2244 printf("%13s memory stalls\n", comma (memory_stalls
));
2245 printf("%13s register stalls\n", comma (register_stalls
));
2246 printf("%13s branches taken (non-return)\n", comma (branch_stalls
));
2247 printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls
));
2248 printf("%13s fast returns\n", comma (fast_returns
));
This page took 0.077247 seconds and 4 git commands to generate.