sim: bfin: unify se_all*opcodes tests

The current se_all*opcodes tests are very similar in how they work.
In preparation for adding more tests along these lines, unify the
common bits into a framework that others can include and build off
of easily.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
This commit is contained in:
Mike Frysinger 2012-03-19 05:34:30 +00:00
parent 6aafca16ed
commit 5f2804c950
4 changed files with 255 additions and 287 deletions

View File

@ -1,3 +1,9 @@
2012-03-19 Mike Frysinger <vapier@gentoo.org>
* se_allopcodes.h: New framework for testing opcode regions.
* se_all16bitopcodes.S: Convert over to se_allopcodes.h.
* se_all32bitopcodes.S: Likewise.
2012-03-19 Stuart Henderson <stuart.henderson@analog.com>
* c_dsp32shiftim_amix.s: Check edge cases in shift behavior.

View File

@ -12,122 +12,20 @@
# sim: --environment operating
#include "test.h"
#include "se_allopcodes.h"
.include "testutils.inc"
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 */
.macro reset_regs
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
reset_regs
RTI;
.align 4;
_evx:
/* Make sure exception reason is single step */
R3 = SEQSTAT;
R4 = 0x3f;
R3 = R3 & R4;
/* find a match */
loadsym P5, _usr;
loadsym P4, _location;
.macro se_all_load_insn
R2 = W[P5];
P1 = [P4];
R0 = R2;
_match:
P2 = P1;
.endm
.macro se_all_load_table
R7 = W[P1++];
R6 = W[P1++];
R5 = W[P1++];
.endm
/* 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:
jump _legal_instruction;
/* 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;
.ifdef BFIN_JTAG_xxxxx
R1 = R0;
R0 = 0x4;
call __emu_out;
R0 = R1 << 16;
R0 = R0 | R3;
call __emu_out;
.else
loadsym P0, _next_location;
P1 = [P0];
W[P1++] = R0;
W[P1++] = R3;
[P0] = P1;
.endif
jump _next_instruction;
_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:
.macro se_all_next_insn
/* increment, and go again. */
R0 = R2;
@ -138,44 +36,20 @@ _next_instruction:
IF CC JUMP pass_lvl;
W[P5] = R0;
.endm
/* Make sure the opcode isn't in a write buffer */
SSYNC;
.macro se_all_new_insn_stub
jump _legal_instruction;
.endm
.macro se_all_new_insn_log
se_all_new_16bit_insn_log
.endm
R1 = P5;
RETX = R1;
/* set up pointers to valid data (32Meg), to reduce address violations */
reset_regs
RETS = r0;
RETN = r0;
RETE = r0;
RETI = r0;
RTX;
pass_lvl:
dbg_pass;
fail_lvl:
dbg_fail;
.section .text.usr
.align 4
_usr:
.macro se_all_insn_init
.dw 0x0000;
loadsym P0, fail_lvl;
JUMP (P0);
.endm
.macro se_all_insn_table
/* this table must be sorted, and end with zero */
.data
.align 4;
_last_excause:
.dd 0xffff
_next_location:
.dd _table_end
_location:
.dd 0
_table:
/* start end SEQSTAT */
.dw 0x0001, 0x000f, 0x21
.dw 0x0011, 0x0013, 0x2e
@ -475,4 +349,6 @@ _table:
.dw 0x9ef0, 0x9eff, 0x21
.dw 0x9f70, 0x9f7f, 0x21
.dw 0x0000, 0x0000, 0x00
_table_end:
.endm
se_all_test

View File

@ -14,125 +14,22 @@
# xfail: too many invalid insns are decoded as valid
#include "test.h"
#include "se_allopcodes.h"
.include "testutils.inc"
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 */
.macro reset_regs
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
reset_regs
RTI;
.align 4;
_evx:
/* Make sure exception reason is single step */
R3 = SEQSTAT;
R4 = 0x3f;
R3 = R3 & R4;
/* find a match */
loadsym P5, _usr;
loadsym P4, _location;
.macro se_all_load_insn
R2 = [P5];
P1 = [P4];
R0 = R2 << 16;
R1 = R2 >> 16;
R0 = R0 | R1;
_match:
P2 = P1;
.endm
.macro se_all_load_table
R7 = [P1++];
R6 = [P1++];
R5 = [P1++];
.endm
/* 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:
jump fail_lvl;
/* 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;
.ifdef BFIN_JTAG_xxxxx
R1 = R0;
R0 = 0x8;
call __emu_out;
R0 = R1;
call __emu_out;
R0 = R3;
call __emu_out;
.else
loadsym P0, _next_location;
P1 = [P0];
[P1++] = R0;
[P1++] = R3;
[P0] = P1;
.endif
jump _next_instruction;
_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:
.macro se_all_next_insn
/* increment, and go again. */
R0 = R2;
@ -169,45 +66,21 @@ _next_instruction:
1:
[P5] = R0;
.endm
/* Make sure the opcode isn't in a write buffer */
SSYNC;
.macro se_all_new_insn_stub
jump fail_lvl;
.endm
.macro se_all_new_insn_log
se_all_new_32bit_insn_log
.endm
R1 = P5;
RETX = R1;
/* set up pointers to valid data (32Meg), to reduce address violations */
reset_regs
RETS = r0;
RETN = r0;
RETE = r0;
RETI = r0;
RTX;
pass_lvl:
dbg_pass;
fail_lvl:
dbg_fail;
.section .text.usr
.align 4
_usr:
.macro se_all_insn_init
.dw 0xc000;
.dw 0x0000;
loadsym P0, fail_lvl;
JUMP (P0);
.endm
.macro se_all_insn_table
/* this table must be sorted, and end with zero */
.data
.align 4;
_last_excause:
.dd 0xffff
_next_location:
.dd _table_end
_location:
.dd 0
_table:
/* start end SEQSTAT */
.dw 0x1a00, 0xc000, 0x1fff, 0xc000, 0x21, 0
.dw 0x3a00, 0xc000, 0x3fff, 0xc000, 0x21, 0
@ -34301,4 +34174,6 @@ _table:
.dw 0x0000, 0xe740, 0xffff, 0xe7ff, 0x21, 0
.dw 0x0000, 0xf001, 0xffff, 0xffff, 0x21, 0
.dw 0x0000, 0x0000, 0x0000, 0x0000, 0x00, 0
_table_end:
.endm
se_all_test

View File

@ -0,0 +1,211 @@
/*
* 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
/*
* 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_new_16bit_insn_log
.ifdef BFIN_JTAG_xxxxx
R1 = R0;
R0 = 0x4;
call __emu_out;
R0 = R1 << 16;
R0 = R0 | R3;
call __emu_out;
.else
loadsym P0, _next_location;
P1 = [P0];
W[P1++] = R0;
W[P1++] = R3;
[P0] = P1;
.endif
.endm
.macro se_all_new_32bit_insn_log
.ifdef BFIN_JTAG_xxxxx
R1 = R0;
R0 = 0x8;
call __emu_out;
R0 = R1;
call __emu_out;
R0 = R3;
call __emu_out;
.else
loadsym P0, _next_location;
P1 = [P0];
[P1++] = R0;
[P1++] = R3;
[P0] = P1;
.endif
.endm