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