lbn960jx.s
上传用户:zbbssh
上传日期:2007-01-08
资源大小:196k
文件大小:9k
源码类别:

CA认证

开发平台:

C/C++

  1. # Assembly-language bignum primitives for the i960 Jx series.
  2. #
  3. # The Jx series is fairly straightforward single-instruction-issue 
  4. # implementation, with a 1-cycle-issue 4-cycle-latency non-pipelined
  5. # multiplier that we can use.  Note also that loads which hit in the
  6. # cache have 2 cycles of latency and stores stall until all pending
  7. # loads are done.
  8. #
  9. # What is intensely annoying about the i960 is that it uses the same
  10. # flags for all conditional branches (even compare-and-branch sets the
  11. # flags) AND for the carry bit.  Further, it is hard to manipulate
  12. # that bit.
  13. #
  14. # Calling conventions:
  15. # The r registers are all local, if you set them up.  There's an alternative
  16. # calling convention that uses bal (branch and link) and doesn't set them up.
  17. # Currently, all of these functions are designed to work that way.
  18. # g0-g7 are argument registers and volatile across calls.  return in g0-g3.
  19. # g8-g11 are extra argument registers, and volatile if used, but
  20. # preserved if not.  Here, they are not.
  21. # g12 is used for PIC, and is preserved.
  22. # g13 is a pointer to a structure return value, if used, and is volatile.
  23. # g14 is magic, and is used as a return address in the branch-and-link
  24. # convention, and as a pointer to an argument block if the arguments
  25. # won't fit in registers, but is usually hardwired 0 and must be
  26. # returned set to zero (0).
  27. # g15 is the frame pointer, and shouldn't be messed with.
  28. # The AC (condition codes) are all volatile.
  29. # The fp registers are all volatile, but irrelevant.
  30. #
  31. # BNWORD32
  32. # lbnMultAdd1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
  33. # This adds "k" * "in" to "len" words of "out" and returns the word of
  34. # carry.
  35. #
  36. # For doing multiply-add, the 960 is a bit annoying because it uses
  37. # the same status bits for the carry flag and for the loop indexing
  38. # computation, and doesn't have an "add with carry out but not carry in"
  39. # instruction.  Fortunately, we can arrange to have the loop indexing
  40. # leave the carry bit clear most of the time.
  41. #
  42. # The basic sequence of the loop is:
  43. # 1. Multiply k * *in++ -> high, low
  44. # 2. Addc carry word and carry bit to low
  45. # 3. Addc carry bit to high, producing carry word (note: cannot generate carry!)
  46. # 4. Addc low to *out++
  47. #
  48. # Note that the carry bit set in step 4 is used in step 2.  The only place
  49. # in this loop that the carry flag isn't in use is between steps 3 and 4,
  50. # so we have to rotate the loop to place the loop indexing operations here.
  51. # (Which consist of a compare-and-decrement and a conditional branch.)
  52. # The loop above ignores the details of when to do loads and stores, which
  53. # have some flexibility, but must be carefully scheduled to avoid stalls.
  54. #
  55. # The first iteration has no carry word in, so it requires only steps 1 and 4,
  56. # and since we begin the loop with step 4, it boils down to just step 1
  57. # followed by the loop indexing (which clears the carry bit in preparation
  58. # for step 4).
  59. #
  60. # Arguments are passed as follows:
  61. # g0 - out pointer
  62. # g1 - in pointer
  63. # g2 - length
  64. # g3 - k
  65. # The other registers are used as follows.
  66. # g4 - low word of product
  67. # g5 - high word of product
  68. # g6 - current word of "out"
  69. # g7 - carry word
  70. # g13 - current word of "in"
  71. .globl _lbnMulAdd1_32
  72. _lbnMulAdd1_32:
  73. ld (g1),g13    # Fetch *in
  74. addo g1,4,g1    # Increment in
  75. emul g13,g3,g4 # Do multiply (step 1)
  76. ld (g0),g6    # Fetch *out
  77. chkbit 0,g2 # Check if loop counter was odd
  78. shro 1,g2,g2    # Divide loop counter by 2
  79. mov g5,g7 # Move high word to carry
  80. bno ma_loop1 # If even, jump to ma_loop1
  81. cmpo 0,g2 # If odd, was it 1 (now 0)?
  82. be ma_done    # If equal (carry set), jump to ending code
  83. # Entered with carry bit clear
  84. ma_loop:
  85. ld (g1),g13   # Fetch *in
  86. addc g4,g6,g6 # Add low to *out (step 4), generate carry
  87. emul g13,g3,g4 # Do multiply (step 1)
  88. st g6,(g0)   # Write out *out
  89. addo g0,4,g0   # Increment out
  90. addo g1,4,g1   # Increment in
  91. ld (g0),g6   # Fetch next *out
  92. addc g7,g4,g4 # Add carries to low (step 2)
  93. addc g5,0,g7   # Add carry bit to high (step 3) & clear carry
  94. ma_loop1:
  95. ld (g1),g13   # Fetch *in
  96. addc g4,g6,g6 # Add low to *out (step 4), generate carry
  97. emul g13,g3,g4 # Do multiply (step 1)
  98. st g6,(g0)   # Write out *out
  99. addo g0,4,g0   # Increment out
  100. addo g1,4,g1   # Increment in
  101. ld (g0),g6   # Fetch next *out
  102. addc g7,g4,g4 # Add carries to low (step 2)
  103. addc g5,0,g7   # Add carry bit to high (step 3) & clear carry
  104. cmpdeco 1,g2,g2
  105. bne ma_loop
  106. # When we come here, carry is *set*, and we stil have to do step 4
  107. ma_done:
  108. cmpi 0,1 # Clear carry (equal flag)
  109. addc g4,g6,g6 # Add low to *out (step 4), generate carry
  110. st g6,(g0)    # Write out *out
  111. addc g7,0,g0    # Add carry bit and word to produce return value
  112. ret
  113. # Now, multiply N by 1 is similarly annoying.  We only have one add in the
  114. # whole loop, which should just be able to leave its carry output in the
  115. # carry flag for the next iteration, but we need the condition codes to do
  116. # loop testing.  *Sigh*.
  117. #
  118. # void
  119. # lbnMultN1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
  120. # This stores len+1 words of "k" * len words of "in" and stores the result
  121. # in "out".
  122. #
  123. # To avoid having to do a move after the first iteration, for the first
  124. # step, g4/g5 is the product.  For second step, g6/g7 is used for product
  125. # storage and g5 is the carry in.  It alternates from then on.
  126. .globl _lbnMulN1_32
  127. _lbnMulN1_32:
  128. ld (g1),g13  # Fetch *in
  129. addo g1,4,g1  # Increment in
  130. emul g13,g3,g4 # Do multiply (step 1)
  131. chkbit 0,g2 # Check if loop counter was odd
  132. shro 1,g2,g2   # Divide loop counter by 2
  133. bno m_loop1   # If even, jump to ma_loop1
  134. mov g4,g6
  135. cmpo 0,g2 # If counter was odd, was it 1 (now 0)?
  136. mov g5,g7
  137. be m_done # If equal (carry set), jump to ending code
  138. # Entered with carry bit clear
  139. m_loop:
  140. # Result in g6, carry word in g7
  141. ld (g1),g13 # Fetch *in
  142. addo g1,4,g1  # Increment in
  143. emul g13,g3,g4 # Do multiply (step 1)
  144. st g6,(g0)  # Write out *out
  145. addo g0,4,g0 # Increment out
  146. addc g7,g4,g4 # Add carries to low (step 2)
  147. # No need to add carry bit here, because it'll get remembered until next addc.
  148. # addc g5,0,g5  # Add carry bit to high (step 3)
  149. m_loop1:
  150. # Carry word in g5
  151. ld (g1),g13 # Fetch *in
  152. addo g1,4,g1 # Increment in
  153. emul g13,g3,g6 # Do multiply (step 1)
  154. st g4,(g0) # Write out *out
  155. addo g0,4,g0  # Increment out
  156. addc g5,g6,g6 # Add carries to low (step 2)
  157. addc g7,0,g7  # Add carry bit to high (step 3)
  158. cmpdeco 1,g2,g2
  159. bne m_loop
  160. # When we come here, we have to store g6 and the carry word in g7.
  161. m_done:
  162. st g6,(g0)  # Write out *out
  163. st g7,4(g0) # Write out *out
  164. ret
  165. # BNWORD32
  166. # lbnMultSub1_32(BNWORD32 *out, BNWORD32 const *in, unsigned len, BNWORD32 k)
  167. # This subtracts "k" * "in" from "len" words of "out" and returns the word of
  168. # borrow.
  169. #
  170. # This is similar to multiply-add, but actually a bit more obnoxious,
  171. # because of the carry situation.  The 960 uses a carry (rather than a borrow)
  172. # bit on subtracts, so the carry bit should be 1 for a subc to do the
  173. # same thing as an ordinary subo.  So we use two carry chains: one from
  174. # the add of the low-order words to the high-order carry word, and a second,
  175. # which uses an extra register, to connect the subtracts.  This avoids
  176. # the need to fiddle with inverting the bit in the usual case.
  177. #
  178. # Arguments are passed as follows:
  179. # g0 - out pointer
  180. # g1 - in pointer
  181. # g2 - length
  182. # g3 - k
  183. # The other registers are used as follows.
  184. # g4 - low word of product
  185. # g5 - high word of product
  186. # g6 - current word of "out"
  187. # g7 - carry word
  188. # g13 - current word of "in"
  189. # g14 - remembered carry bit
  190. .globl _lbnMulSub1_32
  191. _lbnMulSub1_32:
  192. ld (g1),g13 # Fetch *in
  193. addo g1,4,g1  # Increment in
  194. emul g13,g3,g4 # Do multiply (step 1)
  195. ld (g0),g6  # Fetch *out
  196. chkbit 0,g2     # Check if loop counter was odd
  197. mov 1,g14    # Set remembered carry for first iteration
  198. shro 1,g2,g2  # Divide loop counter by 2
  199. mov g5,g7    # Move high word to carry
  200. bno ms_loop1 # If even, jump to ma_loop1
  201. cmpo 0,g2     # If odd, was it 1 (now 0)?
  202. be ms_done  # If equal (carry set), jump to ending code
  203. # Entered with carry bit clear
  204. ms_loop:
  205. ld (g1),g13 # Fetch *in
  206. cmpi g14,1    # Set carry flag
  207. subc g4,g6,g6 # Subtract low from *out (step 4), gen. carry
  208. emul g13,g3,g4 # Do multiply (step 1)
  209. addc 0,0,g14  # g14 = carry, then clear carry
  210. st g6,(g0)  # Write out *out
  211. addo g0,4,g0  # Increment out
  212. addo g1,4,g1  # Increment in
  213. ld (g0),g6  # Fetch next *out
  214. addc g7,g4,g4 # Add carries to low (step 2)
  215. addc g5,0,g7  # Add carry bit to high (step 3)
  216. ms_loop1:
  217. ld (g1),g13 # Fetch *in
  218. cmpi g14,1    # Set carry flag for subtrsct
  219. subc g4,g6,g6 # Subtract low from *out (step 4), gen. carry
  220. emul g13,g3,g4 # Do multiply (step 1)
  221. addc 0,0,g14  # g14 = carry, then clear carry
  222. st g6,(g0)  # Write out *out
  223. addo g0,4,g0  # Increment out
  224. addo g1,4,g1  # Increment in
  225. ld (g0),g6  # Fetch next *out
  226. addc g7,g4,g4 # Add carries to low (step 2)
  227. addc g5,0,g7  # Add carry bit to high (step 3)
  228. cmpdeco 1,g2,g2
  229. bne ms_loop
  230. # When we come here, carry is *set*, and we stil have to do step 4
  231. ms_done:
  232. cmpi g14,1    # set carry (equal flag)
  233. subc g4,g6,g6 # Add low to *out (step 4), generate carry
  234. st g6,(g0)  # Write out *out
  235. subc 0,0,g14  # g14 = -1 if no carry (borrow), 0 if carry
  236. subo g14,g7,g0 # Add borrow bit to produce return value
  237. mov 0,g14    # Restore g14 to 0 for return
  238. ret