unixALib.s
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:9k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* unixALib.s - Assembler optimised UNIX kernel compatability library */
  2. /* Copyright 1996-2001 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01h,17oct01,t_m  convert to FUNC_LABEL:
  7. 01g,11oct01,jb  Enabling removal of pre-pended underscores for new compilers
  8.                  (Diab/Gnu elf)
  9. 01f,21feb01,cdp  fix cksum loss of carry into high-byte (SPR #29703). Comment.
  10. 01e,08jul98,cdp  added preliminary big-endian support.
  11. 01d,10mar98,jpd  layout tidying.
  12. 01c,27oct97,kkk  took out "***EOF***" line from end of file.
  13. 01b,23may97,jpd  Amalgamated into VxWorks.
  14. 01a,16jul96,ams  written.
  15. */
  16. /*
  17. DESCRIPTION
  18. This library provides routines that simulate or replace Unix kernel functions
  19. that are used in the network code.
  20. */
  21. #define _ASMLANGUAGE
  22. #include "vxWorks.h"
  23. #include "asm.h"
  24. .data
  25. .globl FUNC(copyright_wind_river)
  26. .long FUNC(copyright_wind_river)
  27. #if (defined(PORTABLE))
  28. #define unixALib_PORTABLE
  29. #endif
  30. #ifndef unixALib_PORTABLE
  31. /* Exports */
  32. .global FUNC(cksum) /* checksum routine */
  33. .global FUNC(_insque) /* insert node in queue after specified node */
  34. .global FUNC(_remque) /* remove specified node */
  35. .text
  36. .balign 4
  37. /*******************************************************************************
  38. *
  39. * cksum - compute check sum
  40. *
  41. * return 16bit sum of 'sum' and the 16bit sum of the string 'string' of byte
  42. * length 'len'. Complicated by 'len' or 'sumlen' not being even.
  43. * Note, the one's complement is handled by the caller.
  44. *
  45. * RETURNS: the checksum caclulated
  46. *
  47. * NOMANUAL
  48. *
  49. * int cksum
  50. * (
  51. * int sum;
  52. * char * string;
  53. * int len;
  54. * int sumlen;
  55. * )
  56. */
  57. FUNC_LABEL(cksum)
  58. #ifdef STACK_FRAMES
  59. mov ip, sp
  60. stmdb sp!, {fp, ip, lr, pc}
  61. sub fp, ip, #4
  62. #endif /* STACK_FRAMES */
  63. cmp r2, #0
  64. #ifdef STACK_FRAMES
  65. ldmeqdb fp, {fp, sp, pc}
  66. #else /* !STACK_FRAMES */
  67. moveq pc, lr /* Capture 0 */
  68. stmdb sp!, {lr} /* Keep return address */
  69. #endif /* STACK_FRAMES */
  70. tst r3, #1 /* Test sumlen for odd count */
  71. beq L$_Even_Byte
  72. ldrb r3, [r1], #1 /* Byte left over from last call */
  73. #if (_BYTE_ORDER == _BIG_ENDIAN)
  74. add r0, r0, r3
  75. #else
  76. add r0, r0, r3, lsl #8 /* Add upper byte */
  77. #endif
  78. subs r2, r2, #1 /* One less byte */
  79. beq L$_All_Done
  80. L$_Even_Byte:
  81. /* Now try to align to a word boundary */
  82. tst r1, #3 /* Aligned ? */
  83. moveq lr, #0 /* No offset */
  84. beq L$_Word_Align
  85. ldr r3, [r1, #0] /* Load word */
  86. /*
  87.  * The following may help with understanding of the next bit.
  88.  * If the bytes in memory from address a contain 11 22 33 44
  89.  * LDR from a+0 => 44332211 (little-endian) 11223344 (big-endian)
  90.  *          a+1 => 11443322                 44112233
  91.  *          a+2 => 22114433                 33441122
  92.  *          a+3 => 33221144                 22334411
  93.  */
  94. and ip, r1, #3 /* Get no of bytes we need from r3 */
  95. rsb ip, ip, #4 /* The number of bytes we can get */
  96. cmp r2, ip /* Have == Got */
  97. movlt ip, r2 /* Got == Have */
  98. #if (_BYTE_ORDER == _BIG_ENDIAN)
  99. tsts r1, #1
  100. movne r3, r3, ror #16 /* move addressed byte to b31..24 */
  101. cmps ip, #2
  102. mov lr, #0xff000000 /* At least one byte */
  103. orrge lr, lr, lr, lsr #8 /* The 2nd byte */
  104. orrgt lr, lr, lr, lsr #8 /* The third byte */
  105. and r3, r3, lr /* Mask out bytes we do not want */
  106. /*
  107.  * r3 contains up to 3 bytes to add, in highest 3 bytes of register
  108.  * This can cause carry (e.g 0xffff + 0xffffff00).
  109.  */
  110. adds r0, r0, r3 /* Add bytes */
  111. adc r0, r0, #0 /* add in any possible carry */
  112. #else
  113. cmp ip, #2
  114. mov lr, #0xff /* At least one byte */
  115. orrge lr, lr, lr, lsl #8 /* The 2nd byte */
  116. orrgt lr, lr, lr, lsl #8 /* The third byte */
  117. and r3, r3, lr /* Mask out bytes we do not want */
  118. /*
  119.  * r3 contains up to 3 bytes to add, in lowest 3 bytes of register
  120.  * This cannot cause carry.
  121.  */
  122. add r0, r0, r3 /* Add bytes */
  123. #endif
  124. /*
  125.  * Check if rotation of checksum required now so that we do the
  126.  * addition of all the next words the right way round. If we do rotate,
  127.  * save the rotation in lr so we can undo it at the end.
  128.  */
  129. tst r1, #1 /* Odd alignment */
  130. moveq lr, #0 /* No offset */
  131. movne lr, #8 /* Offset from different base */
  132. /*
  133.  * SPR #29703 (T3 SPR #64293): above addition was of a one, two or
  134.  * three byte number to a 16-bit sum and may have caused overflow into
  135.  * the fourth (highest) byte. Original (little-endian) code did an LSL
  136.  * here instead of ROR, incorrectly discarding such overflow. New code
  137.  * is same as big-endian code: it preserves the high byte. (Unimportant
  138.  * whether we shift 8 or 24 bits.)
  139.  */
  140. movne r0, r0, ror #8 /* Offset, work from a different base */
  141. subs r2, r2, ip /* Less bytes */
  142. add r1, r1, ip /* Move the pointer */
  143. beq L$_Boundary_Done /* We know we will shift */
  144. /* Now we are word aligned */
  145. L$_Word_Align:
  146. movs ip, r2, lsr #2 /* How many words can we add */
  147. beq L$_Left_123 /* No complete words left */
  148. sub r2, r2, ip, lsl #2 /* Take number of words off total */
  149. adds r0, r0, #0 /* Clear carry */
  150. ands r3, ip, #0x0f /* Last 16 ? (Does not clear carry) */
  151. /* Compute offset to start with in the loop */
  152. rsbne r3, r3, #16 /* Where to start */
  153. addne r3, pc, r3, lsl #3 /* Where to jump */
  154. movne pc, r3 /* And jump */
  155. 0:
  156. ldr r3, [r1], #4 /* 1 */
  157. adds r0, r0, r3 /* Carry already added */
  158. ldr r3, [r1], #4 /* 2 */
  159. adcs r0, r0, r3
  160. ldr r3, [r1], #4 /* 3 */
  161. adcs r0, r0, r3
  162. ldr r3, [r1], #4 /* 4 */
  163. adcs r0, r0, r3
  164. ldr r3, [r1], #4 /* 5 */
  165. adcs r0, r0, r3
  166. ldr r3, [r1], #4 /* 6 */
  167. adcs r0, r0, r3
  168. ldr r3, [r1], #4 /* 7 */
  169. adcs r0, r0, r3
  170. ldr r3, [r1], #4 /* 8 */
  171. adcs r0, r0, r3
  172. ldr r3, [r1], #4 /* 9 */
  173. adcs r0, r0, r3
  174. ldr r3, [r1], #4 /* 10 */
  175. adcs r0, r0, r3
  176. ldr r3, [r1], #4 /* 11 */
  177. adcs r0, r0, r3
  178. ldr r3, [r1], #4 /* 12 */
  179. adcs r0, r0, r3
  180. ldr r3, [r1], #4 /* 13 */
  181. adcs r0, r0, r3
  182. ldr r3, [r1], #4 /* 14 */
  183. adcs r0, r0, r3
  184. ldr r3, [r1], #4 /* 15 */
  185. adcs r0, r0, r3
  186. ldr r3, [r1], #4 /* 16 */
  187. adcs r0, r0, r3
  188. adc r0, r0, #0 /* Add Carry */
  189. subs ip, ip, #16 /* 16 words less ! */
  190. bgt 0b
  191. /* Main loop complete, less than 4 bytes left */
  192. cmp r2, #0
  193. beq L$_Boundary_Done /* Completed on a word boundary */
  194. /* 1, 2 or 3 bytes left */
  195. L$_Left_123:
  196. /* Completed on an odd boundary, do we shift the sum back ? */
  197. mov r0, r0, ror lr /* Shift total */
  198. /* Extract the last byte/s */
  199. #if (_BYTE_ORDER == _BIG_ENDIAN)
  200. cmp r2, #2
  201. mov r2, #0xff000000 /* At least one byte */
  202. orrge r2, r2, r2, lsr #8 /* The 2nd byte */
  203. orrgt r2, r2, r2, lsr #8 /* The third byte */
  204. ldr r3, [r1, #0] /* Load word */
  205. and r3, r3, r2 /* Mask out bytes we do not want */
  206. adds r0, r0, r3, lsr lr /* Add bytes */
  207. #else
  208. cmp r2, #2
  209. mov r2, #0xff /* At least one byte */
  210. orrge r2, r2, r2, lsl #8 /* The 2nd byte */
  211. orrgt r2, r2, r2, lsl #8 /* The third byte */
  212. ldr r3, [r1, #0] /* Load word */
  213. and r3, r3, r2 /* Mask out bytes we do not want */
  214. adds r0, r0, r3, lsl lr /* Add bytes */
  215. #endif
  216. adc r0, r0, #0 /* Add carry */
  217. adds r0, r0, r0, lsl #16 /* Result in upper 16 bits + C */
  218. mov r0, r0, lsr #16 /* Get upper 16 bits */
  219. adc r0, r0, #0 /* Add carry */
  220. #ifdef STACK_FRAMES
  221. ldmdb fp, {fp, sp, pc} /* Return (sum is in r0) */
  222. #else /* !STACK_FRAMES */
  223. ldmia sp!, {pc} /* Return (sum is in r0) */
  224. #endif /* STACK_FRAMES */
  225. /* Completed on a boundary */
  226. L$_Boundary_Done:
  227. mov r0, r0, ror lr /* Shift total back 8 */
  228. L$_All_Done:
  229. adds r0, r0, r0, lsl #16 /* Result in upper 16 bits + C */
  230. mov r0, r0, lsr #16 /* Get upper 16 bits */
  231. adc r0, r0, #0 /* Add carry */
  232. #ifdef STACK_FRAMES
  233. ldmdb fp, {fp, sp, pc} /* Return (sum is in r0) */
  234. #else /* !STACK_FRAMES */
  235. ldmia sp!, {pc} /* Return (sum is in r0) */
  236. #endif /* STACK_FRAMES */
  237. /*******************************************************************************
  238. *
  239. * _insque - insert node in list after specified node.
  240. *
  241. * RETURNS: N/A
  242. *
  243. * NOMANUAL
  244. *
  245. * void _insque
  246. * (
  247. * NODE * pNode,
  248. * NODE * pPrev
  249. * )
  250. */
  251. FUNC_LABEL(_insque)
  252. #ifdef STACK_FRAMES
  253. mov ip, sp
  254. stmdb sp!, {fp, ip, lr, pc}
  255. sub fp, ip, #4
  256. #endif /* STACK_FRAMES */
  257. ldr r3, [r1, #0] /* r3 = pPrev->next */
  258. str r0, [r1, #0] /* pPrev->next = pNode */
  259. str r0, [r3, #4] /* r3->previous = pNode */
  260. str r3, [r0, #0] /* pNode->next = r3 */
  261. str r1, [r0, #4] /* pNode->previous = pPrev */
  262. /* Done */
  263. #ifdef STACK_FRAMES
  264. ldmdb fp, {fp, sp, pc}
  265. #else /* !STACK_FRAMES */
  266. mov pc, lr
  267. #endif /* STACK_FRAMES */
  268. /*******************************************************************************
  269. *
  270. * _remque - remove specified node in list.
  271. *
  272. * RETURNS: N/A
  273. *
  274. * NOMANUAL
  275. *
  276. * void _remque
  277. * (
  278. * NODE * pNode
  279. * )
  280. */
  281. FUNC_LABEL(_remque)
  282. #ifdef STACK_FRAMES
  283. mov ip, sp
  284. stmdb sp!, {fp, ip, lr, pc}
  285. sub fp, ip, #4
  286. #endif /* STACK_FRAMES */
  287. /* Setup */
  288. ldr r2, [r0, #4] /* r2 = pNode->previous */
  289. ldr r3, [r0, #0] /* r3 = pNode->next */
  290. /*  pNode->previous->next = pNode->next */
  291. str r3, [r2, #0] /* r2->next = r3 */
  292. /* pNode->next->previous = pNode->previous */
  293. str r2, [r3, #4]
  294. #ifdef STACK_FRAMES
  295. ldmdb fp, {fp, sp, pc}
  296. #else /* !STACK_FRAMES */
  297. mov pc, lr
  298. #endif /* STACK_FRAMES */
  299. #endif /* ! unixALib_PORTABLE */