162306a36Sopenharmony_ci| 262306a36Sopenharmony_ci| do_func.sa 3.4 2/18/91 362306a36Sopenharmony_ci| 462306a36Sopenharmony_ci| Do_func performs the unimplemented operation. The operation 562306a36Sopenharmony_ci| to be performed is determined from the lower 7 bits of the 662306a36Sopenharmony_ci| extension word (except in the case of fmovecr and fsincos). 762306a36Sopenharmony_ci| The opcode and tag bits form an index into a jump table in 862306a36Sopenharmony_ci| tbldo.sa. Cases of zero, infinity and NaN are handled in 962306a36Sopenharmony_ci| do_func by forcing the default result. Normalized and 1062306a36Sopenharmony_ci| denormalized (there are no unnormalized numbers at this 1162306a36Sopenharmony_ci| point) are passed onto the emulation code. 1262306a36Sopenharmony_ci| 1362306a36Sopenharmony_ci| CMDREG1B and STAG are extracted from the fsave frame 1462306a36Sopenharmony_ci| and combined to form the table index. The function called 1562306a36Sopenharmony_ci| will start with a0 pointing to the ETEMP operand. Dyadic 1662306a36Sopenharmony_ci| functions can find FPTEMP at -12(a0). 1762306a36Sopenharmony_ci| 1862306a36Sopenharmony_ci| Called functions return their result in fp0. Sincos returns 1962306a36Sopenharmony_ci| sin(x) in fp0 and cos(x) in fp1. 2062306a36Sopenharmony_ci| 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 2362306a36Sopenharmony_ci| All Rights Reserved 2462306a36Sopenharmony_ci| 2562306a36Sopenharmony_ci| For details on the license for this file, please see the 2662306a36Sopenharmony_ci| file, README, in this same directory. 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ciDO_FUNC: |idnt 2,1 | Motorola 040 Floating Point Software Package 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci |section 8 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#include "fpsp.h" 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci |xref t_dz2 3562306a36Sopenharmony_ci |xref t_operr 3662306a36Sopenharmony_ci |xref t_inx2 3762306a36Sopenharmony_ci |xref t_resdnrm 3862306a36Sopenharmony_ci |xref dst_nan 3962306a36Sopenharmony_ci |xref src_nan 4062306a36Sopenharmony_ci |xref nrm_set 4162306a36Sopenharmony_ci |xref sto_cos 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci |xref tblpre 4462306a36Sopenharmony_ci |xref slognp1,slogn,slog10,slog2 4562306a36Sopenharmony_ci |xref slognd,slog10d,slog2d 4662306a36Sopenharmony_ci |xref smod,srem 4762306a36Sopenharmony_ci |xref sscale 4862306a36Sopenharmony_ci |xref smovcr 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciPONE: .long 0x3fff0000,0x80000000,0x00000000 |+1 5162306a36Sopenharmony_ciMONE: .long 0xbfff0000,0x80000000,0x00000000 |-1 5262306a36Sopenharmony_ciPZERO: .long 0x00000000,0x00000000,0x00000000 |+0 5362306a36Sopenharmony_ciMZERO: .long 0x80000000,0x00000000,0x00000000 |-0 5462306a36Sopenharmony_ciPINF: .long 0x7fff0000,0x00000000,0x00000000 |+inf 5562306a36Sopenharmony_ciMINF: .long 0xffff0000,0x00000000,0x00000000 |-inf 5662306a36Sopenharmony_ciQNAN: .long 0x7fff0000,0xffffffff,0xffffffff |non-signaling nan 5762306a36Sopenharmony_ciPPIBY2: .long 0x3FFF0000,0xC90FDAA2,0x2168C235 |+PI/2 5862306a36Sopenharmony_ciMPIBY2: .long 0xbFFF0000,0xC90FDAA2,0x2168C235 |-PI/2 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci .global do_func 6162306a36Sopenharmony_cido_func: 6262306a36Sopenharmony_ci clrb CU_ONLY(%a6) 6362306a36Sopenharmony_ci| 6462306a36Sopenharmony_ci| Check for fmovecr. It does not follow the format of fp gen 6562306a36Sopenharmony_ci| unimplemented instructions. The test is on the upper 6 bits; 6662306a36Sopenharmony_ci| if they are $17, the inst is fmovecr. Call entry smovcr 6762306a36Sopenharmony_ci| directly. 6862306a36Sopenharmony_ci| 6962306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields 7062306a36Sopenharmony_ci cmpil #0x17,%d0 |if op class and size fields are $17, 7162306a36Sopenharmony_ci| ;it is FMOVECR; if not, continue 7262306a36Sopenharmony_ci bnes not_fmovecr 7362306a36Sopenharmony_ci jmp smovcr |fmovecr; jmp directly to emulation 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cinot_fmovecr: 7662306a36Sopenharmony_ci movew CMDREG1B(%a6),%d0 7762306a36Sopenharmony_ci andl #0x7F,%d0 7862306a36Sopenharmony_ci cmpil #0x38,%d0 |if the extension is >= $38, 7962306a36Sopenharmony_ci bge serror |it is illegal 8062306a36Sopenharmony_ci bfextu STAG(%a6){#0:#3},%d1 8162306a36Sopenharmony_ci lsll #3,%d0 |make room for STAG 8262306a36Sopenharmony_ci addl %d1,%d0 |combine for final index into table 8362306a36Sopenharmony_ci leal tblpre,%a1 |start of monster jump table 8462306a36Sopenharmony_ci movel (%a1,%d0.w*4),%a1 |real target address 8562306a36Sopenharmony_ci leal ETEMP(%a6),%a0 |a0 is pointer to src op 8662306a36Sopenharmony_ci movel USER_FPCR(%a6),%d1 8762306a36Sopenharmony_ci andl #0xFF,%d1 | discard all but rounding mode/prec 8862306a36Sopenharmony_ci fmovel #0,%fpcr 8962306a36Sopenharmony_ci jmp (%a1) 9062306a36Sopenharmony_ci| 9162306a36Sopenharmony_ci| ERROR 9262306a36Sopenharmony_ci| 9362306a36Sopenharmony_ci .global serror 9462306a36Sopenharmony_ciserror: 9562306a36Sopenharmony_ci st STORE_FLG(%a6) 9662306a36Sopenharmony_ci rts 9762306a36Sopenharmony_ci| 9862306a36Sopenharmony_ci| These routines load forced values into fp0. They are called 9962306a36Sopenharmony_ci| by index into tbldo. 10062306a36Sopenharmony_ci| 10162306a36Sopenharmony_ci| Load a signed zero to fp0 and set inex2/ainex 10262306a36Sopenharmony_ci| 10362306a36Sopenharmony_ci .global snzrinx 10462306a36Sopenharmony_cisnzrinx: 10562306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) |get sign of source operand 10662306a36Sopenharmony_ci bnes ld_mzinx |if negative, branch 10762306a36Sopenharmony_ci bsr ld_pzero |bsr so we can return and set inx 10862306a36Sopenharmony_ci bra t_inx2 |now, set the inx for the next inst 10962306a36Sopenharmony_cild_mzinx: 11062306a36Sopenharmony_ci bsr ld_mzero |if neg, load neg zero, return here 11162306a36Sopenharmony_ci bra t_inx2 |now, set the inx for the next inst 11262306a36Sopenharmony_ci| 11362306a36Sopenharmony_ci| Load a signed zero to fp0; do not set inex2/ainex 11462306a36Sopenharmony_ci| 11562306a36Sopenharmony_ci .global szero 11662306a36Sopenharmony_ciszero: 11762306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) |get sign of source operand 11862306a36Sopenharmony_ci bne ld_mzero |if neg, load neg zero 11962306a36Sopenharmony_ci bra ld_pzero |load positive zero 12062306a36Sopenharmony_ci| 12162306a36Sopenharmony_ci| Load a signed infinity to fp0; do not set inex2/ainex 12262306a36Sopenharmony_ci| 12362306a36Sopenharmony_ci .global sinf 12462306a36Sopenharmony_cisinf: 12562306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) |get sign of source operand 12662306a36Sopenharmony_ci bne ld_minf |if negative branch 12762306a36Sopenharmony_ci bra ld_pinf 12862306a36Sopenharmony_ci| 12962306a36Sopenharmony_ci| Load a signed one to fp0; do not set inex2/ainex 13062306a36Sopenharmony_ci| 13162306a36Sopenharmony_ci .global sone 13262306a36Sopenharmony_cisone: 13362306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) |check sign of source 13462306a36Sopenharmony_ci bne ld_mone 13562306a36Sopenharmony_ci bra ld_pone 13662306a36Sopenharmony_ci| 13762306a36Sopenharmony_ci| Load a signed pi/2 to fp0; do not set inex2/ainex 13862306a36Sopenharmony_ci| 13962306a36Sopenharmony_ci .global spi_2 14062306a36Sopenharmony_cispi_2: 14162306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) |check sign of source 14262306a36Sopenharmony_ci bne ld_mpi2 14362306a36Sopenharmony_ci bra ld_ppi2 14462306a36Sopenharmony_ci| 14562306a36Sopenharmony_ci| Load either a +0 or +inf for plus/minus operand 14662306a36Sopenharmony_ci| 14762306a36Sopenharmony_ci .global szr_inf 14862306a36Sopenharmony_ciszr_inf: 14962306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) |check sign of source 15062306a36Sopenharmony_ci bne ld_pzero 15162306a36Sopenharmony_ci bra ld_pinf 15262306a36Sopenharmony_ci| 15362306a36Sopenharmony_ci| Result is either an operr or +inf for plus/minus operand 15462306a36Sopenharmony_ci| [Used by slogn, slognp1, slog10, and slog2] 15562306a36Sopenharmony_ci| 15662306a36Sopenharmony_ci .global sopr_inf 15762306a36Sopenharmony_cisopr_inf: 15862306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) |check sign of source 15962306a36Sopenharmony_ci bne t_operr 16062306a36Sopenharmony_ci bra ld_pinf 16162306a36Sopenharmony_ci| 16262306a36Sopenharmony_ci| FLOGNP1 16362306a36Sopenharmony_ci| 16462306a36Sopenharmony_ci .global sslognp1 16562306a36Sopenharmony_cisslognp1: 16662306a36Sopenharmony_ci fmovemx (%a0),%fp0-%fp0 16762306a36Sopenharmony_ci fcmpb #-1,%fp0 16862306a36Sopenharmony_ci fbgt slognp1 16962306a36Sopenharmony_ci fbeq t_dz2 |if = -1, divide by zero exception 17062306a36Sopenharmony_ci fmovel #0,%FPSR |clr N flag 17162306a36Sopenharmony_ci bra t_operr |take care of operands < -1 17262306a36Sopenharmony_ci| 17362306a36Sopenharmony_ci| FETOXM1 17462306a36Sopenharmony_ci| 17562306a36Sopenharmony_ci .global setoxm1i 17662306a36Sopenharmony_cisetoxm1i: 17762306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) |check sign of source 17862306a36Sopenharmony_ci bne ld_mone 17962306a36Sopenharmony_ci bra ld_pinf 18062306a36Sopenharmony_ci| 18162306a36Sopenharmony_ci| FLOGN 18262306a36Sopenharmony_ci| 18362306a36Sopenharmony_ci| Test for 1.0 as an input argument, returning +zero. Also check 18462306a36Sopenharmony_ci| the sign and return operr if negative. 18562306a36Sopenharmony_ci| 18662306a36Sopenharmony_ci .global sslogn 18762306a36Sopenharmony_cisslogn: 18862306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 18962306a36Sopenharmony_ci bne t_operr |take care of operands < 0 19062306a36Sopenharmony_ci cmpiw #0x3fff,LOCAL_EX(%a0) |test for 1.0 input 19162306a36Sopenharmony_ci bne slogn 19262306a36Sopenharmony_ci cmpil #0x80000000,LOCAL_HI(%a0) 19362306a36Sopenharmony_ci bne slogn 19462306a36Sopenharmony_ci tstl LOCAL_LO(%a0) 19562306a36Sopenharmony_ci bne slogn 19662306a36Sopenharmony_ci fmovex PZERO,%fp0 19762306a36Sopenharmony_ci rts 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci .global sslognd 20062306a36Sopenharmony_cisslognd: 20162306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 20262306a36Sopenharmony_ci beq slognd 20362306a36Sopenharmony_ci bra t_operr |take care of operands < 0 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci| 20662306a36Sopenharmony_ci| FLOG10 20762306a36Sopenharmony_ci| 20862306a36Sopenharmony_ci .global sslog10 20962306a36Sopenharmony_cisslog10: 21062306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 21162306a36Sopenharmony_ci bne t_operr |take care of operands < 0 21262306a36Sopenharmony_ci cmpiw #0x3fff,LOCAL_EX(%a0) |test for 1.0 input 21362306a36Sopenharmony_ci bne slog10 21462306a36Sopenharmony_ci cmpil #0x80000000,LOCAL_HI(%a0) 21562306a36Sopenharmony_ci bne slog10 21662306a36Sopenharmony_ci tstl LOCAL_LO(%a0) 21762306a36Sopenharmony_ci bne slog10 21862306a36Sopenharmony_ci fmovex PZERO,%fp0 21962306a36Sopenharmony_ci rts 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci .global sslog10d 22262306a36Sopenharmony_cisslog10d: 22362306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 22462306a36Sopenharmony_ci beq slog10d 22562306a36Sopenharmony_ci bra t_operr |take care of operands < 0 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci| 22862306a36Sopenharmony_ci| FLOG2 22962306a36Sopenharmony_ci| 23062306a36Sopenharmony_ci .global sslog2 23162306a36Sopenharmony_cisslog2: 23262306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 23362306a36Sopenharmony_ci bne t_operr |take care of operands < 0 23462306a36Sopenharmony_ci cmpiw #0x3fff,LOCAL_EX(%a0) |test for 1.0 input 23562306a36Sopenharmony_ci bne slog2 23662306a36Sopenharmony_ci cmpil #0x80000000,LOCAL_HI(%a0) 23762306a36Sopenharmony_ci bne slog2 23862306a36Sopenharmony_ci tstl LOCAL_LO(%a0) 23962306a36Sopenharmony_ci bne slog2 24062306a36Sopenharmony_ci fmovex PZERO,%fp0 24162306a36Sopenharmony_ci rts 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci .global sslog2d 24462306a36Sopenharmony_cisslog2d: 24562306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 24662306a36Sopenharmony_ci beq slog2d 24762306a36Sopenharmony_ci bra t_operr |take care of operands < 0 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci| 25062306a36Sopenharmony_ci| FMOD 25162306a36Sopenharmony_ci| 25262306a36Sopenharmony_cipmodt: 25362306a36Sopenharmony_ci| ;$21 fmod 25462306a36Sopenharmony_ci| ;dtag,stag 25562306a36Sopenharmony_ci .long smod | 00,00 norm,norm = normal 25662306a36Sopenharmony_ci .long smod_oper | 00,01 norm,zero = nan with operr 25762306a36Sopenharmony_ci .long smod_fpn | 00,10 norm,inf = fpn 25862306a36Sopenharmony_ci .long smod_snan | 00,11 norm,nan = nan 25962306a36Sopenharmony_ci .long smod_zro | 01,00 zero,norm = +-zero 26062306a36Sopenharmony_ci .long smod_oper | 01,01 zero,zero = nan with operr 26162306a36Sopenharmony_ci .long smod_zro | 01,10 zero,inf = +-zero 26262306a36Sopenharmony_ci .long smod_snan | 01,11 zero,nan = nan 26362306a36Sopenharmony_ci .long smod_oper | 10,00 inf,norm = nan with operr 26462306a36Sopenharmony_ci .long smod_oper | 10,01 inf,zero = nan with operr 26562306a36Sopenharmony_ci .long smod_oper | 10,10 inf,inf = nan with operr 26662306a36Sopenharmony_ci .long smod_snan | 10,11 inf,nan = nan 26762306a36Sopenharmony_ci .long smod_dnan | 11,00 nan,norm = nan 26862306a36Sopenharmony_ci .long smod_dnan | 11,01 nan,zero = nan 26962306a36Sopenharmony_ci .long smod_dnan | 11,10 nan,inf = nan 27062306a36Sopenharmony_ci .long smod_dnan | 11,11 nan,nan = nan 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci .global pmod 27362306a36Sopenharmony_cipmod: 27462306a36Sopenharmony_ci clrb FPSR_QBYTE(%a6) | clear quotient field 27562306a36Sopenharmony_ci bfextu STAG(%a6){#0:#3},%d0 |stag = d0 27662306a36Sopenharmony_ci bfextu DTAG(%a6){#0:#3},%d1 |dtag = d1 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci| 27962306a36Sopenharmony_ci| Alias extended denorms to norms for the jump table. 28062306a36Sopenharmony_ci| 28162306a36Sopenharmony_ci bclrl #2,%d0 28262306a36Sopenharmony_ci bclrl #2,%d1 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci lslb #2,%d1 28562306a36Sopenharmony_ci orb %d0,%d1 |d1{3:2} = dtag, d1{1:0} = stag 28662306a36Sopenharmony_ci| ;Tag values: 28762306a36Sopenharmony_ci| ;00 = norm or denorm 28862306a36Sopenharmony_ci| ;01 = zero 28962306a36Sopenharmony_ci| ;10 = inf 29062306a36Sopenharmony_ci| ;11 = nan 29162306a36Sopenharmony_ci lea pmodt,%a1 29262306a36Sopenharmony_ci movel (%a1,%d1.w*4),%a1 29362306a36Sopenharmony_ci jmp (%a1) 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cismod_snan: 29662306a36Sopenharmony_ci bra src_nan 29762306a36Sopenharmony_cismod_dnan: 29862306a36Sopenharmony_ci bra dst_nan 29962306a36Sopenharmony_cismod_oper: 30062306a36Sopenharmony_ci bra t_operr 30162306a36Sopenharmony_cismod_zro: 30262306a36Sopenharmony_ci moveb ETEMP(%a6),%d1 |get sign of src op 30362306a36Sopenharmony_ci moveb FPTEMP(%a6),%d0 |get sign of dst op 30462306a36Sopenharmony_ci eorb %d0,%d1 |get exor of sign bits 30562306a36Sopenharmony_ci btstl #7,%d1 |test for sign 30662306a36Sopenharmony_ci beqs smod_zsn |if clr, do not set sign big 30762306a36Sopenharmony_ci bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit 30862306a36Sopenharmony_cismod_zsn: 30962306a36Sopenharmony_ci btstl #7,%d0 |test if + or - 31062306a36Sopenharmony_ci beq ld_pzero |if pos then load +0 31162306a36Sopenharmony_ci bra ld_mzero |else neg load -0 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_cismod_fpn: 31462306a36Sopenharmony_ci moveb ETEMP(%a6),%d1 |get sign of src op 31562306a36Sopenharmony_ci moveb FPTEMP(%a6),%d0 |get sign of dst op 31662306a36Sopenharmony_ci eorb %d0,%d1 |get exor of sign bits 31762306a36Sopenharmony_ci btstl #7,%d1 |test for sign 31862306a36Sopenharmony_ci beqs smod_fsn |if clr, do not set sign big 31962306a36Sopenharmony_ci bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit 32062306a36Sopenharmony_cismod_fsn: 32162306a36Sopenharmony_ci tstb DTAG(%a6) |filter out denormal destination case 32262306a36Sopenharmony_ci bpls smod_nrm | 32362306a36Sopenharmony_ci leal FPTEMP(%a6),%a0 |a0<- addr(FPTEMP) 32462306a36Sopenharmony_ci bra t_resdnrm |force UNFL(but exact) result 32562306a36Sopenharmony_cismod_nrm: 32662306a36Sopenharmony_ci fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision 32762306a36Sopenharmony_ci fmovex FPTEMP(%a6),%fp0 |return dest to fp0 32862306a36Sopenharmony_ci rts 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci| 33162306a36Sopenharmony_ci| FREM 33262306a36Sopenharmony_ci| 33362306a36Sopenharmony_cipremt: 33462306a36Sopenharmony_ci| ;$25 frem 33562306a36Sopenharmony_ci| ;dtag,stag 33662306a36Sopenharmony_ci .long srem | 00,00 norm,norm = normal 33762306a36Sopenharmony_ci .long srem_oper | 00,01 norm,zero = nan with operr 33862306a36Sopenharmony_ci .long srem_fpn | 00,10 norm,inf = fpn 33962306a36Sopenharmony_ci .long srem_snan | 00,11 norm,nan = nan 34062306a36Sopenharmony_ci .long srem_zro | 01,00 zero,norm = +-zero 34162306a36Sopenharmony_ci .long srem_oper | 01,01 zero,zero = nan with operr 34262306a36Sopenharmony_ci .long srem_zro | 01,10 zero,inf = +-zero 34362306a36Sopenharmony_ci .long srem_snan | 01,11 zero,nan = nan 34462306a36Sopenharmony_ci .long srem_oper | 10,00 inf,norm = nan with operr 34562306a36Sopenharmony_ci .long srem_oper | 10,01 inf,zero = nan with operr 34662306a36Sopenharmony_ci .long srem_oper | 10,10 inf,inf = nan with operr 34762306a36Sopenharmony_ci .long srem_snan | 10,11 inf,nan = nan 34862306a36Sopenharmony_ci .long srem_dnan | 11,00 nan,norm = nan 34962306a36Sopenharmony_ci .long srem_dnan | 11,01 nan,zero = nan 35062306a36Sopenharmony_ci .long srem_dnan | 11,10 nan,inf = nan 35162306a36Sopenharmony_ci .long srem_dnan | 11,11 nan,nan = nan 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci .global prem 35462306a36Sopenharmony_ciprem: 35562306a36Sopenharmony_ci clrb FPSR_QBYTE(%a6) |clear quotient field 35662306a36Sopenharmony_ci bfextu STAG(%a6){#0:#3},%d0 |stag = d0 35762306a36Sopenharmony_ci bfextu DTAG(%a6){#0:#3},%d1 |dtag = d1 35862306a36Sopenharmony_ci| 35962306a36Sopenharmony_ci| Alias extended denorms to norms for the jump table. 36062306a36Sopenharmony_ci| 36162306a36Sopenharmony_ci bclr #2,%d0 36262306a36Sopenharmony_ci bclr #2,%d1 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci lslb #2,%d1 36562306a36Sopenharmony_ci orb %d0,%d1 |d1{3:2} = dtag, d1{1:0} = stag 36662306a36Sopenharmony_ci| ;Tag values: 36762306a36Sopenharmony_ci| ;00 = norm or denorm 36862306a36Sopenharmony_ci| ;01 = zero 36962306a36Sopenharmony_ci| ;10 = inf 37062306a36Sopenharmony_ci| ;11 = nan 37162306a36Sopenharmony_ci lea premt,%a1 37262306a36Sopenharmony_ci movel (%a1,%d1.w*4),%a1 37362306a36Sopenharmony_ci jmp (%a1) 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_cisrem_snan: 37662306a36Sopenharmony_ci bra src_nan 37762306a36Sopenharmony_cisrem_dnan: 37862306a36Sopenharmony_ci bra dst_nan 37962306a36Sopenharmony_cisrem_oper: 38062306a36Sopenharmony_ci bra t_operr 38162306a36Sopenharmony_cisrem_zro: 38262306a36Sopenharmony_ci moveb ETEMP(%a6),%d1 |get sign of src op 38362306a36Sopenharmony_ci moveb FPTEMP(%a6),%d0 |get sign of dst op 38462306a36Sopenharmony_ci eorb %d0,%d1 |get exor of sign bits 38562306a36Sopenharmony_ci btstl #7,%d1 |test for sign 38662306a36Sopenharmony_ci beqs srem_zsn |if clr, do not set sign big 38762306a36Sopenharmony_ci bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit 38862306a36Sopenharmony_cisrem_zsn: 38962306a36Sopenharmony_ci btstl #7,%d0 |test if + or - 39062306a36Sopenharmony_ci beq ld_pzero |if pos then load +0 39162306a36Sopenharmony_ci bra ld_mzero |else neg load -0 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_cisrem_fpn: 39462306a36Sopenharmony_ci moveb ETEMP(%a6),%d1 |get sign of src op 39562306a36Sopenharmony_ci moveb FPTEMP(%a6),%d0 |get sign of dst op 39662306a36Sopenharmony_ci eorb %d0,%d1 |get exor of sign bits 39762306a36Sopenharmony_ci btstl #7,%d1 |test for sign 39862306a36Sopenharmony_ci beqs srem_fsn |if clr, do not set sign big 39962306a36Sopenharmony_ci bsetb #q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit 40062306a36Sopenharmony_cisrem_fsn: 40162306a36Sopenharmony_ci tstb DTAG(%a6) |filter out denormal destination case 40262306a36Sopenharmony_ci bpls srem_nrm | 40362306a36Sopenharmony_ci leal FPTEMP(%a6),%a0 |a0<- addr(FPTEMP) 40462306a36Sopenharmony_ci bra t_resdnrm |force UNFL(but exact) result 40562306a36Sopenharmony_cisrem_nrm: 40662306a36Sopenharmony_ci fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision 40762306a36Sopenharmony_ci fmovex FPTEMP(%a6),%fp0 |return dest to fp0 40862306a36Sopenharmony_ci rts 40962306a36Sopenharmony_ci| 41062306a36Sopenharmony_ci| FSCALE 41162306a36Sopenharmony_ci| 41262306a36Sopenharmony_cipscalet: 41362306a36Sopenharmony_ci| ;$26 fscale 41462306a36Sopenharmony_ci| ;dtag,stag 41562306a36Sopenharmony_ci .long sscale | 00,00 norm,norm = result 41662306a36Sopenharmony_ci .long sscale | 00,01 norm,zero = fpn 41762306a36Sopenharmony_ci .long scl_opr | 00,10 norm,inf = nan with operr 41862306a36Sopenharmony_ci .long scl_snan | 00,11 norm,nan = nan 41962306a36Sopenharmony_ci .long scl_zro | 01,00 zero,norm = +-zero 42062306a36Sopenharmony_ci .long scl_zro | 01,01 zero,zero = +-zero 42162306a36Sopenharmony_ci .long scl_opr | 01,10 zero,inf = nan with operr 42262306a36Sopenharmony_ci .long scl_snan | 01,11 zero,nan = nan 42362306a36Sopenharmony_ci .long scl_inf | 10,00 inf,norm = +-inf 42462306a36Sopenharmony_ci .long scl_inf | 10,01 inf,zero = +-inf 42562306a36Sopenharmony_ci .long scl_opr | 10,10 inf,inf = nan with operr 42662306a36Sopenharmony_ci .long scl_snan | 10,11 inf,nan = nan 42762306a36Sopenharmony_ci .long scl_dnan | 11,00 nan,norm = nan 42862306a36Sopenharmony_ci .long scl_dnan | 11,01 nan,zero = nan 42962306a36Sopenharmony_ci .long scl_dnan | 11,10 nan,inf = nan 43062306a36Sopenharmony_ci .long scl_dnan | 11,11 nan,nan = nan 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci .global pscale 43362306a36Sopenharmony_cipscale: 43462306a36Sopenharmony_ci bfextu STAG(%a6){#0:#3},%d0 |stag in d0 43562306a36Sopenharmony_ci bfextu DTAG(%a6){#0:#3},%d1 |dtag in d1 43662306a36Sopenharmony_ci bclrl #2,%d0 |alias denorm into norm 43762306a36Sopenharmony_ci bclrl #2,%d1 |alias denorm into norm 43862306a36Sopenharmony_ci lslb #2,%d1 43962306a36Sopenharmony_ci orb %d0,%d1 |d1{4:2} = dtag, d1{1:0} = stag 44062306a36Sopenharmony_ci| ;dtag values stag values: 44162306a36Sopenharmony_ci| ;000 = norm 00 = norm 44262306a36Sopenharmony_ci| ;001 = zero 01 = zero 44362306a36Sopenharmony_ci| ;010 = inf 10 = inf 44462306a36Sopenharmony_ci| ;011 = nan 11 = nan 44562306a36Sopenharmony_ci| ;100 = dnrm 44662306a36Sopenharmony_ci| 44762306a36Sopenharmony_ci| 44862306a36Sopenharmony_ci leal pscalet,%a1 |load start of jump table 44962306a36Sopenharmony_ci movel (%a1,%d1.w*4),%a1 |load a1 with label depending on tag 45062306a36Sopenharmony_ci jmp (%a1) |go to the routine 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ciscl_opr: 45362306a36Sopenharmony_ci bra t_operr 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ciscl_dnan: 45662306a36Sopenharmony_ci bra dst_nan 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ciscl_zro: 45962306a36Sopenharmony_ci btstb #sign_bit,FPTEMP_EX(%a6) |test if + or - 46062306a36Sopenharmony_ci beq ld_pzero |if pos then load +0 46162306a36Sopenharmony_ci bra ld_mzero |if neg then load -0 46262306a36Sopenharmony_ciscl_inf: 46362306a36Sopenharmony_ci btstb #sign_bit,FPTEMP_EX(%a6) |test if + or - 46462306a36Sopenharmony_ci beq ld_pinf |if pos then load +inf 46562306a36Sopenharmony_ci bra ld_minf |else neg load -inf 46662306a36Sopenharmony_ciscl_snan: 46762306a36Sopenharmony_ci bra src_nan 46862306a36Sopenharmony_ci| 46962306a36Sopenharmony_ci| FSINCOS 47062306a36Sopenharmony_ci| 47162306a36Sopenharmony_ci .global ssincosz 47262306a36Sopenharmony_cissincosz: 47362306a36Sopenharmony_ci btstb #sign_bit,ETEMP(%a6) |get sign 47462306a36Sopenharmony_ci beqs sincosp 47562306a36Sopenharmony_ci fmovex MZERO,%fp0 47662306a36Sopenharmony_ci bras sincoscom 47762306a36Sopenharmony_cisincosp: 47862306a36Sopenharmony_ci fmovex PZERO,%fp0 47962306a36Sopenharmony_cisincoscom: 48062306a36Sopenharmony_ci fmovemx PONE,%fp1-%fp1 |do not allow FPSR to be affected 48162306a36Sopenharmony_ci bra sto_cos |store cosine result 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci .global ssincosi 48462306a36Sopenharmony_cissincosi: 48562306a36Sopenharmony_ci fmovex QNAN,%fp1 |load NAN 48662306a36Sopenharmony_ci bsr sto_cos |store cosine result 48762306a36Sopenharmony_ci fmovex QNAN,%fp0 |load NAN 48862306a36Sopenharmony_ci bra t_operr 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci .global ssincosnan 49162306a36Sopenharmony_cissincosnan: 49262306a36Sopenharmony_ci movel ETEMP_EX(%a6),FP_SCR1(%a6) 49362306a36Sopenharmony_ci movel ETEMP_HI(%a6),FP_SCR1+4(%a6) 49462306a36Sopenharmony_ci movel ETEMP_LO(%a6),FP_SCR1+8(%a6) 49562306a36Sopenharmony_ci bsetb #signan_bit,FP_SCR1+4(%a6) 49662306a36Sopenharmony_ci fmovemx FP_SCR1(%a6),%fp1-%fp1 49762306a36Sopenharmony_ci bsr sto_cos 49862306a36Sopenharmony_ci bra src_nan 49962306a36Sopenharmony_ci| 50062306a36Sopenharmony_ci| This code forces default values for the zero, inf, and nan cases 50162306a36Sopenharmony_ci| in the transcendentals code. The CC bits must be set in the 50262306a36Sopenharmony_ci| stacked FPSR to be correctly reported. 50362306a36Sopenharmony_ci| 50462306a36Sopenharmony_ci|**Returns +PI/2 50562306a36Sopenharmony_ci .global ld_ppi2 50662306a36Sopenharmony_cild_ppi2: 50762306a36Sopenharmony_ci fmovex PPIBY2,%fp0 |load +pi/2 50862306a36Sopenharmony_ci bra t_inx2 |set inex2 exc 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci|**Returns -PI/2 51162306a36Sopenharmony_ci .global ld_mpi2 51262306a36Sopenharmony_cild_mpi2: 51362306a36Sopenharmony_ci fmovex MPIBY2,%fp0 |load -pi/2 51462306a36Sopenharmony_ci orl #neg_mask,USER_FPSR(%a6) |set N bit 51562306a36Sopenharmony_ci bra t_inx2 |set inex2 exc 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci|**Returns +inf 51862306a36Sopenharmony_ci .global ld_pinf 51962306a36Sopenharmony_cild_pinf: 52062306a36Sopenharmony_ci fmovex PINF,%fp0 |load +inf 52162306a36Sopenharmony_ci orl #inf_mask,USER_FPSR(%a6) |set I bit 52262306a36Sopenharmony_ci rts 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci|**Returns -inf 52562306a36Sopenharmony_ci .global ld_minf 52662306a36Sopenharmony_cild_minf: 52762306a36Sopenharmony_ci fmovex MINF,%fp0 |load -inf 52862306a36Sopenharmony_ci orl #neg_mask+inf_mask,USER_FPSR(%a6) |set N and I bits 52962306a36Sopenharmony_ci rts 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci|**Returns +1 53262306a36Sopenharmony_ci .global ld_pone 53362306a36Sopenharmony_cild_pone: 53462306a36Sopenharmony_ci fmovex PONE,%fp0 |load +1 53562306a36Sopenharmony_ci rts 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci|**Returns -1 53862306a36Sopenharmony_ci .global ld_mone 53962306a36Sopenharmony_cild_mone: 54062306a36Sopenharmony_ci fmovex MONE,%fp0 |load -1 54162306a36Sopenharmony_ci orl #neg_mask,USER_FPSR(%a6) |set N bit 54262306a36Sopenharmony_ci rts 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci|**Returns +0 54562306a36Sopenharmony_ci .global ld_pzero 54662306a36Sopenharmony_cild_pzero: 54762306a36Sopenharmony_ci fmovex PZERO,%fp0 |load +0 54862306a36Sopenharmony_ci orl #z_mask,USER_FPSR(%a6) |set Z bit 54962306a36Sopenharmony_ci rts 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci|**Returns -0 55262306a36Sopenharmony_ci .global ld_mzero 55362306a36Sopenharmony_cild_mzero: 55462306a36Sopenharmony_ci fmovex MZERO,%fp0 |load -0 55562306a36Sopenharmony_ci orl #neg_mask+z_mask,USER_FPSR(%a6) |set N and Z bits 55662306a36Sopenharmony_ci rts 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci |end 559