get_op.S 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. |
  2. | get_op.sa 3.6 5/19/92
  3. |
  4. | get_op.sa 3.5 4/26/91
  5. |
  6. | Description: This routine is called by the unsupported format/data
  7. | type exception handler ('unsupp' - vector 55) and the unimplemented
  8. | instruction exception handler ('unimp' - vector 11). 'get_op'
  9. | determines the opclass (0, 2, or 3) and branches to the
  10. | opclass handler routine. See 68881/2 User's Manual table 4-11
  11. | for a description of the opclasses.
  12. |
  13. | For UNSUPPORTED data/format (exception vector 55) and for
  14. | UNIMPLEMENTED instructions (exception vector 11) the following
  15. | applies:
  16. |
  17. | - For unnormalized numbers (opclass 0, 2, or 3) the
  18. | number(s) is normalized and the operand type tag is updated.
  19. |
  20. | - For a packed number (opclass 2) the number is unpacked and the
  21. | operand type tag is updated.
  22. |
  23. | - For denormalized numbers (opclass 0 or 2) the number(s) is not
  24. | changed but passed to the next module. The next module for
  25. | unimp is do_func, the next module for unsupp is res_func.
  26. |
  27. | For UNSUPPORTED data/format (exception vector 55) only the
  28. | following applies:
  29. |
  30. | - If there is a move out with a packed number (opclass 3) the
  31. | number is packed and written to user memory. For the other
  32. | opclasses the number(s) are written back to the fsave stack
  33. | and the instruction is then restored back into the '040. The
  34. | '040 is then able to complete the instruction.
  35. |
  36. | For example:
  37. | fadd.x fpm,fpn where the fpm contains an unnormalized number.
  38. | The '040 takes an unsupported data trap and gets to this
  39. | routine. The number is normalized, put back on the stack and
  40. | then an frestore is done to restore the instruction back into
  41. | the '040. The '040 then re-executes the fadd.x fpm,fpn with
  42. | a normalized number in the source and the instruction is
  43. | successful.
  44. |
  45. | Next consider if in the process of normalizing the un-
  46. | normalized number it becomes a denormalized number. The
  47. | routine which converts the unnorm to a norm (called mk_norm)
  48. | detects this and tags the number as a denorm. The routine
  49. | res_func sees the denorm tag and converts the denorm to a
  50. | norm. The instruction is then restored back into the '040
  51. | which re_executes the instruction.
  52. |
  53. |
  54. | Copyright (C) Motorola, Inc. 1990
  55. | All Rights Reserved
  56. |
  57. | For details on the license for this file, please see the
  58. | file, README, in this same directory.
  59. GET_OP: |idnt 2,1 | Motorola 040 Floating Point Software Package
  60. |section 8
  61. #include "fpsp.h"
  62. .global PIRN,PIRZRM,PIRP
  63. .global SMALRN,SMALRZRM,SMALRP
  64. .global BIGRN,BIGRZRM,BIGRP
  65. PIRN:
  66. .long 0x40000000,0xc90fdaa2,0x2168c235 |pi
  67. PIRZRM:
  68. .long 0x40000000,0xc90fdaa2,0x2168c234 |pi
  69. PIRP:
  70. .long 0x40000000,0xc90fdaa2,0x2168c235 |pi
  71. |round to nearest
  72. SMALRN:
  73. .long 0x3ffd0000,0x9a209a84,0xfbcff798 |log10(2)
  74. .long 0x40000000,0xadf85458,0xa2bb4a9a |e
  75. .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc |log2(e)
  76. .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e)
  77. .long 0x00000000,0x00000000,0x00000000 |0.0
  78. | round to zero;round to negative infinity
  79. SMALRZRM:
  80. .long 0x3ffd0000,0x9a209a84,0xfbcff798 |log10(2)
  81. .long 0x40000000,0xadf85458,0xa2bb4a9a |e
  82. .long 0x3fff0000,0xb8aa3b29,0x5c17f0bb |log2(e)
  83. .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e)
  84. .long 0x00000000,0x00000000,0x00000000 |0.0
  85. | round to positive infinity
  86. SMALRP:
  87. .long 0x3ffd0000,0x9a209a84,0xfbcff799 |log10(2)
  88. .long 0x40000000,0xadf85458,0xa2bb4a9b |e
  89. .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc |log2(e)
  90. .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e)
  91. .long 0x00000000,0x00000000,0x00000000 |0.0
  92. |round to nearest
  93. BIGRN:
  94. .long 0x3ffe0000,0xb17217f7,0xd1cf79ac |ln(2)
  95. .long 0x40000000,0x935d8ddd,0xaaa8ac17 |ln(10)
  96. .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
  97. .global PTENRN
  98. PTENRN:
  99. .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1
  100. .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2
  101. .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4
  102. .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8
  103. .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16
  104. .long 0x40690000,0x9DC5ADA8,0x2B70B59E |10 ^ 32
  105. .long 0x40D30000,0xC2781F49,0xFFCFA6D5 |10 ^ 64
  106. .long 0x41A80000,0x93BA47C9,0x80E98CE0 |10 ^ 128
  107. .long 0x43510000,0xAA7EEBFB,0x9DF9DE8E |10 ^ 256
  108. .long 0x46A30000,0xE319A0AE,0xA60E91C7 |10 ^ 512
  109. .long 0x4D480000,0xC9767586,0x81750C17 |10 ^ 1024
  110. .long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 |10 ^ 2048
  111. .long 0x75250000,0xC4605202,0x8A20979B |10 ^ 4096
  112. |round to minus infinity
  113. BIGRZRM:
  114. .long 0x3ffe0000,0xb17217f7,0xd1cf79ab |ln(2)
  115. .long 0x40000000,0x935d8ddd,0xaaa8ac16 |ln(10)
  116. .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
  117. .global PTENRM
  118. PTENRM:
  119. .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1
  120. .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2
  121. .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4
  122. .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8
  123. .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16
  124. .long 0x40690000,0x9DC5ADA8,0x2B70B59D |10 ^ 32
  125. .long 0x40D30000,0xC2781F49,0xFFCFA6D5 |10 ^ 64
  126. .long 0x41A80000,0x93BA47C9,0x80E98CDF |10 ^ 128
  127. .long 0x43510000,0xAA7EEBFB,0x9DF9DE8D |10 ^ 256
  128. .long 0x46A30000,0xE319A0AE,0xA60E91C6 |10 ^ 512
  129. .long 0x4D480000,0xC9767586,0x81750C17 |10 ^ 1024
  130. .long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 |10 ^ 2048
  131. .long 0x75250000,0xC4605202,0x8A20979A |10 ^ 4096
  132. |round to positive infinity
  133. BIGRP:
  134. .long 0x3ffe0000,0xb17217f7,0xd1cf79ac |ln(2)
  135. .long 0x40000000,0x935d8ddd,0xaaa8ac17 |ln(10)
  136. .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
  137. .global PTENRP
  138. PTENRP:
  139. .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1
  140. .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2
  141. .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4
  142. .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8
  143. .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16
  144. .long 0x40690000,0x9DC5ADA8,0x2B70B59E |10 ^ 32
  145. .long 0x40D30000,0xC2781F49,0xFFCFA6D6 |10 ^ 64
  146. .long 0x41A80000,0x93BA47C9,0x80E98CE0 |10 ^ 128
  147. .long 0x43510000,0xAA7EEBFB,0x9DF9DE8E |10 ^ 256
  148. .long 0x46A30000,0xE319A0AE,0xA60E91C7 |10 ^ 512
  149. .long 0x4D480000,0xC9767586,0x81750C18 |10 ^ 1024
  150. .long 0x5A920000,0x9E8B3B5D,0xC53D5DE6 |10 ^ 2048
  151. .long 0x75250000,0xC4605202,0x8A20979B |10 ^ 4096
  152. |xref nrm_zero
  153. |xref decbin
  154. |xref round
  155. .global get_op
  156. .global uns_getop
  157. .global uni_getop
  158. get_op:
  159. clrb DY_MO_FLG(%a6)
  160. tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state
  161. beq uni_getop
  162. uns_getop:
  163. btstb #direction_bit,CMDREG1B(%a6)
  164. bne opclass3 |branch if a fmove out (any kind)
  165. btstb #6,CMDREG1B(%a6)
  166. beqs uns_notpacked
  167. bfextu CMDREG1B(%a6){#3:#3},%d0
  168. cmpb #3,%d0
  169. beq pack_source |check for a packed src op, branch if so
  170. uns_notpacked:
  171. bsr chk_dy_mo |set the dyadic/monadic flag
  172. tstb DY_MO_FLG(%a6)
  173. beqs src_op_ck |if monadic, go check src op
  174. | ;else, check dst op (fall through)
  175. btstb #7,DTAG(%a6)
  176. beqs src_op_ck |if dst op is norm, check src op
  177. bras dst_ex_dnrm |else, handle destination unnorm/dnrm
  178. uni_getop:
  179. bfextu CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
  180. cmpil #0x17,%d0 |if op class and size fields are $17,
  181. | ;it is FMOVECR; if not, continue
  182. |
  183. | If the instruction is fmovecr, exit get_op. It is handled
  184. | in do_func and smovecr.sa.
  185. |
  186. bne not_fmovecr |handle fmovecr as an unimplemented inst
  187. rts
  188. not_fmovecr:
  189. btstb #E1,E_BYTE(%a6) |if set, there is a packed operand
  190. bne pack_source |check for packed src op, branch if so
  191. | The following lines of are coded to optimize on normalized operands
  192. moveb STAG(%a6),%d0
  193. orb DTAG(%a6),%d0 |check if either of STAG/DTAG msb set
  194. bmis dest_op_ck |if so, some op needs to be fixed
  195. rts
  196. dest_op_ck:
  197. btstb #7,DTAG(%a6) |check for unsupported data types in
  198. beqs src_op_ck |the destination, if not, check src op
  199. bsr chk_dy_mo |set dyadic/monadic flag
  200. tstb DY_MO_FLG(%a6) |
  201. beqs src_op_ck |if monadic, check src op
  202. |
  203. | At this point, destination has an extended denorm or unnorm.
  204. |
  205. dst_ex_dnrm:
  206. movew FPTEMP_EX(%a6),%d0 |get destination exponent
  207. andiw #0x7fff,%d0 |mask sign, check if exp = 0000
  208. beqs src_op_ck |if denorm then check source op.
  209. | ;denorms are taken care of in res_func
  210. | ;(unsupp) or do_func (unimp)
  211. | ;else unnorm fall through
  212. leal FPTEMP(%a6),%a0 |point a0 to dop - used in mk_norm
  213. bsr mk_norm |go normalize - mk_norm returns:
  214. | ;L_SCR1{7:5} = operand tag
  215. | ; (000 = norm, 100 = denorm)
  216. | ;L_SCR1{4} = fpte15 or ete15
  217. | ; 0 = exp > $3fff
  218. | ; 1 = exp <= $3fff
  219. | ;and puts the normalized num back
  220. | ;on the fsave stack
  221. |
  222. moveb L_SCR1(%a6),DTAG(%a6) |write the new tag & fpte15
  223. | ;to the fsave stack and fall
  224. | ;through to check source operand
  225. |
  226. src_op_ck:
  227. btstb #7,STAG(%a6)
  228. beq end_getop |check for unsupported data types on the
  229. | ;source operand
  230. btstb #5,STAG(%a6)
  231. bnes src_sd_dnrm |if bit 5 set, handle sgl/dbl denorms
  232. |
  233. | At this point only unnorms or extended denorms are possible.
  234. |
  235. src_ex_dnrm:
  236. movew ETEMP_EX(%a6),%d0 |get source exponent
  237. andiw #0x7fff,%d0 |mask sign, check if exp = 0000
  238. beq end_getop |if denorm then exit, denorms are
  239. | ;handled in do_func
  240. leal ETEMP(%a6),%a0 |point a0 to sop - used in mk_norm
  241. bsr mk_norm |go normalize - mk_norm returns:
  242. | ;L_SCR1{7:5} = operand tag
  243. | ; (000 = norm, 100 = denorm)
  244. | ;L_SCR1{4} = fpte15 or ete15
  245. | ; 0 = exp > $3fff
  246. | ; 1 = exp <= $3fff
  247. | ;and puts the normalized num back
  248. | ;on the fsave stack
  249. |
  250. moveb L_SCR1(%a6),STAG(%a6) |write the new tag & ete15
  251. rts |end_getop
  252. |
  253. | At this point, only single or double denorms are possible.
  254. | If the inst is not fmove, normalize the source. If it is,
  255. | do nothing to the input.
  256. |
  257. src_sd_dnrm:
  258. btstb #4,CMDREG1B(%a6) |differentiate between sgl/dbl denorm
  259. bnes is_double
  260. is_single:
  261. movew #0x3f81,%d1 |write bias for sgl denorm
  262. bras common |goto the common code
  263. is_double:
  264. movew #0x3c01,%d1 |write the bias for a dbl denorm
  265. common:
  266. btstb #sign_bit,ETEMP_EX(%a6) |grab sign bit of mantissa
  267. beqs pos
  268. bset #15,%d1 |set sign bit because it is negative
  269. pos:
  270. movew %d1,ETEMP_EX(%a6)
  271. | ;put exponent on stack
  272. movew CMDREG1B(%a6),%d1
  273. andw #0xe3ff,%d1 |clear out source specifier
  274. orw #0x0800,%d1 |set source specifier to extended prec
  275. movew %d1,CMDREG1B(%a6) |write back to the command word in stack
  276. | ;this is needed to fix unsupp data stack
  277. leal ETEMP(%a6),%a0 |point a0 to sop
  278. bsr mk_norm |convert sgl/dbl denorm to norm
  279. moveb L_SCR1(%a6),STAG(%a6) |put tag into source tag reg - d0
  280. rts |end_getop
  281. |
  282. | At this point, the source is definitely packed, whether
  283. | instruction is dyadic or monadic is still unknown
  284. |
  285. pack_source:
  286. movel FPTEMP_LO(%a6),ETEMP(%a6) |write ms part of packed
  287. | ;number to etemp slot
  288. bsr chk_dy_mo |set dyadic/monadic flag
  289. bsr unpack
  290. tstb DY_MO_FLG(%a6)
  291. beqs end_getop |if monadic, exit
  292. | ;else, fix FPTEMP
  293. pack_dya:
  294. bfextu CMDREG1B(%a6){#6:#3},%d0 |extract dest fp reg
  295. movel #7,%d1
  296. subl %d0,%d1
  297. clrl %d0
  298. bsetl %d1,%d0 |set up d0 as a dynamic register mask
  299. fmovemx %d0,FPTEMP(%a6) |write to FPTEMP
  300. btstb #7,DTAG(%a6) |check dest tag for unnorm or denorm
  301. bne dst_ex_dnrm |else, handle the unnorm or ext denorm
  302. |
  303. | Dest is not denormalized. Check for norm, and set fpte15
  304. | accordingly.
  305. |
  306. moveb DTAG(%a6),%d0
  307. andib #0xf0,%d0 |strip to only dtag:fpte15
  308. tstb %d0 |check for normalized value
  309. bnes end_getop |if inf/nan/zero leave get_op
  310. movew FPTEMP_EX(%a6),%d0
  311. andiw #0x7fff,%d0
  312. cmpiw #0x3fff,%d0 |check if fpte15 needs setting
  313. bges end_getop |if >= $3fff, leave fpte15=0
  314. orb #0x10,DTAG(%a6)
  315. bras end_getop
  316. |
  317. | At this point, it is either an fmoveout packed, unnorm or denorm
  318. |
  319. opclass3:
  320. clrb DY_MO_FLG(%a6) |set dyadic/monadic flag to monadic
  321. bfextu CMDREG1B(%a6){#4:#2},%d0
  322. cmpib #3,%d0
  323. bne src_ex_dnrm |if not equal, must be unnorm or denorm
  324. | ;else it is a packed move out
  325. | ;exit
  326. end_getop:
  327. rts
  328. |
  329. | Sets the DY_MO_FLG correctly. This is used only on if it is an
  330. | unsupported data type exception. Set if dyadic.
  331. |
  332. chk_dy_mo:
  333. movew CMDREG1B(%a6),%d0
  334. btstl #5,%d0 |testing extension command word
  335. beqs set_mon |if bit 5 = 0 then monadic
  336. btstl #4,%d0 |know that bit 5 = 1
  337. beqs set_dya |if bit 4 = 0 then dyadic
  338. andiw #0x007f,%d0 |get rid of all but extension bits {6:0}
  339. cmpiw #0x0038,%d0 |if extension = $38 then fcmp (dyadic)
  340. bnes set_mon
  341. set_dya:
  342. st DY_MO_FLG(%a6) |set the inst flag type to dyadic
  343. rts
  344. set_mon:
  345. clrb DY_MO_FLG(%a6) |set the inst flag type to monadic
  346. rts
  347. |
  348. | MK_NORM
  349. |
  350. | Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl
  351. | exception if denorm.
  352. |
  353. | CASE opclass 0x0 unsupp
  354. | mk_norm till msb set
  355. | set tag = norm
  356. |
  357. | CASE opclass 0x0 unimp
  358. | mk_norm till msb set or exp = 0
  359. | if integer bit = 0
  360. | tag = denorm
  361. | else
  362. | tag = norm
  363. |
  364. | CASE opclass 011 unsupp
  365. | mk_norm till msb set or exp = 0
  366. | if integer bit = 0
  367. | tag = denorm
  368. | set unfl_nmcexe = 1
  369. | else
  370. | tag = norm
  371. |
  372. | if exp <= $3fff
  373. | set ete15 or fpte15 = 1
  374. | else set ete15 or fpte15 = 0
  375. | input:
  376. | a0 = points to operand to be normalized
  377. | output:
  378. | L_SCR1{7:5} = operand tag (000 = norm, 100 = denorm)
  379. | L_SCR1{4} = fpte15 or ete15 (0 = exp > $3fff, 1 = exp <=$3fff)
  380. | the normalized operand is placed back on the fsave stack
  381. mk_norm:
  382. clrl L_SCR1(%a6)
  383. bclrb #sign_bit,LOCAL_EX(%a0)
  384. sne LOCAL_SGN(%a0) |transform into internal extended format
  385. cmpib #0x2c,1+EXC_VEC(%a6) |check if unimp
  386. bnes uns_data |branch if unsupp
  387. bsr uni_inst |call if unimp (opclass 0x0)
  388. bras reload
  389. uns_data:
  390. btstb #direction_bit,CMDREG1B(%a6) |check transfer direction
  391. bnes bit_set |branch if set (opclass 011)
  392. bsr uns_opx |call if opclass 0x0
  393. bras reload
  394. bit_set:
  395. bsr uns_op3 |opclass 011
  396. reload:
  397. cmpw #0x3fff,LOCAL_EX(%a0) |if exp > $3fff
  398. bgts end_mk | fpte15/ete15 already set to 0
  399. bsetb #4,L_SCR1(%a6) |else set fpte15/ete15 to 1
  400. | ;calling routine actually sets the
  401. | ;value on the stack (along with the
  402. | ;tag), since this routine doesn't
  403. | ;know if it should set ete15 or fpte15
  404. | ;ie, it doesn't know if this is the
  405. | ;src op or dest op.
  406. end_mk:
  407. bfclr LOCAL_SGN(%a0){#0:#8}
  408. beqs end_mk_pos
  409. bsetb #sign_bit,LOCAL_EX(%a0) |convert back to IEEE format
  410. end_mk_pos:
  411. rts
  412. |
  413. | CASE opclass 011 unsupp
  414. |
  415. uns_op3:
  416. bsr nrm_zero |normalize till msb = 1 or exp = zero
  417. btstb #7,LOCAL_HI(%a0) |if msb = 1
  418. bnes no_unfl |then branch
  419. set_unfl:
  420. orw #dnrm_tag,L_SCR1(%a6) |set denorm tag
  421. bsetb #unfl_bit,FPSR_EXCEPT(%a6) |set unfl exception bit
  422. no_unfl:
  423. rts
  424. |
  425. | CASE opclass 0x0 unsupp
  426. |
  427. uns_opx:
  428. bsr nrm_zero |normalize the number
  429. btstb #7,LOCAL_HI(%a0) |check if integer bit (j-bit) is set
  430. beqs uns_den |if clear then now have a denorm
  431. uns_nrm:
  432. orb #norm_tag,L_SCR1(%a6) |set tag to norm
  433. rts
  434. uns_den:
  435. orb #dnrm_tag,L_SCR1(%a6) |set tag to denorm
  436. rts
  437. |
  438. | CASE opclass 0x0 unimp
  439. |
  440. uni_inst:
  441. bsr nrm_zero
  442. btstb #7,LOCAL_HI(%a0) |check if integer bit (j-bit) is set
  443. beqs uni_den |if clear then now have a denorm
  444. uni_nrm:
  445. orb #norm_tag,L_SCR1(%a6) |set tag to norm
  446. rts
  447. uni_den:
  448. orb #dnrm_tag,L_SCR1(%a6) |set tag to denorm
  449. rts
  450. |
  451. | Decimal to binary conversion
  452. |
  453. | Special cases of inf and NaNs are completed outside of decbin.
  454. | If the input is an snan, the snan bit is not set.
  455. |
  456. | input:
  457. | ETEMP(a6) - points to packed decimal string in memory
  458. | output:
  459. | fp0 - contains packed string converted to extended precision
  460. | ETEMP - same as fp0
  461. unpack:
  462. movew CMDREG1B(%a6),%d0 |examine command word, looking for fmove's
  463. andw #0x3b,%d0
  464. beq move_unpack |special handling for fmove: must set FPSR_CC
  465. movew ETEMP(%a6),%d0 |get word with inf information
  466. bfextu %d0{#20:#12},%d1 |get exponent into d1
  467. cmpiw #0x0fff,%d1 |test for inf or NaN
  468. bnes try_zero |if not equal, it is not special
  469. bfextu %d0{#17:#3},%d1 |get SE and y bits into d1
  470. cmpiw #7,%d1 |SE and y bits must be on for special
  471. bnes try_zero |if not on, it is not special
  472. |input is of the special cases of inf and NaN
  473. tstl ETEMP_HI(%a6) |check ms mantissa
  474. bnes fix_nan |if non-zero, it is a NaN
  475. tstl ETEMP_LO(%a6) |check ls mantissa
  476. bnes fix_nan |if non-zero, it is a NaN
  477. bra finish |special already on stack
  478. fix_nan:
  479. btstb #signan_bit,ETEMP_HI(%a6) |test for snan
  480. bne finish
  481. orl #snaniop_mask,USER_FPSR(%a6) |always set snan if it is so
  482. bra finish
  483. try_zero:
  484. movew ETEMP_EX+2(%a6),%d0 |get word 4
  485. andiw #0x000f,%d0 |clear all but last ni(y)bble
  486. tstw %d0 |check for zero.
  487. bne not_spec
  488. tstl ETEMP_HI(%a6) |check words 3 and 2
  489. bne not_spec
  490. tstl ETEMP_LO(%a6) |check words 1 and 0
  491. bne not_spec
  492. tstl ETEMP(%a6) |test sign of the zero
  493. bges pos_zero
  494. movel #0x80000000,ETEMP(%a6) |write neg zero to etemp
  495. clrl ETEMP_HI(%a6)
  496. clrl ETEMP_LO(%a6)
  497. bra finish
  498. pos_zero:
  499. clrl ETEMP(%a6)
  500. clrl ETEMP_HI(%a6)
  501. clrl ETEMP_LO(%a6)
  502. bra finish
  503. not_spec:
  504. fmovemx %fp0-%fp1,-(%a7) |save fp0 - decbin returns in it
  505. bsr decbin
  506. fmovex %fp0,ETEMP(%a6) |put the unpacked sop in the fsave stack
  507. fmovemx (%a7)+,%fp0-%fp1
  508. fmovel #0,%FPSR |clr fpsr from decbin
  509. bra finish
  510. |
  511. | Special handling for packed move in: Same results as all other
  512. | packed cases, but we must set the FPSR condition codes properly.
  513. |
  514. move_unpack:
  515. movew ETEMP(%a6),%d0 |get word with inf information
  516. bfextu %d0{#20:#12},%d1 |get exponent into d1
  517. cmpiw #0x0fff,%d1 |test for inf or NaN
  518. bnes mtry_zero |if not equal, it is not special
  519. bfextu %d0{#17:#3},%d1 |get SE and y bits into d1
  520. cmpiw #7,%d1 |SE and y bits must be on for special
  521. bnes mtry_zero |if not on, it is not special
  522. |input is of the special cases of inf and NaN
  523. tstl ETEMP_HI(%a6) |check ms mantissa
  524. bnes mfix_nan |if non-zero, it is a NaN
  525. tstl ETEMP_LO(%a6) |check ls mantissa
  526. bnes mfix_nan |if non-zero, it is a NaN
  527. |input is inf
  528. orl #inf_mask,USER_FPSR(%a6) |set I bit
  529. tstl ETEMP(%a6) |check sign
  530. bge finish
  531. orl #neg_mask,USER_FPSR(%a6) |set N bit
  532. bra finish |special already on stack
  533. mfix_nan:
  534. orl #nan_mask,USER_FPSR(%a6) |set NaN bit
  535. moveb #nan_tag,STAG(%a6) |set stag to NaN
  536. btstb #signan_bit,ETEMP_HI(%a6) |test for snan
  537. bnes mn_snan
  538. orl #snaniop_mask,USER_FPSR(%a6) |set snan bit
  539. btstb #snan_bit,FPCR_ENABLE(%a6) |test for snan enabled
  540. bnes mn_snan
  541. bsetb #signan_bit,ETEMP_HI(%a6) |force snans to qnans
  542. mn_snan:
  543. tstl ETEMP(%a6) |check for sign
  544. bge finish |if clr, go on
  545. orl #neg_mask,USER_FPSR(%a6) |set N bit
  546. bra finish
  547. mtry_zero:
  548. movew ETEMP_EX+2(%a6),%d0 |get word 4
  549. andiw #0x000f,%d0 |clear all but last ni(y)bble
  550. tstw %d0 |check for zero.
  551. bnes mnot_spec
  552. tstl ETEMP_HI(%a6) |check words 3 and 2
  553. bnes mnot_spec
  554. tstl ETEMP_LO(%a6) |check words 1 and 0
  555. bnes mnot_spec
  556. tstl ETEMP(%a6) |test sign of the zero
  557. bges mpos_zero
  558. orl #neg_mask+z_mask,USER_FPSR(%a6) |set N and Z
  559. movel #0x80000000,ETEMP(%a6) |write neg zero to etemp
  560. clrl ETEMP_HI(%a6)
  561. clrl ETEMP_LO(%a6)
  562. bras finish
  563. mpos_zero:
  564. orl #z_mask,USER_FPSR(%a6) |set Z
  565. clrl ETEMP(%a6)
  566. clrl ETEMP_HI(%a6)
  567. clrl ETEMP_LO(%a6)
  568. bras finish
  569. mnot_spec:
  570. fmovemx %fp0-%fp1,-(%a7) |save fp0 ,fp1 - decbin returns in fp0
  571. bsr decbin
  572. fmovex %fp0,ETEMP(%a6)
  573. | ;put the unpacked sop in the fsave stack
  574. fmovemx (%a7)+,%fp0-%fp1
  575. finish:
  576. movew CMDREG1B(%a6),%d0 |get the command word
  577. andw #0xfbff,%d0 |change the source specifier field to
  578. | ;extended (was packed).
  579. movew %d0,CMDREG1B(%a6) |write command word back to fsave stack
  580. | ;we need to do this so the 040 will
  581. | ;re-execute the inst. without taking
  582. | ;another packed trap.
  583. fix_stag:
  584. |Converted result is now in etemp on fsave stack, now set the source
  585. |tag (stag)
  586. | if (ete =$7fff) then INF or NAN
  587. | if (etemp = $x.0----0) then
  588. | stag = INF
  589. | else
  590. | stag = NAN
  591. | else
  592. | if (ete = $0000) then
  593. | stag = ZERO
  594. | else
  595. | stag = NORM
  596. |
  597. | Note also that the etemp_15 bit (just right of the stag) must
  598. | be set accordingly.
  599. |
  600. movew ETEMP_EX(%a6),%d1
  601. andiw #0x7fff,%d1 |strip sign
  602. cmpw #0x7fff,%d1
  603. bnes z_or_nrm
  604. movel ETEMP_HI(%a6),%d1
  605. bnes is_nan
  606. movel ETEMP_LO(%a6),%d1
  607. bnes is_nan
  608. is_inf:
  609. moveb #0x40,STAG(%a6)
  610. movel #0x40,%d0
  611. rts
  612. is_nan:
  613. moveb #0x60,STAG(%a6)
  614. movel #0x60,%d0
  615. rts
  616. z_or_nrm:
  617. tstw %d1
  618. bnes is_nrm
  619. is_zro:
  620. | For a zero, set etemp_15
  621. moveb #0x30,STAG(%a6)
  622. movel #0x20,%d0
  623. rts
  624. is_nrm:
  625. | For a norm, check if the exp <= $3fff; if so, set etemp_15
  626. cmpiw #0x3fff,%d1
  627. bles set_bit15
  628. moveb #0,STAG(%a6)
  629. bras end_is_nrm
  630. set_bit15:
  631. moveb #0x10,STAG(%a6)
  632. end_is_nrm:
  633. movel #0,%d0
  634. end_fix:
  635. rts
  636. end_get:
  637. rts
  638. |end