Home | History | Annotate | Line # | Download | only in bfin
      1 /*
      2  * set up pointers to valid data (32Meg), to reduce address violations
      3  */
      4 .macro reset_dags
      5 	imm32 r0, 0x2000000;
      6 	l0 = 0; l1 = 0; l2 = 0; l3 = 0;
      7 	p0 = r0; p1 = r0; p2 = r0; p3 = r0; p4 = r0; p5 = r0;
      8 	usp = r0; fp = r0;
      9 	i0 = r0; i1 = r0; i2 = r0; i3 = r0;
     10 	b0 = r0; b1 = r0; b2 = r0; b3 = r0;
     11 .endm
     12 
     13 #if SE_ALL_BITS == 32
     14 # define LOAD_PFX
     15 #elif SE_ALL_BITS == 16
     16 # define LOAD_PFX W
     17 #else
     18 # error "Please define SE_ALL_BITS"
     19 #endif
     20 
     21 /*
     22  * execute a test of an opcode space.  host test
     23  * has to fill out a number of callbacks.
     24  *
     25  *	se_all_insn_init
     26  *		the first insn to start executing
     27  *	se_all_insn_table
     28  *		the table of insn ranges and expected seqstat
     29  *
     30  *	se_all_load_insn
     31  *	  in: P5
     32  *	  out: R0, R2
     33  *	  scratch: R1
     34  *		load current user insn via register P5 into R0.
     35  *		register R2 is available for caching with se_all_next_insn.
     36  *	se_all_load_table
     37  *	  in: P1
     38  *	  out: R7, R6, R5
     39  *	  scratch: R1
     40  *		load insn range/seqstat entry from table via register P1
     41  *		R7: low range
     42  *		R6: high range
     43  *		R5: seqstat
     44  *
     45  *	se_all_next_insn
     46  *	  in: P5, R2
     47  *	  out: <nothing>
     48  *	  scratch: all but P5
     49  *		advance current insn to next one for testing.  register R2
     50  *		is retained from se_all_load_insn.  write out new insn to
     51  *		the location via register P5.
     52  *
     53  *	se_all_new_insn_stub
     54  *	se_all_new_insn_log
     55  *		for handling of new insns ... generally not needed once done
     56  */
     57 .macro se_all_test
     58 	start
     59 
     60 	/* Set up exception handler */
     61 	imm32 P4, EVT3;
     62 	loadsym R1, _evx;
     63 	[P4] = R1;
     64 
     65 	/* set up the _location */
     66 	loadsym P0, _location
     67 	loadsym P1, _table;
     68 	[P0] = P1;
     69 
     70 	/* Enable single stepping */
     71 	R0 = 1;
     72 	SYSCFG = R0;
     73 
     74 	/* Lower to the code we want to single step through */
     75 	loadsym P1, _usr;
     76 	RETI = P1;
     77 
     78 	/* set up pointers to valid data (32Meg), to reduce address violations */
     79 	reset_dags
     80 
     81 	RTI;
     82 
     83 pass_lvl:
     84 	dbg_pass;
     85 fail_lvl:
     86 	dbg_fail;
     87 
     88 _evx:
     89 	/* Make sure exception reason is as we expect */
     90 	R3 = SEQSTAT;
     91 	R4 = 0x3f;
     92 	R3 = R3 & R4;
     93 
     94 	/* find a match */
     95 	loadsym P5, _usr;
     96 	loadsym P4, _location;
     97 	P1 = [P4];
     98 	se_all_load_insn
     99 
    100 _match:
    101 	P2 = P1;
    102 	se_all_load_table
    103 
    104 	/* is this the end of the table? */
    105 	CC = R7 == 0;
    106 	IF CC jump _new_instruction;
    107 
    108 	/* is the opcode (R0) greater than the 2nd entry in the table (R6) */
    109 	/* if so look at the next line in the table */
    110 	CC = R6 < R0;
    111 	if CC jump _match;
    112 
    113 	/* is the opcode (R0) smaller than the first entry in the table (R7) */
    114 	/* this means it's somewhere between the two lines, and should be legal */
    115 	CC = R7 <= R0;
    116 	if !CC jump _legal_instruction;
    117 
    118 	/* is the current EXCAUSE (R3), the same as the table (R5) */
    119 	/* if not, fail */
    120 	CC = R3 == R5
    121 	if !CC jump fail_lvl;
    122 
    123 _match_done:
    124 	/* back up, and store the location to search next */
    125 	[P4] = P2;
    126 
    127 	/* it matches, so fall through */
    128 	jump _next_instruction;
    129 
    130 _new_instruction:
    131 	/* The table is generated in memory and can be extracted:
    132 	   (gdb) dump binary memory bin &table next_location
    133 
    134 	   16bit:
    135 	   $ od -j6 -x --width=4 bin | \
    136 	     awk '{ s=last; e=strtonum("0x"$2); \
    137 	       printf "\t.dw 0x%04x,\t0x%04x,\t\t0x%02x\n", \
    138 	          s, e-1, strtonum("0x"seq); \
    139 	       last=e; seq=$3}'
    140 
    141 	   32bit:
    142 	   $ od -j12 -x --width=8 bin | \
    143 	     awk '{ s=last; e=strtonum("0x"$3$2); \
    144 	       printf "\t.dw 0x%04x, 0x%04x,\t0x%04x, 0x%04x,\t\t0x%02x, 0\n", \
    145 	          and(s,0xffff), rshift(s,16), and(e-1,0xffff), rshift(e-1,16), \
    146 	          strtonum("0x"seq); \
    147 	       last=e; seq=$3}'
    148 
    149 	   This should be much faster than dumping over serial/jtag.  */
    150 	se_all_new_insn_stub
    151 
    152 	/* output the insn (R0) and excause (R3) if diff from last */
    153 	loadsym P0, _last_excause;
    154 	R2 = [P0];
    155 	CC = R2 == R3;
    156 	IF CC jump _next_instruction;
    157 	[P0] = R3;
    158 
    159 	se_all_new_insn_log
    160 
    161 _legal_instruction:
    162 	R4 = 0x10;
    163 	CC = R3 == R4;
    164 	IF !CC JUMP fail_lvl;
    165 	/* it wasn't in the list, and was a single step, so fall through */
    166 
    167 _next_instruction:
    168 	se_all_next_insn
    169 
    170 .ifdef BFIN_JTAG
    171 	/* Make sure the opcode isn't in a write buffer */
    172 	SSYNC;
    173 .endif
    174 
    175 	R1 = P5;
    176 	RETX = R1;
    177 
    178 	/* set up pointers to valid data (32Meg), to reduce address violations */
    179 	reset_dags
    180 	RETS = r0;
    181 
    182 	RTX;
    183 
    184 .section .text.usr
    185 	.align 4
    186 _usr:
    187 	se_all_insn_init
    188 	loadsym P0, fail_lvl;
    189 	JUMP (P0);
    190 
    191 .data
    192 	.align 4;
    193 _last_excause:
    194 	.dd 0xffff
    195 _next_location:
    196 	.dd _table_end
    197 _location:
    198 	.dd 0
    199 _table:
    200 	se_all_insn_table
    201 _table_end:
    202 .endm
    203 
    204 .macro se_all_load_table
    205 	R7 = LOAD_PFX[P1++];
    206 	R6 = LOAD_PFX[P1++];
    207 	R5 = LOAD_PFX[P1++];
    208 .endm
    209 
    210 #ifndef SE_ALL_NEW_INSN_STUB
    211 .macro se_all_new_insn_stub
    212 	jump fail_lvl;
    213 .endm
    214 #endif
    215 
    216 .macro se_all_new_insn_log
    217 .ifdef BFIN_JTAG_xxxxx
    218 	R1 = R0;
    219 #if SE_ALL_BITS == 32
    220 	R0 = 0x8;
    221 	call __emu_out;
    222 	R0 = R1;
    223 	call __emu_out;
    224 	R0 = R3;
    225 #else
    226 	R0 = 0x4;
    227 	call __emu_out;
    228 	R0 = R1 << 16;
    229 	R0 = R0 | R3;
    230 #endif
    231 	call __emu_out;
    232 .else
    233 	loadsym P0, _next_location;
    234 	P1 = [P0];
    235 	LOAD_PFX[P1++] = R0;
    236 	LOAD_PFX[P1++] = R3;
    237 	[P0] = P1;
    238 .endif
    239 .endm
    240