bitwiseARM.s 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. @ Tremolo library
  2. @-----------------------------------------------------------------------
  3. @ Copyright (C) 2002-2009, Xiph.org Foundation
  4. @ Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
  5. @ All rights reserved.
  6. @ Redistribution and use in source and binary forms, with or without
  7. @ modification, are permitted provided that the following conditions
  8. @ are met:
  9. @ * Redistributions of source code must retain the above copyright
  10. @ notice, this list of conditions and the following disclaimer.
  11. @ * Redistributions in binary form must reproduce the above
  12. @ copyright notice, this list of conditions and the following disclaimer
  13. @ in the documentation and/or other materials provided with the
  14. @ distribution.
  15. @ * Neither the names of the Xiph.org Foundation nor Pinknoise
  16. @ Productions Ltd nor the names of its contributors may be used to
  17. @ endorse or promote products derived from this software without
  18. @ specific prior written permission.
  19. @
  20. @ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. @ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. @ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. @ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. @ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. @ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. @ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. @ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. @ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. @ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. @ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. @ ----------------------------------------------------------------------
  32. .text
  33. .global oggpack_look
  34. .global oggpack_adv
  35. .global oggpack_readinit
  36. .global oggpack_read
  37. oggpack_look:
  38. @ r0 = oggpack_buffer *b
  39. @ r1 = int bits
  40. STMFD r13!,{r10,r11,r14}
  41. LDMIA r0,{r2,r3,r12}
  42. @ r2 = bitsLeftInSegment
  43. @ r3 = ptr
  44. @ r12= bitsLeftInWord
  45. SUBS r2,r2,r1 @ bitsLeftinSegment -= bits
  46. BLT look_slow @ Not enough bits in this segment for
  47. @ this request. Do it slowly.
  48. LDR r10,[r3] @ r10= ptr[0]
  49. RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
  50. SUBS r12,r12,r1 @ r12= bitsLeftInWord -= bits
  51. LDRLT r11,[r3,#4]! @ r11= ptr[1]
  52. MOV r10,r10,LSR r14 @ r10= ptr[0]>>(32-bitsLeftInWord)
  53. ADDLE r12,r12,#32 @ r12= bitsLeftInWord += 32
  54. RSB r14,r14,#32 @ r14= 32-bitsLeftInWord
  55. ORRLT r10,r10,r11,LSL r14 @ r10= Next 32 bits.
  56. MOV r14,#1
  57. RSB r14,r14,r14,LSL r1
  58. AND r0,r10,r14
  59. LDMFD r13!,{r10,r11,PC}
  60. look_slow:
  61. STMFD r13!,{r5,r6}
  62. ADDS r10,r2,r1 @ r10= bitsLeftInSegment + bits (i.e.
  63. @ the initial value of bitsLeftInSeg)
  64. @ r10 = bitsLeftInSegment (initial)
  65. @ r12 = bitsLeftInWord
  66. RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
  67. MOV r5,r10 @ r5 = bitsLeftInSegment (initial)
  68. BLT look_overrun
  69. BEQ look_next_segment @ r10= r12 = 0, if we branch
  70. CMP r12,r10 @ If bitsLeftInWord < bitsLeftInSeg
  71. @ there must be more in the next word
  72. LDR r10,[r3],#4 @ r10= ptr[0]
  73. LDRLT r6,[r3] @ r6 = ptr[1]
  74. MOV r11,#1
  75. MOV r10,r10,LSR r14 @ r10= first bitsLeftInWord bits
  76. ORRLT r10,r10,r6,LSL r12 @ r10= first bitsLeftInSeg bits+crap
  77. RSB r11,r11,r11,LSL r5 @ r11= mask
  78. AND r10,r10,r11 @ r10= first r5 bits
  79. @ Load the next segments data
  80. look_next_segment:
  81. @ At this point, r10 contains the first r5 bits of the result
  82. LDR r11,[r0,#12] @ r11= head = b->head
  83. @ Stall
  84. @ Stall
  85. look_next_segment_2:
  86. LDR r11,[r11,#12] @ r11= head = head->next
  87. @ Stall
  88. @ Stall
  89. CMP r11,#0
  90. BEQ look_out_of_data
  91. LDMIA r11,{r6,r12,r14} @ r6 = buffer
  92. @ r12= begin
  93. @ r14= length
  94. LDR r6,[r6] @ r6 = buffer->data
  95. CMP r14,#0
  96. BEQ look_next_segment_2
  97. ADD r6,r6,r12 @ r6 = buffer->data+begin
  98. look_slow_loop:
  99. LDRB r12,[r6],#1 @ r12= *buffer
  100. SUBS r14,r14,#1 @ r14= length
  101. @ Stall
  102. ORR r10,r10,r12,LSL r5 @ r10= first r5+8 bits
  103. ADD r5,r5,#8
  104. BLE look_really_slow
  105. CMP r5,r1
  106. BLT look_slow_loop
  107. MOV r14,#1
  108. RSB r14,r14,r14,LSL r1
  109. AND r0,r10,r14
  110. LDMFD r13!,{r5,r6,r10,r11,PC}
  111. look_really_slow:
  112. CMP r5,r1
  113. BLT look_next_segment_2
  114. MOV r14,#1
  115. RSB r14,r14,r14,LSL r1
  116. AND r0,r10,r14
  117. LDMFD r13!,{r5,r6,r10,r11,PC}
  118. look_out_of_data:
  119. @MVN r0,#0 ; return -1
  120. MOV r0,#0
  121. LDMFD r13!,{r5,r6,r10,r11,PC}
  122. look_overrun:
  123. @ We had overrun when we started, so we need to skip -r10 bits.
  124. LDR r11,[r0,#12] @ r11 = head = b->head
  125. @ stall
  126. @ stall
  127. look_overrun_next_segment:
  128. LDR r11,[r11,#12] @ r11 = head->next
  129. @ stall
  130. @ stall
  131. CMP r11,#0
  132. BEQ look_out_of_data
  133. LDMIA r11,{r6,r7,r14} @ r6 = buffer
  134. @ r7 = begin
  135. @ r14= length
  136. LDR r6,[r6] @ r6 = buffer->data
  137. @ stall
  138. @ stall
  139. ADD r6,r6,r7 @ r6 = buffer->data+begin
  140. MOV r14,r14,LSL #3 @ r14= length in bits
  141. ADDS r14,r14,r10 @ r14= length in bits-bits to skip
  142. MOVLE r10,r14
  143. BLE look_overrun_next_segment
  144. RSB r10,r10,#0 @ r10= bits to skip
  145. ADD r6,r10,r10,LSR #3 @ r6 = pointer to data
  146. MOV r10,#0
  147. B look_slow_loop
  148. oggpack_adv:
  149. @ r0 = oggpack_buffer *b
  150. @ r1 = bits
  151. LDMIA r0,{r2,r3,r12}
  152. @ r2 = bitsLeftInSegment
  153. @ r3 = ptr
  154. @ r12= bitsLeftInWord
  155. SUBS r2,r2,r1 @ Does this run us out of bits in the
  156. BLE adv_slow @ segment? If so, do it slowly
  157. SUBS r12,r12,r1
  158. ADDLE r12,r12,#32
  159. ADDLE r3,r3,#4
  160. STMIA r0,{r2,r3,r12}
  161. BX LR
  162. adv_slow:
  163. STMFD r13!,{r10,r14}
  164. LDR r14,[r0,#12] @ r14= head
  165. @ stall
  166. adv_slow_loop:
  167. LDR r1,[r0,#20] @ r1 = count
  168. LDR r10,[r14,#8] @ r10= head->length
  169. LDR r14,[r14,#12] @ r14= head->next
  170. @ stall
  171. ADD r1,r1,r10 @ r1 = count += head->length
  172. CMP r14,#0
  173. BEQ adv_end
  174. STR r1,[r0,#20] @ b->count = count
  175. STR r14,[r0,#12] @ b->head = head
  176. LDMIA r14,{r3,r10,r12} @ r3 = buffer
  177. @ r10= begin
  178. @ r12= length
  179. LDR r3,[r3] @ r3 = buffer->data
  180. ADD r3,r3,r10 @ r3 = Pointer to start (byte)
  181. AND r10,r3,#3 @ r10= bytes to backtrk to word align
  182. MOV r10,r10,LSL #3 @ r10= bits to backtrk to word align
  183. RSB r10,r10,#32 @ r10= bits left in word
  184. ADDS r10,r10,r2 @ r10= bits left in word after skip
  185. ADDLE r10,r10,#32
  186. ADDLE r3,r3,#4
  187. BIC r3,r3,#3 @ r3 = Pointer to start (word)
  188. ADDS r2,r2,r12,LSL #3 @ r2 = length in bits after advance
  189. BLE adv_slow_loop
  190. STMIA r0,{r2,r3,r10}
  191. LDMFD r13!,{r10,PC}
  192. adv_end:
  193. MOV r2, #0
  194. MOV r12,#0
  195. STMIA r0,{r2,r3,r12}
  196. LDMFD r13!,{r10,PC}
  197. oggpack_readinit:
  198. @ r0 = oggpack_buffer *b
  199. @ r1 = oggreference *r
  200. STR r1,[r0,#12] @ b->head = r1
  201. STR r1,[r0,#16] @ b->tail = r1
  202. LDMIA r1,{r2,r3,r12} @ r2 = b->head->buffer
  203. @ r3 = b->head->begin
  204. @ r12= b->head->length
  205. LDR r2,[r2] @ r2 = b->head->buffer->data
  206. MOV r1,r12,LSL #3 @ r1 = BitsInSegment
  207. MOV r12,#0
  208. ADD r3,r2,r3 @ r3 = r2+b->head->begin
  209. BIC r2,r3,#3 @ r2 = b->headptr (word)
  210. AND r3,r3,#3
  211. MOV r3,r3,LSL #3
  212. RSB r3,r3,#32 @ r3 = BitsInWord
  213. STMIA r0,{r1,r2,r3}
  214. STR r12,[r0,#20]
  215. BX LR
  216. oggpack_read:
  217. @ r0 = oggpack_buffer *b
  218. @ r1 = int bits
  219. STMFD r13!,{r10,r11,r14}
  220. LDMIA r0,{r2,r3,r12}
  221. @ r2 = bitsLeftInSegment
  222. @ r3 = ptr
  223. @ r12= bitsLeftInWord
  224. SUBS r2,r2,r1 @ bitsLeftinSegment -= bits
  225. BLT read_slow @ Not enough bits in this segment for
  226. @ this request. Do it slowly.
  227. LDR r10,[r3] @ r10= ptr[0]
  228. RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
  229. SUBS r12,r12,r1 @ r12= bitsLeftInWord -= bits
  230. ADDLE r3,r3,#4
  231. LDRLT r11,[r3] @ r11= ptr[1]
  232. MOV r10,r10,LSR r14 @ r10= ptr[0]>>(32-bitsLeftInWord)
  233. ADDLE r12,r12,#32 @ r12= bitsLeftInWord += 32
  234. RSB r14,r14,#32 @ r14= 32-bitsLeftInWord
  235. ORRLT r10,r10,r11,LSL r14 @ r10= Next 32 bits.
  236. STMIA r0,{r2,r3,r12}
  237. MOV r14,#1
  238. RSB r14,r14,r14,LSL r1
  239. AND r0,r10,r14
  240. LDMFD r13!,{r10,r11,PC}
  241. read_slow:
  242. STMFD r13!,{r5,r6}
  243. ADDS r10,r2,r1 @ r10= bitsLeftInSegment + bits (i.e.
  244. @ the initial value of bitsLeftInSeg)
  245. @ r10 = bitsLeftInSegment (initial)
  246. @ r12 = bitsLeftInWord
  247. RSB r14,r12,#32 @ r14= 32-bitsLeftInWord
  248. MOV r5,r10 @ r5 = bitsLeftInSegment (initial)
  249. BLT read_overrun
  250. BEQ read_next_segment @ r10= r12 = 0, if we branch
  251. CMP r12,r10 @ If bitsLeftInWord < bitsLeftInSeg
  252. @ there must be more in the next word
  253. LDR r10,[r3],#4 @ r10= ptr[0]
  254. LDRLT r6,[r3] @ r6 = ptr[1]
  255. MOV r11,#1
  256. MOV r10,r10,LSR r14 @ r10= first bitsLeftInWord bits
  257. ORRLT r10,r10,r6,LSL r12 @ r10= first bitsLeftInSeg bits+crap
  258. RSB r11,r11,r11,LSL r5 @ r11= mask
  259. AND r10,r10,r11 @ r10= first r5 bits
  260. @ Load the next segments data
  261. read_next_segment:
  262. @ At this point, r10 contains the first r5 bits of the result
  263. LDR r11,[r0,#12] @ r11= head = b->head
  264. @ Stall
  265. read_next_segment_2:
  266. @ r11 = head
  267. LDR r6,[r0,#20] @ r6 = count
  268. LDR r12,[r11,#8] @ r12= length
  269. LDR r11,[r11,#12] @ r11= head = head->next
  270. @ Stall
  271. ADD r6,r6,r12 @ count += length
  272. CMP r11,#0
  273. BEQ read_out_of_data
  274. STR r11,[r0,#12]
  275. STR r6,[r0,#20] @ b->count = count
  276. LDMIA r11,{r6,r12,r14} @ r6 = buffer
  277. @ r12= begin
  278. @ r14= length
  279. LDR r6,[r6] @ r6 = buffer->data
  280. CMP r14,#0
  281. BEQ read_next_segment_2
  282. ADD r6,r6,r12 @ r6 = buffer->data+begin
  283. read_slow_loop:
  284. LDRB r12,[r6],#1 @ r12= *buffer
  285. SUBS r14,r14,#1 @ r14= length
  286. @ Stall
  287. ORR r10,r10,r12,LSL r5 @ r10= first r5+8 bits
  288. ADD r5,r5,#8
  289. BLE read_really_slow
  290. CMP r5,r1
  291. BLT read_slow_loop
  292. read_end:
  293. MOV r12,#1
  294. RSB r12,r12,r12,LSL r1
  295. @ Store back the new position
  296. @ r2 = -number of bits to go from this segment
  297. @ r6 = ptr
  298. @ r14= bytesLeftInSegment
  299. @ r11= New head value
  300. LDMIA r11,{r3,r6,r14} @ r3 = buffer
  301. @ r6 = begin
  302. @ r14= length
  303. LDR r3,[r3] @ r3 = buffer->data
  304. ADD r1,r2,r14,LSL #3 @ r1 = bitsLeftInSegment
  305. @ stall
  306. ADD r6,r3,r6 @ r6 = pointer
  307. AND r3,r6,#3 @ r3 = bytes used in first word
  308. RSB r3,r2,r3,LSL #3 @ r3 = bits used in first word
  309. BIC r2,r6,#3 @ r2 = word ptr
  310. RSBS r3,r3,#32 @ r3 = bitsLeftInWord
  311. ADDLE r3,r3,#32
  312. ADDLE r2,r2,#4
  313. STMIA r0,{r1,r2,r3}
  314. AND r0,r10,r12
  315. LDMFD r13!,{r5,r6,r10,r11,PC}
  316. read_really_slow:
  317. CMP r5,r1
  318. BGE read_end
  319. LDR r14,[r11,#8] @ r14= length of segment just done
  320. @ stall
  321. @ stall
  322. ADD r2,r2,r14,LSL #3 @ r2 = -bits to use from next seg
  323. B read_next_segment_2
  324. read_out_of_data:
  325. @ Store back the new position
  326. @ r2 = -number of bits to go from this segment
  327. @ r6 = ptr
  328. @ r14= bytesLeftInSegment
  329. @ RJW: This may be overkill - we leave the buffer empty, with -1
  330. @ bits left in it. We might get away with just storing the
  331. @ bitsLeftInSegment as -1.
  332. LDR r11,[r0,#12] @ r11=head
  333. LDMIA r11,{r3,r6,r14} @ r3 = buffer
  334. @ r6 = begin
  335. @ r14= length
  336. LDR r3,[r3] @ r3 = buffer->data
  337. ADD r6,r3,r6 @ r6 = pointer
  338. ADD r6,r6,r14
  339. AND r3,r6,#3 @ r3 = bytes used in first word
  340. MOV r3,r3,LSL #3 @ r3 = bits used in first word
  341. BIC r2,r6,#3 @ r2 = word ptr
  342. RSBS r3,r3,#32 @ r3 = bitsLeftInWord
  343. MVN r1,#0 @ r1 = -1 = bitsLeftInSegment
  344. STMIA r0,{r1,r2,r3}
  345. @MVN r0,#0 ; return -1
  346. MOV r0,#0
  347. LDMFD r13!,{r5,r6,r10,r11,PC}
  348. read_overrun:
  349. @ We had overrun when we started, so we need to skip -r10 bits.
  350. LDR r11,[r0,#12] @ r11 = head = b->head
  351. @ stall
  352. @ stall
  353. read_overrun_next_segment:
  354. LDR r11,[r11,#12] @ r11 = head->next
  355. @ stall
  356. @ stall
  357. CMP r11,#0
  358. BEQ read_out_of_data
  359. LDMIA r11,{r6,r7,r14} @ r6 = buffer
  360. @ r7 = begin
  361. @ r14= length
  362. LDR r6,[r6] @ r6 = buffer->data
  363. @ stall
  364. @ stall
  365. ADD r6,r6,r7 @ r6 = buffer->data+begin
  366. MOV r14,r14,LSL #3 @ r14= length in bits
  367. ADDS r14,r14,r10 @ r14= length in bits-bits to skip
  368. MOVLE r10,r14
  369. BLE read_overrun_next_segment
  370. RSB r10,r10,#0 @ r10= bits to skip
  371. ADD r6,r10,r10,LSR #3 @ r6 = pointer to data
  372. MOV r10,#0
  373. B read_slow_loop
  374. @ END