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