bitwiseARM.s 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. .text
  2. .global oggpack_look
  3. .global oggpack_adv
  4. .global oggpack_readinit
  5. .global oggpack_read
  6. oggpack_look:
  7. @ r0 = oggpack_buffer *b
  8. @ r1 = int bits
  9. STMFD r13!,{r10,r11,r14}
  10. LDMIA r0,{r2,r3,r12}
  11. @ r2 = bitsLeftInSegment
  12. @ r3 = ptr
  13. @ r12= bitsLeftInWord
  14. SUBS r2,r2,r1 @ bitsLeftinSegment -= bits
  15. BLT look_slow @ Not enough bits in this segment for
  16. @ this request. Do it slowly.
  17. LDR r10,[r3] @ r10= ptr[0]
  18. RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
  19. SUBS r12,r12,r1 @ r12= bitsLeftInWord -= bits
  20. LDRLT r11,[r3,#4]! @ r11= ptr[1]
  21. MOV r10,r10,LSR r14 @ r10= ptr[0]>>(32-bitsLeftInWord)
  22. ADDLE r12,r12,#32 @ r12= bitsLeftInWord += 32
  23. RSB r14,r14,#32 @ r14= 32-bitsLeftInWord
  24. ORRLT r10,r10,r11,LSL r14 @ r10= Next 32 bits.
  25. MOV r14,#1
  26. RSB r14,r14,r14,LSL r1
  27. AND r0,r10,r14
  28. LDMFD r13!,{r10,r11,PC}
  29. look_slow:
  30. STMFD r13!,{r5,r6}
  31. ADDS r10,r2,r1 @ r10= bitsLeftInSegment + bits (i.e.
  32. @ the initial value of bitsLeftInSeg)
  33. @ r10 = bitsLeftInSegment (initial)
  34. @ r12 = bitsLeftInWord
  35. RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
  36. MOV r5,r10 @ r5 = bitsLeftInSegment (initial)
  37. BLT look_overrun
  38. BEQ look_next_segment @ r10= r12 = 0, if we branch
  39. CMP r12,r10 @ If bitsLeftInWord < bitsLeftInSeg
  40. @ there must be more in the next word
  41. LDR r10,[r3],#4 @ r10= ptr[0]
  42. LDRLT r6,[r3] @ r6 = ptr[1]
  43. MOV r11,#1
  44. MOV r10,r10,LSR r14 @ r10= first bitsLeftInWord bits
  45. ORRLT r10,r10,r6,LSL r12 @ r10= first bitsLeftInSeg bits+crap
  46. RSB r11,r11,r11,LSL r5 @ r11= mask
  47. AND r10,r10,r11 @ r10= first r5 bits
  48. @ Load the next segments data
  49. look_next_segment:
  50. @ At this point, r10 contains the first r5 bits of the result
  51. LDR r11,[r0,#12] @ r11= head = b->head
  52. @ Stall
  53. @ Stall
  54. look_next_segment_2:
  55. LDR r11,[r11,#12] @ r11= head = head->next
  56. @ Stall
  57. @ Stall
  58. CMP r11,#0
  59. BEQ look_out_of_data
  60. LDMIA r11,{r6,r12,r14} @ r6 = buffer
  61. @ r12= begin
  62. @ r14= length
  63. LDR r6,[r6] @ r6 = buffer->data
  64. CMP r14,#0
  65. BEQ look_next_segment_2
  66. ADD r6,r6,r12 @ r6 = buffer->data+begin
  67. look_slow_loop:
  68. LDRB r12,[r6],#1 @ r12= *buffer
  69. SUBS r14,r14,#1 @ r14= length
  70. @ Stall
  71. ORR r10,r10,r12,LSL r5 @ r10= first r5+8 bits
  72. ADD r5,r5,#8
  73. BLE look_really_slow
  74. CMP r5,r1
  75. BLT look_slow_loop
  76. MOV r14,#1
  77. RSB r14,r14,r14,LSL r1
  78. AND r0,r10,r14
  79. LDMFD r13!,{r5,r6,r10,r11,PC}
  80. look_really_slow:
  81. CMP r5,r1
  82. BLT look_next_segment_2
  83. MOV r14,#1
  84. RSB r14,r14,r14,LSL r1
  85. AND r0,r10,r14
  86. LDMFD r13!,{r5,r6,r10,r11,PC}
  87. look_out_of_data:
  88. MVN r0,#0 @ return -1
  89. LDMFD r13!,{r5,r6,r10,r11,PC}
  90. look_overrun:
  91. @ We had overrun when we started, so we need to skip -r10 bits.
  92. LDR r11,[r0,#12] @ r11 = head = b->head
  93. @ stall
  94. @ stall
  95. look_overrun_next_segment:
  96. LDR r11,[r11,#12] @ r11 = head->next
  97. @ stall
  98. @ stall
  99. CMP r11,#0
  100. BEQ look_out_of_data
  101. LDMIA r11,{r6,r7,r14} @ r6 = buffer
  102. @ r7 = begin
  103. @ r14= length
  104. LDR r6,[r6] @ r6 = buffer->data
  105. @ stall
  106. @ stall
  107. ADD r6,r6,r7 @ r6 = buffer->data+begin
  108. MOV r14,r14,LSL #3 @ r14= length in bits
  109. ADDS r14,r14,r10 @ r14= length in bits-bits to skip
  110. MOVLE r10,r14
  111. BLE look_overrun_next_segment
  112. RSB r10,r10,#0 @ r10= bits to skip
  113. ADD r6,r10,r10,LSR #3 @ r6 = pointer to data
  114. MOV r10,#0
  115. B look_slow_loop
  116. oggpack_adv:
  117. @ r0 = oggpack_buffer *b
  118. @ r1 = bits
  119. LDMIA r0,{r2,r3,r12}
  120. @ r2 = bitsLeftInSegment
  121. @ r3 = ptr
  122. @ r12= bitsLeftInWord
  123. SUBS r2,r2,r1 @ Does this run us out of bits in the
  124. BLE adv_slow @ segment? If so, do it slowly
  125. SUBS r12,r12,r1
  126. ADDLE r12,r12,#32
  127. ADDLE r3,r3,#4
  128. STMIA r0,{r2,r3,r12}
  129. MOV PC,R14
  130. adv_slow:
  131. STMFD r13!,{r10,r14}
  132. LDR r14,[r0,#12] @ r14= head
  133. @ stall
  134. adv_slow_loop:
  135. LDR r1,[r0,#20] @ r1 = count
  136. LDR r10,[r14,#8] @ r10= head->length
  137. LDR r14,[r14,#12] @ r14= head->next
  138. @ stall
  139. ADD r1,r1,r10 @ r1 = count += head->length
  140. CMP r14,#0
  141. BEQ adv_end
  142. STR r1,[r0,#20] @ b->count = count
  143. STR r14,[r0,#12] @ b->head = head
  144. LDMIA r14,{r3,r10,r12} @ r3 = buffer
  145. @ r10= begin
  146. @ r12= length
  147. LDR r3,[r3] @ r3 = buffer->data
  148. ADD r3,r3,r10 @ r3 = Pointer to start (byte)
  149. AND r10,r3,#3 @ r10= bytes to backtrk to word align
  150. MOV r10,r10,LSL #3 @ r10= bits to backtrk to word align
  151. RSB r10,r10,#32 @ r10= bits left in word
  152. ADDS r10,r10,r2 @ r10= bits left in word after skip
  153. ADDLE r10,r10,#32
  154. ADDLE r3,r3,#4
  155. BIC r3,r3,#3 @ r3 = Pointer to start (word)
  156. ADDS r2,r2,r12,LSL #3 @ r2 = length in bits after advance
  157. BLE adv_slow_loop
  158. STMIA r0,{r2,r3,r10}
  159. LDMFD r13!,{r10,PC}
  160. adv_end:
  161. STMIA r0,{r2,r3,r12}
  162. LDMFD r13!,{r10,PC}
  163. oggpack_readinit:
  164. @ r0 = oggpack_buffer *b
  165. @ r1 = oggreference *r
  166. STR r1,[r0,#12] @ b->head = r1
  167. STR r1,[r0,#16] @ b->tail = r1
  168. LDMIA r1,{r2,r3,r12} @ r2 = b->head->buffer
  169. @ r3 = b->head->begin
  170. @ r12= b->head->length
  171. LDR r2,[r2] @ r2 = b->head->buffer->data
  172. MOV r1,r12,LSL #3 @ r1 = BitsInSegment
  173. MOV r12,#0
  174. ADD r3,r2,r3 @ r3 = r2+b->head->begin
  175. BIC r2,r3,#3 @ r2 = b->headptr (word)
  176. AND r3,r3,#3
  177. MOV r3,r3,LSL #3
  178. RSB r3,r3,#32 @ r3 = BitsInWord
  179. STMIA r0,{r1,r2,r3}
  180. STR r12,[r0,#20]
  181. MOV PC,R14
  182. oggpack_read:
  183. @ r0 = oggpack_buffer *b
  184. @ r1 = int bits
  185. STMFD r13!,{r10,r11,r14}
  186. LDMIA r0,{r2,r3,r12}
  187. @ r2 = bitsLeftInSegment
  188. @ r3 = ptr
  189. @ r12= bitsLeftInWord
  190. SUBS r2,r2,r1 @ bitsLeftinSegment -= bits
  191. BLT read_slow @ Not enough bits in this segment for
  192. @ this request. Do it slowly.
  193. LDR r10,[r3] @ r10= ptr[0]
  194. RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
  195. SUBS r12,r12,r1 @ r12= bitsLeftInWord -= bits
  196. ADDLE r3,r3,#4
  197. LDRLT r11,[r3] @ r11= ptr[1]
  198. MOV r10,r10,LSR r14 @ r10= ptr[0]>>(32-bitsLeftInWord)
  199. ADDLE r12,r12,#32 @ r12= bitsLeftInWord += 32
  200. RSB r14,r14,#32 @ r14= 32-bitsLeftInWord
  201. ORRLT r10,r10,r11,LSL r14 @ r10= Next 32 bits.
  202. STMIA r0,{r2,r3,r12}
  203. MOV r14,#1
  204. RSB r14,r14,r14,LSL r1
  205. AND r0,r10,r14
  206. LDMFD r13!,{r10,r11,PC}
  207. read_slow:
  208. STMFD r13!,{r5,r6}
  209. ADDS r10,r2,r1 @ r10= bitsLeftInSegment + bits (i.e.
  210. @ the initial value of bitsLeftInSeg)
  211. @ r10 = bitsLeftInSegment (initial)
  212. @ r12 = bitsLeftInWord
  213. RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
  214. MOV r5,r10 @ r5 = bitsLeftInSegment (initial)
  215. BLT read_overrun
  216. BEQ read_next_segment @ r10= r12 = 0, if we branch
  217. CMP r12,r10 @ If bitsLeftInWord < bitsLeftInSeg
  218. @ there must be more in the next word
  219. LDR r10,[r3],#4 @ r10= ptr[0]
  220. LDRLT r6,[r3] @ r6 = ptr[1]
  221. MOV r11,#1
  222. MOV r10,r10,LSR r14 @ r10= first bitsLeftInWord bits
  223. ORRLT r10,r10,r6,LSL r12 @ r10= first bitsLeftInSeg bits+crap
  224. RSB r11,r11,r11,LSL r5 @ r11= mask
  225. AND r10,r10,r11 @ r10= first r5 bits
  226. @ Load the next segments data
  227. read_next_segment:
  228. @ At this point, r10 contains the first r5 bits of the result
  229. LDR r11,[r0,#12] @ r11= head = b->head
  230. @ Stall
  231. read_next_segment_2:
  232. @ r11 = head
  233. LDR r6,[r0,#20] @ r6 = count
  234. LDR r12,[r11,#8] @ r12= length
  235. LDR r11,[r11,#12] @ r11= head = head->next
  236. @ Stall
  237. ADD r6,r6,r12 @ count += length
  238. CMP r11,#0
  239. BEQ read_out_of_data
  240. STR r11,[r0,#12]
  241. STR r6,[r0,#20] @ b->count = count
  242. LDMIA r11,{r6,r12,r14} @ r6 = buffer
  243. @ r12= begin
  244. @ r14= length
  245. LDR r6,[r6] @ r6 = buffer->data
  246. CMP r14,#0
  247. BEQ read_next_segment_2
  248. ADD r6,r6,r12 @ r6 = buffer->data+begin
  249. read_slow_loop:
  250. LDRB r12,[r6],#1 @ r12= *buffer
  251. SUBS r14,r14,#1 @ r14= length
  252. @ Stall
  253. ORR r10,r10,r12,LSL r5 @ r10= first r5+8 bits
  254. ADD r5,r5,#8
  255. BLE read_really_slow
  256. CMP r5,r1
  257. BLT read_slow_loop
  258. read_end:
  259. MOV r12,#1
  260. RSB r12,r12,r12,LSL r1
  261. @ Store back the new position
  262. @ r2 = -number of bits to go from this segment
  263. @ r6 = ptr
  264. @ r14= bytesLeftInSegment
  265. @ r11= New head value
  266. LDMIA r11,{r3,r6,r14} @ r3 = buffer
  267. @ r6 = begin
  268. @ r14= length
  269. LDR r3,[r3] @ r3 = buffer->data
  270. ADD r1,r2,r14,LSL #3 @ r1 = bitsLeftInSegment
  271. @ stall
  272. ADD r6,r3,r6 @ r6 = pointer
  273. AND r3,r6,#3 @ r3 = bytes used in first word
  274. RSB r3,r2,r3,LSL #3 @ r3 = bits used in first word
  275. BIC r2,r6,#3 @ r2 = word ptr
  276. RSBS r3,r3,#32 @ r3 = bitsLeftInWord
  277. ADDLE r3,r3,#32
  278. ADDLE r2,r2,#4
  279. STMIA r0,{r1,r2,r3}
  280. AND r0,r10,r12
  281. LDMFD r13!,{r5,r6,r10,r11,PC}
  282. read_really_slow:
  283. CMP r5,r1
  284. BGE read_end
  285. LDR r14,[r11,#8] @ r14= length of segment just done
  286. @ stall
  287. @ stall
  288. ADD r2,r2,r14,LSL #3 @ r2 = -bits to use from next seg
  289. B read_next_segment_2
  290. read_out_of_data:
  291. @ Store back the new position
  292. @ r2 = -number of bits to go from this segment
  293. @ r6 = ptr
  294. @ r14= bytesLeftInSegment
  295. @ RJW: This may be overkill - we leave the buffer empty, with -1
  296. @ bits left in it. We might get away with just storing the
  297. @ bitsLeftInSegment as -1.
  298. LDR r11,[r0,#12] @ r11=head
  299. LDMIA r11,{r3,r6,r14} @ r3 = buffer
  300. @ r6 = begin
  301. @ r14= length
  302. LDR r3,[r3] @ r3 = buffer->data
  303. ADD r6,r3,r6 @ r6 = pointer
  304. ADD r6,r6,r14
  305. AND r3,r6,#3 @ r3 = bytes used in first word
  306. MOV r3,r3,LSL #3 @ r3 = bits used in first word
  307. BIC r2,r6,#3 @ r2 = word ptr
  308. RSBS r3,r3,#32 @ r3 = bitsLeftInWord
  309. MVN r1,#0 @ r1 = -1 = bitsLeftInSegment
  310. STMIA r0,{r1,r2,r3}
  311. MVN r0,#0 @ return -1
  312. LDMFD r13!,{r5,r6,r10,r11,PC}
  313. read_overrun:
  314. @ We had overrun when we started, so we need to skip -r10 bits.
  315. LDR r11,[r0,#12] @ r11 = head = b->head
  316. @ stall
  317. @ stall
  318. read_overrun_next_segment:
  319. LDR r11,[r11,#12] @ r11 = head->next
  320. @ stall
  321. @ stall
  322. CMP r11,#0
  323. BEQ read_out_of_data
  324. LDMIA r11,{r6,r7,r14} @ r6 = buffer
  325. @ r7 = begin
  326. @ r14= length
  327. LDR r6,[r6] @ r6 = buffer->data
  328. @ stall
  329. @ stall
  330. ADD r6,r6,r7 @ r6 = buffer->data+begin
  331. MOV r14,r14,LSL #3 @ r14= length in bits
  332. ADDS r14,r14,r10 @ r14= length in bits-bits to skip
  333. MOVLE r10,r14
  334. BLE read_overrun_next_segment
  335. RSB r10,r10,#0 @ r10= bits to skip
  336. ADD r6,r10,r10,LSR #3 @ r6 = pointer to data
  337. MOV r10,#0
  338. B read_slow_loop