do_func.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. |
  2. | do_func.sa 3.4 2/18/91
  3. |
  4. | Do_func performs the unimplemented operation. The operation
  5. | to be performed is determined from the lower 7 bits of the
  6. | extension word (except in the case of fmovecr and fsincos).
  7. | The opcode and tag bits form an index into a jump table in
  8. | tbldo.sa. Cases of zero, infinity and NaN are handled in
  9. | do_func by forcing the default result. Normalized and
  10. | denormalized (there are no unnormalized numbers at this
  11. | point) are passed onto the emulation code.
  12. |
  13. | CMDREG1B and STAG are extracted from the fsave frame
  14. | and combined to form the table index. The function called
  15. | will start with a0 pointing to the ETEMP operand. Dyadic
  16. | functions can find FPTEMP at -12(a0).
  17. |
  18. | Called functions return their result in fp0. Sincos returns
  19. | sin(x) in fp0 and cos(x) in fp1.
  20. |
  21. | Copyright (C) Motorola, Inc. 1990
  22. | All Rights Reserved
  23. |
  24. | For details on the license for this file, please see the
  25. | file, README, in this same directory.
  26. DO_FUNC: |idnt 2,1 | Motorola 040 Floating Point Software Package
  27. |section 8
  28. #include "fpsp.h"
  29. |xref t_dz2
  30. |xref t_operr
  31. |xref t_inx2
  32. |xref t_resdnrm
  33. |xref dst_nan
  34. |xref src_nan
  35. |xref nrm_set
  36. |xref sto_cos
  37. |xref tblpre
  38. |xref slognp1,slogn,slog10,slog2
  39. |xref slognd,slog10d,slog2d
  40. |xref smod,srem
  41. |xref sscale
  42. |xref smovcr
  43. PONE: .long 0x3fff0000,0x80000000,0x00000000 |+1
  44. MONE: .long 0xbfff0000,0x80000000,0x00000000 |-1
  45. PZERO: .long 0x00000000,0x00000000,0x00000000 |+0
  46. MZERO: .long 0x80000000,0x00000000,0x00000000 |-0
  47. PINF: .long 0x7fff0000,0x00000000,0x00000000 |+inf
  48. MINF: .long 0xffff0000,0x00000000,0x00000000 |-inf
  49. QNAN: .long 0x7fff0000,0xffffffff,0xffffffff |non-signaling nan
  50. PPIBY2: .long 0x3FFF0000,0xC90FDAA2,0x2168C235 |+PI/2
  51. MPIBY2: .long 0xbFFF0000,0xC90FDAA2,0x2168C235 |-PI/2
  52. .global do_func
  53. do_func:
  54. clrb CU_ONLY(%a6)
  55. |
  56. | Check for fmovecr. It does not follow the format of fp gen
  57. | unimplemented instructions. The test is on the upper 6 bits;
  58. | if they are $17, the inst is fmovecr. Call entry smovcr
  59. | directly.
  60. |
  61. bfextu CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
  62. cmpil #0x17,%d0 |if op class and size fields are $17,
  63. | ;it is FMOVECR; if not, continue
  64. bnes not_fmovecr
  65. jmp smovcr |fmovecr; jmp directly to emulation
  66. not_fmovecr:
  67. movew CMDREG1B(%a6),%d0
  68. andl #0x7F,%d0
  69. cmpil #0x38,%d0 |if the extension is >= $38,
  70. bge serror |it is illegal
  71. bfextu STAG(%a6){#0:#3},%d1
  72. lsll #3,%d0 |make room for STAG
  73. addl %d1,%d0 |combine for final index into table
  74. leal tblpre,%a1 |start of monster jump table
  75. movel (%a1,%d0.w*4),%a1 |real target address
  76. leal ETEMP(%a6),%a0 |a0 is pointer to src op
  77. movel USER_FPCR(%a6),%d1
  78. andl #0xFF,%d1 | discard all but rounding mode/prec
  79. fmovel #0,%fpcr
  80. jmp (%a1)
  81. |
  82. | ERROR
  83. |
  84. .global serror
  85. serror:
  86. st STORE_FLG(%a6)
  87. rts
  88. |
  89. | These routines load forced values into fp0. They are called
  90. | by index into tbldo.
  91. |
  92. | Load a signed zero to fp0 and set inex2/ainex
  93. |
  94. .global snzrinx
  95. snzrinx:
  96. btstb #sign_bit,LOCAL_EX(%a0) |get sign of source operand
  97. bnes ld_mzinx |if negative, branch
  98. bsr ld_pzero |bsr so we can return and set inx
  99. bra t_inx2 |now, set the inx for the next inst
  100. ld_mzinx:
  101. bsr ld_mzero |if neg, load neg zero, return here
  102. bra t_inx2 |now, set the inx for the next inst
  103. |
  104. | Load a signed zero to fp0; do not set inex2/ainex
  105. |
  106. .global szero
  107. szero:
  108. btstb #sign_bit,LOCAL_EX(%a0) |get sign of source operand
  109. bne ld_mzero |if neg, load neg zero
  110. bra ld_pzero |load positive zero
  111. |
  112. | Load a signed infinity to fp0; do not set inex2/ainex
  113. |
  114. .global sinf
  115. sinf:
  116. btstb #sign_bit,LOCAL_EX(%a0) |get sign of source operand
  117. bne ld_minf |if negative branch
  118. bra ld_pinf
  119. |
  120. | Load a signed one to fp0; do not set inex2/ainex
  121. |
  122. .global sone
  123. sone:
  124. btstb #sign_bit,LOCAL_EX(%a0) |check sign of source
  125. bne ld_mone
  126. bra ld_pone
  127. |
  128. | Load a signed pi/2 to fp0; do not set inex2/ainex
  129. |
  130. .global spi_2
  131. spi_2:
  132. btstb #sign_bit,LOCAL_EX(%a0) |check sign of source
  133. bne ld_mpi2
  134. bra ld_ppi2
  135. |
  136. | Load either a +0 or +inf for plus/minus operand
  137. |
  138. .global szr_inf
  139. szr_inf:
  140. btstb #sign_bit,LOCAL_EX(%a0) |check sign of source
  141. bne ld_pzero
  142. bra ld_pinf
  143. |
  144. | Result is either an operr or +inf for plus/minus operand
  145. | [Used by slogn, slognp1, slog10, and slog2]
  146. |
  147. .global sopr_inf
  148. sopr_inf:
  149. btstb #sign_bit,LOCAL_EX(%a0) |check sign of source
  150. bne t_operr
  151. bra ld_pinf
  152. |
  153. | FLOGNP1
  154. |
  155. .global sslognp1
  156. sslognp1:
  157. fmovemx (%a0),%fp0-%fp0
  158. fcmpb #-1,%fp0
  159. fbgt slognp1
  160. fbeq t_dz2 |if = -1, divide by zero exception
  161. fmovel #0,%FPSR |clr N flag
  162. bra t_operr |take care of operands < -1
  163. |
  164. | FETOXM1
  165. |
  166. .global setoxm1i
  167. setoxm1i:
  168. btstb #sign_bit,LOCAL_EX(%a0) |check sign of source
  169. bne ld_mone
  170. bra ld_pinf
  171. |
  172. | FLOGN
  173. |
  174. | Test for 1.0 as an input argument, returning +zero. Also check
  175. | the sign and return operr if negative.
  176. |
  177. .global sslogn
  178. sslogn:
  179. btstb #sign_bit,LOCAL_EX(%a0)
  180. bne t_operr |take care of operands < 0
  181. cmpiw #0x3fff,LOCAL_EX(%a0) |test for 1.0 input
  182. bne slogn
  183. cmpil #0x80000000,LOCAL_HI(%a0)
  184. bne slogn
  185. tstl LOCAL_LO(%a0)
  186. bne slogn
  187. fmovex PZERO,%fp0
  188. rts
  189. .global sslognd
  190. sslognd:
  191. btstb #sign_bit,LOCAL_EX(%a0)
  192. beq slognd
  193. bra t_operr |take care of operands < 0
  194. |
  195. | FLOG10
  196. |
  197. .global sslog10
  198. sslog10:
  199. btstb #sign_bit,LOCAL_EX(%a0)
  200. bne t_operr |take care of operands < 0
  201. cmpiw #0x3fff,LOCAL_EX(%a0) |test for 1.0 input
  202. bne slog10
  203. cmpil #0x80000000,LOCAL_HI(%a0)
  204. bne slog10
  205. tstl LOCAL_LO(%a0)
  206. bne slog10
  207. fmovex PZERO,%fp0
  208. rts
  209. .global sslog10d
  210. sslog10d:
  211. btstb #sign_bit,LOCAL_EX(%a0)
  212. beq slog10d
  213. bra t_operr |take care of operands < 0
  214. |
  215. | FLOG2
  216. |
  217. .global sslog2
  218. sslog2:
  219. btstb #sign_bit,LOCAL_EX(%a0)
  220. bne t_operr |take care of operands < 0
  221. cmpiw #0x3fff,LOCAL_EX(%a0) |test for 1.0 input
  222. bne slog2
  223. cmpil #0x80000000,LOCAL_HI(%a0)
  224. bne slog2
  225. tstl LOCAL_LO(%a0)
  226. bne slog2
  227. fmovex PZERO,%fp0
  228. rts
  229. .global sslog2d
  230. sslog2d:
  231. btstb #sign_bit,LOCAL_EX(%a0)
  232. beq slog2d
  233. bra t_operr |take care of operands < 0
  234. |
  235. | FMOD
  236. |
  237. pmodt:
  238. | ;$21 fmod
  239. | ;dtag,stag
  240. .long smod | 00,00 norm,norm = normal
  241. .long smod_oper | 00,01 norm,zero = nan with operr
  242. .long smod_fpn | 00,10 norm,inf = fpn
  243. .long smod_snan | 00,11 norm,nan = nan
  244. .long smod_zro | 01,00 zero,norm = +-zero
  245. .long smod_oper | 01,01 zero,zero = nan with operr
  246. .long smod_zro | 01,10 zero,inf = +-zero
  247. .long smod_snan | 01,11 zero,nan = nan
  248. .long smod_oper | 10,00 inf,norm = nan with operr
  249. .long smod_oper | 10,01 inf,zero = nan with operr
  250. .long smod_oper | 10,10 inf,inf = nan with operr
  251. .long smod_snan | 10,11 inf,nan = nan
  252. .long smod_dnan | 11,00 nan,norm = nan
  253. .long smod_dnan | 11,01 nan,zero = nan
  254. .long smod_dnan | 11,10 nan,inf = nan
  255. .long smod_dnan | 11,11 nan,nan = nan
  256. .global pmod
  257. pmod:
  258. clrb FPSR_QBYTE(%a6) | clear quotient field
  259. bfextu STAG(%a6){#0:#3},%d0 |stag = d0
  260. bfextu DTAG(%a6){#0:#3},%d1 |dtag = d1
  261. |
  262. | Alias extended denorms to norms for the jump table.
  263. |
  264. bclrl #2,%d0
  265. bclrl #2,%d1
  266. lslb #2,%d1
  267. orb %d0,%d1 |d1{3:2} = dtag, d1{1:0} = stag
  268. | ;Tag values:
  269. | ;00 = norm or denorm
  270. | ;01 = zero
  271. | ;10 = inf
  272. | ;11 = nan
  273. lea pmodt,%a1
  274. movel (%a1,%d1.w*4),%a1
  275. jmp (%a1)
  276. smod_snan:
  277. bra src_nan
  278. smod_dnan:
  279. bra dst_nan
  280. smod_oper:
  281. bra t_operr
  282. smod_zro:
  283. moveb ETEMP(%a6),%d1 |get sign of src op
  284. moveb FPTEMP(%a6),%d0 |get sign of dst op
  285. eorb %d0,%d1 |get exor of sign bits
  286. btstl #7,%d1 |test for sign
  287. beqs smod_zsn |if clr, do not set sign big
  288. bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
  289. smod_zsn:
  290. btstl #7,%d0 |test if + or -
  291. beq ld_pzero |if pos then load +0
  292. bra ld_mzero |else neg load -0
  293. smod_fpn:
  294. moveb ETEMP(%a6),%d1 |get sign of src op
  295. moveb FPTEMP(%a6),%d0 |get sign of dst op
  296. eorb %d0,%d1 |get exor of sign bits
  297. btstl #7,%d1 |test for sign
  298. beqs smod_fsn |if clr, do not set sign big
  299. bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
  300. smod_fsn:
  301. tstb DTAG(%a6) |filter out denormal destination case
  302. bpls smod_nrm |
  303. leal FPTEMP(%a6),%a0 |a0<- addr(FPTEMP)
  304. bra t_resdnrm |force UNFL(but exact) result
  305. smod_nrm:
  306. fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
  307. fmovex FPTEMP(%a6),%fp0 |return dest to fp0
  308. rts
  309. |
  310. | FREM
  311. |
  312. premt:
  313. | ;$25 frem
  314. | ;dtag,stag
  315. .long srem | 00,00 norm,norm = normal
  316. .long srem_oper | 00,01 norm,zero = nan with operr
  317. .long srem_fpn | 00,10 norm,inf = fpn
  318. .long srem_snan | 00,11 norm,nan = nan
  319. .long srem_zro | 01,00 zero,norm = +-zero
  320. .long srem_oper | 01,01 zero,zero = nan with operr
  321. .long srem_zro | 01,10 zero,inf = +-zero
  322. .long srem_snan | 01,11 zero,nan = nan
  323. .long srem_oper | 10,00 inf,norm = nan with operr
  324. .long srem_oper | 10,01 inf,zero = nan with operr
  325. .long srem_oper | 10,10 inf,inf = nan with operr
  326. .long srem_snan | 10,11 inf,nan = nan
  327. .long srem_dnan | 11,00 nan,norm = nan
  328. .long srem_dnan | 11,01 nan,zero = nan
  329. .long srem_dnan | 11,10 nan,inf = nan
  330. .long srem_dnan | 11,11 nan,nan = nan
  331. .global prem
  332. prem:
  333. clrb FPSR_QBYTE(%a6) |clear quotient field
  334. bfextu STAG(%a6){#0:#3},%d0 |stag = d0
  335. bfextu DTAG(%a6){#0:#3},%d1 |dtag = d1
  336. |
  337. | Alias extended denorms to norms for the jump table.
  338. |
  339. bclr #2,%d0
  340. bclr #2,%d1
  341. lslb #2,%d1
  342. orb %d0,%d1 |d1{3:2} = dtag, d1{1:0} = stag
  343. | ;Tag values:
  344. | ;00 = norm or denorm
  345. | ;01 = zero
  346. | ;10 = inf
  347. | ;11 = nan
  348. lea premt,%a1
  349. movel (%a1,%d1.w*4),%a1
  350. jmp (%a1)
  351. srem_snan:
  352. bra src_nan
  353. srem_dnan:
  354. bra dst_nan
  355. srem_oper:
  356. bra t_operr
  357. srem_zro:
  358. moveb ETEMP(%a6),%d1 |get sign of src op
  359. moveb FPTEMP(%a6),%d0 |get sign of dst op
  360. eorb %d0,%d1 |get exor of sign bits
  361. btstl #7,%d1 |test for sign
  362. beqs srem_zsn |if clr, do not set sign big
  363. bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
  364. srem_zsn:
  365. btstl #7,%d0 |test if + or -
  366. beq ld_pzero |if pos then load +0
  367. bra ld_mzero |else neg load -0
  368. srem_fpn:
  369. moveb ETEMP(%a6),%d1 |get sign of src op
  370. moveb FPTEMP(%a6),%d0 |get sign of dst op
  371. eorb %d0,%d1 |get exor of sign bits
  372. btstl #7,%d1 |test for sign
  373. beqs srem_fsn |if clr, do not set sign big
  374. bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
  375. srem_fsn:
  376. tstb DTAG(%a6) |filter out denormal destination case
  377. bpls srem_nrm |
  378. leal FPTEMP(%a6),%a0 |a0<- addr(FPTEMP)
  379. bra t_resdnrm |force UNFL(but exact) result
  380. srem_nrm:
  381. fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
  382. fmovex FPTEMP(%a6),%fp0 |return dest to fp0
  383. rts
  384. |
  385. | FSCALE
  386. |
  387. pscalet:
  388. | ;$26 fscale
  389. | ;dtag,stag
  390. .long sscale | 00,00 norm,norm = result
  391. .long sscale | 00,01 norm,zero = fpn
  392. .long scl_opr | 00,10 norm,inf = nan with operr
  393. .long scl_snan | 00,11 norm,nan = nan
  394. .long scl_zro | 01,00 zero,norm = +-zero
  395. .long scl_zro | 01,01 zero,zero = +-zero
  396. .long scl_opr | 01,10 zero,inf = nan with operr
  397. .long scl_snan | 01,11 zero,nan = nan
  398. .long scl_inf | 10,00 inf,norm = +-inf
  399. .long scl_inf | 10,01 inf,zero = +-inf
  400. .long scl_opr | 10,10 inf,inf = nan with operr
  401. .long scl_snan | 10,11 inf,nan = nan
  402. .long scl_dnan | 11,00 nan,norm = nan
  403. .long scl_dnan | 11,01 nan,zero = nan
  404. .long scl_dnan | 11,10 nan,inf = nan
  405. .long scl_dnan | 11,11 nan,nan = nan
  406. .global pscale
  407. pscale:
  408. bfextu STAG(%a6){#0:#3},%d0 |stag in d0
  409. bfextu DTAG(%a6){#0:#3},%d1 |dtag in d1
  410. bclrl #2,%d0 |alias denorm into norm
  411. bclrl #2,%d1 |alias denorm into norm
  412. lslb #2,%d1
  413. orb %d0,%d1 |d1{4:2} = dtag, d1{1:0} = stag
  414. | ;dtag values stag values:
  415. | ;000 = norm 00 = norm
  416. | ;001 = zero 01 = zero
  417. | ;010 = inf 10 = inf
  418. | ;011 = nan 11 = nan
  419. | ;100 = dnrm
  420. |
  421. |
  422. leal pscalet,%a1 |load start of jump table
  423. movel (%a1,%d1.w*4),%a1 |load a1 with label depending on tag
  424. jmp (%a1) |go to the routine
  425. scl_opr:
  426. bra t_operr
  427. scl_dnan:
  428. bra dst_nan
  429. scl_zro:
  430. btstb #sign_bit,FPTEMP_EX(%a6) |test if + or -
  431. beq ld_pzero |if pos then load +0
  432. bra ld_mzero |if neg then load -0
  433. scl_inf:
  434. btstb #sign_bit,FPTEMP_EX(%a6) |test if + or -
  435. beq ld_pinf |if pos then load +inf
  436. bra ld_minf |else neg load -inf
  437. scl_snan:
  438. bra src_nan
  439. |
  440. | FSINCOS
  441. |
  442. .global ssincosz
  443. ssincosz:
  444. btstb #sign_bit,ETEMP(%a6) |get sign
  445. beqs sincosp
  446. fmovex MZERO,%fp0
  447. bras sincoscom
  448. sincosp:
  449. fmovex PZERO,%fp0
  450. sincoscom:
  451. fmovemx PONE,%fp1-%fp1 |do not allow FPSR to be affected
  452. bra sto_cos |store cosine result
  453. .global ssincosi
  454. ssincosi:
  455. fmovex QNAN,%fp1 |load NAN
  456. bsr sto_cos |store cosine result
  457. fmovex QNAN,%fp0 |load NAN
  458. bra t_operr
  459. .global ssincosnan
  460. ssincosnan:
  461. movel ETEMP_EX(%a6),FP_SCR1(%a6)
  462. movel ETEMP_HI(%a6),FP_SCR1+4(%a6)
  463. movel ETEMP_LO(%a6),FP_SCR1+8(%a6)
  464. bsetb #signan_bit,FP_SCR1+4(%a6)
  465. fmovemx FP_SCR1(%a6),%fp1-%fp1
  466. bsr sto_cos
  467. bra src_nan
  468. |
  469. | This code forces default values for the zero, inf, and nan cases
  470. | in the transcendentals code. The CC bits must be set in the
  471. | stacked FPSR to be correctly reported.
  472. |
  473. |**Returns +PI/2
  474. .global ld_ppi2
  475. ld_ppi2:
  476. fmovex PPIBY2,%fp0 |load +pi/2
  477. bra t_inx2 |set inex2 exc
  478. |**Returns -PI/2
  479. .global ld_mpi2
  480. ld_mpi2:
  481. fmovex MPIBY2,%fp0 |load -pi/2
  482. orl #neg_mask,USER_FPSR(%a6) |set N bit
  483. bra t_inx2 |set inex2 exc
  484. |**Returns +inf
  485. .global ld_pinf
  486. ld_pinf:
  487. fmovex PINF,%fp0 |load +inf
  488. orl #inf_mask,USER_FPSR(%a6) |set I bit
  489. rts
  490. |**Returns -inf
  491. .global ld_minf
  492. ld_minf:
  493. fmovex MINF,%fp0 |load -inf
  494. orl #neg_mask+inf_mask,USER_FPSR(%a6) |set N and I bits
  495. rts
  496. |**Returns +1
  497. .global ld_pone
  498. ld_pone:
  499. fmovex PONE,%fp0 |load +1
  500. rts
  501. |**Returns -1
  502. .global ld_mone
  503. ld_mone:
  504. fmovex MONE,%fp0 |load -1
  505. orl #neg_mask,USER_FPSR(%a6) |set N bit
  506. rts
  507. |**Returns +0
  508. .global ld_pzero
  509. ld_pzero:
  510. fmovex PZERO,%fp0 |load +0
  511. orl #z_mask,USER_FPSR(%a6) |set Z bit
  512. rts
  513. |**Returns -0
  514. .global ld_mzero
  515. ld_mzero:
  516. fmovex MZERO,%fp0 |load -0
  517. orl #neg_mask+z_mask,USER_FPSR(%a6) |set N and Z bits
  518. rts
  519. |end