]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/rx/rx.c
1 /* rx.c --- opcode semantics for stand-alone RX simulator.
3 Copyright (C) 2008, 2009, 2010 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
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
[0].type
== RX_Operand_Register
1383 && opcode
->op
[0].reg
== 16 /* PSW */)
1385 /* Special case, LDC and POPC can't ever modify PM. */
1386 int pm
= regs
.r_psw
& FLAGBIT_PM
;
1391 v
&= ~ (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1397 /* various things can't be changed in user mode. */
1398 if (opcode
->op
[0].type
== RX_Operand_Register
)
1399 if (opcode
->op
[0].reg
== 32)
1401 v
&= ~ (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1402 v
|= regs
.r_psw
& (FLAGBIT_I
| FLAGBIT_U
| FLAGBITS_IPL
);
1404 if (opcode
->op
[0].reg
== 34 /* ISP */
1405 || opcode
->op
[0].reg
== 37 /* BPSW */
1406 || opcode
->op
[0].reg
== 39 /* INTB */
1407 || opcode
->op
[0].reg
== 38 /* VCT */)
1408 /* These are ignored. */
1418 #ifdef CYCLE_ACCURATE
1419 if ((opcode
->op
[0].type
== RX_Operand_Predec
1420 && opcode
->op
[1].type
== RX_Operand_Register
)
1421 || (opcode
->op
[0].type
== RX_Operand_Postinc
1422 && opcode
->op
[1].type
== RX_Operand_Register
))
1424 /* Special case: push reg doesn't cause a memory stall. */
1426 tprintf("push special case\n");
1445 ll
= (unsigned long long) US1() * (unsigned long long) v
;
1452 ll
= (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v
>> 16);
1454 put_reg64 (acc64
, ll
);
1460 ll
= (long long)(signed short)(GS()) * (long long)(signed short)(v
);
1462 put_reg64 (acc64
, ll
);
1467 PD (get_reg (acchi
));
1472 PD (get_reg (acclo
));
1477 PD (get_reg (accmi
));
1482 put_reg (acchi
, GS ());
1487 put_reg (acclo
, GS ());
1492 regs
.r_psw
&= ~ FLAGBITS_IPL
;
1493 regs
.r_psw
|= (GS () << FLAGSHIFT_IPL
) & FLAGBITS_IPL
;
1508 /* POPM cannot pop R0 (sp). */
1509 if (opcode
->op
[1].reg
== 0 || opcode
->op
[2].reg
== 0)
1510 EXCEPTION (EX_UNDEFINED
);
1511 if (opcode
->op
[1].reg
>= opcode
->op
[2].reg
)
1513 regs
.r_pc
= opcode_pc
;
1514 DO_RETURN (RX_MAKE_STOPPED (SIGILL
));
1516 for (v
= opcode
->op
[1].reg
; v
<= opcode
->op
[2].reg
; v
++)
1520 put_reg (v
, pop ());
1525 /* PUSHM cannot push R0 (sp). */
1526 if (opcode
->op
[1].reg
== 0 || opcode
->op
[2].reg
== 0)
1527 EXCEPTION (EX_UNDEFINED
);
1528 if (opcode
->op
[1].reg
>= opcode
->op
[2].reg
)
1530 regs
.r_pc
= opcode_pc
;
1531 return RX_MAKE_STOPPED (SIGILL
);
1533 for (v
= opcode
->op
[2].reg
; v
>= opcode
->op
[1].reg
; v
--)
1538 cycles (opcode
->op
[2].reg
- opcode
->op
[1].reg
+ 1);
1542 ll
= get_reg64 (acc64
) << GS ();
1543 ll
+= 0x80000000ULL
;
1544 if ((signed long long)ll
> (signed long long)0x00007fff00000000ULL
)
1545 ll
= 0x00007fff00000000ULL
;
1546 else if ((signed long long)ll
< (signed long long)0xffff800000000000ULL
)
1547 ll
= 0xffff800000000000ULL
;
1549 ll
&= 0xffffffff00000000ULL
;
1550 put_reg64 (acc64
, ll
);
1556 regs
.r_pc
= poppc ();
1557 regs
.r_psw
= poppc ();
1559 regs
.r_psw
|= FLAGBIT_U
;
1560 #ifdef CYCLE_ACCURATE
1561 regs
.fast_return
= 0;
1568 umb
= (((uma
>> 24) & 0xff)
1569 | ((uma
>> 8) & 0xff00)
1570 | ((uma
<< 8) & 0xff0000)
1571 | ((uma
<< 24) & 0xff000000UL
));
1578 umb
= (((uma
>> 8) & 0x00ff00ff)
1579 | ((uma
<< 8) & 0xff00ff00UL
));
1587 #ifdef CYCLE_ACCURATE
1591 while (regs
.r
[3] != 0)
1595 switch (opcode
->size
)
1598 ma
= mem_get_si (regs
.r
[1]);
1599 mb
= mem_get_si (regs
.r
[2]);
1604 ma
= sign_ext (mem_get_hi (regs
.r
[1]), 16);
1605 mb
= sign_ext (mem_get_hi (regs
.r
[2]), 16);
1610 ma
= sign_ext (mem_get_qi (regs
.r
[1]), 8);
1611 mb
= sign_ext (mem_get_qi (regs
.r
[2]), 8);
1618 /* We do the multiply as a signed value. */
1619 sll
= (long long)ma
* (long long)mb
;
1620 tprintf(" %016llx = %d * %d\n", sll
, ma
, mb
);
1621 /* but we do the sum as unsigned, while sign extending the operands. */
1622 tmp
= regs
.r
[4] + (sll
& 0xffffffffUL
);
1623 regs
.r
[4] = tmp
& 0xffffffffUL
;
1626 tmp
+= regs
.r
[5] + (sll
& 0xffffffffUL
);
1627 regs
.r
[5] = tmp
& 0xffffffffUL
;
1630 tmp
+= regs
.r
[6] + (sll
& 0xffffffffUL
);
1631 regs
.r
[6] = tmp
& 0xffffffffUL
;
1632 tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
1633 (unsigned long) regs
.r
[6],
1634 (unsigned long) regs
.r
[5],
1635 (unsigned long) regs
.r
[4]);
1639 if (regs
.r
[6] & 0x00008000)
1640 regs
.r
[6] |= 0xffff0000UL
;
1642 regs
.r
[6] &= 0x0000ffff;
1643 ma
= (regs
.r
[6] & 0x80000000UL
) ? FLAGBIT_S
: 0;
1644 if (regs
.r
[6] != 0 && regs
.r
[6] != 0xffffffffUL
)
1645 set_flags (FLAGBIT_O
|FLAGBIT_S
, ma
| FLAGBIT_O
);
1647 set_flags (FLAGBIT_O
|FLAGBIT_S
, ma
);
1648 #ifdef CYCLE_ACCURATE
1649 switch (opcode
->size
)
1652 cycles (6 + 4 * tx
);
1655 cycles (6 + 5 * (tx
/ 2) + 4 * (tx
% 2));
1658 cycles (6 + 7 * (tx
/ 4) + 4 * (tx
% 4));
1668 ma
= v
& 0x80000000UL
;
1680 uma
|= (carry
? 0x80000000UL
: 0);
1681 set_szc (uma
, 4, mb
);
1691 uma
= (uma
<< mb
) | (uma
>> (32-mb
));
1694 set_szc (uma
, 4, mb
);
1704 uma
= (uma
>> mb
) | (uma
<< (32-mb
));
1705 mb
= uma
& 0x80000000;
1707 set_szc (uma
, 4, mb
);
1715 mb
= rxfp_ftoi (ma
, regs
.r_fpsw
);
1718 tprintf("(int) %g = %d\n", int2float(ma
), mb
);
1725 #ifdef CYCLE_ACCURATE
1728 regs
.r_pc
= poppc ();
1729 #ifdef CYCLE_ACCURATE
1730 /* Note: specs say 5, chip says 3. */
1731 if (regs
.fast_return
&& regs
.link_register
== regs
.r_pc
)
1736 tprintf("fast return bonus\n");
1740 regs
.fast_return
= 0;
1741 branch_alignment_penalty
= 1;
1747 if (opcode
->op
[2].type
== RX_Operand_Register
)
1750 /* RTSD cannot pop R0 (sp). */
1751 put_reg (0, get_reg (0) + GS() - (opcode
->op
[0].reg
-opcode
->op
[2].reg
+1)*4);
1752 if (opcode
->op
[2].reg
== 0)
1753 EXCEPTION (EX_UNDEFINED
);
1754 #ifdef CYCLE_ACCURATE
1755 tx
= opcode
->op
[0].reg
- opcode
->op
[2].reg
+ 1;
1757 for (i
= opcode
->op
[2].reg
; i
<= opcode
->op
[0].reg
; i
++)
1760 put_reg (i
, pop ());
1765 #ifdef CYCLE_ACCURATE
1768 put_reg (0, get_reg (0) + GS());
1770 put_reg (pc
, poppc());
1771 #ifdef CYCLE_ACCURATE
1772 if (regs
.fast_return
&& regs
.link_register
== regs
.r_pc
)
1774 tprintf("fast return bonus\n");
1778 cycles (tx
< 3 ? 3 : tx
+ 1);
1782 cycles (tx
< 5 ? 5 : tx
+ 1);
1784 regs
.fast_return
= 0;
1785 branch_alignment_penalty
= 1;
1790 if (FLAG_O
&& FLAG_S
)
1792 else if (FLAG_O
&& ! FLAG_S
)
1798 MATH_OP (-, ! carry
);
1810 #ifdef CYCLE_ACCURATE
1813 while (regs
.r
[3] != 0)
1815 uma
= mem_get_qi (regs
.r
[1] ++);
1816 umb
= mem_get_qi (regs
.r
[2] ++);
1818 if (uma
!= umb
|| uma
== 0)
1824 set_zc (0, ((int)uma
- (int)umb
) >= 0);
1825 cycles (2 + 4 * (tx
/ 4) + 4 * (tx
% 4));
1829 v
= 1 << opcode
->op
[0].reg
;
1840 #ifdef CYCLE_ACCURATE
1845 uma
= mem_get_qi (regs
.r
[2] --);
1846 mem_put_qi (regs
.r
[1]--, uma
);
1849 #ifdef CYCLE_ACCURATE
1851 cycles (6 + 3 * (tx
/ 4) + 3 * (tx
% 4));
1853 cycles (2 + 3 * (tx
% 4));
1859 #ifdef CYCLE_ACCURATE
1864 uma
= mem_get_qi (regs
.r
[2] ++);
1865 mem_put_qi (regs
.r
[1]++, uma
);
1868 cycles (2 + 3 * (int)(tx
/ 4) + 3 * (tx
% 4));
1872 #ifdef CYCLE_ACCURATE
1875 while (regs
.r
[3] != 0)
1877 uma
= mem_get_qi (regs
.r
[2] ++);
1878 mem_put_qi (regs
.r
[1]++, uma
);
1883 cycles (2 + 3 * (int)(tx
/ 4) + 3 * (tx
% 4));
1886 case RXO_shar
: /* d = ma >> mb */
1887 SHIFT_OP (sll
, int, mb
, >>=, 1);
1891 case RXO_shll
: /* d = ma << mb */
1892 SHIFT_OP (ll
, int, mb
, <<=, 0x80000000UL
);
1896 case RXO_shlr
: /* d = ma >> mb */
1897 SHIFT_OP (ll
, unsigned int, mb
, >>=, 1);
1903 #ifdef CYCLE_ACCURATE
1906 switch (opcode
->size
)
1909 while (regs
.r
[3] != 0)
1911 mem_put_si (regs
.r
[1], regs
.r
[2]);
1918 while (regs
.r
[3] != 0)
1920 mem_put_hi (regs
.r
[1], regs
.r
[2]);
1924 cycles (2 + (int)(tx
/ 2) + tx
% 2);
1927 while (regs
.r
[3] != 0)
1929 mem_put_qi (regs
.r
[1], regs
.r
[2]);
1933 cycles (2 + (int)(tx
/ 4) + tx
% 4);
1948 regs
.r_psw
|= FLAGBIT_I
;
1949 DO_RETURN (RX_MAKE_STOPPED(0));
1957 #ifdef CYCLE_ACCURATE
1965 switch (opcode
->size
)
1969 while (regs
.r
[3] != 0)
1972 umb
= mem_get_si (get_reg (1));
1974 #ifdef CYCLE_ACCURATE
1980 #ifdef CYCLE_ACCURATE
1981 cycles (3 + 3 * tx
);
1985 uma
= get_reg (2) & 0xffff;
1986 while (regs
.r
[3] != 0)
1989 umb
= mem_get_hi (get_reg (1));
1991 #ifdef CYCLE_ACCURATE
1997 #ifdef CYCLE_ACCURATE
1998 cycles (3 + 3 * (tx
/ 2) + 3 * (tx
% 2));
2002 uma
= get_reg (2) & 0xff;
2003 while (regs
.r
[3] != 0)
2006 umb
= mem_get_qi (regs
.r
[1]);
2008 #ifdef CYCLE_ACCURATE
2014 #ifdef CYCLE_ACCURATE
2015 cycles (3 + 3 * (tx
/ 4) + 3 * (tx
% 4));
2024 set_zc (0, ((int)uma
- (int)umb
) >= 0);
2029 #ifdef CYCLE_ACCURATE
2034 switch (opcode
->size
)
2038 while (regs
.r
[3] != 0)
2041 umb
= mem_get_si (get_reg (1));
2043 #ifdef CYCLE_ACCURATE
2049 #ifdef CYCLE_ACCURATE
2050 cycles (3 + 3 * tx
);
2054 uma
= get_reg (2) & 0xffff;
2055 while (regs
.r
[3] != 0)
2058 umb
= mem_get_hi (get_reg (1));
2060 #ifdef CYCLE_ACCURATE
2066 #ifdef CYCLE_ACCURATE
2067 cycles (3 + 3 * (tx
/ 2) + 3 * (tx
% 2));
2071 uma
= get_reg (2) & 0xff;
2072 while (regs
.r
[3] != 0)
2075 umb
= mem_get_qi (regs
.r
[1]);
2077 #ifdef CYCLE_ACCURATE
2083 #ifdef CYCLE_ACCURATE
2084 cycles (3 + 3 * (tx
/ 4) + 3 * (tx
% 4));
2093 set_zc (0, ((int)uma
- (int)umb
) >= 0);
2098 regs
.r_psw
|= FLAGBIT_I
;
2099 DO_RETURN (RX_MAKE_STOPPED(0));
2102 #ifdef CYCLE_ACCURATE
2105 v
= GS (); /* This is the memory operand, if any. */
2106 PS (GD ()); /* and this may change the address register. */
2109 #ifdef CYCLE_ACCURATE
2110 /* all M cycles happen during xchg's cycles. */
2121 EXCEPTION (EX_UNDEFINED
);
2124 #ifdef CYCLE_ACCURATE
2127 regs
.m2m
|= M2M_SRC
;
2129 regs
.m2m
|= M2M_DST
;
2136 if (prev_cycle_count
== regs
.cycle_count
)
2138 printf("Cycle count not updated! id %s\n", id_names
[opcode
->id
]);
2144 if (running_benchmark
)
2146 int omap
= op_lookup (opcode
->op
[0].type
, opcode
->op
[1].type
, opcode
->op
[2].type
);
2149 cycles_per_id
[opcode
->id
][omap
] += regs
.cycle_count
- prev_cycle_count
;
2150 times_per_id
[opcode
->id
][omap
] ++;
2152 times_per_pair
[prev_opcode_id
][po0
][opcode
->id
][omap
] ++;
2154 prev_opcode_id
= opcode
->id
;
2159 return RX_MAKE_STEPPED ();
2164 reset_pipeline_stats (void)
2166 memset (cycles_per_id
, 0, sizeof(cycles_per_id
));
2167 memset (times_per_id
, 0, sizeof(times_per_id
));
2169 register_stalls
= 0;
2171 branch_alignment_stalls
= 0;
2173 memset (times_per_pair
, 0, sizeof(times_per_pair
));
2174 running_benchmark
= 1;
2176 benchmark_start_cycle
= regs
.cycle_count
;
2180 halt_pipeline_stats (void)
2182 running_benchmark
= 0;
2183 benchmark_end_cycle
= regs
.cycle_count
;
2188 pipeline_stats (void)
2195 #ifdef CYCLE_ACCURATE
2198 printf ("cycles: %llu\n", regs
.cycle_count
);
2202 printf ("cycles: %13s\n", comma (regs
.cycle_count
));
2206 if (benchmark_start_cycle
)
2207 printf ("bmark: %13s\n", comma (benchmark_end_cycle
- benchmark_start_cycle
));
2210 for (i
= 0; i
< N_RXO
; i
++)
2211 for (o1
= 0; o1
< N_MAP
; o1
++)
2212 if (times_per_id
[i
][o1
])
2213 printf("%13s %13s %7.2f %s %s\n",
2214 comma (cycles_per_id
[i
][o1
]),
2215 comma (times_per_id
[i
][o1
]),
2216 (double)cycles_per_id
[i
][o1
] / times_per_id
[i
][o1
],
2217 op_cache_string(o1
),
2221 for (p
= 0; p
< N_RXO
; p
++)
2222 for (p1
= 0; p1
< N_MAP
; p1
++)
2223 for (i
= 0; i
< N_RXO
; i
++)
2224 for (o1
= 0; o1
< N_MAP
; o1
++)
2225 if (times_per_pair
[p
][p1
][i
][o1
])
2227 printf("%13s %s %-9s -> %s %s\n",
2228 comma (times_per_pair
[p
][p1
][i
][o1
]),
2229 op_cache_string(p1
),
2231 op_cache_string(o1
),
2236 printf("%13s memory stalls\n", comma (memory_stalls
));
2237 printf("%13s register stalls\n", comma (register_stalls
));
2238 printf("%13s branches taken (non-return)\n", comma (branch_stalls
));
2239 printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls
));
2240 printf("%13s fast returns\n", comma (fast_returns
));