x_store.S 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. |
  2. | x_store.sa 3.2 1/24/91
  3. |
  4. | store --- store operand to memory or register
  5. |
  6. | Used by underflow and overflow handlers.
  7. |
  8. | a6 = points to fp value to be stored.
  9. |
  10. | Copyright (C) Motorola, Inc. 1990
  11. | All Rights Reserved
  12. |
  13. | For details on the license for this file, please see the
  14. | file, README, in this same directory.
  15. X_STORE: |idnt 2,1 | Motorola 040 Floating Point Software Package
  16. |section 8
  17. fpreg_mask:
  18. .byte 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
  19. #include "fpsp.h"
  20. |xref mem_write
  21. |xref get_fline
  22. |xref g_opcls
  23. |xref g_dfmtou
  24. |xref reg_dest
  25. .global dest_ext
  26. .global dest_dbl
  27. .global dest_sgl
  28. .global store
  29. store:
  30. btstb #E3,E_BYTE(%a6)
  31. beqs E1_sto
  32. E3_sto:
  33. movel CMDREG3B(%a6),%d0
  34. bfextu %d0{#6:#3},%d0 |isolate dest. reg from cmdreg3b
  35. sto_fp:
  36. lea fpreg_mask,%a1
  37. moveb (%a1,%d0.w),%d0 |convert reg# to dynamic register mask
  38. tstb LOCAL_SGN(%a0)
  39. beqs is_pos
  40. bsetb #sign_bit,LOCAL_EX(%a0)
  41. is_pos:
  42. fmovemx (%a0),%d0 |move to correct register
  43. |
  44. | if fp0-fp3 is being modified, we must put a copy
  45. | in the USER_FPn variable on the stack because all exception
  46. | handlers restore fp0-fp3 from there.
  47. |
  48. cmpb #0x80,%d0
  49. bnes not_fp0
  50. fmovemx %fp0-%fp0,USER_FP0(%a6)
  51. rts
  52. not_fp0:
  53. cmpb #0x40,%d0
  54. bnes not_fp1
  55. fmovemx %fp1-%fp1,USER_FP1(%a6)
  56. rts
  57. not_fp1:
  58. cmpb #0x20,%d0
  59. bnes not_fp2
  60. fmovemx %fp2-%fp2,USER_FP2(%a6)
  61. rts
  62. not_fp2:
  63. cmpb #0x10,%d0
  64. bnes not_fp3
  65. fmovemx %fp3-%fp3,USER_FP3(%a6)
  66. rts
  67. not_fp3:
  68. rts
  69. E1_sto:
  70. bsrl g_opcls |returns opclass in d0
  71. cmpib #3,%d0
  72. beq opc011 |branch if opclass 3
  73. movel CMDREG1B(%a6),%d0
  74. bfextu %d0{#6:#3},%d0 |extract destination register
  75. bras sto_fp
  76. opc011:
  77. bsrl g_dfmtou |returns dest format in d0
  78. | ;ext=00, sgl=01, dbl=10
  79. movel %a0,%a1 |save source addr in a1
  80. movel EXC_EA(%a6),%a0 |get the address
  81. cmpil #0,%d0 |if dest format is extended
  82. beq dest_ext |then branch
  83. cmpil #1,%d0 |if dest format is single
  84. beq dest_sgl |then branch
  85. |
  86. | fall through to dest_dbl
  87. |
  88. |
  89. | dest_dbl --- write double precision value to user space
  90. |
  91. |Input
  92. | a0 -> destination address
  93. | a1 -> source in extended precision
  94. |Output
  95. | a0 -> destroyed
  96. | a1 -> destroyed
  97. | d0 -> 0
  98. |
  99. |Changes extended precision to double precision.
  100. | Note: no attempt is made to round the extended value to double.
  101. | dbl_sign = ext_sign
  102. | dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)
  103. | get rid of ext integer bit
  104. | dbl_mant = ext_mant{62:12}
  105. |
  106. | --------------- --------------- ---------------
  107. | extended -> |s| exp | |1| ms mant | | ls mant |
  108. | --------------- --------------- ---------------
  109. | 95 64 63 62 32 31 11 0
  110. | | |
  111. | | |
  112. | | |
  113. | v v
  114. | --------------- ---------------
  115. | double -> |s|exp| mant | | mant |
  116. | --------------- ---------------
  117. | 63 51 32 31 0
  118. |
  119. dest_dbl:
  120. clrl %d0 |clear d0
  121. movew LOCAL_EX(%a1),%d0 |get exponent
  122. subw #0x3fff,%d0 |subtract extended precision bias
  123. cmpw #0x4000,%d0 |check if inf
  124. beqs inf |if so, special case
  125. addw #0x3ff,%d0 |add double precision bias
  126. swap %d0 |d0 now in upper word
  127. lsll #4,%d0 |d0 now in proper place for dbl prec exp
  128. tstb LOCAL_SGN(%a1)
  129. beqs get_mant |if positive, go process mantissa
  130. bsetl #31,%d0 |if negative, put in sign information
  131. | ; before continuing
  132. bras get_mant |go process mantissa
  133. inf:
  134. movel #0x7ff00000,%d0 |load dbl inf exponent
  135. clrl LOCAL_HI(%a1) |clear msb
  136. tstb LOCAL_SGN(%a1)
  137. beqs dbl_inf |if positive, go ahead and write it
  138. bsetl #31,%d0 |if negative put in sign information
  139. dbl_inf:
  140. movel %d0,LOCAL_EX(%a1) |put the new exp back on the stack
  141. bras dbl_wrt
  142. get_mant:
  143. movel LOCAL_HI(%a1),%d1 |get ms mantissa
  144. bfextu %d1{#1:#20},%d1 |get upper 20 bits of ms
  145. orl %d1,%d0 |put these bits in ms word of double
  146. movel %d0,LOCAL_EX(%a1) |put the new exp back on the stack
  147. movel LOCAL_HI(%a1),%d1 |get ms mantissa
  148. movel #21,%d0 |load shift count
  149. lsll %d0,%d1 |put lower 11 bits in upper bits
  150. movel %d1,LOCAL_HI(%a1) |build lower lword in memory
  151. movel LOCAL_LO(%a1),%d1 |get ls mantissa
  152. bfextu %d1{#0:#21},%d0 |get ls 21 bits of double
  153. orl %d0,LOCAL_HI(%a1) |put them in double result
  154. dbl_wrt:
  155. movel #0x8,%d0 |byte count for double precision number
  156. exg %a0,%a1 |a0=supervisor source, a1=user dest
  157. bsrl mem_write |move the number to the user's memory
  158. rts
  159. |
  160. | dest_sgl --- write single precision value to user space
  161. |
  162. |Input
  163. | a0 -> destination address
  164. | a1 -> source in extended precision
  165. |
  166. |Output
  167. | a0 -> destroyed
  168. | a1 -> destroyed
  169. | d0 -> 0
  170. |
  171. |Changes extended precision to single precision.
  172. | sgl_sign = ext_sign
  173. | sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)
  174. | get rid of ext integer bit
  175. | sgl_mant = ext_mant{62:12}
  176. |
  177. | --------------- --------------- ---------------
  178. | extended -> |s| exp | |1| ms mant | | ls mant |
  179. | --------------- --------------- ---------------
  180. | 95 64 63 62 40 32 31 12 0
  181. | | |
  182. | | |
  183. | | |
  184. | v v
  185. | ---------------
  186. | single -> |s|exp| mant |
  187. | ---------------
  188. | 31 22 0
  189. |
  190. dest_sgl:
  191. clrl %d0
  192. movew LOCAL_EX(%a1),%d0 |get exponent
  193. subw #0x3fff,%d0 |subtract extended precision bias
  194. cmpw #0x4000,%d0 |check if inf
  195. beqs sinf |if so, special case
  196. addw #0x7f,%d0 |add single precision bias
  197. swap %d0 |put exp in upper word of d0
  198. lsll #7,%d0 |shift it into single exp bits
  199. tstb LOCAL_SGN(%a1)
  200. beqs get_sman |if positive, continue
  201. bsetl #31,%d0 |if negative, put in sign first
  202. bras get_sman |get mantissa
  203. sinf:
  204. movel #0x7f800000,%d0 |load single inf exp to d0
  205. tstb LOCAL_SGN(%a1)
  206. beqs sgl_wrt |if positive, continue
  207. bsetl #31,%d0 |if negative, put in sign info
  208. bras sgl_wrt
  209. get_sman:
  210. movel LOCAL_HI(%a1),%d1 |get ms mantissa
  211. bfextu %d1{#1:#23},%d1 |get upper 23 bits of ms
  212. orl %d1,%d0 |put these bits in ms word of single
  213. sgl_wrt:
  214. movel %d0,L_SCR1(%a6) |put the new exp back on the stack
  215. movel #0x4,%d0 |byte count for single precision number
  216. tstl %a0 |users destination address
  217. beqs sgl_Dn |destination is a data register
  218. exg %a0,%a1 |a0=supervisor source, a1=user dest
  219. leal L_SCR1(%a6),%a0 |point a0 to data
  220. bsrl mem_write |move the number to the user's memory
  221. rts
  222. sgl_Dn:
  223. bsrl get_fline |returns fline word in d0
  224. andw #0x7,%d0 |isolate register number
  225. movel %d0,%d1 |d1 has size:reg formatted for reg_dest
  226. orl #0x10,%d1 |reg_dest wants size added to reg#
  227. bral reg_dest |size is X, rts in reg_dest will
  228. | ;return to caller of dest_sgl
  229. dest_ext:
  230. tstb LOCAL_SGN(%a1) |put back sign into exponent word
  231. beqs dstx_cont
  232. bsetb #sign_bit,LOCAL_EX(%a1)
  233. dstx_cont:
  234. clrb LOCAL_SGN(%a1) |clear out the sign byte
  235. movel #0x0c,%d0 |byte count for extended number
  236. exg %a0,%a1 |a0=supervisor source, a1=user dest
  237. bsrl mem_write |move the number to the user's memory
  238. rts
  239. |end