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.
 
 
 
 
 
 

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