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