diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 1998-12-14 23:15:38 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 1998-12-14 23:15:38 +0000 |
commit | 01629105c2817a59a4f1f05039593f211cf5ddaa (patch) | |
tree | 76f6bb8f9ca6ddbd015e3b81964a8dacffaf5cf9 /c/src/lib/libcpu/m68k/m68040/fpsp/res_func.s | |
parent | Patch from Ralf Corsepius <corsepiu@faw.uni-ulm.de> to rename all (diff) | |
download | rtems-01629105c2817a59a4f1f05039593f211cf5ddaa.tar.bz2 |
Patch from Ralf Corsepius <corsepiu@faw.uni-ulm.de> to rename all
.s files to .S in conformance with GNU conventions. This is a
minor step along the way to supporting automake.
Diffstat (limited to 'c/src/lib/libcpu/m68k/m68040/fpsp/res_func.s')
-rw-r--r-- | c/src/lib/libcpu/m68k/m68040/fpsp/res_func.s | 2042 |
1 files changed, 0 insertions, 2042 deletions
diff --git a/c/src/lib/libcpu/m68k/m68040/fpsp/res_func.s b/c/src/lib/libcpu/m68k/m68040/fpsp/res_func.s deleted file mode 100644 index 2f6b22870a..0000000000 --- a/c/src/lib/libcpu/m68k/m68040/fpsp/res_func.s +++ /dev/null @@ -1,2042 +0,0 @@ -// -// $Id$ -// -// res_func.sa 3.9 7/29/91 -// -// Normalizes denormalized numbers if necessary and updates the -// stack frame. The function is then restored back into the -// machine and the 040 completes the operation. This routine -// is only used by the unsupported data type/format handler. -// (Exception vector 55). -// -// For packed move out (fmove.p fpm,<ea>) the operation is -// completed here; data is packed and moved to user memory. -// The stack is restored to the 040 only in the case of a -// reportable exception in the conversion. -// -// -// 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. - -RES_FUNC: //idnt 2,1 | Motorola 040 Floating Point Software Package - - |section 8 - -#include "fpsp.defs" - -sp_bnds: .short 0x3f81,0x407e - .short 0x3f6a,0x0000 -dp_bnds: .short 0x3c01,0x43fe - .short 0x3bcd,0x0000 - - |xref mem_write - |xref bindec - |xref get_fline - |xref round - |xref denorm - |xref dest_ext - |xref dest_dbl - |xref dest_sgl - |xref unf_sub - |xref nrm_set - |xref dnrm_lp - |xref ovf_res - |xref reg_dest - |xref t_ovfl - |xref t_unfl - - .global res_func - .global p_move - -res_func: - clrb DNRM_FLG(%a6) - clrb RES_FLG(%a6) - clrb CU_ONLY(%a6) - tstb DY_MO_FLG(%a6) - beqs monadic -dyadic: - btstb #7,DTAG(%a6) //if dop = norm=000, zero=001, -// ;inf=010 or nan=011 - beqs monadic //then branch -// ;else denorm -// HANDLE DESTINATION DENORM HERE -// ;set dtag to norm -// ;write the tag & fpte15 to the fstack - leal FPTEMP(%a6),%a0 - - bclrb #sign_bit,LOCAL_EX(%a0) - sne LOCAL_SGN(%a0) - - bsr nrm_set //normalize number (exp will go negative) - bclrb #sign_bit,LOCAL_EX(%a0) //get rid of false sign - bfclr LOCAL_SGN(%a0){#0:#8} //change back to IEEE ext format - beqs dpos - bsetb #sign_bit,LOCAL_EX(%a0) -dpos: - bfclr DTAG(%a6){#0:#4} //set tag to normalized, FPTE15 = 0 - bsetb #4,DTAG(%a6) //set FPTE15 - orb #0x0f,DNRM_FLG(%a6) -monadic: - leal ETEMP(%a6),%a0 - btstb #direction_bit,CMDREG1B(%a6) //check direction - bne opclass3 //it is a mv out -// -// At this point, only opclass 0 and 2 possible -// - btstb #7,STAG(%a6) //if sop = norm=000, zero=001, -// ;inf=010 or nan=011 - bne mon_dnrm //else denorm - tstb DY_MO_FLG(%a6) //all cases of dyadic instructions would - bne normal //require normalization of denorm - -// At this point: -// monadic instructions: fabs = $18 fneg = $1a ftst = $3a -// fmove = $00 fsmove = $40 fdmove = $44 -// fsqrt = $05* fssqrt = $41 fdsqrt = $45 -// (*fsqrt reencoded to $05) -// - movew CMDREG1B(%a6),%d0 //get command register - andil #0x7f,%d0 //strip to only command word -// -// At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and -// fdsqrt are possible. -// For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize) -// For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize) -// - btstl #0,%d0 - bne normal //weed out fsqrt instructions -// -// cu_norm handles fmove in instructions with normalized inputs. -// The routine round is used to correctly round the input for the -// destination precision and mode. -// -cu_norm: - st CU_ONLY(%a6) //set cu-only inst flag - movew CMDREG1B(%a6),%d0 - andib #0x3b,%d0 //isolate bits to select inst - tstb %d0 - beql cu_nmove //if zero, it is an fmove - cmpib #0x18,%d0 - beql cu_nabs //if $18, it is fabs - cmpib #0x1a,%d0 - beql cu_nneg //if $1a, it is fneg -// -// Inst is ftst. Check the source operand and set the cc's accordingly. -// No write is done, so simply rts. -// -cu_ntst: - movew LOCAL_EX(%a0),%d0 - bclrl #15,%d0 - sne LOCAL_SGN(%a0) - beqs cu_ntpo - orl #neg_mask,USER_FPSR(%a6) //set N -cu_ntpo: - cmpiw #0x7fff,%d0 //test for inf/nan - bnes cu_ntcz - tstl LOCAL_HI(%a0) - bnes cu_ntn - tstl LOCAL_LO(%a0) - bnes cu_ntn - orl #inf_mask,USER_FPSR(%a6) - rts -cu_ntn: - orl #nan_mask,USER_FPSR(%a6) - movel ETEMP_EX(%a6),FPTEMP_EX(%a6) //set up fptemp sign for -// ;snan handler - - rts -cu_ntcz: - tstl LOCAL_HI(%a0) - bnel cu_ntsx - tstl LOCAL_LO(%a0) - bnel cu_ntsx - orl #z_mask,USER_FPSR(%a6) -cu_ntsx: - rts -// -// Inst is fabs. Execute the absolute value function on the input. -// Branch to the fmove code. If the operand is NaN, do nothing. -// -cu_nabs: - moveb STAG(%a6),%d0 - btstl #5,%d0 //test for NaN or zero - bne wr_etemp //if either, simply write it - bclrb #7,LOCAL_EX(%a0) //do abs - bras cu_nmove //fmove code will finish -// -// Inst is fneg. Execute the negate value function on the input. -// Fall though to the fmove code. If the operand is NaN, do nothing. -// -cu_nneg: - moveb STAG(%a6),%d0 - btstl #5,%d0 //test for NaN or zero - bne wr_etemp //if either, simply write it - bchgb #7,LOCAL_EX(%a0) //do neg -// -// Inst is fmove. This code also handles all result writes. -// If bit 2 is set, round is forced to double. If it is clear, -// and bit 6 is set, round is forced to single. If both are clear, -// the round precision is found in the fpcr. If the rounding precision -// is double or single, round the result before the write. -// -cu_nmove: - moveb STAG(%a6),%d0 - andib #0xe0,%d0 //isolate stag bits - bne wr_etemp //if not norm, simply write it - btstb #2,CMDREG1B+1(%a6) //check for rd - bne cu_nmrd - btstb #6,CMDREG1B+1(%a6) //check for rs - bne cu_nmrs -// -// The move or operation is not with forced precision. Test for -// nan or inf as the input; if so, simply write it to FPn. Use the -// FPCR_MODE byte to get rounding on norms and zeros. -// -cu_nmnr: - bfextu FPCR_MODE(%a6){#0:#2},%d0 - tstb %d0 //check for extended - beq cu_wrexn //if so, just write result - cmpib #1,%d0 //check for single - beq cu_nmrs //fall through to double -// -// The move is fdmove or round precision is double. -// -cu_nmrd: - movel #2,%d0 //set up the size for denorm - movew LOCAL_EX(%a0),%d1 //compare exponent to double threshold - andw #0x7fff,%d1 - cmpw #0x3c01,%d1 - bls cu_nunfl - bfextu FPCR_MODE(%a6){#2:#2},%d1 //get rmode - orl #0x00020000,%d1 //or in rprec (double) - clrl %d0 //clear g,r,s for round - bclrb #sign_bit,LOCAL_EX(%a0) //convert to internal format - sne LOCAL_SGN(%a0) - bsrl round - bfclr LOCAL_SGN(%a0){#0:#8} - beqs cu_nmrdc - bsetb #sign_bit,LOCAL_EX(%a0) -cu_nmrdc: - movew LOCAL_EX(%a0),%d1 //check for overflow - andw #0x7fff,%d1 - cmpw #0x43ff,%d1 - bge cu_novfl //take care of overflow case - bra cu_wrexn -// -// The move is fsmove or round precision is single. -// -cu_nmrs: - movel #1,%d0 - movew LOCAL_EX(%a0),%d1 - andw #0x7fff,%d1 - cmpw #0x3f81,%d1 - bls cu_nunfl - bfextu FPCR_MODE(%a6){#2:#2},%d1 - orl #0x00010000,%d1 - clrl %d0 - bclrb #sign_bit,LOCAL_EX(%a0) - sne LOCAL_SGN(%a0) - bsrl round - bfclr LOCAL_SGN(%a0){#0:#8} - beqs cu_nmrsc - bsetb #sign_bit,LOCAL_EX(%a0) -cu_nmrsc: - movew LOCAL_EX(%a0),%d1 - andw #0x7FFF,%d1 - cmpw #0x407f,%d1 - blt cu_wrexn -// -// The operand is above precision boundaries. Use t_ovfl to -// generate the correct value. -// -cu_novfl: - bsr t_ovfl - bra cu_wrexn -// -// The operand is below precision boundaries. Use denorm to -// generate the correct value. -// -cu_nunfl: - bclrb #sign_bit,LOCAL_EX(%a0) - sne LOCAL_SGN(%a0) - bsr denorm - bfclr LOCAL_SGN(%a0){#0:#8} //change back to IEEE ext format - beqs cu_nucont - bsetb #sign_bit,LOCAL_EX(%a0) -cu_nucont: - bfextu FPCR_MODE(%a6){#2:#2},%d1 - btstb #2,CMDREG1B+1(%a6) //check for rd - bne inst_d - btstb #6,CMDREG1B+1(%a6) //check for rs - bne inst_s - swap %d1 - moveb FPCR_MODE(%a6),%d1 - lsrb #6,%d1 - swap %d1 - bra inst_sd -inst_d: - orl #0x00020000,%d1 - bra inst_sd -inst_s: - orl #0x00010000,%d1 -inst_sd: - bclrb #sign_bit,LOCAL_EX(%a0) - sne LOCAL_SGN(%a0) - bsrl round - bfclr LOCAL_SGN(%a0){#0:#8} - beqs cu_nuflp - bsetb #sign_bit,LOCAL_EX(%a0) -cu_nuflp: - btstb #inex2_bit,FPSR_EXCEPT(%a6) - beqs cu_nuninx - orl #aunfl_mask,USER_FPSR(%a6) //if the round was inex, set AUNFL -cu_nuninx: - tstl LOCAL_HI(%a0) //test for zero - bnes cu_nunzro - tstl LOCAL_LO(%a0) - bnes cu_nunzro -// -// The mantissa is zero from the denorm loop. Check sign and rmode -// to see if rounding should have occurred which would leave the lsb. -// - movel USER_FPCR(%a6),%d0 - andil #0x30,%d0 //isolate rmode - cmpil #0x20,%d0 - blts cu_nzro - bnes cu_nrp -cu_nrm: - tstw LOCAL_EX(%a0) //if positive, set lsb - bges cu_nzro - btstb #7,FPCR_MODE(%a6) //check for double - beqs cu_nincs - bras cu_nincd -cu_nrp: - tstw LOCAL_EX(%a0) //if positive, set lsb - blts cu_nzro - btstb #7,FPCR_MODE(%a6) //check for double - beqs cu_nincs -cu_nincd: - orl #0x800,LOCAL_LO(%a0) //inc for double - bra cu_nunzro -cu_nincs: - orl #0x100,LOCAL_HI(%a0) //inc for single - bra cu_nunzro -cu_nzro: - orl #z_mask,USER_FPSR(%a6) - moveb STAG(%a6),%d0 - andib #0xe0,%d0 - cmpib #0x40,%d0 //check if input was tagged zero - beqs cu_numv -cu_nunzro: - orl #unfl_mask,USER_FPSR(%a6) //set unfl -cu_numv: - movel (%a0),ETEMP(%a6) - movel 4(%a0),ETEMP_HI(%a6) - movel 8(%a0),ETEMP_LO(%a6) -// -// Write the result to memory, setting the fpsr cc bits. NaN and Inf -// bypass cu_wrexn. -// -cu_wrexn: - tstw LOCAL_EX(%a0) //test for zero - beqs cu_wrzero - cmpw #0x8000,LOCAL_EX(%a0) //test for zero - bnes cu_wreon -cu_wrzero: - orl #z_mask,USER_FPSR(%a6) //set Z bit -cu_wreon: - tstw LOCAL_EX(%a0) - bpl wr_etemp - orl #neg_mask,USER_FPSR(%a6) - bra wr_etemp - -// -// HANDLE SOURCE DENORM HERE -// -// ;clear denorm stag to norm -// ;write the new tag & ete15 to the fstack -mon_dnrm: -// -// At this point, check for the cases in which normalizing the -// denorm produces incorrect results. -// - tstb DY_MO_FLG(%a6) //all cases of dyadic instructions would - bnes nrm_src //require normalization of denorm - -// At this point: -// monadic instructions: fabs = $18 fneg = $1a ftst = $3a -// fmove = $00 fsmove = $40 fdmove = $44 -// fsqrt = $05* fssqrt = $41 fdsqrt = $45 -// (*fsqrt reencoded to $05) -// - movew CMDREG1B(%a6),%d0 //get command register - andil #0x7f,%d0 //strip to only command word -// -// At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and -// fdsqrt are possible. -// For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize) -// For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize) -// - btstl #0,%d0 - bnes nrm_src //weed out fsqrt instructions - st CU_ONLY(%a6) //set cu-only inst flag - bra cu_dnrm //fmove, fabs, fneg, ftst -// ;cases go to cu_dnrm -nrm_src: - bclrb #sign_bit,LOCAL_EX(%a0) - sne LOCAL_SGN(%a0) - bsr nrm_set //normalize number (exponent will go -// ; negative) - bclrb #sign_bit,LOCAL_EX(%a0) //get rid of false sign - - bfclr LOCAL_SGN(%a0){#0:#8} //change back to IEEE ext format - beqs spos - bsetb #sign_bit,LOCAL_EX(%a0) -spos: - bfclr STAG(%a6){#0:#4} //set tag to normalized, FPTE15 = 0 - bsetb #4,STAG(%a6) //set ETE15 - orb #0xf0,DNRM_FLG(%a6) -normal: - tstb DNRM_FLG(%a6) //check if any of the ops were denorms - bne ck_wrap //if so, check if it is a potential -// ;wrap-around case -fix_stk: - moveb #0xfe,CU_SAVEPC(%a6) - bclrb #E1,E_BYTE(%a6) - - clrw NMNEXC(%a6) - - st RES_FLG(%a6) //indicate that a restore is needed - rts - -// -// cu_dnrm handles all cu-only instructions (fmove, fabs, fneg, and -// ftst) completely in software without an frestore to the 040. -// -cu_dnrm: - st CU_ONLY(%a6) - movew CMDREG1B(%a6),%d0 - andib #0x3b,%d0 //isolate bits to select inst - tstb %d0 - beql cu_dmove //if zero, it is an fmove - cmpib #0x18,%d0 - beql cu_dabs //if $18, it is fabs - cmpib #0x1a,%d0 - beql cu_dneg //if $1a, it is fneg -// -// Inst is ftst. Check the source operand and set the cc's accordingly. -// No write is done, so simply rts. -// -cu_dtst: - movew LOCAL_EX(%a0),%d0 - bclrl #15,%d0 - sne LOCAL_SGN(%a0) - beqs cu_dtpo - orl #neg_mask,USER_FPSR(%a6) //set N -cu_dtpo: - cmpiw #0x7fff,%d0 //test for inf/nan - bnes cu_dtcz - tstl LOCAL_HI(%a0) - bnes cu_dtn - tstl LOCAL_LO(%a0) - bnes cu_dtn - orl #inf_mask,USER_FPSR(%a6) - rts -cu_dtn: - orl #nan_mask,USER_FPSR(%a6) - movel ETEMP_EX(%a6),FPTEMP_EX(%a6) //set up fptemp sign for -// ;snan handler - rts -cu_dtcz: - tstl LOCAL_HI(%a0) - bnel cu_dtsx - tstl LOCAL_LO(%a0) - bnel cu_dtsx - orl #z_mask,USER_FPSR(%a6) -cu_dtsx: - rts -// -// Inst is fabs. Execute the absolute value function on the input. -// Branch to the fmove code. -// -cu_dabs: - bclrb #7,LOCAL_EX(%a0) //do abs - bras cu_dmove //fmove code will finish -// -// Inst is fneg. Execute the negate value function on the input. -// Fall though to the fmove code. -// -cu_dneg: - bchgb #7,LOCAL_EX(%a0) //do neg -// -// Inst is fmove. This code also handles all result writes. -// If bit 2 is set, round is forced to double. If it is clear, -// and bit 6 is set, round is forced to single. If both are clear, -// the round precision is found in the fpcr. If the rounding precision -// is double or single, the result is zero, and the mode is checked -// to determine if the lsb of the result should be set. -// -cu_dmove: - btstb #2,CMDREG1B+1(%a6) //check for rd - bne cu_dmrd - btstb #6,CMDREG1B+1(%a6) //check for rs - bne cu_dmrs -// -// The move or operation is not with forced precision. Use the -// FPCR_MODE byte to get rounding. -// -cu_dmnr: - bfextu FPCR_MODE(%a6){#0:#2},%d0 - tstb %d0 //check for extended - beq cu_wrexd //if so, just write result - cmpib #1,%d0 //check for single - beq cu_dmrs //fall through to double -// -// The move is fdmove or round precision is double. Result is zero. -// Check rmode for rp or rm and set lsb accordingly. -// -cu_dmrd: - bfextu FPCR_MODE(%a6){#2:#2},%d1 //get rmode - tstw LOCAL_EX(%a0) //check sign - blts cu_dmdn - cmpib #3,%d1 //check for rp - bne cu_dpd //load double pos zero - bra cu_dpdr //load double pos zero w/lsb -cu_dmdn: - cmpib #2,%d1 //check for rm - bne cu_dnd //load double neg zero - bra cu_dndr //load double neg zero w/lsb -// -// The move is fsmove or round precision is single. Result is zero. -// Check for rp or rm and set lsb accordingly. -// -cu_dmrs: - bfextu FPCR_MODE(%a6){#2:#2},%d1 //get rmode - tstw LOCAL_EX(%a0) //check sign - blts cu_dmsn - cmpib #3,%d1 //check for rp - bne cu_spd //load single pos zero - bra cu_spdr //load single pos zero w/lsb -cu_dmsn: - cmpib #2,%d1 //check for rm - bne cu_snd //load single neg zero - bra cu_sndr //load single neg zero w/lsb -// -// The precision is extended, so the result in etemp is correct. -// Simply set unfl (not inex2 or aunfl) and write the result to -// the correct fp register. -cu_wrexd: - orl #unfl_mask,USER_FPSR(%a6) - tstw LOCAL_EX(%a0) - beq wr_etemp - orl #neg_mask,USER_FPSR(%a6) - bra wr_etemp -// -// These routines write +/- zero in double format. The routines -// cu_dpdr and cu_dndr set the double lsb. -// -cu_dpd: - movel #0x3c010000,LOCAL_EX(%a0) //force pos double zero - clrl LOCAL_HI(%a0) - clrl LOCAL_LO(%a0) - orl #z_mask,USER_FPSR(%a6) - orl #unfinx_mask,USER_FPSR(%a6) - bra wr_etemp -cu_dpdr: - movel #0x3c010000,LOCAL_EX(%a0) //force pos double zero - clrl LOCAL_HI(%a0) - movel #0x800,LOCAL_LO(%a0) //with lsb set - orl #unfinx_mask,USER_FPSR(%a6) - bra wr_etemp -cu_dnd: - movel #0xbc010000,LOCAL_EX(%a0) //force pos double zero - clrl LOCAL_HI(%a0) - clrl LOCAL_LO(%a0) - orl #z_mask,USER_FPSR(%a6) - orl #neg_mask,USER_FPSR(%a6) - orl #unfinx_mask,USER_FPSR(%a6) - bra wr_etemp -cu_dndr: - movel #0xbc010000,LOCAL_EX(%a0) //force pos double zero - clrl LOCAL_HI(%a0) - movel #0x800,LOCAL_LO(%a0) //with lsb set - orl #neg_mask,USER_FPSR(%a6) - orl #unfinx_mask,USER_FPSR(%a6) - bra wr_etemp -// -// These routines write +/- zero in single format. The routines -// cu_dpdr and cu_dndr set the single lsb. -// -cu_spd: - movel #0x3f810000,LOCAL_EX(%a0) //force pos single zero - clrl LOCAL_HI(%a0) - clrl LOCAL_LO(%a0) - orl #z_mask,USER_FPSR(%a6) - orl #unfinx_mask,USER_FPSR(%a6) - bra wr_etemp -cu_spdr: - movel #0x3f810000,LOCAL_EX(%a0) //force pos single zero - movel #0x100,LOCAL_HI(%a0) //with lsb set - clrl LOCAL_LO(%a0) - orl #unfinx_mask,USER_FPSR(%a6) - bra wr_etemp -cu_snd: - movel #0xbf810000,LOCAL_EX(%a0) //force pos single zero - clrl LOCAL_HI(%a0) - clrl LOCAL_LO(%a0) - orl #z_mask,USER_FPSR(%a6) - orl #neg_mask,USER_FPSR(%a6) - orl #unfinx_mask,USER_FPSR(%a6) - bra wr_etemp -cu_sndr: - movel #0xbf810000,LOCAL_EX(%a0) //force pos single zero - movel #0x100,LOCAL_HI(%a0) //with lsb set - clrl LOCAL_LO(%a0) - orl #neg_mask,USER_FPSR(%a6) - orl #unfinx_mask,USER_FPSR(%a6) - bra wr_etemp - -// -// This code checks for 16-bit overflow conditions on dyadic -// operations which are not restorable into the floating-point -// unit and must be completed in software. Basically, this -// condition exists with a very large norm and a denorm. One -// of the operands must be denormalized to enter this code. -// -// Flags used: -// DY_MO_FLG contains 0 for monadic op, $ff for dyadic -// DNRM_FLG contains $00 for neither op denormalized -// $0f for the destination op denormalized -// $f0 for the source op denormalized -// $ff for both ops denormalized -// -// The wrap-around condition occurs for add, sub, div, and cmp -// when -// -// abs(dest_exp - src_exp) >= $8000 -// -// and for mul when -// -// (dest_exp + src_exp) < $0 -// -// we must process the operation here if this case is true. -// -// The rts following the frcfpn routine is the exit from res_func -// for this condition. The restore flag (RES_FLG) is left clear. -// No frestore is done unless an exception is to be reported. -// -// For fadd: -// if(sign_of(dest) != sign_of(src)) -// replace exponent of src with $3fff (keep sign) -// use fpu to perform dest+new_src (user's rmode and X) -// clr sticky -// else -// set sticky -// call round with user's precision and mode -// move result to fpn and wbtemp -// -// For fsub: -// if(sign_of(dest) == sign_of(src)) -// replace exponent of src with $3fff (keep sign) -// use fpu to perform dest+new_src (user's rmode and X) -// clr sticky -// else -// set sticky -// call round with user's precision and mode -// move result to fpn and wbtemp -// -// For fdiv/fsgldiv: -// if(both operands are denorm) -// restore_to_fpu; -// if(dest is norm) -// force_ovf; -// else(dest is denorm) -// force_unf: -// -// For fcmp: -// if(dest is norm) -// N = sign_of(dest); -// else(dest is denorm) -// N = sign_of(src); -// -// For fmul: -// if(both operands are denorm) -// force_unf; -// if((dest_exp + src_exp) < 0) -// force_unf: -// else -// restore_to_fpu; -// -// local equates: - .set addcode,0x22 - .set subcode,0x28 - .set mulcode,0x23 - .set divcode,0x20 - .set cmpcode,0x38 -ck_wrap: - | tstb DY_MO_FLG(%a6) ;check for fsqrt - beq fix_stk //if zero, it is fsqrt - movew CMDREG1B(%a6),%d0 - andiw #0x3b,%d0 //strip to command bits - cmpiw #addcode,%d0 - beq wrap_add - cmpiw #subcode,%d0 - beq wrap_sub - cmpiw #mulcode,%d0 - beq wrap_mul - cmpiw #cmpcode,%d0 - beq wrap_cmp -// -// Inst is fdiv. -// -wrap_div: - cmpb #0xff,DNRM_FLG(%a6) //if both ops denorm, - beq fix_stk //restore to fpu -// -// One of the ops is denormalized. Test for wrap condition -// and force the result. -// - cmpb #0x0f,DNRM_FLG(%a6) //check for dest denorm - bnes div_srcd -div_destd: - bsrl ckinf_ns - bne fix_stk - bfextu ETEMP_EX(%a6){#1:#15},%d0 //get src exp (always pos) - bfexts FPTEMP_EX(%a6){#1:#15},%d1 //get dest exp (always neg) - subl %d1,%d0 //subtract dest from src - cmpl #0x7fff,%d0 - blt fix_stk //if less, not wrap case - clrb WBTEMP_SGN(%a6) - movew ETEMP_EX(%a6),%d0 //find the sign of the result - movew FPTEMP_EX(%a6),%d1 - eorw %d1,%d0 - andiw #0x8000,%d0 - beq force_unf - st WBTEMP_SGN(%a6) - bra force_unf - -ckinf_ns: - moveb STAG(%a6),%d0 //check source tag for inf or nan - bra ck_in_com -ckinf_nd: - moveb DTAG(%a6),%d0 //check destination tag for inf or nan -ck_in_com: - andib #0x60,%d0 //isolate tag bits - cmpb #0x40,%d0 //is it inf? - beq nan_or_inf //not wrap case - cmpb #0x60,%d0 //is it nan? - beq nan_or_inf //yes, not wrap case? - cmpb #0x20,%d0 //is it a zero? - beq nan_or_inf //yes - clrl %d0 - rts //then ; it is either a zero of norm, -// ;check wrap case -nan_or_inf: - moveql #-1,%d0 - rts - - - -div_srcd: - bsrl ckinf_nd - bne fix_stk - bfextu FPTEMP_EX(%a6){#1:#15},%d0 //get dest exp (always pos) - bfexts ETEMP_EX(%a6){#1:#15},%d1 //get src exp (always neg) - subl %d1,%d0 //subtract src from dest - cmpl #0x8000,%d0 - blt fix_stk //if less, not wrap case - clrb WBTEMP_SGN(%a6) - movew ETEMP_EX(%a6),%d0 //find the sign of the result - movew FPTEMP_EX(%a6),%d1 - eorw %d1,%d0 - andiw #0x8000,%d0 - beqs force_ovf - st WBTEMP_SGN(%a6) -// -// This code handles the case of the instruction resulting in -// an overflow condition. -// -force_ovf: - bclrb #E1,E_BYTE(%a6) - orl #ovfl_inx_mask,USER_FPSR(%a6) - clrw NMNEXC(%a6) - leal WBTEMP(%a6),%a0 //point a0 to memory location - movew CMDREG1B(%a6),%d0 - btstl #6,%d0 //test for forced precision - beqs frcovf_fpcr - btstl #2,%d0 //check for double - bnes frcovf_dbl - movel #0x1,%d0 //inst is forced single - bras frcovf_rnd -frcovf_dbl: - movel #0x2,%d0 //inst is forced double - bras frcovf_rnd -frcovf_fpcr: - bfextu FPCR_MODE(%a6){#0:#2},%d0 //inst not forced - use fpcr prec -frcovf_rnd: - -// The 881/882 does not set inex2 for the following case, so the -// line is commented out to be compatible with 881/882 -// tst.b %d0 -// beq.b frcovf_x -// or.l #inex2_mask,USER_FPSR(%a6) ;if prec is s or d, set inex2 - -//frcovf_x: - bsrl ovf_res //get correct result based on -// ;round precision/mode. This -// ;sets FPSR_CC correctly -// ;returns in external format - bfclr WBTEMP_SGN(%a6){#0:#8} - beq frcfpn - bsetb #sign_bit,WBTEMP_EX(%a6) - bra frcfpn -// -// Inst is fadd. -// -wrap_add: - cmpb #0xff,DNRM_FLG(%a6) //if both ops denorm, - beq fix_stk //restore to fpu -// -// One of the ops is denormalized. Test for wrap condition -// and complete the instruction. -// - cmpb #0x0f,DNRM_FLG(%a6) //check for dest denorm - bnes add_srcd -add_destd: - bsrl ckinf_ns - bne fix_stk - bfextu ETEMP_EX(%a6){#1:#15},%d0 //get src exp (always pos) - bfexts FPTEMP_EX(%a6){#1:#15},%d1 //get dest exp (always neg) - subl %d1,%d0 //subtract dest from src - cmpl #0x8000,%d0 - blt fix_stk //if less, not wrap case - bra add_wrap -add_srcd: - bsrl ckinf_nd - bne fix_stk - bfextu FPTEMP_EX(%a6){#1:#15},%d0 //get dest exp (always pos) - bfexts ETEMP_EX(%a6){#1:#15},%d1 //get src exp (always neg) - subl %d1,%d0 //subtract src from dest - cmpl #0x8000,%d0 - blt fix_stk //if less, not wrap case -// -// Check the signs of the operands. If they are unlike, the fpu -// can be used to add the norm and 1.0 with the sign of the -// denorm and it will correctly generate the result in extended -// precision. We can then call round with no sticky and the result -// will be correct for the user's rounding mode and precision. If -// the signs are the same, we call round with the sticky bit set -// and the result will be correct for the user's rounding mode and -// precision. -// -add_wrap: - movew ETEMP_EX(%a6),%d0 - movew FPTEMP_EX(%a6),%d1 - eorw %d1,%d0 - andiw #0x8000,%d0 - beq add_same -// -// The signs are unlike. -// - cmpb #0x0f,DNRM_FLG(%a6) //is dest the denorm? - bnes add_u_srcd - movew FPTEMP_EX(%a6),%d0 - andiw #0x8000,%d0 - orw #0x3fff,%d0 //force the exponent to +/- 1 - movew %d0,FPTEMP_EX(%a6) //in the denorm - movel USER_FPCR(%a6),%d0 - andil #0x30,%d0 - fmovel %d0,%fpcr //set up users rmode and X - fmovex ETEMP(%a6),%fp0 - faddx FPTEMP(%a6),%fp0 - leal WBTEMP(%a6),%a0 //point a0 to wbtemp in frame - fmovel %fpsr,%d1 - orl %d1,USER_FPSR(%a6) //capture cc's and inex from fadd - fmovex %fp0,WBTEMP(%a6) //write result to memory - lsrl #4,%d0 //put rmode in lower 2 bits - movel USER_FPCR(%a6),%d1 - andil #0xc0,%d1 - lsrl #6,%d1 //put precision in upper word - swap %d1 - orl %d0,%d1 //set up for round call - clrl %d0 //force sticky to zero - bclrb #sign_bit,WBTEMP_EX(%a6) - sne WBTEMP_SGN(%a6) - bsrl round //round result to users rmode & prec - bfclr WBTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format - beq frcfpnr - bsetb #sign_bit,WBTEMP_EX(%a6) - bra frcfpnr -add_u_srcd: - movew ETEMP_EX(%a6),%d0 - andiw #0x8000,%d0 - orw #0x3fff,%d0 //force the exponent to +/- 1 - movew %d0,ETEMP_EX(%a6) //in the denorm - movel USER_FPCR(%a6),%d0 - andil #0x30,%d0 - fmovel %d0,%fpcr //set up users rmode and X - fmovex ETEMP(%a6),%fp0 - faddx FPTEMP(%a6),%fp0 - fmovel %fpsr,%d1 - orl %d1,USER_FPSR(%a6) //capture cc's and inex from fadd - leal WBTEMP(%a6),%a0 //point a0 to wbtemp in frame - fmovex %fp0,WBTEMP(%a6) //write result to memory - lsrl #4,%d0 //put rmode in lower 2 bits - movel USER_FPCR(%a6),%d1 - andil #0xc0,%d1 - lsrl #6,%d1 //put precision in upper word - swap %d1 - orl %d0,%d1 //set up for round call - clrl %d0 //force sticky to zero - bclrb #sign_bit,WBTEMP_EX(%a6) - sne WBTEMP_SGN(%a6) //use internal format for round - bsrl round //round result to users rmode & prec - bfclr WBTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format - beq frcfpnr - bsetb #sign_bit,WBTEMP_EX(%a6) - bra frcfpnr -// -// Signs are alike: -// -add_same: - cmpb #0x0f,DNRM_FLG(%a6) //is dest the denorm? - bnes add_s_srcd -add_s_destd: - leal ETEMP(%a6),%a0 - movel USER_FPCR(%a6),%d0 - andil #0x30,%d0 - lsrl #4,%d0 //put rmode in lower 2 bits - movel USER_FPCR(%a6),%d1 - andil #0xc0,%d1 - lsrl #6,%d1 //put precision in upper word - swap %d1 - orl %d0,%d1 //set up for round call - movel #0x20000000,%d0 //set sticky for round - bclrb #sign_bit,ETEMP_EX(%a6) - sne ETEMP_SGN(%a6) - bsrl round //round result to users rmode & prec - bfclr ETEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format - beqs add_s_dclr - bsetb #sign_bit,ETEMP_EX(%a6) -add_s_dclr: - leal WBTEMP(%a6),%a0 - movel ETEMP(%a6),(%a0) //write result to wbtemp - movel ETEMP_HI(%a6),4(%a0) - movel ETEMP_LO(%a6),8(%a0) - tstw ETEMP_EX(%a6) - bgt add_ckovf - orl #neg_mask,USER_FPSR(%a6) - bra add_ckovf -add_s_srcd: - leal FPTEMP(%a6),%a0 - movel USER_FPCR(%a6),%d0 - andil #0x30,%d0 - lsrl #4,%d0 //put rmode in lower 2 bits - movel USER_FPCR(%a6),%d1 - andil #0xc0,%d1 - lsrl #6,%d1 //put precision in upper word - swap %d1 - orl %d0,%d1 //set up for round call - movel #0x20000000,%d0 //set sticky for round - bclrb #sign_bit,FPTEMP_EX(%a6) - sne FPTEMP_SGN(%a6) - bsrl round //round result to users rmode & prec - bfclr FPTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format - beqs add_s_sclr - bsetb #sign_bit,FPTEMP_EX(%a6) -add_s_sclr: - leal WBTEMP(%a6),%a0 - movel FPTEMP(%a6),(%a0) //write result to wbtemp - movel FPTEMP_HI(%a6),4(%a0) - movel FPTEMP_LO(%a6),8(%a0) - tstw FPTEMP_EX(%a6) - bgt add_ckovf - orl #neg_mask,USER_FPSR(%a6) -add_ckovf: - movew WBTEMP_EX(%a6),%d0 - andiw #0x7fff,%d0 - cmpiw #0x7fff,%d0 - bne frcfpnr -// -// The result has overflowed to $7fff exponent. Set I, ovfl, -// and aovfl, and clr the mantissa (incorrectly set by the -// round routine.) -// - orl #inf_mask+ovfl_inx_mask,USER_FPSR(%a6) - clrl 4(%a0) - bra frcfpnr -// -// Inst is fsub. -// -wrap_sub: - cmpb #0xff,DNRM_FLG(%a6) //if both ops denorm, - beq fix_stk //restore to fpu -// -// One of the ops is denormalized. Test for wrap condition -// and complete the instruction. -// - cmpb #0x0f,DNRM_FLG(%a6) //check for dest denorm - bnes sub_srcd -sub_destd: - bsrl ckinf_ns - bne fix_stk - bfextu ETEMP_EX(%a6){#1:#15},%d0 //get src exp (always pos) - bfexts FPTEMP_EX(%a6){#1:#15},%d1 //get dest exp (always neg) - subl %d1,%d0 //subtract src from dest - cmpl #0x8000,%d0 - blt fix_stk //if less, not wrap case - bra sub_wrap -sub_srcd: - bsrl ckinf_nd - bne fix_stk - bfextu FPTEMP_EX(%a6){#1:#15},%d0 //get dest exp (always pos) - bfexts ETEMP_EX(%a6){#1:#15},%d1 //get src exp (always neg) - subl %d1,%d0 //subtract dest from src - cmpl #0x8000,%d0 - blt fix_stk //if less, not wrap case -// -// Check the signs of the operands. If they are alike, the fpu -// can be used to subtract from the norm 1.0 with the sign of the -// denorm and it will correctly generate the result in extended -// precision. We can then call round with no sticky and the result -// will be correct for the user's rounding mode and precision. If -// the signs are unlike, we call round with the sticky bit set -// and the result will be correct for the user's rounding mode and -// precision. -// -sub_wrap: - movew ETEMP_EX(%a6),%d0 - movew FPTEMP_EX(%a6),%d1 - eorw %d1,%d0 - andiw #0x8000,%d0 - bne sub_diff -// -// The signs are alike. -// - cmpb #0x0f,DNRM_FLG(%a6) //is dest the denorm? - bnes sub_u_srcd - movew FPTEMP_EX(%a6),%d0 - andiw #0x8000,%d0 - orw #0x3fff,%d0 //force the exponent to +/- 1 - movew %d0,FPTEMP_EX(%a6) //in the denorm - movel USER_FPCR(%a6),%d0 - andil #0x30,%d0 - fmovel %d0,%fpcr //set up users rmode and X - fmovex FPTEMP(%a6),%fp0 - fsubx ETEMP(%a6),%fp0 - fmovel %fpsr,%d1 - orl %d1,USER_FPSR(%a6) //capture cc's and inex from fadd - leal WBTEMP(%a6),%a0 //point a0 to wbtemp in frame - fmovex %fp0,WBTEMP(%a6) //write result to memory - lsrl #4,%d0 //put rmode in lower 2 bits - movel USER_FPCR(%a6),%d1 - andil #0xc0,%d1 - lsrl #6,%d1 //put precision in upper word - swap %d1 - orl %d0,%d1 //set up for round call - clrl %d0 //force sticky to zero - bclrb #sign_bit,WBTEMP_EX(%a6) - sne WBTEMP_SGN(%a6) - bsrl round //round result to users rmode & prec - bfclr WBTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format - beq frcfpnr - bsetb #sign_bit,WBTEMP_EX(%a6) - bra frcfpnr -sub_u_srcd: - movew ETEMP_EX(%a6),%d0 - andiw #0x8000,%d0 - orw #0x3fff,%d0 //force the exponent to +/- 1 - movew %d0,ETEMP_EX(%a6) //in the denorm - movel USER_FPCR(%a6),%d0 - andil #0x30,%d0 - fmovel %d0,%fpcr //set up users rmode and X - fmovex FPTEMP(%a6),%fp0 - fsubx ETEMP(%a6),%fp0 - fmovel %fpsr,%d1 - orl %d1,USER_FPSR(%a6) //capture cc's and inex from fadd - leal WBTEMP(%a6),%a0 //point a0 to wbtemp in frame - fmovex %fp0,WBTEMP(%a6) //write result to memory - lsrl #4,%d0 //put rmode in lower 2 bits - movel USER_FPCR(%a6),%d1 - andil #0xc0,%d1 - lsrl #6,%d1 //put precision in upper word - swap %d1 - orl %d0,%d1 //set up for round call - clrl %d0 //force sticky to zero - bclrb #sign_bit,WBTEMP_EX(%a6) - sne WBTEMP_SGN(%a6) - bsrl round //round result to users rmode & prec - bfclr WBTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format - beq frcfpnr - bsetb #sign_bit,WBTEMP_EX(%a6) - bra frcfpnr -// -// Signs are unlike: -// -sub_diff: - cmpb #0x0f,DNRM_FLG(%a6) //is dest the denorm? - bnes sub_s_srcd -sub_s_destd: - leal ETEMP(%a6),%a0 - movel USER_FPCR(%a6),%d0 - andil #0x30,%d0 - lsrl #4,%d0 //put rmode in lower 2 bits - movel USER_FPCR(%a6),%d1 - andil #0xc0,%d1 - lsrl #6,%d1 //put precision in upper word - swap %d1 - orl %d0,%d1 //set up for round call - movel #0x20000000,%d0 //set sticky for round -// -// Since the dest is the denorm, the sign is the opposite of the -// norm sign. -// - eoriw #0x8000,ETEMP_EX(%a6) //flip sign on result - tstw ETEMP_EX(%a6) - bgts sub_s_dwr - orl #neg_mask,USER_FPSR(%a6) -sub_s_dwr: - bclrb #sign_bit,ETEMP_EX(%a6) - sne ETEMP_SGN(%a6) - bsrl round //round result to users rmode & prec - bfclr ETEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format - beqs sub_s_dclr - bsetb #sign_bit,ETEMP_EX(%a6) -sub_s_dclr: - leal WBTEMP(%a6),%a0 - movel ETEMP(%a6),(%a0) //write result to wbtemp - movel ETEMP_HI(%a6),4(%a0) - movel ETEMP_LO(%a6),8(%a0) - bra sub_ckovf -sub_s_srcd: - leal FPTEMP(%a6),%a0 - movel USER_FPCR(%a6),%d0 - andil #0x30,%d0 - lsrl #4,%d0 //put rmode in lower 2 bits - movel USER_FPCR(%a6),%d1 - andil #0xc0,%d1 - lsrl #6,%d1 //put precision in upper word - swap %d1 - orl %d0,%d1 //set up for round call - movel #0x20000000,%d0 //set sticky for round - bclrb #sign_bit,FPTEMP_EX(%a6) - sne FPTEMP_SGN(%a6) - bsrl round //round result to users rmode & prec - bfclr FPTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format - beqs sub_s_sclr - bsetb #sign_bit,FPTEMP_EX(%a6) -sub_s_sclr: - leal WBTEMP(%a6),%a0 - movel FPTEMP(%a6),(%a0) //write result to wbtemp - movel FPTEMP_HI(%a6),4(%a0) - movel FPTEMP_LO(%a6),8(%a0) - tstw FPTEMP_EX(%a6) - bgt sub_ckovf - orl #neg_mask,USER_FPSR(%a6) -sub_ckovf: - movew WBTEMP_EX(%a6),%d0 - andiw #0x7fff,%d0 - cmpiw #0x7fff,%d0 - bne frcfpnr -// -// The result has overflowed to $7fff exponent. Set I, ovfl, -// and aovfl, and clr the mantissa (incorrectly set by the -// round routine.) -// - orl #inf_mask+ovfl_inx_mask,USER_FPSR(%a6) - clrl 4(%a0) - bra frcfpnr -// -// Inst is fcmp. -// -wrap_cmp: - cmpb #0xff,DNRM_FLG(%a6) //if both ops denorm, - beq fix_stk //restore to fpu -// -// One of the ops is denormalized. Test for wrap condition -// and complete the instruction. -// - cmpb #0x0f,DNRM_FLG(%a6) //check for dest denorm - bnes cmp_srcd -cmp_destd: - bsrl ckinf_ns - bne fix_stk - bfextu ETEMP_EX(%a6){#1:#15},%d0 //get src exp (always pos) - bfexts FPTEMP_EX(%a6){#1:#15},%d1 //get dest exp (always neg) - subl %d1,%d0 //subtract dest from src - cmpl #0x8000,%d0 - blt fix_stk //if less, not wrap case - tstw ETEMP_EX(%a6) //set N to ~sign_of(src) - bge cmp_setn - rts -cmp_srcd: - bsrl ckinf_nd - bne fix_stk - bfextu FPTEMP_EX(%a6){#1:#15},%d0 //get dest exp (always pos) - bfexts ETEMP_EX(%a6){#1:#15},%d1 //get src exp (always neg) - subl %d1,%d0 //subtract src from dest - cmpl #0x8000,%d0 - blt fix_stk //if less, not wrap case - tstw FPTEMP_EX(%a6) //set N to sign_of(dest) - blt cmp_setn - rts -cmp_setn: - orl #neg_mask,USER_FPSR(%a6) - rts - -// -// Inst is fmul. -// -wrap_mul: - cmpb #0xff,DNRM_FLG(%a6) //if both ops denorm, - beq force_unf //force an underflow (really!) -// -// One of the ops is denormalized. Test for wrap condition -// and complete the instruction. -// - cmpb #0x0f,DNRM_FLG(%a6) //check for dest denorm - bnes mul_srcd -mul_destd: - bsrl ckinf_ns - bne fix_stk - bfextu ETEMP_EX(%a6){#1:#15},%d0 //get src exp (always pos) - bfexts FPTEMP_EX(%a6){#1:#15},%d1 //get dest exp (always neg) - addl %d1,%d0 //subtract dest from src - bgt fix_stk - bra force_unf -mul_srcd: - bsrl ckinf_nd - bne fix_stk - bfextu FPTEMP_EX(%a6){#1:#15},%d0 //get dest exp (always pos) - bfexts ETEMP_EX(%a6){#1:#15},%d1 //get src exp (always neg) - addl %d1,%d0 //subtract src from dest - bgt fix_stk - -// -// This code handles the case of the instruction resulting in -// an underflow condition. -// -force_unf: - bclrb #E1,E_BYTE(%a6) - orl #unfinx_mask,USER_FPSR(%a6) - clrw NMNEXC(%a6) - clrb WBTEMP_SGN(%a6) - movew ETEMP_EX(%a6),%d0 //find the sign of the result - movew FPTEMP_EX(%a6),%d1 - eorw %d1,%d0 - andiw #0x8000,%d0 - beqs frcunfcont - st WBTEMP_SGN(%a6) -frcunfcont: - lea WBTEMP(%a6),%a0 //point a0 to memory location - movew CMDREG1B(%a6),%d0 - btstl #6,%d0 //test for forced precision - beqs frcunf_fpcr - btstl #2,%d0 //check for double - bnes frcunf_dbl - movel #0x1,%d0 //inst is forced single - bras frcunf_rnd -frcunf_dbl: - movel #0x2,%d0 //inst is forced double - bras frcunf_rnd -frcunf_fpcr: - bfextu FPCR_MODE(%a6){#0:#2},%d0 //inst not forced - use fpcr prec -frcunf_rnd: - bsrl unf_sub //get correct result based on -// ;round precision/mode. This -// ;sets FPSR_CC correctly - bfclr WBTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format - beqs frcfpn - bsetb #sign_bit,WBTEMP_EX(%a6) - bra frcfpn - -// -// Write the result to the user's fpn. All results must be HUGE to be -// written; otherwise the results would have overflowed or underflowed. -// If the rounding precision is single or double, the ovf_res routine -// is needed to correctly supply the max value. -// -frcfpnr: - movew CMDREG1B(%a6),%d0 - btstl #6,%d0 //test for forced precision - beqs frcfpn_fpcr - btstl #2,%d0 //check for double - bnes frcfpn_dbl - movel #0x1,%d0 //inst is forced single - bras frcfpn_rnd -frcfpn_dbl: - movel #0x2,%d0 //inst is forced double - bras frcfpn_rnd -frcfpn_fpcr: - bfextu FPCR_MODE(%a6){#0:#2},%d0 //inst not forced - use fpcr prec - tstb %d0 - beqs frcfpn //if extended, write what you got -frcfpn_rnd: - bclrb #sign_bit,WBTEMP_EX(%a6) - sne WBTEMP_SGN(%a6) - bsrl ovf_res //get correct result based on -// ;round precision/mode. This -// ;sets FPSR_CC correctly - bfclr WBTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format - beqs frcfpn_clr - bsetb #sign_bit,WBTEMP_EX(%a6) -frcfpn_clr: - orl #ovfinx_mask,USER_FPSR(%a6) -// -// Perform the write. -// -frcfpn: - bfextu CMDREG1B(%a6){#6:#3},%d0 //extract fp destination register - cmpib #3,%d0 - bles frc0123 //check if dest is fp0-fp3 - movel #7,%d1 - subl %d0,%d1 - clrl %d0 - bsetl %d1,%d0 - fmovemx WBTEMP(%a6),%d0 - rts -frc0123: - cmpib #0,%d0 - beqs frc0_dst - cmpib #1,%d0 - beqs frc1_dst - cmpib #2,%d0 - beqs frc2_dst -frc3_dst: - movel WBTEMP_EX(%a6),USER_FP3(%a6) - movel WBTEMP_HI(%a6),USER_FP3+4(%a6) - movel WBTEMP_LO(%a6),USER_FP3+8(%a6) - rts -frc2_dst: - movel WBTEMP_EX(%a6),USER_FP2(%a6) - movel WBTEMP_HI(%a6),USER_FP2+4(%a6) - movel WBTEMP_LO(%a6),USER_FP2+8(%a6) - rts -frc1_dst: - movel WBTEMP_EX(%a6),USER_FP1(%a6) - movel WBTEMP_HI(%a6),USER_FP1+4(%a6) - movel WBTEMP_LO(%a6),USER_FP1+8(%a6) - rts -frc0_dst: - movel WBTEMP_EX(%a6),USER_FP0(%a6) - movel WBTEMP_HI(%a6),USER_FP0+4(%a6) - movel WBTEMP_LO(%a6),USER_FP0+8(%a6) - rts - -// -// Write etemp to fpn. -// A check is made on enabled and signalled snan exceptions, -// and the destination is not overwritten if this condition exists. -// This code is designed to make fmoveins of unsupported data types -// faster. -// -wr_etemp: - btstb #snan_bit,FPSR_EXCEPT(%a6) //if snan is set, and - beqs fmoveinc //enabled, force restore - btstb #snan_bit,FPCR_ENABLE(%a6) //and don't overwrite - beqs fmoveinc //the dest - movel ETEMP_EX(%a6),FPTEMP_EX(%a6) //set up fptemp sign for -// ;snan handler - tstb ETEMP(%a6) //check for negative - blts snan_neg - rts -snan_neg: - orl #neg_bit,USER_FPSR(%a6) //snan is negative; set N - rts -fmoveinc: - clrw NMNEXC(%a6) - bclrb #E1,E_BYTE(%a6) - moveb STAG(%a6),%d0 //check if stag is inf - andib #0xe0,%d0 - cmpib #0x40,%d0 - bnes fminc_cnan - orl #inf_mask,USER_FPSR(%a6) //if inf, nothing yet has set I - tstw LOCAL_EX(%a0) //check sign - bges fminc_con - orl #neg_mask,USER_FPSR(%a6) - bra fminc_con -fminc_cnan: - cmpib #0x60,%d0 //check if stag is NaN - bnes fminc_czero - orl #nan_mask,USER_FPSR(%a6) //if nan, nothing yet has set NaN - movel ETEMP_EX(%a6),FPTEMP_EX(%a6) //set up fptemp sign for -// ;snan handler - tstw LOCAL_EX(%a0) //check sign - bges fminc_con - orl #neg_mask,USER_FPSR(%a6) - bra fminc_con -fminc_czero: - cmpib #0x20,%d0 //check if zero - bnes fminc_con - orl #z_mask,USER_FPSR(%a6) //if zero, set Z - tstw LOCAL_EX(%a0) //check sign - bges fminc_con - orl #neg_mask,USER_FPSR(%a6) -fminc_con: - bfextu CMDREG1B(%a6){#6:#3},%d0 //extract fp destination register - cmpib #3,%d0 - bles fp0123 //check if dest is fp0-fp3 - movel #7,%d1 - subl %d0,%d1 - clrl %d0 - bsetl %d1,%d0 - fmovemx ETEMP(%a6),%d0 - rts - -fp0123: - cmpib #0,%d0 - beqs fp0_dst - cmpib #1,%d0 - beqs fp1_dst - cmpib #2,%d0 - beqs fp2_dst -fp3_dst: - movel ETEMP_EX(%a6),USER_FP3(%a6) - movel ETEMP_HI(%a6),USER_FP3+4(%a6) - movel ETEMP_LO(%a6),USER_FP3+8(%a6) - rts -fp2_dst: - movel ETEMP_EX(%a6),USER_FP2(%a6) - movel ETEMP_HI(%a6),USER_FP2+4(%a6) - movel ETEMP_LO(%a6),USER_FP2+8(%a6) - rts -fp1_dst: - movel ETEMP_EX(%a6),USER_FP1(%a6) - movel ETEMP_HI(%a6),USER_FP1+4(%a6) - movel ETEMP_LO(%a6),USER_FP1+8(%a6) - rts -fp0_dst: - movel ETEMP_EX(%a6),USER_FP0(%a6) - movel ETEMP_HI(%a6),USER_FP0+4(%a6) - movel ETEMP_LO(%a6),USER_FP0+8(%a6) - rts - -opclass3: - st CU_ONLY(%a6) - movew CMDREG1B(%a6),%d0 //check if packed moveout - andiw #0x0c00,%d0 //isolate last 2 bits of size field - cmpiw #0x0c00,%d0 //if size is 011 or 111, it is packed - beq pack_out //else it is norm or denorm - bra mv_out - - -// -// MOVE OUT -// - -mv_tbl: - .long li - .long sgp - .long xp - .long mvout_end //should never be taken - .long wi - .long dp - .long bi - .long mvout_end //should never be taken -mv_out: - bfextu CMDREG1B(%a6){#3:#3},%d1 //put source specifier in d1 - leal mv_tbl,%a0 - movel %a0@(%d1:l:4),%a0 - jmp (%a0) - -// -// This exit is for move-out to memory. The aunfl bit is -// set if the result is inex and unfl is signalled. -// -mvout_end: - btstb #inex2_bit,FPSR_EXCEPT(%a6) - beqs no_aufl - btstb #unfl_bit,FPSR_EXCEPT(%a6) - beqs no_aufl - bsetb #aunfl_bit,FPSR_AEXCEPT(%a6) -no_aufl: - clrw NMNEXC(%a6) - bclrb #E1,E_BYTE(%a6) - fmovel #0,%FPSR //clear any cc bits from res_func -// -// Return ETEMP to extended format from internal extended format so -// that gen_except will have a correctly signed value for ovfl/unfl -// handlers. -// - bfclr ETEMP_SGN(%a6){#0:#8} - beqs mvout_con - bsetb #sign_bit,ETEMP_EX(%a6) -mvout_con: - rts -// -// This exit is for move-out to int register. The aunfl bit is -// not set in any case for this move. -// -mvouti_end: - clrw NMNEXC(%a6) - bclrb #E1,E_BYTE(%a6) - fmovel #0,%FPSR //clear any cc bits from res_func -// -// Return ETEMP to extended format from internal extended format so -// that gen_except will have a correctly signed value for ovfl/unfl -// handlers. -// - bfclr ETEMP_SGN(%a6){#0:#8} - beqs mvouti_con - bsetb #sign_bit,ETEMP_EX(%a6) -mvouti_con: - rts -// -// li is used to handle a long integer source specifier -// - -li: - moveql #4,%d0 //set byte count - - btstb #7,STAG(%a6) //check for extended denorm - bne int_dnrm //if so, branch - - fmovemx ETEMP(%a6),%fp0-%fp0 - fcmpd #0x41dfffffffc00000,%fp0 -// 41dfffffffc00000 in dbl prec = 401d0000fffffffe00000000 in ext prec - fbge lo_plrg - fcmpd #0xc1e0000000000000,%fp0 -// c1e0000000000000 in dbl prec = c01e00008000000000000000 in ext prec - fble lo_nlrg -// -// at this point, the answer is between the largest pos and neg values -// - movel USER_FPCR(%a6),%d1 //use user's rounding mode - andil #0x30,%d1 - fmovel %d1,%fpcr - fmovel %fp0,L_SCR1(%a6) //let the 040 perform conversion - fmovel %fpsr,%d1 - orl %d1,USER_FPSR(%a6) //capture inex2/ainex if set - bra int_wrt - - -lo_plrg: - movel #0x7fffffff,L_SCR1(%a6) //answer is largest positive int - fbeq int_wrt //exact answer - fcmpd #0x41dfffffffe00000,%fp0 -// 41dfffffffe00000 in dbl prec = 401d0000ffffffff00000000 in ext prec - fbge int_operr //set operr - bra int_inx //set inexact - -lo_nlrg: - movel #0x80000000,L_SCR1(%a6) - fbeq int_wrt //exact answer - fcmpd #0xc1e0000000100000,%fp0 -// c1e0000000100000 in dbl prec = c01e00008000000080000000 in ext prec - fblt int_operr //set operr - bra int_inx //set inexact - -// -// wi is used to handle a word integer source specifier -// - -wi: - moveql #2,%d0 //set byte count - - btstb #7,STAG(%a6) //check for extended denorm - bne int_dnrm //branch if so - - fmovemx ETEMP(%a6),%fp0-%fp0 - fcmps #0x46fffe00,%fp0 -// 46fffe00 in sgl prec = 400d0000fffe000000000000 in ext prec - fbge wo_plrg - fcmps #0xc7000000,%fp0 -// c7000000 in sgl prec = c00e00008000000000000000 in ext prec - fble wo_nlrg - -// -// at this point, the answer is between the largest pos and neg values -// - movel USER_FPCR(%a6),%d1 //use user's rounding mode - andil #0x30,%d1 - fmovel %d1,%fpcr - fmovew %fp0,L_SCR1(%a6) //let the 040 perform conversion - fmovel %fpsr,%d1 - orl %d1,USER_FPSR(%a6) //capture inex2/ainex if set - bra int_wrt - -wo_plrg: - movew #0x7fff,L_SCR1(%a6) //answer is largest positive int - fbeq int_wrt //exact answer - fcmps #0x46ffff00,%fp0 -// 46ffff00 in sgl prec = 400d0000ffff000000000000 in ext prec - fbge int_operr //set operr - bra int_inx //set inexact - -wo_nlrg: - movew #0x8000,L_SCR1(%a6) - fbeq int_wrt //exact answer - fcmps #0xc7000080,%fp0 -// c7000080 in sgl prec = c00e00008000800000000000 in ext prec - fblt int_operr //set operr - bra int_inx //set inexact - -// -// bi is used to handle a byte integer source specifier -// - -bi: - moveql #1,%d0 //set byte count - - btstb #7,STAG(%a6) //check for extended denorm - bne int_dnrm //branch if so - - fmovemx ETEMP(%a6),%fp0-%fp0 - fcmps #0x42fe0000,%fp0 -// 42fe0000 in sgl prec = 40050000fe00000000000000 in ext prec - fbge by_plrg - fcmps #0xc3000000,%fp0 -// c3000000 in sgl prec = c00600008000000000000000 in ext prec - fble by_nlrg - -// -// at this point, the answer is between the largest pos and neg values -// - movel USER_FPCR(%a6),%d1 //use user's rounding mode - andil #0x30,%d1 - fmovel %d1,%fpcr - fmoveb %fp0,L_SCR1(%a6) //let the 040 perform conversion - fmovel %fpsr,%d1 - orl %d1,USER_FPSR(%a6) //capture inex2/ainex if set - bra int_wrt - -by_plrg: - moveb #0x7f,L_SCR1(%a6) //answer is largest positive int - fbeq int_wrt //exact answer - fcmps #0x42ff0000,%fp0 -// 42ff0000 in sgl prec = 40050000ff00000000000000 in ext prec - fbge int_operr //set operr - bra int_inx //set inexact - -by_nlrg: - moveb #0x80,L_SCR1(%a6) - fbeq int_wrt //exact answer - fcmps #0xc3008000,%fp0 -// c3008000 in sgl prec = c00600008080000000000000 in ext prec - fblt int_operr //set operr - bra int_inx //set inexact - -// -// Common integer routines -// -// int_drnrm---account for possible nonzero result for round up with positive -// operand and round down for negative answer. In the first case (result = 1) -// byte-width (store in d0) of result must be honored. In the second case, -// -1 in L_SCR1(a6) will cover all contingencies (FMOVE.B/W/L out). - -int_dnrm: - movel #0,L_SCR1(%a6) // initialize result to 0 - bfextu FPCR_MODE(%a6){#2:#2},%d1 // d1 is the rounding mode - cmpb #2,%d1 - bmis int_inx // if RN or RZ, done - bnes int_rp // if RP, continue below - tstw ETEMP(%a6) // RM: store -1 in L_SCR1 if src is negative - bpls int_inx // otherwise result is 0 - movel #-1,L_SCR1(%a6) - bras int_inx -int_rp: - tstw ETEMP(%a6) // RP: store +1 of proper width in L_SCR1 if -// ; source is greater than 0 - bmis int_inx // otherwise, result is 0 - lea L_SCR1(%a6),%a1 // a1 is address of L_SCR1 - addal %d0,%a1 // offset by destination width -1 - subal #1,%a1 - bsetb #0,(%a1) // set low bit at a1 address -int_inx: - oril #inx2a_mask,USER_FPSR(%a6) - bras int_wrt -int_operr: - fmovemx %fp0-%fp0,FPTEMP(%a6) //FPTEMP must contain the extended -// ;precision source that needs to be -// ;converted to integer this is required -// ;if the operr exception is enabled. -// ;set operr/aiop (no inex2 on int ovfl) - - oril #opaop_mask,USER_FPSR(%a6) -// ;fall through to perform int_wrt -int_wrt: - movel EXC_EA(%a6),%a1 //load destination address - tstl %a1 //check to see if it is a dest register - beqs wrt_dn //write data register - lea L_SCR1(%a6),%a0 //point to supervisor source address - bsrl mem_write - bra mvouti_end - -wrt_dn: - movel %d0,-(%sp) //d0 currently contains the size to write - bsrl get_fline //get_fline returns Dn in d0 - andiw #0x7,%d0 //isolate register - movel (%sp)+,%d1 //get size - cmpil #4,%d1 //most frequent case - beqs sz_long - cmpil #2,%d1 - bnes sz_con - orl #8,%d0 //add 'word' size to register# - bras sz_con -sz_long: - orl #0x10,%d0 //add 'long' size to register# -sz_con: - movel %d0,%d1 //reg_dest expects size:reg in d1 - bsrl reg_dest //load proper data register - bra mvouti_end -xp: - lea ETEMP(%a6),%a0 - bclrb #sign_bit,LOCAL_EX(%a0) - sne LOCAL_SGN(%a0) - btstb #7,STAG(%a6) //check for extended denorm - bne xdnrm - clrl %d0 - bras do_fp //do normal case -sgp: - lea ETEMP(%a6),%a0 - bclrb #sign_bit,LOCAL_EX(%a0) - sne LOCAL_SGN(%a0) - btstb #7,STAG(%a6) //check for extended denorm - bne sp_catas //branch if so - movew LOCAL_EX(%a0),%d0 - lea sp_bnds,%a1 - cmpw (%a1),%d0 - blt sp_under - cmpw 2(%a1),%d0 - bgt sp_over - movel #1,%d0 //set destination format to single - bras do_fp //do normal case -dp: - lea ETEMP(%a6),%a0 - bclrb #sign_bit,LOCAL_EX(%a0) - sne LOCAL_SGN(%a0) - - btstb #7,STAG(%a6) //check for extended denorm - bne dp_catas //branch if so - - movew LOCAL_EX(%a0),%d0 - lea dp_bnds,%a1 - - cmpw (%a1),%d0 - blt dp_under - cmpw 2(%a1),%d0 - bgt dp_over - - movel #2,%d0 //set destination format to double -// ;fall through to do_fp -// -do_fp: - bfextu FPCR_MODE(%a6){#2:#2},%d1 //rnd mode in d1 - swap %d0 //rnd prec in upper word - addl %d0,%d1 //d1 has PREC/MODE info - - clrl %d0 //clear g,r,s - - bsrl round //round - - movel %a0,%a1 - movel EXC_EA(%a6),%a0 - - bfextu CMDREG1B(%a6){#3:#3},%d1 //extract destination format -// ;at this point only the dest -// ;formats sgl, dbl, ext are -// ;possible - cmpb #2,%d1 - bgts ddbl //double=5, extended=2, single=1 - bnes dsgl -// ;fall through to dext -dext: - bsrl dest_ext - bra mvout_end -dsgl: - bsrl dest_sgl - bra mvout_end -ddbl: - bsrl dest_dbl - bra mvout_end - -// -// Handle possible denorm or catastrophic underflow cases here -// -xdnrm: - bsr set_xop //initialize WBTEMP - bsetb #wbtemp15_bit,WB_BYTE(%a6) //set wbtemp15 - - movel %a0,%a1 - movel EXC_EA(%a6),%a0 //a0 has the destination pointer - bsrl dest_ext //store to memory - bsetb #unfl_bit,FPSR_EXCEPT(%a6) - bra mvout_end - -sp_under: - bsetb #etemp15_bit,STAG(%a6) - - cmpw 4(%a1),%d0 - blts sp_catas //catastrophic underflow case - - movel #1,%d0 //load in round precision - movel #sgl_thresh,%d1 //load in single denorm threshold - bsrl dpspdnrm //expects d1 to have the proper -// ;denorm threshold - bsrl dest_sgl //stores value to destination - bsetb #unfl_bit,FPSR_EXCEPT(%a6) - bra mvout_end //exit - -dp_under: - bsetb #etemp15_bit,STAG(%a6) - - cmpw 4(%a1),%d0 - blts dp_catas //catastrophic underflow case - - movel #dbl_thresh,%d1 //load in double precision threshold - movel #2,%d0 - bsrl dpspdnrm //expects d1 to have proper -// ;denorm threshold -// ;expects d0 to have round precision - bsrl dest_dbl //store value to destination - bsetb #unfl_bit,FPSR_EXCEPT(%a6) - bra mvout_end //exit - -// -// Handle catastrophic underflow cases here -// -sp_catas: -// Temp fix for z bit set in unf_sub - movel USER_FPSR(%a6),-(%a7) - - movel #1,%d0 //set round precision to sgl - - bsrl unf_sub //a0 points to result - - movel (%a7)+,USER_FPSR(%a6) - - movel #1,%d0 - subw %d0,LOCAL_EX(%a0) //account for difference between -// ;denorm/norm bias - - movel %a0,%a1 //a1 has the operand input - movel EXC_EA(%a6),%a0 //a0 has the destination pointer - - bsrl dest_sgl //store the result - oril #unfinx_mask,USER_FPSR(%a6) - bra mvout_end - -dp_catas: -// Temp fix for z bit set in unf_sub - movel USER_FPSR(%a6),-(%a7) - - movel #2,%d0 //set round precision to dbl - bsrl unf_sub //a0 points to result - - movel (%a7)+,USER_FPSR(%a6) - - movel #1,%d0 - subw %d0,LOCAL_EX(%a0) //account for difference between -// ;denorm/norm bias - - movel %a0,%a1 //a1 has the operand input - movel EXC_EA(%a6),%a0 //a0 has the destination pointer - - bsrl dest_dbl //store the result - oril #unfinx_mask,USER_FPSR(%a6) - bra mvout_end - -// -// Handle catastrophic overflow cases here -// -sp_over: -// Temp fix for z bit set in unf_sub - movel USER_FPSR(%a6),-(%a7) - - movel #1,%d0 - leal FP_SCR1(%a6),%a0 //use FP_SCR1 for creating result - movel ETEMP_EX(%a6),(%a0) - movel ETEMP_HI(%a6),4(%a0) - movel ETEMP_LO(%a6),8(%a0) - bsrl ovf_res - - movel (%a7)+,USER_FPSR(%a6) - - movel %a0,%a1 - movel EXC_EA(%a6),%a0 - bsrl dest_sgl - orl #ovfinx_mask,USER_FPSR(%a6) - bra mvout_end - -dp_over: -// Temp fix for z bit set in ovf_res - movel USER_FPSR(%a6),-(%a7) - - movel #2,%d0 - leal FP_SCR1(%a6),%a0 //use FP_SCR1 for creating result - movel ETEMP_EX(%a6),(%a0) - movel ETEMP_HI(%a6),4(%a0) - movel ETEMP_LO(%a6),8(%a0) - bsrl ovf_res - - movel (%a7)+,USER_FPSR(%a6) - - movel %a0,%a1 - movel EXC_EA(%a6),%a0 - bsrl dest_dbl - orl #ovfinx_mask,USER_FPSR(%a6) - bra mvout_end - -// -// DPSPDNRM -// -// This subroutine takes an extended normalized number and denormalizes -// it to the given round precision. This subroutine also decrements -// the input operand's exponent by 1 to account for the fact that -// dest_sgl or dest_dbl expects a normalized number's bias. -// -// Input: a0 points to a normalized number in internal extended format -// d0 is the round precision (=1 for sgl; =2 for dbl) -// d1 is the the single precision or double precision -// denorm threshold -// -// Output: (In the format for dest_sgl or dest_dbl) -// a0 points to the destination -// a1 points to the operand -// -// Exceptions: Reports inexact 2 exception by setting USER_FPSR bits -// -dpspdnrm: - movel %d0,-(%a7) //save round precision - clrl %d0 //clear initial g,r,s - bsrl dnrm_lp //careful with d0, it's needed by round - - bfextu FPCR_MODE(%a6){#2:#2},%d1 //get rounding mode - swap %d1 - movew 2(%a7),%d1 //set rounding precision - swap %d1 //at this point d1 has PREC/MODE info - bsrl round //round result, sets the inex bit in -// ;USER_FPSR if needed - - movew #1,%d0 - subw %d0,LOCAL_EX(%a0) //account for difference in denorm -// ;vs norm bias - - movel %a0,%a1 //a1 has the operand input - movel EXC_EA(%a6),%a0 //a0 has the destination pointer - addw #4,%a7 //pop stack - rts -// -// SET_XOP initialized WBTEMP with the value pointed to by a0 -// input: a0 points to input operand in the internal extended format -// -set_xop: - movel LOCAL_EX(%a0),WBTEMP_EX(%a6) - movel LOCAL_HI(%a0),WBTEMP_HI(%a6) - movel LOCAL_LO(%a0),WBTEMP_LO(%a6) - bfclr WBTEMP_SGN(%a6){#0:#8} - beqs sxop - bsetb #sign_bit,WBTEMP_EX(%a6) -sxop: - bfclr STAG(%a6){#5:#4} //clear wbtm66,wbtm1,wbtm0,sbit - rts -// -// P_MOVE -// -p_movet: - .long p_move - .long p_movez - .long p_movei - .long p_moven - .long p_move -p_regd: - .long p_dyd0 - .long p_dyd1 - .long p_dyd2 - .long p_dyd3 - .long p_dyd4 - .long p_dyd5 - .long p_dyd6 - .long p_dyd7 - -pack_out: - leal p_movet,%a0 //load jmp table address - movew STAG(%a6),%d0 //get source tag - bfextu %d0{#16:#3},%d0 //isolate source bits - movel (%a0,%d0.w*4),%a0 //load a0 with routine label for tag - jmp (%a0) //go to the routine - -p_write: - movel #0x0c,%d0 //get byte count - movel EXC_EA(%a6),%a1 //get the destination address - bsr mem_write //write the user's destination - moveb #0,CU_SAVEPC(%a6) //set the cu save pc to all 0's - -// -// Also note that the dtag must be set to norm here - this is because -// the 040 uses the dtag to execute the correct microcode. -// - bfclr DTAG(%a6){#0:#3} //set dtag to norm - - rts - -// Notes on handling of special case (zero, inf, and nan) inputs: -// 1. Operr is not signalled if the k-factor is greater than 18. -// 2. Per the manual, status bits are not set. -// - -p_move: - movew CMDREG1B(%a6),%d0 - btstl #kfact_bit,%d0 //test for dynamic k-factor - beqs statick //if clear, k-factor is static -dynamick: - bfextu %d0{#25:#3},%d0 //isolate register for dynamic k-factor - lea p_regd,%a0 - movel %a0@(%d0:l:4),%a0 - jmp (%a0) -statick: - andiw #0x007f,%d0 //get k-factor - bfexts %d0{#25:#7},%d0 //sign extend d0 for bindec - leal ETEMP(%a6),%a0 //a0 will point to the packed decimal - bsrl bindec //perform the convert; data at a6 - leal FP_SCR1(%a6),%a0 //load a0 with result address - bral p_write -p_movez: - leal ETEMP(%a6),%a0 //a0 will point to the packed decimal - clrw 2(%a0) //clear lower word of exp - clrl 4(%a0) //load second lword of ZERO - clrl 8(%a0) //load third lword of ZERO - bra p_write //go write results -p_movei: - fmovel #0,%FPSR //clear aiop - leal ETEMP(%a6),%a0 //a0 will point to the packed decimal - clrw 2(%a0) //clear lower word of exp - bra p_write //go write the result -p_moven: - leal ETEMP(%a6),%a0 //a0 will point to the packed decimal - clrw 2(%a0) //clear lower word of exp - bra p_write //go write the result - -// -// Routines to read the dynamic k-factor from Dn. -// -p_dyd0: - movel USER_D0(%a6),%d0 - bras statick -p_dyd1: - movel USER_D1(%a6),%d0 - bras statick -p_dyd2: - movel %d2,%d0 - bras statick -p_dyd3: - movel %d3,%d0 - bras statick -p_dyd4: - movel %d4,%d0 - bras statick -p_dyd5: - movel %d5,%d0 - bras statick -p_dyd6: - movel %d6,%d0 - bra statick -p_dyd7: - movel %d7,%d0 - bra statick - - |end |