Back to home page

LXR

 
 

    


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 //**Returns +PI/2
0508     .global ld_ppi2
0509 ld_ppi2:
0510     fmovex PPIBY2,%fp0      //load +pi/2
0511     bra t_inx2          //set inex2 exc
0512 
0513 //**Returns -PI/2
0514     .global ld_mpi2
0515 ld_mpi2:
0516     fmovex MPIBY2,%fp0      //load -pi/2
0517     orl #neg_mask,USER_FPSR(%a6)    //set N bit
0518     bra t_inx2          //set inex2 exc
0519 
0520 //**Returns +inf
0521     .global ld_pinf
0522 ld_pinf:
0523     fmovex PINF,%fp0        //load +inf
0524     orl #inf_mask,USER_FPSR(%a6)    //set I bit
0525     rts
0526 
0527 //**Returns -inf
0528     .global ld_minf
0529 ld_minf:
0530     fmovex MINF,%fp0        //load -inf
0531     orl #neg_mask+inf_mask,USER_FPSR(%a6)   //set N and I bits
0532     rts
0533 
0534 //**Returns +1
0535     .global ld_pone
0536 ld_pone:
0537     fmovex PONE,%fp0        //load +1
0538     rts
0539 
0540 //**Returns -1
0541     .global ld_mone
0542 ld_mone:
0543     fmovex MONE,%fp0        //load -1
0544     orl #neg_mask,USER_FPSR(%a6)    //set N bit
0545     rts
0546 
0547 //**Returns +0
0548     .global ld_pzero
0549 ld_pzero:
0550     fmovex PZERO,%fp0       //load +0
0551     orl #z_mask,USER_FPSR(%a6)  //set Z bit
0552     rts
0553 
0554 //**Returns -0
0555     .global ld_mzero
0556 ld_mzero:
0557     fmovex MZERO,%fp0       //load -0
0558     orl #neg_mask+z_mask,USER_FPSR(%a6) //set N and Z bits
0559     rts
0560 
0561     |end