do_func.S
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:14k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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