OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [lib/] [libcpu/] [m68k/] [m68040/] [fpsp/] [do_func.S] - Rev 158

Go to most recent revision | Compare with Previous | Blame | View Log

//
//      $Id: do_func.S,v 1.1.1.1 2001-07-10 09:55:48 chris Exp $
//
//      do_func.sa 3.4 2/18/91
//
// Do_func performs the unimplemented operation.  The operation
// to be performed is determined from the lower 7 bits of the
// extension word (except in the case of fmovecr and fsincos).
// The opcode and tag bits form an index into a jump table in 
// tbldo.sa.  Cases of zero, infinity and NaN are handled in 
// do_func by forcing the default result.  Normalized and
// denormalized (there are no unnormalized numbers at this
// point) are passed onto the emulation code.  
//
// CMDREG1B and STAG are extracted from the fsave frame
// and combined to form the table index.  The function called
// will start with a0 pointing to the ETEMP operand.  Dyadic
// functions can find FPTEMP at -12(a0).
//
// Called functions return their result in fp0.  Sincos returns
// sin(x) in fp0 and cos(x) in fp1.
//

//              Copyright (C) Motorola, Inc. 1990
//                      All Rights Reserved
//
//      THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 
//      The copyright notice above does not evidence any  
//      actual or intended publication of such source code.

DO_FUNC:        //idnt    2,1 | Motorola 040 Floating Point Software Package

        |section        8

#include "fpsp.defs"

        |xref   t_dz2
        |xref   t_operr
        |xref   t_inx2
        |xref   t_resdnrm
        |xref   dst_nan
        |xref   src_nan
        |xref   nrm_set
        |xref   sto_cos

        |xref   tblpre
        |xref   slognp1,slogn,slog10,slog2
        |xref   slognd,slog10d,slog2d
        |xref   smod,srem
        |xref   sscale
        |xref   smovcr

PONE:   .long   0x3fff0000,0x80000000,0x00000000        //+1
MONE:   .long   0xbfff0000,0x80000000,0x00000000        //-1
PZERO:  .long   0x00000000,0x00000000,0x00000000        //+0
MZERO:  .long   0x80000000,0x00000000,0x00000000        //-0
PINF:   .long   0x7fff0000,0x00000000,0x00000000        //+inf
MINF:   .long   0xffff0000,0x00000000,0x00000000        //-inf
QNAN:   .long   0x7fff0000,0xffffffff,0xffffffff        //non-signaling nan
PPIBY2:  .long  0x3FFF0000,0xC90FDAA2,0x2168C235        //+PI/2
MPIBY2:  .long  0xbFFF0000,0xC90FDAA2,0x2168C235        //-PI/2

        .global do_func
do_func:
        clrb    CU_ONLY(%a6)
//
// Check for fmovecr.  It does not follow the format of fp gen
// unimplemented instructions.  The test is on the upper 6 bits;
// if they are $17, the inst is fmovecr.  Call entry smovcr
// directly.
//
        bfextu  CMDREG1B(%a6){#0:#6},%d0 //get opclass and src fields
        cmpil   #0x17,%d0               //if op class and size fields are $17, 
//                              ;it is FMOVECR; if not, continue
        bnes    not_fmovecr
        jmp     smovcr          //fmovecr; jmp directly to emulation

not_fmovecr:
        movew   CMDREG1B(%a6),%d0
        andl    #0x7F,%d0
        cmpil   #0x38,%d0               //if the extension is >= $38, 
        bge     serror          //it is illegal
        bfextu  STAG(%a6){#0:#3},%d1
        lsll    #3,%d0          //make room for STAG
        addl    %d1,%d0         //combine for final index into table
        leal    tblpre,%a1      //start of monster jump table
        movel   (%a1,%d0.w*4),%a1       //real target address
        leal    ETEMP(%a6),%a0  //a0 is pointer to src op
        movel   USER_FPCR(%a6),%d1
        andl    #0xFF,%d1               // discard all but rounding mode/prec
        fmovel  #0,%fpcr
        jmp     (%a1)
//
//      ERROR
//
        .global serror
serror:
        st      STORE_FLG(%a6)
        rts
//
// These routines load forced values into fp0.  They are called
// by index into tbldo.
//
// Load a signed zero to fp0 and set inex2/ainex
//
        .global snzrinx
snzrinx:
        btstb   #sign_bit,LOCAL_EX(%a0) //get sign of source operand
        bnes    ld_mzinx        //if negative, branch
        bsr     ld_pzero        //bsr so we can return and set inx
        bra     t_inx2          //now, set the inx for the next inst
ld_mzinx:
        bsr     ld_mzero        //if neg, load neg zero, return here
        bra     t_inx2          //now, set the inx for the next inst
//
// Load a signed zero to fp0; do not set inex2/ainex 
//
        .global szero
szero:
        btstb   #sign_bit,LOCAL_EX(%a0) //get sign of source operand
        bne     ld_mzero        //if neg, load neg zero
        bra     ld_pzero        //load positive zero
//
// Load a signed infinity to fp0; do not set inex2/ainex 
//
        .global sinf
sinf:
        btstb   #sign_bit,LOCAL_EX(%a0) //get sign of source operand
        bne     ld_minf                 //if negative branch
        bra     ld_pinf
//
// Load a signed one to fp0; do not set inex2/ainex 
//
        .global sone
sone:
        btstb   #sign_bit,LOCAL_EX(%a0) //check sign of source
        bne     ld_mone
        bra     ld_pone
//
// Load a signed pi/2 to fp0; do not set inex2/ainex 
//
        .global spi_2
spi_2:
        btstb   #sign_bit,LOCAL_EX(%a0) //check sign of source
        bne     ld_mpi2
        bra     ld_ppi2
//
// Load either a +0 or +inf for plus/minus operand
//
        .global szr_inf
szr_inf:
        btstb   #sign_bit,LOCAL_EX(%a0) //check sign of source
        bne     ld_pzero
        bra     ld_pinf
//
// Result is either an operr or +inf for plus/minus operand
// [Used by slogn, slognp1, slog10, and slog2]
//
        .global sopr_inf
sopr_inf:
        btstb   #sign_bit,LOCAL_EX(%a0) //check sign of source
        bne     t_operr
        bra     ld_pinf
//
//      FLOGNP1 
//
        .global sslognp1
sslognp1:
        fmovemx (%a0),%fp0-%fp0
        fcmpb   #-1,%fp0
        fbgt    slognp1         
        fbeq    t_dz2           //if = -1, divide by zero exception
        fmovel  #0,%FPSR                //clr N flag
        bra     t_operr         //take care of operands < -1
//
//      FETOXM1
//
        .global setoxm1i
setoxm1i:
        btstb   #sign_bit,LOCAL_EX(%a0) //check sign of source
        bne     ld_mone
        bra     ld_pinf
//
//      FLOGN
//
// Test for 1.0 as an input argument, returning +zero.  Also check
// the sign and return operr if negative.
//
        .global sslogn
sslogn:
        btstb   #sign_bit,LOCAL_EX(%a0) 
        bne     t_operr         //take care of operands < 0
        cmpiw   #0x3fff,LOCAL_EX(%a0) //test for 1.0 input
        bne     slogn
        cmpil   #0x80000000,LOCAL_HI(%a0)
        bne     slogn
        tstl    LOCAL_LO(%a0)
        bne     slogn
        fmovex  PZERO,%fp0
        rts

        .global sslognd
sslognd:
        btstb   #sign_bit,LOCAL_EX(%a0) 
        beq     slognd
        bra     t_operr         //take care of operands < 0

//
//      FLOG10
//
        .global sslog10
sslog10:
        btstb   #sign_bit,LOCAL_EX(%a0)
        bne     t_operr         //take care of operands < 0
        cmpiw   #0x3fff,LOCAL_EX(%a0) //test for 1.0 input
        bne     slog10
        cmpil   #0x80000000,LOCAL_HI(%a0)
        bne     slog10
        tstl    LOCAL_LO(%a0)
        bne     slog10
        fmovex  PZERO,%fp0
        rts

        .global sslog10d
sslog10d:
        btstb   #sign_bit,LOCAL_EX(%a0) 
        beq     slog10d
        bra     t_operr         //take care of operands < 0

//
//      FLOG2
//
        .global sslog2
sslog2:
        btstb   #sign_bit,LOCAL_EX(%a0)
        bne     t_operr         //take care of operands < 0
        cmpiw   #0x3fff,LOCAL_EX(%a0) //test for 1.0 input
        bne     slog2
        cmpil   #0x80000000,LOCAL_HI(%a0)
        bne     slog2
        tstl    LOCAL_LO(%a0)
        bne     slog2
        fmovex  PZERO,%fp0
        rts

        .global sslog2d
sslog2d:
        btstb   #sign_bit,LOCAL_EX(%a0) 
        beq     slog2d
        bra     t_operr         //take care of operands < 0

//
//      FMOD
//
pmodt:
//                              ;$21 fmod
//                              ;dtag,stag
        .long   smod            //  00,00  norm,norm = normal
        .long   smod_oper       //  00,01  norm,zero = nan with operr
        .long   smod_fpn        //  00,10  norm,inf  = fpn
        .long   smod_snan       //  00,11  norm,nan  = nan
        .long   smod_zro        //  01,00  zero,norm = +-zero
        .long   smod_oper       //  01,01  zero,zero = nan with operr
        .long   smod_zro        //  01,10  zero,inf  = +-zero
        .long   smod_snan       //  01,11  zero,nan  = nan
        .long   smod_oper       //  10,00  inf,norm  = nan with operr
        .long   smod_oper       //  10,01  inf,zero  = nan with operr
        .long   smod_oper       //  10,10  inf,inf   = nan with operr
        .long   smod_snan       //  10,11  inf,nan   = nan
        .long   smod_dnan       //  11,00  nan,norm  = nan
        .long   smod_dnan       //  11,01  nan,zero  = nan
        .long   smod_dnan       //  11,10  nan,inf   = nan
        .long   smod_dnan       //  11,11  nan,nan   = nan

        .global pmod
pmod:
        clrb    FPSR_QBYTE(%a6) // clear quotient field
        bfextu  STAG(%a6){#0:#3},%d0 //stag = d0
        bfextu  DTAG(%a6){#0:#3},%d1 //dtag = d1

//
// Alias extended denorms to norms for the jump table.
//
        bclrl   #2,%d0
        bclrl   #2,%d1

        lslb    #2,%d1
        orb     %d0,%d1         //d1{3:2} = dtag, d1{1:0} = stag
//                              ;Tag values:
//                              ;00 = norm or denorm
//                              ;01 = zero
//                              ;10 = inf
//                              ;11 = nan
        lea     pmodt,%a1
        movel   (%a1,%d1.w*4),%a1
        jmp     (%a1)

smod_snan:
        bra     src_nan
smod_dnan:
        bra     dst_nan
smod_oper:
        bra     t_operr
smod_zro:
        moveb   ETEMP(%a6),%d1  //get sign of src op
        moveb   FPTEMP(%a6),%d0 //get sign of dst op
        eorb    %d0,%d1         //get exor of sign bits
        btstl   #7,%d1          //test for sign
        beqs    smod_zsn        //if clr, do not set sign big
        bsetb   #q_sn_bit,FPSR_QBYTE(%a6) //set q-byte sign bit
smod_zsn:
        btstl   #7,%d0          //test if + or -
        beq     ld_pzero        //if pos then load +0
        bra     ld_mzero        //else neg load -0
        
smod_fpn:
        moveb   ETEMP(%a6),%d1  //get sign of src op
        moveb   FPTEMP(%a6),%d0 //get sign of dst op
        eorb    %d0,%d1         //get exor of sign bits
        btstl   #7,%d1          //test for sign
        beqs    smod_fsn        //if clr, do not set sign big
        bsetb   #q_sn_bit,FPSR_QBYTE(%a6) //set q-byte sign bit
smod_fsn:
        tstb    DTAG(%a6)       //filter out denormal destination case
        bpls    smod_nrm        //
        leal    FPTEMP(%a6),%a0 //a0<- addr(FPTEMP)
        bra     t_resdnrm       //force UNFL(but exact) result
smod_nrm:
        fmovel USER_FPCR(%a6),%fpcr //use user's rmode and precision
        fmovex FPTEMP(%a6),%fp0 //return dest to fp0
        rts
                
//
//      FREM
//
premt:
//                              ;$25 frem
//                              ;dtag,stag
        .long   srem            //  00,00  norm,norm = normal
        .long   srem_oper       //  00,01  norm,zero = nan with operr
        .long   srem_fpn        //  00,10  norm,inf  = fpn
        .long   srem_snan       //  00,11  norm,nan  = nan
        .long   srem_zro        //  01,00  zero,norm = +-zero
        .long   srem_oper       //  01,01  zero,zero = nan with operr
        .long   srem_zro        //  01,10  zero,inf  = +-zero
        .long   srem_snan       //  01,11  zero,nan  = nan
        .long   srem_oper       //  10,00  inf,norm  = nan with operr
        .long   srem_oper       //  10,01  inf,zero  = nan with operr
        .long   srem_oper       //  10,10  inf,inf   = nan with operr
        .long   srem_snan       //  10,11  inf,nan   = nan
        .long   srem_dnan       //  11,00  nan,norm  = nan
        .long   srem_dnan       //  11,01  nan,zero  = nan
        .long   srem_dnan       //  11,10  nan,inf   = nan
        .long   srem_dnan       //  11,11  nan,nan   = nan

        .global prem
prem:
        clrb    FPSR_QBYTE(%a6)   //clear quotient field
        bfextu  STAG(%a6){#0:#3},%d0 //stag = d0
        bfextu  DTAG(%a6){#0:#3},%d1 //dtag = d1
//
// Alias extended denorms to norms for the jump table.
//
        bclr    #2,%d0
        bclr    #2,%d1

        lslb    #2,%d1
        orb     %d0,%d1         //d1{3:2} = dtag, d1{1:0} = stag
//                              ;Tag values:
//                              ;00 = norm or denorm
//                              ;01 = zero
//                              ;10 = inf
//                              ;11 = nan
        lea     premt,%a1
        movel   (%a1,%d1.w*4),%a1
        jmp     (%a1)
        
srem_snan:
        bra     src_nan
srem_dnan:
        bra     dst_nan
srem_oper:
        bra     t_operr
srem_zro:
        moveb   ETEMP(%a6),%d1  //get sign of src op
        moveb   FPTEMP(%a6),%d0 //get sign of dst op
        eorb    %d0,%d1         //get exor of sign bits
        btstl   #7,%d1          //test for sign
        beqs    srem_zsn        //if clr, do not set sign big
        bsetb   #q_sn_bit,FPSR_QBYTE(%a6) //set q-byte sign bit
srem_zsn:
        btstl   #7,%d0          //test if + or -
        beq     ld_pzero        //if pos then load +0
        bra     ld_mzero        //else neg load -0
        
srem_fpn:
        moveb   ETEMP(%a6),%d1  //get sign of src op
        moveb   FPTEMP(%a6),%d0 //get sign of dst op
        eorb    %d0,%d1         //get exor of sign bits
        btstl   #7,%d1          //test for sign
        beqs    srem_fsn        //if clr, do not set sign big
        bsetb   #q_sn_bit,FPSR_QBYTE(%a6) //set q-byte sign bit
srem_fsn:
        tstb    DTAG(%a6)       //filter out denormal destination case
        bpls    srem_nrm        //
        leal    FPTEMP(%a6),%a0 //a0<- addr(FPTEMP)
        bra     t_resdnrm       //force UNFL(but exact) result
srem_nrm:
        fmovel USER_FPCR(%a6),%fpcr //use user's rmode and precision
        fmovex FPTEMP(%a6),%fp0 //return dest to fp0
        rts
//
//      FSCALE
//
pscalet:
//                              ;$26 fscale
//                              ;dtag,stag
        .long   sscale          //  00,00  norm,norm = result
        .long   sscale          //  00,01  norm,zero = fpn
        .long   scl_opr         //  00,10  norm,inf  = nan with operr
        .long   scl_snan        //  00,11  norm,nan  = nan
        .long   scl_zro         //  01,00  zero,norm = +-zero
        .long   scl_zro         //  01,01  zero,zero = +-zero
        .long   scl_opr         //  01,10  zero,inf  = nan with operr
        .long   scl_snan        //  01,11  zero,nan  = nan
        .long   scl_inf         //  10,00  inf,norm  = +-inf
        .long   scl_inf         //  10,01  inf,zero  = +-inf
        .long   scl_opr         //  10,10  inf,inf   = nan with operr
        .long   scl_snan        //  10,11  inf,nan   = nan
        .long   scl_dnan        //  11,00  nan,norm  = nan
        .long   scl_dnan        //  11,01  nan,zero  = nan
        .long   scl_dnan        //  11,10  nan,inf   = nan
        .long   scl_dnan        //  11,11  nan,nan   = nan

        .global pscale
pscale:
        bfextu  STAG(%a6){#0:#3},%d0 //stag in d0
        bfextu  DTAG(%a6){#0:#3},%d1 //dtag in d1
        bclrl   #2,%d0          //alias  denorm into norm
        bclrl   #2,%d1          //alias  denorm into norm
        lslb    #2,%d1
        orb     %d0,%d1         //d1{4:2} = dtag, d1{1:0} = stag
//                              ;dtag values     stag values:
//                              ;000 = norm      00 = norm
//                              ;001 = zero      01 = zero
//                              ;010 = inf       10 = inf
//                              ;011 = nan       11 = nan
//                              ;100 = dnrm
//
//
        leal    pscalet,%a1     //load start of jump table
        movel   (%a1,%d1.w*4),%a1       //load a1 with label depending on tag
        jmp     (%a1)           //go to the routine

scl_opr:
        bra     t_operr

scl_dnan:
        bra     dst_nan

scl_zro:
        btstb   #sign_bit,FPTEMP_EX(%a6)        //test if + or -
        beq     ld_pzero                //if pos then load +0
        bra     ld_mzero                //if neg then load -0
scl_inf:
        btstb   #sign_bit,FPTEMP_EX(%a6)        //test if + or -
        beq     ld_pinf                 //if pos then load +inf
        bra     ld_minf                 //else neg load -inf
scl_snan:
        bra     src_nan
//
//      FSINCOS
//
        .global ssincosz
ssincosz:
        btstb   #sign_bit,ETEMP(%a6)    //get sign
        beqs    sincosp
        fmovex  MZERO,%fp0
        bras    sincoscom
sincosp:
        fmovex PZERO,%fp0
sincoscom:
        fmovemx PONE,%fp1-%fp1  //do not allow FPSR to be affected
        bra     sto_cos         //store cosine result

        .global ssincosi
ssincosi:
        fmovex QNAN,%fp1        //load NAN
        bsr     sto_cos         //store cosine result
        fmovex QNAN,%fp0        //load NAN
        bra     t_operr

        .global ssincosnan
ssincosnan:
        movel   ETEMP_EX(%a6),FP_SCR1(%a6)
        movel   ETEMP_HI(%a6),FP_SCR1+4(%a6)
        movel   ETEMP_LO(%a6),FP_SCR1+8(%a6)
        bsetb   #signan_bit,FP_SCR1+4(%a6)
        fmovemx FP_SCR1(%a6),%fp1-%fp1
        bsr     sto_cos
        bra     src_nan
//
// This code forces default values for the zero, inf, and nan cases 
// in the transcendentals code.  The CC bits must be set in the
// stacked FPSR to be correctly reported.
//
//**Returns +PI/2
        .global ld_ppi2
ld_ppi2:
        fmovex PPIBY2,%fp0              //load +pi/2
        bra     t_inx2                  //set inex2 exc

//**Returns -PI/2
        .global ld_mpi2
ld_mpi2:
        fmovex MPIBY2,%fp0              //load -pi/2
        orl     #neg_mask,USER_FPSR(%a6)        //set N bit
        bra     t_inx2                  //set inex2 exc

//**Returns +inf
        .global ld_pinf
ld_pinf:
        fmovex PINF,%fp0                //load +inf
        orl     #inf_mask,USER_FPSR(%a6)        //set I bit
        rts

//**Returns -inf
        .global ld_minf
ld_minf:
        fmovex MINF,%fp0                //load -inf
        orl     #neg_mask+inf_mask,USER_FPSR(%a6)       //set N and I bits
        rts

//**Returns +1
        .global ld_pone
ld_pone:
        fmovex PONE,%fp0                //load +1
        rts

//**Returns -1
        .global ld_mone
ld_mone:
        fmovex MONE,%fp0                //load -1
        orl     #neg_mask,USER_FPSR(%a6)        //set N bit
        rts

//**Returns +0
        .global ld_pzero
ld_pzero:
        fmovex PZERO,%fp0               //load +0
        orl     #z_mask,USER_FPSR(%a6)  //set Z bit
        rts

//**Returns -0
        .global ld_mzero
ld_mzero:
        fmovex MZERO,%fp0               //load -0
        orl     #neg_mask+z_mask,USER_FPSR(%a6) //set N and Z bits
        rts

        |end

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.