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