binstr.S 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. |
  2. | binstr.sa 3.3 12/19/90
  3. |
  4. |
  5. | Description: Converts a 64-bit binary integer to bcd.
  6. |
  7. | Input: 64-bit binary integer in d2:d3, desired length (LEN) in
  8. | d0, and a pointer to start in memory for bcd characters
  9. | in d0. (This pointer must point to byte 4 of the first
  10. | lword of the packed decimal memory string.)
  11. |
  12. | Output: LEN bcd digits representing the 64-bit integer.
  13. |
  14. | Algorithm:
  15. | The 64-bit binary is assumed to have a decimal point before
  16. | bit 63. The fraction is multiplied by 10 using a mul by 2
  17. | shift and a mul by 8 shift. The bits shifted out of the
  18. | msb form a decimal digit. This process is iterated until
  19. | LEN digits are formed.
  20. |
  21. | A1. Init d7 to 1. D7 is the byte digit counter, and if 1, the
  22. | digit formed will be assumed the least significant. This is
  23. | to force the first byte formed to have a 0 in the upper 4 bits.
  24. |
  25. | A2. Beginning of the loop:
  26. | Copy the fraction in d2:d3 to d4:d5.
  27. |
  28. | A3. Multiply the fraction in d2:d3 by 8 using bit-field
  29. | extracts and shifts. The three msbs from d2 will go into
  30. | d1.
  31. |
  32. | A4. Multiply the fraction in d4:d5 by 2 using shifts. The msb
  33. | will be collected by the carry.
  34. |
  35. | A5. Add using the carry the 64-bit quantities in d2:d3 and d4:d5
  36. | into d2:d3. D1 will contain the bcd digit formed.
  37. |
  38. | A6. Test d7. If zero, the digit formed is the ms digit. If non-
  39. | zero, it is the ls digit. Put the digit in its place in the
  40. | upper word of d0. If it is the ls digit, write the word
  41. | from d0 to memory.
  42. |
  43. | A7. Decrement d6 (LEN counter) and repeat the loop until zero.
  44. |
  45. | Implementation Notes:
  46. |
  47. | The registers are used as follows:
  48. |
  49. | d0: LEN counter
  50. | d1: temp used to form the digit
  51. | d2: upper 32-bits of fraction for mul by 8
  52. | d3: lower 32-bits of fraction for mul by 8
  53. | d4: upper 32-bits of fraction for mul by 2
  54. | d5: lower 32-bits of fraction for mul by 2
  55. | d6: temp for bit-field extracts
  56. | d7: byte digit formation word;digit count {0,1}
  57. | a0: pointer into memory for packed bcd string formation
  58. |
  59. | Copyright (C) Motorola, Inc. 1990
  60. | All Rights Reserved
  61. |
  62. | For details on the license for this file, please see the
  63. | file, README, in this same directory.
  64. |BINSTR idnt 2,1 | Motorola 040 Floating Point Software Package
  65. |section 8
  66. #include "fpsp.h"
  67. .global binstr
  68. binstr:
  69. moveml %d0-%d7,-(%a7)
  70. |
  71. | A1: Init d7
  72. |
  73. moveql #1,%d7 |init d7 for second digit
  74. subql #1,%d0 |for dbf d0 would have LEN+1 passes
  75. |
  76. | A2. Copy d2:d3 to d4:d5. Start loop.
  77. |
  78. loop:
  79. movel %d2,%d4 |copy the fraction before muls
  80. movel %d3,%d5 |to d4:d5
  81. |
  82. | A3. Multiply d2:d3 by 8; extract msbs into d1.
  83. |
  84. bfextu %d2{#0:#3},%d1 |copy 3 msbs of d2 into d1
  85. asll #3,%d2 |shift d2 left by 3 places
  86. bfextu %d3{#0:#3},%d6 |copy 3 msbs of d3 into d6
  87. asll #3,%d3 |shift d3 left by 3 places
  88. orl %d6,%d2 |or in msbs from d3 into d2
  89. |
  90. | A4. Multiply d4:d5 by 2; add carry out to d1.
  91. |
  92. asll #1,%d5 |mul d5 by 2
  93. roxll #1,%d4 |mul d4 by 2
  94. swap %d6 |put 0 in d6 lower word
  95. addxw %d6,%d1 |add in extend from mul by 2
  96. |
  97. | A5. Add mul by 8 to mul by 2. D1 contains the digit formed.
  98. |
  99. addl %d5,%d3 |add lower 32 bits
  100. nop |ERRATA ; FIX #13 (Rev. 1.2 6/6/90)
  101. addxl %d4,%d2 |add with extend upper 32 bits
  102. nop |ERRATA ; FIX #13 (Rev. 1.2 6/6/90)
  103. addxw %d6,%d1 |add in extend from add to d1
  104. swap %d6 |with d6 = 0; put 0 in upper word
  105. |
  106. | A6. Test d7 and branch.
  107. |
  108. tstw %d7 |if zero, store digit & to loop
  109. beqs first_d |if non-zero, form byte & write
  110. sec_d:
  111. swap %d7 |bring first digit to word d7b
  112. aslw #4,%d7 |first digit in upper 4 bits d7b
  113. addw %d1,%d7 |add in ls digit to d7b
  114. moveb %d7,(%a0)+ |store d7b byte in memory
  115. swap %d7 |put LEN counter in word d7a
  116. clrw %d7 |set d7a to signal no digits done
  117. dbf %d0,loop |do loop some more!
  118. bras end_bstr |finished, so exit
  119. first_d:
  120. swap %d7 |put digit word in d7b
  121. movew %d1,%d7 |put new digit in d7b
  122. swap %d7 |put LEN counter in word d7a
  123. addqw #1,%d7 |set d7a to signal first digit done
  124. dbf %d0,loop |do loop some more!
  125. swap %d7 |put last digit in string
  126. lslw #4,%d7 |move it to upper 4 bits
  127. moveb %d7,(%a0)+ |store it in memory string
  128. |
  129. | Clean up and return with result in fp0.
  130. |
  131. end_bstr:
  132. moveml (%a7)+,%d0-%d7
  133. rts
  134. |end