You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

484 lines
12 KiB

  1. m4_divert(`-1')
  2. /***************************************************************************
  3. * Copyright (C) 2008 Lou Deluxe *
  4. * lou.openocd012@fixit.nospammail.net *
  5. * *
  6. * This program is free software; you can redistribute it and/or modify *
  7. * it under the terms of the GNU General Public License as published by *
  8. * the Free Software Foundation; either version 2 of the License, or *
  9. * (at your option) any later version. *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * You should have received a copy of the GNU General Public License *
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  18. ***************************************************************************/
  19. m4_dnl Setup and hold times depend on SHIFTER_PRESCALER
  20. m4_define(`SETUP_DELAY_CYCLES', m4_eval(`('SHIFTER_PRESCALER` + 1) / 2'))
  21. m4_define(`HOLD_DELAY_CYCLES', m4_eval(`'SHIFTER_PRESCALER` / 2'))
  22. m4_dnl Some macros to make nybble handling a little easier
  23. m4_define(`m4_high_nybble', `m4_eval(`(($1) >> 4) & 0xf')')
  24. m4_define(`m4_low_nybble', `m4_eval(`($1) & 0xf')')
  25. m4_dnl A macro to generate a number of NOPs depending on the argument
  26. m4_define(`m4_0_to_5_nops', `m4_ifelse(m4_eval(`($1) >= 1'), 1, ` NOP
  27. 'm4_ifelse(m4_eval(`($1) >= 2'), 1, ` NOP
  28. 'm4_ifelse(m4_eval(`($1) >= 3'), 1, ` NOP
  29. 'm4_ifelse(m4_eval(`($1) >= 4'), 1, ` NOP
  30. 'm4_ifelse(m4_eval(`($1) >= 5'), 1, ` NOP
  31. ')))))')
  32. m4_dnl Some macros to facilitate bit-banging delays.
  33. m4_dnl There are 3 of them. One for self-contained delays, and two for those which must be split between setup and loop to keep from disturbing A at delay time.
  34. m4_dnl The argument passed to any of them is the number of cycles which the delay should consume.
  35. m4_dnl This one is self-contained.
  36. m4_define(`m4_delay',
  37. `; delay (m4_eval($1) cycles)'
  38. `m4_ifelse(m4_eval(`('$1`) < 6'), 1,
  39. m4_0_to_5_nops($1)
  40. ,
  41. m4_ifelse(m4_eval(`(('$1`) - 3) % 2'), 1, ` NOP')
  42. A.H = m4_high_nybble(`(('$1`) - 3) / 2')
  43. A.L = m4_low_nybble(`(('$1`) - 3) / 2')
  44. Y = A
  45. DECY
  46. JP -1
  47. )')
  48. m4_dnl These are the setup and loop parts of the split delay.
  49. m4_dnl The argument passed to both must match for the result to make sense.
  50. m4_dnl The setup does not figure into the delay. It takes 3 cycles when a loop is used and none if nops are used.
  51. m4_define(`m4_delay_setup',
  52. `; delay setup (m4_eval($1) cycles)'
  53. `m4_ifelse(m4_eval(`('$1`) < 6'), 0, ` '
  54. A.H = m4_high_nybble(`('$1`) / 2')
  55. A.L = m4_low_nybble(`('$1`) / 2')
  56. Y = A
  57. )')
  58. m4_define(`m4_delay_loop',
  59. `; delay loop (m4_eval($1) cycles)'
  60. `m4_ifelse(m4_eval(`('$1`) < 6'), 1,
  61. m4_0_to_5_nops($1)
  62. ,
  63. m4_ifelse(m4_eval(`('$1`) % 2'), 1, ` NOP')
  64. DECY
  65. JP -1
  66. )')
  67. m4_dnl These are utility macros for use with delays. Specifically, there is code below which needs some predictability in code size for relative jumps to reach. The m4_delay macro generates an extra NOP when an even delay is needed, and the m4_delay_loop macro generates an extra NOP when an odd delay is needed. Using this for the argument to the respective macro rounds up the argument so that the extra NOP will not be generated. There is also logic built in to cancel the rounding when the result is small enough that a loop would not be generated.
  68. m4_define(`m4_delay_loop_round_up', `m4_ifelse(m4_eval($1` < 6'), 1, $1, m4_eval(`(('$1`) + 1) / 2 * 2'))')
  69. m4_define(`m4_delay_round_up', `m4_ifelse(m4_eval($1` < 6'), 1, $1, m4_eval(`(('$1`) / 2 * 2) + 1'))')
  70. m4_divert(`0')m4_dnl
  71. ;------------------------------------------------------------------------------
  72. :opcode_error
  73. ; This is at address 0x00 in case of empty LUT entries
  74. STATUS STOP ERROR
  75. ;------------------------------------------------------------------------------
  76. ; Command interpreter at address 0x01 because it is branched to a lot and having it be 0x01 means we can use X for it, which is already used for other purposes which want it to be 1.
  77. ; Assumes X is 1
  78. ; Assumes ADR_BUFFER0 points to the next command byte
  79. ; Stores the current command byte in CMP01
  80. :command_interpreter
  81. A = DATA_BUFFER0
  82. ADR_BUFFER0 += X
  83. CMP01 = A ; store the current command for later
  84. EXCHANGE ; put MSN into LSN
  85. A.H = 0xc ; lookup table at 0x1550 + 0xc0 = 0x1610
  86. ; branch to address in lookup table
  87. Y = A
  88. A = <Y>
  89. BRANCH
  90. ;------------------------------------------------------------------------------
  91. ; LUT for high nybble
  92. ;LUT; c0 opcode_error
  93. ;LUT; c1 opcode_shift_tdi_andor_tms_bytes
  94. ;LUT; c2 opcode_shift_tdi_andor_tms_bytes
  95. ;LUT; c3 opcode_shift_tdi_andor_tms_bytes
  96. ;LUT; c4 opcode_shift_tdo_bytes
  97. ;LUT; c5 opcode_error
  98. ;LUT; c6 opcode_shift_tdio_bytes
  99. ;LUT; c7 opcode_error
  100. ;LUT; c8 opcode_shift_tms_tdi_bit_pair
  101. ;LUT; c9 opcode_shift_tms_bits
  102. ;LUT; ca opcode_error
  103. ;LUT; cb opcode_error
  104. ;LUT; cc opcode_error
  105. ;LUT; cd opcode_error
  106. ;LUT; ce opcode_shift_tdio_bits
  107. ;LUT; cf opcode_stop
  108. ;------------------------------------------------------------------------------
  109. ; USB/buffer handling
  110. ;
  111. ;ENTRY; download entry_download
  112. opcode_stop:
  113. opcode_next_buffer:
  114. ; pointer to completion flag
  115. A.H = 0xf
  116. A.L = 0xf
  117. Y = A
  118. A = OR_MPEG ; buffer indicator from previous iteration
  119. <Y> = A ; either indicator will have bit 0 set
  120. BSET 1 ; was buffer 1 previously current?
  121. ; A.H = 0 ; already zero from OR_MPEG
  122. JP opcode_next_buffer_0
  123. opcode_next_buffer_1:
  124. A.L = 0x1 ; ack buffer 0
  125. BUFFER_MNGT = A
  126. ; A.H = 0x0 ; already zero from BUFFER_MNGT
  127. A.L = 0x3 ; Input buffer 1 = 0x1850 (0x0300)
  128. JP +4
  129. opcode_next_buffer_0:
  130. A.L = 0x2 ; ack buffer 1
  131. BUFFER_MNGT = A
  132. entry_download:
  133. A = X ; Input buffer 0 = 0x1650 (0x0100)
  134. ADR_BUFFER01 = A
  135. OR_MPEG = A ; store for next iteration
  136. A.L = 0x0
  137. BUFFER_MNGT = A ; finish acking previous buffer
  138. Y = A
  139. ADR_BUFFER00 = A
  140. ADR_BUFFER11 = A
  141. A.H = 0x4 ; Output buffer = 0x1590 (0x0040)
  142. ADR_BUFFER10 = A
  143. EXCHANGE ; 0x04
  144. X = A ; for the spin loop below
  145. ; pointer to status in shared memory
  146. DECY ; setting to 0 above and decrementing here saves a byte
  147. ; wait until a command buffer is available
  148. A = BUFFER_MNGT ; spin while neither of bits 2 or 3 are set
  149. CP A<X ; this is slightly faster and smaller than trying to AND and compare the result, and it lets us just use the nybble-swapped 0x40 from the output buffer setup.
  150. JP -2
  151. <Y> = A ; update status once done spinning
  152. ; restore X, since we used it
  153. ; A.H = 0 ; high nybble of BUFFER_MNGT will always be 0 the way we use it
  154. A.L = 1
  155. X = A
  156. ; go to command interpreter
  157. BRANCH
  158. ;;------------------------------------------------------------------------------
  159. ;:opcode_stop
  160. ;;
  161. ;
  162. ; ; Ack buffer 0 in download mode
  163. ; A.L = 0x1
  164. ; BUFFER_MNGT = A
  165. ;
  166. ; STATUS STOP
  167. ;------------------------------------------------------------------------------
  168. :opcode_shift_tdi_andor_tms_bytes
  169. ;
  170. A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1
  171. A.H = 0
  172. Y = A ; loop counter
  173. A = CMP01
  174. EXCHANGE
  175. CMP01 = A ; we're interested in bits in the high nybble
  176. opcode_shift_tdi_andor_tms_bytes__loop:
  177. ; set tdi to supplied byte or zero
  178. A = CMP01
  179. BSET 1
  180. JP +4
  181. A.H = 0
  182. A.L = 0
  183. JP +3
  184. A = DATA_BUFFER0
  185. ADR_BUFFER0 += X
  186. SHIFT_MPEG = A
  187. ; set tms to supplied byte or zero
  188. A = CMP01
  189. BCLR 0
  190. JP +5
  191. A = DATA_BUFFER0
  192. ADR_BUFFER0 += X
  193. SHIFT_CARD = A
  194. SHIFT CARD OUT=>PIN0
  195. ; run both shifters as nearly simultaneously as possible
  196. SHIFT MPEG OUT=>PIN1
  197. A = CTRL_FCI
  198. EXCHANGE
  199. BCLR 3
  200. JP -3
  201. DECY
  202. JP opcode_shift_tdi_andor_tms_bytes__loop
  203. A = X
  204. BRANCH
  205. ;------------------------------------------------------------------------------
  206. :opcode_shift_tdo_bytes
  207. ;
  208. A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1
  209. A.H = 0
  210. Y = A ; loop counter
  211. opcode_shift_tdo_bytes__loop:
  212. SHIFT MPEG PIN0=>IN
  213. A = CTRL_FCI
  214. EXCHANGE
  215. BCLR 3
  216. JP -3
  217. ; put shifted byte into output buffer
  218. A = SHIFT_MPEG
  219. DATA_BUFFER1 = A
  220. ADR_BUFFER1 += X
  221. DECY
  222. JP opcode_shift_tdo_bytes__loop
  223. A = X
  224. BRANCH
  225. ;------------------------------------------------------------------------------
  226. :opcode_shift_tdio_bytes
  227. ;
  228. A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1
  229. A.H = 0
  230. CMP10 = A ; byte loop counter
  231. A.H = opcode_shift_tdio_bytes__sub_return
  232. A.L = opcode_shift_tdio_bytes__sub_return
  233. CMP00 = A ; return address
  234. opcode_shift_tdio_bytes__loop:
  235. A.H = 0
  236. A.L = 7
  237. CMP11 = A ; always use 8 bits
  238. JP sub_shift_tdio_bits
  239. opcode_shift_tdio_bytes__sub_return:
  240. A = CMP10 ; byte loop counter
  241. CP A=>X
  242. CLC
  243. A -= X
  244. CMP10 = A
  245. JP opcode_shift_tdio_bytes__loop
  246. A = X
  247. ;DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
  248. BRANCH
  249. ;------------------------------------------------------------------------------
  250. :opcode_shift_tdio_bits
  251. ;
  252. A = CMP01 ; bits 2..0 contain the number of bits to shift - 1
  253. A.H = 0
  254. BCLR 3 ; set TMS=1 if bit 3 was set
  255. CMP11 = A ; bit loop counter
  256. A.H = opcode_shift_tdio_bits__sub_return
  257. A.L = opcode_shift_tdio_bits__sub_return
  258. CMP00 = A ; return address
  259. JP sub_shift_tdio_bits
  260. A.L = 0x1 ; TMS=1
  261. DR_CARD = A
  262. JP sub_shift_tdio_bits
  263. opcode_shift_tdio_bits__sub_return:
  264. A = X
  265. ;DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
  266. BRANCH
  267. ;------------------------------------------------------------------------------
  268. :sub_shift_tdio_bits
  269. ;
  270. A = DATA_BUFFER0 ; get byte from input buffer
  271. ADR_BUFFER0 += X
  272. MASK = A ; put it in MASK where bit routine will use it
  273. :sub_shift_tdio_bits__loop
  274. m4_delay_setup(m4_delay_loop_round_up(SETUP_DELAY_CYCLES - 1))
  275. A = MASK ; shift TDO into and TDI out of MASK via carry
  276. A += MASK
  277. MASK = A
  278. ; shifting out TDI
  279. A.L = 0x2 ; TCK=0, TDI=1
  280. CP CARRY
  281. JP +2
  282. A.L = 0x0 ; TCK=0, TDI=0
  283. DR_MPEG = A
  284. m4_delay_loop(m4_delay_loop_round_up(SETUP_DELAY_CYCLES - 1))
  285. BSET 2 ; TCK high
  286. DR_MPEG = A
  287. A = DR_MPEG ; set carry bit to TDO
  288. CLC
  289. BCLR 0
  290. JP +2
  291. SEC
  292. m4_delay(HOLD_DELAY_CYCLES - 10)
  293. A = CMP11 ; bit loop counter
  294. Y = A ; use Y to avoid corrupting carry bit with subtract
  295. DECY
  296. A = Y
  297. CMP11 = A
  298. JP :sub_shift_tdio_bits__loop
  299. ; shift last TDO bit into result
  300. A = MASK
  301. A += MASK
  302. DATA_BUFFER1 = A
  303. ADR_BUFFER1 += X
  304. A = CMP00 ; return to caller
  305. BRANCH
  306. ;------------------------------------------------------------------------------
  307. :opcode_shift_tms_tdi_bit_pair
  308. ;
  309. ; set TMS line manually
  310. A = CMP01 ; bits 3..0 contain TDI and TMS bits and whether to return TDO
  311. BSET 0 ; TMS bit
  312. A.L = 0x1 ; TMS=1
  313. JP +2
  314. A.L = 0x0 ; TMS=0
  315. DR_CARD = A
  316. ; stuff command buffer with bitmap of single TDI bit
  317. A = CMP01
  318. BSET 1 ; TDI bit
  319. A.H = 0x8 ; TDI=1
  320. JP +2
  321. A.H = 0x0 ; TDI=0
  322. ADR_BUFFER0 -= X
  323. DATA_BUFFER0 = A
  324. A.H = 0
  325. A.L = 0
  326. CMP11 = A ; bit loop counter (only doing one bit)
  327. A.H = opcode_shift_tms_tdi_bit_pair__sub_return
  328. A.L = opcode_shift_tms_tdi_bit_pair__sub_return
  329. CMP00 = A ; return address
  330. ; jump this way due to relative jump range issues
  331. A.H = sub_shift_tdio_bits
  332. A.L = sub_shift_tdio_bits
  333. BRANCH
  334. opcode_shift_tms_tdi_bit_pair__sub_return:
  335. A = CMP01
  336. BSET 3 ; bit says whether to return TDO
  337. JP +2
  338. ADR_BUFFER1 -= X ; subroutine returns it, so undo that
  339. A = X
  340. DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
  341. BRANCH
  342. ;------------------------------------------------------------------------------
  343. :opcode_shift_tms_bits
  344. ;
  345. A = CMP01 ; bits 3..0 contain the number of bits to shift - 1 (only 1-8 bits is valid... no checking, just improper operation)
  346. A.H = 0
  347. CMP11 = A ; bit loop counter
  348. A = DATA_BUFFER0 ; get byte from input buffer
  349. ADR_BUFFER0 += X
  350. MASK = A ; The byte we'll be shifting
  351. :opcode_shift_tms_bits__loop
  352. m4_delay_setup(SETUP_DELAY_CYCLES - 1)
  353. A = MASK ; shift TMS out of MASK via carry
  354. A += MASK
  355. MASK = A
  356. ; shifting out TMS
  357. A.L = 0x1 ; TCK=0, TDI=0, TMS=1
  358. CP CARRY
  359. JP +2
  360. A.L = 0x0 ; TCK=0, TDI=0, TMS=0
  361. DR_CARD = A
  362. DR_MPEG = A
  363. m4_delay_loop(SETUP_DELAY_CYCLES - 1)
  364. BSET 2 ; TCK high
  365. DR_MPEG = A
  366. m4_delay(HOLD_DELAY_CYCLES - 10)
  367. A = CMP11 ; bit loop counter
  368. CP A=>X
  369. CLC
  370. A -= X
  371. CMP11 = A
  372. JP :opcode_shift_tms_bits__loop
  373. A = X
  374. DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
  375. BRANCH