se_allopcodes.h 4.8 KB

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