util.S 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. |
  2. | util.sa 3.7 7/29/91
  3. |
  4. | This file contains routines used by other programs.
  5. |
  6. | ovf_res: used by overflow to force the correct
  7. | result. ovf_r_k, ovf_r_x2, ovf_r_x3 are
  8. | derivatives of this routine.
  9. | get_fline: get user's opcode word
  10. | g_dfmtou: returns the destination format.
  11. | g_opcls: returns the opclass of the float instruction.
  12. | g_rndpr: returns the rounding precision.
  13. | reg_dest: write byte, word, or long data to Dn
  14. |
  15. |
  16. | Copyright (C) Motorola, Inc. 1990
  17. | All Rights Reserved
  18. |
  19. | For details on the license for this file, please see the
  20. | file, README, in this same directory.
  21. |UTIL idnt 2,1 | Motorola 040 Floating Point Software Package
  22. |section 8
  23. #include "fpsp.h"
  24. |xref mem_read
  25. .global g_dfmtou
  26. .global g_opcls
  27. .global g_rndpr
  28. .global get_fline
  29. .global reg_dest
  30. |
  31. | Final result table for ovf_res. Note that the negative counterparts
  32. | are unnecessary as ovf_res always returns the sign separately from
  33. | the exponent.
  34. | ;+inf
  35. EXT_PINF: .long 0x7fff0000,0x00000000,0x00000000,0x00000000
  36. | ;largest +ext
  37. EXT_PLRG: .long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000
  38. | ;largest magnitude +sgl in ext
  39. SGL_PLRG: .long 0x407e0000,0xffffff00,0x00000000,0x00000000
  40. | ;largest magnitude +dbl in ext
  41. DBL_PLRG: .long 0x43fe0000,0xffffffff,0xfffff800,0x00000000
  42. | ;largest -ext
  43. tblovfl:
  44. .long EXT_RN
  45. .long EXT_RZ
  46. .long EXT_RM
  47. .long EXT_RP
  48. .long SGL_RN
  49. .long SGL_RZ
  50. .long SGL_RM
  51. .long SGL_RP
  52. .long DBL_RN
  53. .long DBL_RZ
  54. .long DBL_RM
  55. .long DBL_RP
  56. .long error
  57. .long error
  58. .long error
  59. .long error
  60. |
  61. | ovf_r_k --- overflow result calculation
  62. |
  63. | This entry point is used by kernel_ex.
  64. |
  65. | This forces the destination precision to be extended
  66. |
  67. | Input: operand in ETEMP
  68. | Output: a result is in ETEMP (internal extended format)
  69. |
  70. .global ovf_r_k
  71. ovf_r_k:
  72. lea ETEMP(%a6),%a0 |a0 points to source operand
  73. bclrb #sign_bit,ETEMP_EX(%a6)
  74. sne ETEMP_SGN(%a6) |convert to internal IEEE format
  75. |
  76. | ovf_r_x2 --- overflow result calculation
  77. |
  78. | This entry point used by x_ovfl. (opclass 0 and 2)
  79. |
  80. | Input a0 points to an operand in the internal extended format
  81. | Output a0 points to the result in the internal extended format
  82. |
  83. | This sets the round precision according to the user's FPCR unless the
  84. | instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul,
  85. | fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg.
  86. | If the instruction is fsgldiv of fsglmul, the rounding precision must be
  87. | extended. If the instruction is not fsgldiv or fsglmul but a force-
  88. | precision instruction, the rounding precision is then set to the force
  89. | precision.
  90. .global ovf_r_x2
  91. ovf_r_x2:
  92. btstb #E3,E_BYTE(%a6) |check for nu exception
  93. beql ovf_e1_exc |it is cu exception
  94. ovf_e3_exc:
  95. movew CMDREG3B(%a6),%d0 |get the command word
  96. andiw #0x00000060,%d0 |clear all bits except 6 and 5
  97. cmpil #0x00000040,%d0
  98. beql ovff_sgl |force precision is single
  99. cmpil #0x00000060,%d0
  100. beql ovff_dbl |force precision is double
  101. movew CMDREG3B(%a6),%d0 |get the command word again
  102. andil #0x7f,%d0 |clear all except operation
  103. cmpil #0x33,%d0
  104. beql ovf_fsgl |fsglmul or fsgldiv
  105. cmpil #0x30,%d0
  106. beql ovf_fsgl
  107. bra ovf_fpcr |instruction is none of the above
  108. | ;use FPCR
  109. ovf_e1_exc:
  110. movew CMDREG1B(%a6),%d0 |get command word
  111. andil #0x00000044,%d0 |clear all bits except 6 and 2
  112. cmpil #0x00000040,%d0
  113. beql ovff_sgl |the instruction is force single
  114. cmpil #0x00000044,%d0
  115. beql ovff_dbl |the instruction is force double
  116. movew CMDREG1B(%a6),%d0 |again get the command word
  117. andil #0x0000007f,%d0 |clear all except the op code
  118. cmpil #0x00000027,%d0
  119. beql ovf_fsgl |fsglmul
  120. cmpil #0x00000024,%d0
  121. beql ovf_fsgl |fsgldiv
  122. bra ovf_fpcr |none of the above, use FPCR
  123. |
  124. |
  125. | Inst is either fsgldiv or fsglmul. Force extended precision.
  126. |
  127. ovf_fsgl:
  128. clrl %d0
  129. bra ovf_res
  130. ovff_sgl:
  131. movel #0x00000001,%d0 |set single
  132. bra ovf_res
  133. ovff_dbl:
  134. movel #0x00000002,%d0 |set double
  135. bra ovf_res
  136. |
  137. | The precision is in the fpcr.
  138. |
  139. ovf_fpcr:
  140. bfextu FPCR_MODE(%a6){#0:#2},%d0 |set round precision
  141. bra ovf_res
  142. |
  143. |
  144. | ovf_r_x3 --- overflow result calculation
  145. |
  146. | This entry point used by x_ovfl. (opclass 3 only)
  147. |
  148. | Input a0 points to an operand in the internal extended format
  149. | Output a0 points to the result in the internal extended format
  150. |
  151. | This sets the round precision according to the destination size.
  152. |
  153. .global ovf_r_x3
  154. ovf_r_x3:
  155. bsr g_dfmtou |get dest fmt in d0{1:0}
  156. | ;for fmovout, the destination format
  157. | ;is the rounding precision
  158. |
  159. | ovf_res --- overflow result calculation
  160. |
  161. | Input:
  162. | a0 points to operand in internal extended format
  163. | Output:
  164. | a0 points to result in internal extended format
  165. |
  166. .global ovf_res
  167. ovf_res:
  168. lsll #2,%d0 |move round precision to d0{3:2}
  169. bfextu FPCR_MODE(%a6){#2:#2},%d1 |set round mode
  170. orl %d1,%d0 |index is fmt:mode in d0{3:0}
  171. leal tblovfl,%a1 |load a1 with table address
  172. movel %a1@(%d0:l:4),%a1 |use d0 as index to the table
  173. jmp (%a1) |go to the correct routine
  174. |
  175. |case DEST_FMT = EXT
  176. |
  177. EXT_RN:
  178. leal EXT_PINF,%a1 |answer is +/- infinity
  179. bsetb #inf_bit,FPSR_CC(%a6)
  180. bra set_sign |now go set the sign
  181. EXT_RZ:
  182. leal EXT_PLRG,%a1 |answer is +/- large number
  183. bra set_sign |now go set the sign
  184. EXT_RM:
  185. tstb LOCAL_SGN(%a0) |if negative overflow
  186. beqs e_rm_pos
  187. e_rm_neg:
  188. leal EXT_PINF,%a1 |answer is negative infinity
  189. orl #neginf_mask,USER_FPSR(%a6)
  190. bra end_ovfr
  191. e_rm_pos:
  192. leal EXT_PLRG,%a1 |answer is large positive number
  193. bra end_ovfr
  194. EXT_RP:
  195. tstb LOCAL_SGN(%a0) |if negative overflow
  196. beqs e_rp_pos
  197. e_rp_neg:
  198. leal EXT_PLRG,%a1 |answer is large negative number
  199. bsetb #neg_bit,FPSR_CC(%a6)
  200. bra end_ovfr
  201. e_rp_pos:
  202. leal EXT_PINF,%a1 |answer is positive infinity
  203. bsetb #inf_bit,FPSR_CC(%a6)
  204. bra end_ovfr
  205. |
  206. |case DEST_FMT = DBL
  207. |
  208. DBL_RN:
  209. leal EXT_PINF,%a1 |answer is +/- infinity
  210. bsetb #inf_bit,FPSR_CC(%a6)
  211. bra set_sign
  212. DBL_RZ:
  213. leal DBL_PLRG,%a1 |answer is +/- large number
  214. bra set_sign |now go set the sign
  215. DBL_RM:
  216. tstb LOCAL_SGN(%a0) |if negative overflow
  217. beqs d_rm_pos
  218. d_rm_neg:
  219. leal EXT_PINF,%a1 |answer is negative infinity
  220. orl #neginf_mask,USER_FPSR(%a6)
  221. bra end_ovfr |inf is same for all precisions (ext,dbl,sgl)
  222. d_rm_pos:
  223. leal DBL_PLRG,%a1 |answer is large positive number
  224. bra end_ovfr
  225. DBL_RP:
  226. tstb LOCAL_SGN(%a0) |if negative overflow
  227. beqs d_rp_pos
  228. d_rp_neg:
  229. leal DBL_PLRG,%a1 |answer is large negative number
  230. bsetb #neg_bit,FPSR_CC(%a6)
  231. bra end_ovfr
  232. d_rp_pos:
  233. leal EXT_PINF,%a1 |answer is positive infinity
  234. bsetb #inf_bit,FPSR_CC(%a6)
  235. bra end_ovfr
  236. |
  237. |case DEST_FMT = SGL
  238. |
  239. SGL_RN:
  240. leal EXT_PINF,%a1 |answer is +/- infinity
  241. bsetb #inf_bit,FPSR_CC(%a6)
  242. bras set_sign
  243. SGL_RZ:
  244. leal SGL_PLRG,%a1 |answer is +/- large number
  245. bras set_sign
  246. SGL_RM:
  247. tstb LOCAL_SGN(%a0) |if negative overflow
  248. beqs s_rm_pos
  249. s_rm_neg:
  250. leal EXT_PINF,%a1 |answer is negative infinity
  251. orl #neginf_mask,USER_FPSR(%a6)
  252. bras end_ovfr
  253. s_rm_pos:
  254. leal SGL_PLRG,%a1 |answer is large positive number
  255. bras end_ovfr
  256. SGL_RP:
  257. tstb LOCAL_SGN(%a0) |if negative overflow
  258. beqs s_rp_pos
  259. s_rp_neg:
  260. leal SGL_PLRG,%a1 |answer is large negative number
  261. bsetb #neg_bit,FPSR_CC(%a6)
  262. bras end_ovfr
  263. s_rp_pos:
  264. leal EXT_PINF,%a1 |answer is positive infinity
  265. bsetb #inf_bit,FPSR_CC(%a6)
  266. bras end_ovfr
  267. set_sign:
  268. tstb LOCAL_SGN(%a0) |if negative overflow
  269. beqs end_ovfr
  270. neg_sign:
  271. bsetb #neg_bit,FPSR_CC(%a6)
  272. end_ovfr:
  273. movew LOCAL_EX(%a1),LOCAL_EX(%a0) |do not overwrite sign
  274. movel LOCAL_HI(%a1),LOCAL_HI(%a0)
  275. movel LOCAL_LO(%a1),LOCAL_LO(%a0)
  276. rts
  277. |
  278. | ERROR
  279. |
  280. error:
  281. rts
  282. |
  283. | get_fline --- get f-line opcode of interrupted instruction
  284. |
  285. | Returns opcode in the low word of d0.
  286. |
  287. get_fline:
  288. movel USER_FPIAR(%a6),%a0 |opcode address
  289. movel #0,-(%a7) |reserve a word on the stack
  290. leal 2(%a7),%a1 |point to low word of temporary
  291. movel #2,%d0 |count
  292. bsrl mem_read
  293. movel (%a7)+,%d0
  294. rts
  295. |
  296. | g_rndpr --- put rounding precision in d0{1:0}
  297. |
  298. | valid return codes are:
  299. | 00 - extended
  300. | 01 - single
  301. | 10 - double
  302. |
  303. | begin
  304. | get rounding precision (cmdreg3b{6:5})
  305. | begin
  306. | case opclass = 011 (move out)
  307. | get destination format - this is the also the rounding precision
  308. |
  309. | case opclass = 0x0
  310. | if E3
  311. | *case RndPr(from cmdreg3b{6:5} = 11 then RND_PREC = DBL
  312. | *case RndPr(from cmdreg3b{6:5} = 10 then RND_PREC = SGL
  313. | case RndPr(from cmdreg3b{6:5} = 00 | 01
  314. | use precision from FPCR{7:6}
  315. | case 00 then RND_PREC = EXT
  316. | case 01 then RND_PREC = SGL
  317. | case 10 then RND_PREC = DBL
  318. | else E1
  319. | use precision in FPCR{7:6}
  320. | case 00 then RND_PREC = EXT
  321. | case 01 then RND_PREC = SGL
  322. | case 10 then RND_PREC = DBL
  323. | end
  324. |
  325. g_rndpr:
  326. bsr g_opcls |get opclass in d0{2:0}
  327. cmpw #0x0003,%d0 |check for opclass 011
  328. bnes op_0x0
  329. |
  330. | For move out instructions (opclass 011) the destination format
  331. | is the same as the rounding precision. Pass results from g_dfmtou.
  332. |
  333. bsr g_dfmtou
  334. rts
  335. op_0x0:
  336. btstb #E3,E_BYTE(%a6)
  337. beql unf_e1_exc |branch to e1 underflow
  338. unf_e3_exc:
  339. movel CMDREG3B(%a6),%d0 |rounding precision in d0{10:9}
  340. bfextu %d0{#9:#2},%d0 |move the rounding prec bits to d0{1:0}
  341. cmpil #0x2,%d0
  342. beql unff_sgl |force precision is single
  343. cmpil #0x3,%d0 |force precision is double
  344. beql unff_dbl
  345. movew CMDREG3B(%a6),%d0 |get the command word again
  346. andil #0x7f,%d0 |clear all except operation
  347. cmpil #0x33,%d0
  348. beql unf_fsgl |fsglmul or fsgldiv
  349. cmpil #0x30,%d0
  350. beql unf_fsgl |fsgldiv or fsglmul
  351. bra unf_fpcr
  352. unf_e1_exc:
  353. movel CMDREG1B(%a6),%d0 |get 32 bits off the stack, 1st 16 bits
  354. | ;are the command word
  355. andil #0x00440000,%d0 |clear all bits except bits 6 and 2
  356. cmpil #0x00400000,%d0
  357. beql unff_sgl |force single
  358. cmpil #0x00440000,%d0 |force double
  359. beql unff_dbl
  360. movel CMDREG1B(%a6),%d0 |get the command word again
  361. andil #0x007f0000,%d0 |clear all bits except the operation
  362. cmpil #0x00270000,%d0
  363. beql unf_fsgl |fsglmul
  364. cmpil #0x00240000,%d0
  365. beql unf_fsgl |fsgldiv
  366. bra unf_fpcr
  367. |
  368. | Convert to return format. The values from cmdreg3b and the return
  369. | values are:
  370. | cmdreg3b return precision
  371. | -------- ------ ---------
  372. | 00,01 0 ext
  373. | 10 1 sgl
  374. | 11 2 dbl
  375. | Force single
  376. |
  377. unff_sgl:
  378. movel #1,%d0 |return 1
  379. rts
  380. |
  381. | Force double
  382. |
  383. unff_dbl:
  384. movel #2,%d0 |return 2
  385. rts
  386. |
  387. | Force extended
  388. |
  389. unf_fsgl:
  390. movel #0,%d0
  391. rts
  392. |
  393. | Get rounding precision set in FPCR{7:6}.
  394. |
  395. unf_fpcr:
  396. movel USER_FPCR(%a6),%d0 |rounding precision bits in d0{7:6}
  397. bfextu %d0{#24:#2},%d0 |move the rounding prec bits to d0{1:0}
  398. rts
  399. |
  400. | g_opcls --- put opclass in d0{2:0}
  401. |
  402. g_opcls:
  403. btstb #E3,E_BYTE(%a6)
  404. beqs opc_1b |if set, go to cmdreg1b
  405. opc_3b:
  406. clrl %d0 |if E3, only opclass 0x0 is possible
  407. rts
  408. opc_1b:
  409. movel CMDREG1B(%a6),%d0
  410. bfextu %d0{#0:#3},%d0 |shift opclass bits d0{31:29} to d0{2:0}
  411. rts
  412. |
  413. | g_dfmtou --- put destination format in d0{1:0}
  414. |
  415. | If E1, the format is from cmdreg1b{12:10}
  416. | If E3, the format is extended.
  417. |
  418. | Dest. Fmt.
  419. | extended 010 -> 00
  420. | single 001 -> 01
  421. | double 101 -> 10
  422. |
  423. g_dfmtou:
  424. btstb #E3,E_BYTE(%a6)
  425. beqs op011
  426. clrl %d0 |if E1, size is always ext
  427. rts
  428. op011:
  429. movel CMDREG1B(%a6),%d0
  430. bfextu %d0{#3:#3},%d0 |dest fmt from cmdreg1b{12:10}
  431. cmpb #1,%d0 |check for single
  432. bnes not_sgl
  433. movel #1,%d0
  434. rts
  435. not_sgl:
  436. cmpb #5,%d0 |check for double
  437. bnes not_dbl
  438. movel #2,%d0
  439. rts
  440. not_dbl:
  441. clrl %d0 |must be extended
  442. rts
  443. |
  444. |
  445. | Final result table for unf_sub. Note that the negative counterparts
  446. | are unnecessary as unf_sub always returns the sign separately from
  447. | the exponent.
  448. | ;+zero
  449. EXT_PZRO: .long 0x00000000,0x00000000,0x00000000,0x00000000
  450. | ;+zero
  451. SGL_PZRO: .long 0x3f810000,0x00000000,0x00000000,0x00000000
  452. | ;+zero
  453. DBL_PZRO: .long 0x3c010000,0x00000000,0x00000000,0x00000000
  454. | ;smallest +ext denorm
  455. EXT_PSML: .long 0x00000000,0x00000000,0x00000001,0x00000000
  456. | ;smallest +sgl denorm
  457. SGL_PSML: .long 0x3f810000,0x00000100,0x00000000,0x00000000
  458. | ;smallest +dbl denorm
  459. DBL_PSML: .long 0x3c010000,0x00000000,0x00000800,0x00000000
  460. |
  461. | UNF_SUB --- underflow result calculation
  462. |
  463. | Input:
  464. | d0 contains round precision
  465. | a0 points to input operand in the internal extended format
  466. |
  467. | Output:
  468. | a0 points to correct internal extended precision result.
  469. |
  470. tblunf:
  471. .long uEXT_RN
  472. .long uEXT_RZ
  473. .long uEXT_RM
  474. .long uEXT_RP
  475. .long uSGL_RN
  476. .long uSGL_RZ
  477. .long uSGL_RM
  478. .long uSGL_RP
  479. .long uDBL_RN
  480. .long uDBL_RZ
  481. .long uDBL_RM
  482. .long uDBL_RP
  483. .long uDBL_RN
  484. .long uDBL_RZ
  485. .long uDBL_RM
  486. .long uDBL_RP
  487. .global unf_sub
  488. unf_sub:
  489. lsll #2,%d0 |move round precision to d0{3:2}
  490. bfextu FPCR_MODE(%a6){#2:#2},%d1 |set round mode
  491. orl %d1,%d0 |index is fmt:mode in d0{3:0}
  492. leal tblunf,%a1 |load a1 with table address
  493. movel %a1@(%d0:l:4),%a1 |use d0 as index to the table
  494. jmp (%a1) |go to the correct routine
  495. |
  496. |case DEST_FMT = EXT
  497. |
  498. uEXT_RN:
  499. leal EXT_PZRO,%a1 |answer is +/- zero
  500. bsetb #z_bit,FPSR_CC(%a6)
  501. bra uset_sign |now go set the sign
  502. uEXT_RZ:
  503. leal EXT_PZRO,%a1 |answer is +/- zero
  504. bsetb #z_bit,FPSR_CC(%a6)
  505. bra uset_sign |now go set the sign
  506. uEXT_RM:
  507. tstb LOCAL_SGN(%a0) |if negative underflow
  508. beqs ue_rm_pos
  509. ue_rm_neg:
  510. leal EXT_PSML,%a1 |answer is negative smallest denorm
  511. bsetb #neg_bit,FPSR_CC(%a6)
  512. bra end_unfr
  513. ue_rm_pos:
  514. leal EXT_PZRO,%a1 |answer is positive zero
  515. bsetb #z_bit,FPSR_CC(%a6)
  516. bra end_unfr
  517. uEXT_RP:
  518. tstb LOCAL_SGN(%a0) |if negative underflow
  519. beqs ue_rp_pos
  520. ue_rp_neg:
  521. leal EXT_PZRO,%a1 |answer is negative zero
  522. oril #negz_mask,USER_FPSR(%a6)
  523. bra end_unfr
  524. ue_rp_pos:
  525. leal EXT_PSML,%a1 |answer is positive smallest denorm
  526. bra end_unfr
  527. |
  528. |case DEST_FMT = DBL
  529. |
  530. uDBL_RN:
  531. leal DBL_PZRO,%a1 |answer is +/- zero
  532. bsetb #z_bit,FPSR_CC(%a6)
  533. bra uset_sign
  534. uDBL_RZ:
  535. leal DBL_PZRO,%a1 |answer is +/- zero
  536. bsetb #z_bit,FPSR_CC(%a6)
  537. bra uset_sign |now go set the sign
  538. uDBL_RM:
  539. tstb LOCAL_SGN(%a0) |if negative overflow
  540. beqs ud_rm_pos
  541. ud_rm_neg:
  542. leal DBL_PSML,%a1 |answer is smallest denormalized negative
  543. bsetb #neg_bit,FPSR_CC(%a6)
  544. bra end_unfr
  545. ud_rm_pos:
  546. leal DBL_PZRO,%a1 |answer is positive zero
  547. bsetb #z_bit,FPSR_CC(%a6)
  548. bra end_unfr
  549. uDBL_RP:
  550. tstb LOCAL_SGN(%a0) |if negative overflow
  551. beqs ud_rp_pos
  552. ud_rp_neg:
  553. leal DBL_PZRO,%a1 |answer is negative zero
  554. oril #negz_mask,USER_FPSR(%a6)
  555. bra end_unfr
  556. ud_rp_pos:
  557. leal DBL_PSML,%a1 |answer is smallest denormalized negative
  558. bra end_unfr
  559. |
  560. |case DEST_FMT = SGL
  561. |
  562. uSGL_RN:
  563. leal SGL_PZRO,%a1 |answer is +/- zero
  564. bsetb #z_bit,FPSR_CC(%a6)
  565. bras uset_sign
  566. uSGL_RZ:
  567. leal SGL_PZRO,%a1 |answer is +/- zero
  568. bsetb #z_bit,FPSR_CC(%a6)
  569. bras uset_sign
  570. uSGL_RM:
  571. tstb LOCAL_SGN(%a0) |if negative overflow
  572. beqs us_rm_pos
  573. us_rm_neg:
  574. leal SGL_PSML,%a1 |answer is smallest denormalized negative
  575. bsetb #neg_bit,FPSR_CC(%a6)
  576. bras end_unfr
  577. us_rm_pos:
  578. leal SGL_PZRO,%a1 |answer is positive zero
  579. bsetb #z_bit,FPSR_CC(%a6)
  580. bras end_unfr
  581. uSGL_RP:
  582. tstb LOCAL_SGN(%a0) |if negative overflow
  583. beqs us_rp_pos
  584. us_rp_neg:
  585. leal SGL_PZRO,%a1 |answer is negative zero
  586. oril #negz_mask,USER_FPSR(%a6)
  587. bras end_unfr
  588. us_rp_pos:
  589. leal SGL_PSML,%a1 |answer is smallest denormalized positive
  590. bras end_unfr
  591. uset_sign:
  592. tstb LOCAL_SGN(%a0) |if negative overflow
  593. beqs end_unfr
  594. uneg_sign:
  595. bsetb #neg_bit,FPSR_CC(%a6)
  596. end_unfr:
  597. movew LOCAL_EX(%a1),LOCAL_EX(%a0) |be careful not to overwrite sign
  598. movel LOCAL_HI(%a1),LOCAL_HI(%a0)
  599. movel LOCAL_LO(%a1),LOCAL_LO(%a0)
  600. rts
  601. |
  602. | reg_dest --- write byte, word, or long data to Dn
  603. |
  604. |
  605. | Input:
  606. | L_SCR1: Data
  607. | d1: data size and dest register number formatted as:
  608. |
  609. | 32 5 4 3 2 1 0
  610. | -----------------------------------------------
  611. | | 0 | Size | Dest Reg # |
  612. | -----------------------------------------------
  613. |
  614. | Size is:
  615. | 0 - Byte
  616. | 1 - Word
  617. | 2 - Long/Single
  618. |
  619. pregdst:
  620. .long byte_d0
  621. .long byte_d1
  622. .long byte_d2
  623. .long byte_d3
  624. .long byte_d4
  625. .long byte_d5
  626. .long byte_d6
  627. .long byte_d7
  628. .long word_d0
  629. .long word_d1
  630. .long word_d2
  631. .long word_d3
  632. .long word_d4
  633. .long word_d5
  634. .long word_d6
  635. .long word_d7
  636. .long long_d0
  637. .long long_d1
  638. .long long_d2
  639. .long long_d3
  640. .long long_d4
  641. .long long_d5
  642. .long long_d6
  643. .long long_d7
  644. reg_dest:
  645. leal pregdst,%a0
  646. movel %a0@(%d1:l:4),%a0
  647. jmp (%a0)
  648. byte_d0:
  649. moveb L_SCR1(%a6),USER_D0+3(%a6)
  650. rts
  651. byte_d1:
  652. moveb L_SCR1(%a6),USER_D1+3(%a6)
  653. rts
  654. byte_d2:
  655. moveb L_SCR1(%a6),%d2
  656. rts
  657. byte_d3:
  658. moveb L_SCR1(%a6),%d3
  659. rts
  660. byte_d4:
  661. moveb L_SCR1(%a6),%d4
  662. rts
  663. byte_d5:
  664. moveb L_SCR1(%a6),%d5
  665. rts
  666. byte_d6:
  667. moveb L_SCR1(%a6),%d6
  668. rts
  669. byte_d7:
  670. moveb L_SCR1(%a6),%d7
  671. rts
  672. word_d0:
  673. movew L_SCR1(%a6),USER_D0+2(%a6)
  674. rts
  675. word_d1:
  676. movew L_SCR1(%a6),USER_D1+2(%a6)
  677. rts
  678. word_d2:
  679. movew L_SCR1(%a6),%d2
  680. rts
  681. word_d3:
  682. movew L_SCR1(%a6),%d3
  683. rts
  684. word_d4:
  685. movew L_SCR1(%a6),%d4
  686. rts
  687. word_d5:
  688. movew L_SCR1(%a6),%d5
  689. rts
  690. word_d6:
  691. movew L_SCR1(%a6),%d6
  692. rts
  693. word_d7:
  694. movew L_SCR1(%a6),%d7
  695. rts
  696. long_d0:
  697. movel L_SCR1(%a6),USER_D0(%a6)
  698. rts
  699. long_d1:
  700. movel L_SCR1(%a6),USER_D1(%a6)
  701. rts
  702. long_d2:
  703. movel L_SCR1(%a6),%d2
  704. rts
  705. long_d3:
  706. movel L_SCR1(%a6),%d3
  707. rts
  708. long_d4:
  709. movel L_SCR1(%a6),%d4
  710. rts
  711. long_d5:
  712. movel L_SCR1(%a6),%d5
  713. rts
  714. long_d6:
  715. movel L_SCR1(%a6),%d6
  716. rts
  717. long_d7:
  718. movel L_SCR1(%a6),%d7
  719. rts
  720. |end