Index: sim/testsuite/sim/bfin/se_allopcodes.h |
diff --git a/sim/testsuite/sim/bfin/se_allopcodes.h b/sim/testsuite/sim/bfin/se_allopcodes.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7ff8d2b9fa0b55d1e6877236de8b06314128386e |
--- /dev/null |
+++ b/sim/testsuite/sim/bfin/se_allopcodes.h |
@@ -0,0 +1,222 @@ |
+/* |
+ * set up pointers to valid data (32Meg), to reduce address violations |
+ */ |
+.macro reset_dags |
+ imm32 r0, 0x2000000; |
+ l0 = 0; l1 = 0; l2 = 0; l3 = 0; |
+ p0 = r0; p1 = r0; p2 = r0; p3 = r0; p4 = r0; p5 = r0; |
+ usp = r0; fp = r0; |
+ i0 = r0; i1 = r0; i2 = r0; i3 = r0; |
+ b0 = r0; b1 = r0; b2 = r0; b3 = r0; |
+.endm |
+ |
+#if SE_ALL_BITS == 32 |
+# define LOAD_PFX |
+#elif SE_ALL_BITS == 16 |
+# define LOAD_PFX W |
+#else |
+# error "Please define SE_ALL_BITS" |
+#endif |
+ |
+/* |
+ * execute a test of an opcode space. host test |
+ * has to fill out a number of callbacks. |
+ * |
+ * se_all_insn_init |
+ * the first insn to start executing |
+ * se_all_insn_table |
+ * the table of insn ranges and expected seqstat |
+ * |
+ * se_all_load_insn |
+ * in: P5 |
+ * out: R0, R2 |
+ * scratch: R1 |
+ * load current user insn via register P5 into R0. |
+ * register R2 is available for caching with se_all_next_insn. |
+ * se_all_load_table |
+ * in: P1 |
+ * out: R7, R6, R5 |
+ * scratch: R1 |
+ * load insn range/seqstat entry from table via register P1 |
+ * R7: low range |
+ * R6: high range |
+ * R5: seqstat |
+ * |
+ * se_all_next_insn |
+ * in: P5, R2 |
+ * out: <nothing> |
+ * scratch: all but P5 |
+ * advance current insn to next one for testing. register R2 |
+ * is retained from se_all_load_insn. write out new insn to |
+ * the location via register P5. |
+ * |
+ * se_all_new_insn_stub |
+ * se_all_new_insn_log |
+ * for handling of new insns ... generally not needed once done |
+ */ |
+.macro se_all_test |
+ start |
+ |
+ /* Set up exception handler */ |
+ imm32 P4, EVT3; |
+ loadsym R1, _evx; |
+ [P4] = R1; |
+ |
+ /* set up the _location */ |
+ loadsym P0, _location |
+ loadsym P1, _table; |
+ [P0] = P1; |
+ |
+ /* Enable single stepping */ |
+ R0 = 1; |
+ SYSCFG = R0; |
+ |
+ /* Lower to the code we want to single step through */ |
+ loadsym P1, _usr; |
+ RETI = P1; |
+ |
+ /* set up pointers to valid data (32Meg), to reduce address violations */ |
+ reset_dags |
+ |
+ RTI; |
+ |
+pass_lvl: |
+ dbg_pass; |
+fail_lvl: |
+ dbg_fail; |
+ |
+_evx: |
+ /* Make sure exception reason is as we expect */ |
+ R3 = SEQSTAT; |
+ R4 = 0x3f; |
+ R3 = R3 & R4; |
+ |
+ /* find a match */ |
+ loadsym P5, _usr; |
+ loadsym P4, _location; |
+ P1 = [P4]; |
+ se_all_load_insn |
+ |
+_match: |
+ P2 = P1; |
+ se_all_load_table |
+ |
+ /* is this the end of the table? */ |
+ R4 = 0; |
+ CC = R4 == R7; |
+ IF CC jump _new_instruction; |
+ |
+ /* is the opcode (R0) greater than the 2nd entry in the table (R6) */ |
+ /* if so look at the next line in the table */ |
+ CC = R6 < R0; |
+ if CC jump _match; |
+ |
+ /* is the opcode (R0) smaller than the first entry in the table (R7) */ |
+ /* this means it's somewhere between the two lines, and should be legal */ |
+ CC = R7 <= R0; |
+ if !CC jump _legal_instruction; |
+ |
+ /* is the current EXCAUSE (R3), the same as the table (R5) */ |
+ /* if not, fail */ |
+ CC = R3 == R5 |
+ if !CC jump fail_lvl; |
+ |
+_match_done: |
+ /* back up, and store the location to search next */ |
+ [P4] = P2; |
+ |
+ /* it matches, so fall through */ |
+ jump _next_instruction; |
+ |
+_new_instruction: |
+ se_all_new_insn_stub |
+ |
+ /* output the insn (R0) and excause (R3) if diff from last */ |
+ loadsym P0, _last_excause; |
+ R2 = [P0]; |
+ CC = R2 == R3; |
+ IF CC jump _next_instruction; |
+ [P0] = R3; |
+ |
+ se_all_new_insn_log |
+ |
+_legal_instruction: |
+ R4 = 0x10; |
+ CC = R3 == R4; |
+ IF !CC JUMP fail_lvl; |
+ /* it wasn't in the list, and was a single step, so fall through */ |
+ |
+_next_instruction: |
+ se_all_next_insn |
+ |
+ /* Make sure the opcode isn't in a write buffer */ |
+ SSYNC; |
+ |
+ R1 = P5; |
+ RETX = R1; |
+ |
+ /* set up pointers to valid data (32Meg), to reduce address violations */ |
+ reset_dags |
+ RETS = r0; |
+ RETN = r0; |
+ RETE = r0; |
+ RETI = r0; |
+ |
+ RTX; |
+ |
+.section .text.usr |
+ .align 4 |
+_usr: |
+ se_all_insn_init |
+ loadsym P0, fail_lvl; |
+ JUMP (P0); |
+ |
+.data |
+ .align 4; |
+_last_excause: |
+ .dd 0xffff |
+_next_location: |
+ .dd _table_end |
+_location: |
+ .dd 0 |
+_table: |
+ se_all_insn_table |
+_table_end: |
+.endm |
+ |
+.macro se_all_load_table |
+ R7 = LOAD_PFX[P1++]; |
+ R6 = LOAD_PFX[P1++]; |
+ R5 = LOAD_PFX[P1++]; |
+.endm |
+ |
+#ifndef SE_ALL_NEW_INSN_STUB |
+.macro se_all_new_insn_stub |
+ jump fail_lvl; |
+.endm |
+#endif |
+ |
+.macro se_all_new_insn_log |
+.ifdef BFIN_JTAG_xxxxx |
+ R1 = R0; |
+#if SE_ALL_BITS == 32 |
+ R0 = 0x8; |
+ call __emu_out; |
+ R0 = R1; |
+ call __emu_out; |
+ R0 = R3; |
+#else |
+ R0 = 0x4; |
+ call __emu_out; |
+ R0 = R1 << 16; |
+ R0 = R0 | R3; |
+#endif |
+ call __emu_out; |
+.else |
+ loadsym P0, _next_location; |
+ P1 = [P0]; |
+ LOAD_PFX[P1++] = R0; |
+ LOAD_PFX[P1++] = R3; |
+ [P0] = P1; |
+.endif |
+.endm |