util.s
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:19k
源码类别:

VxWorks

开发平台:

C/C++

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