File indexing completed on 2025-05-11 08:23:48
0001 #include "fpsp-namespace.h"
0002 //
0003 //
0004 // do_func.sa 3.4 2/18/91
0005 //
0006 // Do_func performs the unimplemented operation. The operation
0007 // to be performed is determined from the lower 7 bits of the
0008 // extension word (except in the case of fmovecr and fsincos).
0009 // The opcode and tag bits form an index into a jump table in
0010 // tbldo.sa. Cases of zero, infinity and NaN are handled in
0011 // do_func by forcing the default result. Normalized and
0012 // denormalized (there are no unnormalized numbers at this
0013 // point) are passed onto the emulation code.
0014 //
0015 // CMDREG1B and STAG are extracted from the fsave frame
0016 // and combined to form the table index. The function called
0017 // will start with a0 pointing to the ETEMP operand. Dyadic
0018 // functions can find FPTEMP at -12(a0).
0019 //
0020 // Called functions return their result in fp0. Sincos returns
0021 // sin(x) in fp0 and cos(x) in fp1.
0022 //
0023
0024 // Copyright (C) Motorola, Inc. 1990
0025 // All Rights Reserved
0026 //
0027 // THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
0028 // The copyright notice above does not evidence any
0029 // actual or intended publication of such source code.
0030
0031 DO_FUNC: //idnt 2,1 | Motorola 040 Floating Point Software Package
0032
0033 |section 8
0034
0035 #include "fpsp.defs"
0036
0037 |xref t_dz2
0038 |xref t_operr
0039 |xref t_inx2
0040 |xref t_resdnrm
0041 |xref dst_nan
0042 |xref src_nan
0043 |xref nrm_set
0044 |xref sto_cos
0045
0046 |xref tblpre
0047 |xref slognp1,slogn,slog10,slog2
0048 |xref slognd,slog10d,slog2d
0049 |xref smod,srem
0050 |xref sscale
0051 |xref smovcr
0052
0053 PONE: .long 0x3fff0000,0x80000000,0x00000000 //+1
0054 MONE: .long 0xbfff0000,0x80000000,0x00000000 //-1
0055 PZERO: .long 0x00000000,0x00000000,0x00000000 //+0
0056 MZERO: .long 0x80000000,0x00000000,0x00000000 //-0
0057 PINF: .long 0x7fff0000,0x00000000,0x00000000 //+inf
0058 MINF: .long 0xffff0000,0x00000000,0x00000000 //-inf
0059 QNAN: .long 0x7fff0000,0xffffffff,0xffffffff //non-signaling nan
0060 PPIBY2: .long 0x3FFF0000,0xC90FDAA2,0x2168C235 //+PI/2
0061 MPIBY2: .long 0xbFFF0000,0xC90FDAA2,0x2168C235 //-PI/2
0062
0063 .global do_func
0064 do_func:
0065 clrb CU_ONLY(%a6)
0066 //
0067 // Check for fmovecr. It does not follow the format of fp gen
0068 // unimplemented instructions. The test is on the upper 6 bits;
0069 // if they are $17, the inst is fmovecr. Call entry smovcr
0070 // directly.
0071 //
0072 bfextu CMDREG1B(%a6){#0:#6},%d0 //get opclass and src fields
0073 cmpil #0x17,%d0 //if op class and size fields are $17,
0074 // ;it is FMOVECR; if not, continue
0075 bnes not_fmovecr
0076 jmp smovcr //fmovecr; jmp directly to emulation
0077
0078 not_fmovecr:
0079 movew CMDREG1B(%a6),%d0
0080 andl #0x7F,%d0
0081 cmpil #0x38,%d0 //if the extension is >= $38,
0082 bge serror //it is illegal
0083 bfextu STAG(%a6){#0:#3},%d1
0084 lsll #3,%d0 //make room for STAG
0085 addl %d1,%d0 //combine for final index into table
0086 leal tblpre,%a1 //start of monster jump table
0087 movel (%a1,%d0.w*4),%a1 //real target address
0088 leal ETEMP(%a6),%a0 //a0 is pointer to src op
0089 movel USER_FPCR(%a6),%d1
0090 andl #0xFF,%d1 // discard all but rounding mode/prec
0091 fmovel #0,%fpcr
0092 jmp (%a1)
0093 //
0094 // ERROR
0095 //
0096 .global serror
0097 serror:
0098 st STORE_FLG(%a6)
0099 rts
0100 //
0101 // These routines load forced values into fp0. They are called
0102 // by index into tbldo.
0103 //
0104 // Load a signed zero to fp0 and set inex2/ainex
0105 //
0106 .global snzrinx
0107 snzrinx:
0108 btstb #sign_bit,LOCAL_EX(%a0) //get sign of source operand
0109 bnes ld_mzinx //if negative, branch
0110 bsr ld_pzero //bsr so we can return and set inx
0111 bra t_inx2 //now, set the inx for the next inst
0112 ld_mzinx:
0113 bsr ld_mzero //if neg, load neg zero, return here
0114 bra t_inx2 //now, set the inx for the next inst
0115 //
0116 // Load a signed zero to fp0; do not set inex2/ainex
0117 //
0118 .global szero
0119 szero:
0120 btstb #sign_bit,LOCAL_EX(%a0) //get sign of source operand
0121 bne ld_mzero //if neg, load neg zero
0122 bra ld_pzero //load positive zero
0123 //
0124 // Load a signed infinity to fp0; do not set inex2/ainex
0125 //
0126 .global sinf
0127 sinf:
0128 btstb #sign_bit,LOCAL_EX(%a0) //get sign of source operand
0129 bne ld_minf //if negative branch
0130 bra ld_pinf
0131 //
0132 // Load a signed one to fp0; do not set inex2/ainex
0133 //
0134 .global sone
0135 sone:
0136 btstb #sign_bit,LOCAL_EX(%a0) //check sign of source
0137 bne ld_mone
0138 bra ld_pone
0139 //
0140 // Load a signed pi/2 to fp0; do not set inex2/ainex
0141 //
0142 .global spi_2
0143 spi_2:
0144 btstb #sign_bit,LOCAL_EX(%a0) //check sign of source
0145 bne ld_mpi2
0146 bra ld_ppi2
0147 //
0148 // Load either a +0 or +inf for plus/minus operand
0149 //
0150 .global szr_inf
0151 szr_inf:
0152 btstb #sign_bit,LOCAL_EX(%a0) //check sign of source
0153 bne ld_pzero
0154 bra ld_pinf
0155 //
0156 // Result is either an operr or +inf for plus/minus operand
0157 // [Used by slogn, slognp1, slog10, and slog2]
0158 //
0159 .global sopr_inf
0160 sopr_inf:
0161 btstb #sign_bit,LOCAL_EX(%a0) //check sign of source
0162 bne t_operr
0163 bra ld_pinf
0164 //
0165 // FLOGNP1
0166 //
0167 .global sslognp1
0168 sslognp1:
0169 fmovemx (%a0),%fp0-%fp0
0170 fcmpb #-1,%fp0
0171 fbgt slognp1
0172 fbeq t_dz2 //if = -1, divide by zero exception
0173 fmovel #0,%FPSR //clr N flag
0174 bra t_operr //take care of operands < -1
0175 //
0176 // FETOXM1
0177 //
0178 .global setoxm1i
0179 setoxm1i:
0180 btstb #sign_bit,LOCAL_EX(%a0) //check sign of source
0181 bne ld_mone
0182 bra ld_pinf
0183 //
0184 // FLOGN
0185 //
0186 // Test for 1.0 as an input argument, returning +zero. Also check
0187 // the sign and return operr if negative.
0188 //
0189 .global sslogn
0190 sslogn:
0191 btstb #sign_bit,LOCAL_EX(%a0)
0192 bne t_operr //take care of operands < 0
0193 cmpiw #0x3fff,LOCAL_EX(%a0) //test for 1.0 input
0194 bne slogn
0195 cmpil #0x80000000,LOCAL_HI(%a0)
0196 bne slogn
0197 tstl LOCAL_LO(%a0)
0198 bne slogn
0199 fmovex PZERO,%fp0
0200 rts
0201
0202 .global sslognd
0203 sslognd:
0204 btstb #sign_bit,LOCAL_EX(%a0)
0205 beq slognd
0206 bra t_operr //take care of operands < 0
0207
0208 //
0209 // FLOG10
0210 //
0211 .global sslog10
0212 sslog10:
0213 btstb #sign_bit,LOCAL_EX(%a0)
0214 bne t_operr //take care of operands < 0
0215 cmpiw #0x3fff,LOCAL_EX(%a0) //test for 1.0 input
0216 bne slog10
0217 cmpil #0x80000000,LOCAL_HI(%a0)
0218 bne slog10
0219 tstl LOCAL_LO(%a0)
0220 bne slog10
0221 fmovex PZERO,%fp0
0222 rts
0223
0224 .global sslog10d
0225 sslog10d:
0226 btstb #sign_bit,LOCAL_EX(%a0)
0227 beq slog10d
0228 bra t_operr //take care of operands < 0
0229
0230 //
0231 // FLOG2
0232 //
0233 .global sslog2
0234 sslog2:
0235 btstb #sign_bit,LOCAL_EX(%a0)
0236 bne t_operr //take care of operands < 0
0237 cmpiw #0x3fff,LOCAL_EX(%a0) //test for 1.0 input
0238 bne slog2
0239 cmpil #0x80000000,LOCAL_HI(%a0)
0240 bne slog2
0241 tstl LOCAL_LO(%a0)
0242 bne slog2
0243 fmovex PZERO,%fp0
0244 rts
0245
0246 .global sslog2d
0247 sslog2d:
0248 btstb #sign_bit,LOCAL_EX(%a0)
0249 beq slog2d
0250 bra t_operr //take care of operands < 0
0251
0252 //
0253 // FMOD
0254 //
0255 pmodt:
0256 // ;$21 fmod
0257 // ;dtag,stag
0258 .long smod // 00,00 norm,norm = normal
0259 .long smod_oper // 00,01 norm,zero = nan with operr
0260 .long smod_fpn // 00,10 norm,inf = fpn
0261 .long smod_snan // 00,11 norm,nan = nan
0262 .long smod_zro // 01,00 zero,norm = +-zero
0263 .long smod_oper // 01,01 zero,zero = nan with operr
0264 .long smod_zro // 01,10 zero,inf = +-zero
0265 .long smod_snan // 01,11 zero,nan = nan
0266 .long smod_oper // 10,00 inf,norm = nan with operr
0267 .long smod_oper // 10,01 inf,zero = nan with operr
0268 .long smod_oper // 10,10 inf,inf = nan with operr
0269 .long smod_snan // 10,11 inf,nan = nan
0270 .long smod_dnan // 11,00 nan,norm = nan
0271 .long smod_dnan // 11,01 nan,zero = nan
0272 .long smod_dnan // 11,10 nan,inf = nan
0273 .long smod_dnan // 11,11 nan,nan = nan
0274
0275 .global pmod
0276 pmod:
0277 clrb FPSR_QBYTE(%a6) // clear quotient field
0278 bfextu STAG(%a6){#0:#3},%d0 //stag = d0
0279 bfextu DTAG(%a6){#0:#3},%d1 //dtag = d1
0280
0281 //
0282 // Alias extended denorms to norms for the jump table.
0283 //
0284 bclrl #2,%d0
0285 bclrl #2,%d1
0286
0287 lslb #2,%d1
0288 orb %d0,%d1 //d1{3:2} = dtag, d1{1:0} = stag
0289 // ;Tag values:
0290 // ;00 = norm or denorm
0291 // ;01 = zero
0292 // ;10 = inf
0293 // ;11 = nan
0294 lea pmodt,%a1
0295 movel (%a1,%d1.w*4),%a1
0296 jmp (%a1)
0297
0298 smod_snan:
0299 bra src_nan
0300 smod_dnan:
0301 bra dst_nan
0302 smod_oper:
0303 bra t_operr
0304 smod_zro:
0305 moveb ETEMP(%a6),%d1 //get sign of src op
0306 moveb FPTEMP(%a6),%d0 //get sign of dst op
0307 eorb %d0,%d1 //get exor of sign bits
0308 btstl #7,%d1 //test for sign
0309 beqs smod_zsn //if clr, do not set sign big
0310 bsetb #q_sn_bit,FPSR_QBYTE(%a6) //set q-byte sign bit
0311 smod_zsn:
0312 btstl #7,%d0 //test if + or -
0313 beq ld_pzero //if pos then load +0
0314 bra ld_mzero //else neg load -0
0315
0316 smod_fpn:
0317 moveb ETEMP(%a6),%d1 //get sign of src op
0318 moveb FPTEMP(%a6),%d0 //get sign of dst op
0319 eorb %d0,%d1 //get exor of sign bits
0320 btstl #7,%d1 //test for sign
0321 beqs smod_fsn //if clr, do not set sign big
0322 bsetb #q_sn_bit,FPSR_QBYTE(%a6) //set q-byte sign bit
0323 smod_fsn:
0324 tstb DTAG(%a6) //filter out denormal destination case
0325 bpls smod_nrm //
0326 leal FPTEMP(%a6),%a0 //a0<- addr(FPTEMP)
0327 bra t_resdnrm //force UNFL(but exact) result
0328 smod_nrm:
0329 fmovel USER_FPCR(%a6),%fpcr //use user's rmode and precision
0330 fmovex FPTEMP(%a6),%fp0 //return dest to fp0
0331 rts
0332
0333 //
0334 // FREM
0335 //
0336 premt:
0337 // ;$25 frem
0338 // ;dtag,stag
0339 .long srem // 00,00 norm,norm = normal
0340 .long srem_oper // 00,01 norm,zero = nan with operr
0341 .long srem_fpn // 00,10 norm,inf = fpn
0342 .long srem_snan // 00,11 norm,nan = nan
0343 .long srem_zro // 01,00 zero,norm = +-zero
0344 .long srem_oper // 01,01 zero,zero = nan with operr
0345 .long srem_zro // 01,10 zero,inf = +-zero
0346 .long srem_snan // 01,11 zero,nan = nan
0347 .long srem_oper // 10,00 inf,norm = nan with operr
0348 .long srem_oper // 10,01 inf,zero = nan with operr
0349 .long srem_oper // 10,10 inf,inf = nan with operr
0350 .long srem_snan // 10,11 inf,nan = nan
0351 .long srem_dnan // 11,00 nan,norm = nan
0352 .long srem_dnan // 11,01 nan,zero = nan
0353 .long srem_dnan // 11,10 nan,inf = nan
0354 .long srem_dnan // 11,11 nan,nan = nan
0355
0356 .global prem
0357 prem:
0358 clrb FPSR_QBYTE(%a6) //clear quotient field
0359 bfextu STAG(%a6){#0:#3},%d0 //stag = d0
0360 bfextu DTAG(%a6){#0:#3},%d1 //dtag = d1
0361 //
0362 // Alias extended denorms to norms for the jump table.
0363 //
0364 bclr #2,%d0
0365 bclr #2,%d1
0366
0367 lslb #2,%d1
0368 orb %d0,%d1 //d1{3:2} = dtag, d1{1:0} = stag
0369 // ;Tag values:
0370 // ;00 = norm or denorm
0371 // ;01 = zero
0372 // ;10 = inf
0373 // ;11 = nan
0374 lea premt,%a1
0375 movel (%a1,%d1.w*4),%a1
0376 jmp (%a1)
0377
0378 srem_snan:
0379 bra src_nan
0380 srem_dnan:
0381 bra dst_nan
0382 srem_oper:
0383 bra t_operr
0384 srem_zro:
0385 moveb ETEMP(%a6),%d1 //get sign of src op
0386 moveb FPTEMP(%a6),%d0 //get sign of dst op
0387 eorb %d0,%d1 //get exor of sign bits
0388 btstl #7,%d1 //test for sign
0389 beqs srem_zsn //if clr, do not set sign big
0390 bsetb #q_sn_bit,FPSR_QBYTE(%a6) //set q-byte sign bit
0391 srem_zsn:
0392 btstl #7,%d0 //test if + or -
0393 beq ld_pzero //if pos then load +0
0394 bra ld_mzero //else neg load -0
0395
0396 srem_fpn:
0397 moveb ETEMP(%a6),%d1 //get sign of src op
0398 moveb FPTEMP(%a6),%d0 //get sign of dst op
0399 eorb %d0,%d1 //get exor of sign bits
0400 btstl #7,%d1 //test for sign
0401 beqs srem_fsn //if clr, do not set sign big
0402 bsetb #q_sn_bit,FPSR_QBYTE(%a6) //set q-byte sign bit
0403 srem_fsn:
0404 tstb DTAG(%a6) //filter out denormal destination case
0405 bpls srem_nrm //
0406 leal FPTEMP(%a6),%a0 //a0<- addr(FPTEMP)
0407 bra t_resdnrm //force UNFL(but exact) result
0408 srem_nrm:
0409 fmovel USER_FPCR(%a6),%fpcr //use user's rmode and precision
0410 fmovex FPTEMP(%a6),%fp0 //return dest to fp0
0411 rts
0412 //
0413 // FSCALE
0414 //
0415 pscalet:
0416 // ;$26 fscale
0417 // ;dtag,stag
0418 .long sscale // 00,00 norm,norm = result
0419 .long sscale // 00,01 norm,zero = fpn
0420 .long scl_opr // 00,10 norm,inf = nan with operr
0421 .long scl_snan // 00,11 norm,nan = nan
0422 .long scl_zro // 01,00 zero,norm = +-zero
0423 .long scl_zro // 01,01 zero,zero = +-zero
0424 .long scl_opr // 01,10 zero,inf = nan with operr
0425 .long scl_snan // 01,11 zero,nan = nan
0426 .long scl_inf // 10,00 inf,norm = +-inf
0427 .long scl_inf // 10,01 inf,zero = +-inf
0428 .long scl_opr // 10,10 inf,inf = nan with operr
0429 .long scl_snan // 10,11 inf,nan = nan
0430 .long scl_dnan // 11,00 nan,norm = nan
0431 .long scl_dnan // 11,01 nan,zero = nan
0432 .long scl_dnan // 11,10 nan,inf = nan
0433 .long scl_dnan // 11,11 nan,nan = nan
0434
0435 .global pscale
0436 pscale:
0437 bfextu STAG(%a6){#0:#3},%d0 //stag in d0
0438 bfextu DTAG(%a6){#0:#3},%d1 //dtag in d1
0439 bclrl #2,%d0 //alias denorm into norm
0440 bclrl #2,%d1 //alias denorm into norm
0441 lslb #2,%d1
0442 orb %d0,%d1 //d1{4:2} = dtag, d1{1:0} = stag
0443 // ;dtag values stag values:
0444 // ;000 = norm 00 = norm
0445 // ;001 = zero 01 = zero
0446 // ;010 = inf 10 = inf
0447 // ;011 = nan 11 = nan
0448 // ;100 = dnrm
0449 //
0450 //
0451 leal pscalet,%a1 //load start of jump table
0452 movel (%a1,%d1.w*4),%a1 //load a1 with label depending on tag
0453 jmp (%a1) //go to the routine
0454
0455 scl_opr:
0456 bra t_operr
0457
0458 scl_dnan:
0459 bra dst_nan
0460
0461 scl_zro:
0462 btstb #sign_bit,FPTEMP_EX(%a6) //test if + or -
0463 beq ld_pzero //if pos then load +0
0464 bra ld_mzero //if neg then load -0
0465 scl_inf:
0466 btstb #sign_bit,FPTEMP_EX(%a6) //test if + or -
0467 beq ld_pinf //if pos then load +inf
0468 bra ld_minf //else neg load -inf
0469 scl_snan:
0470 bra src_nan
0471 //
0472 // FSINCOS
0473 //
0474 .global ssincosz
0475 ssincosz:
0476 btstb #sign_bit,ETEMP(%a6) //get sign
0477 beqs sincosp
0478 fmovex MZERO,%fp0
0479 bras sincoscom
0480 sincosp:
0481 fmovex PZERO,%fp0
0482 sincoscom:
0483 fmovemx PONE,%fp1-%fp1 //do not allow FPSR to be affected
0484 bra sto_cos //store cosine result
0485
0486 .global ssincosi
0487 ssincosi:
0488 fmovex QNAN,%fp1 //load NAN
0489 bsr sto_cos //store cosine result
0490 fmovex QNAN,%fp0 //load NAN
0491 bra t_operr
0492
0493 .global ssincosnan
0494 ssincosnan:
0495 movel ETEMP_EX(%a6),FP_SCR1(%a6)
0496 movel ETEMP_HI(%a6),FP_SCR1+4(%a6)
0497 movel ETEMP_LO(%a6),FP_SCR1+8(%a6)
0498 bsetb #signan_bit,FP_SCR1+4(%a6)
0499 fmovemx FP_SCR1(%a6),%fp1-%fp1
0500 bsr sto_cos
0501 bra src_nan
0502 //
0503 // This code forces default values for the zero, inf, and nan cases
0504 // in the transcendentals code. The CC bits must be set in the
0505 // stacked FPSR to be correctly reported.
0506 //
0507 /
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561