URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [fpsp040/] [scale.S] - Rev 1765
Compare with Previous | Blame | View Log
|| scale.sa 3.3 7/30/91|| The entry point sSCALE computes the destination operand| scaled by the source operand. If the absolute value of| the source operand is (>= 2^14) an overflow or underflow| is returned.|| The entry point sscale is called from do_func to emulate| the fscale unimplemented instruction.|| Input: Double-extended destination operand in FPTEMP,| double-extended source operand in ETEMP.|| Output: The function returns scale(X,Y) to fp0.|| Modifies: fp0.|| Algorithm:|| 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.|SCALE idnt 2,1 | Motorola 040 Floating Point Software Package|section 8.include "fpsp.h"|xref t_ovfl2|xref t_unfl|xref round|xref t_resdnrmSRC_BNDS: .short 0x3fff,0x400c|| This entry point is used by the unimplemented instruction exception| handler.|||| FSCALE|.global sscalesscale:fmovel #0,%fpcr |clr user enabled excclrl %d1movew FPTEMP(%a6),%d1 |get dest exponentsmi L_SCR1(%a6) |use L_SCR1 to hold signandil #0x7fff,%d1 |strip signmovew ETEMP(%a6),%d0 |check src boundsandiw #0x7fff,%d0 |clr sign bitcmp2w SRC_BNDS,%d0bccs src_incmpiw #0x400c,%d0 |test for too largebge src_out|| The source input is below 1, so we check for denormalized numbers| and set unfl.|src_small:moveb DTAG(%a6),%d0andib #0xe0,%d0tstb %d0beqs no_denormst STORE_FLG(%a6) |dest already contains resultorl #unfl_mask,USER_FPSR(%a6) |set UNFLden_done:leal FPTEMP(%a6),%a0bra t_resdnrmno_denorm:fmovel USER_FPCR(%a6),%FPCRfmovex FPTEMP(%a6),%fp0 |simply return destrts|| Source is within 2^14 range. To perform the int operation,| move it to d0.|src_in:fmovex ETEMP(%a6),%fp0 |move in src for intfmovel #rz_mode,%fpcr |force rz for src conversionfmovel %fp0,%d0 |int src to d0fmovel #0,%FPSR |clr status from abovetstw ETEMP(%a6) |check src signblt src_neg|| Source is positive. Add the src to the dest exponent.| The result can be denormalized, if src = 0, or overflow,| if the result of the add sets a bit in the upper word.|src_pos:tstw %d1 |check for denormbeq dst_dnrmaddl %d0,%d1 |add src to dest expbeqs denorm |if zero, result is denormcmpil #0x7fff,%d1 |test for overflowbges ovfltstb L_SCR1(%a6)beqs spos_posorw #0x8000,%d1spos_pos:movew %d1,FPTEMP(%a6) |result in FPTEMPfmovel USER_FPCR(%a6),%FPCRfmovex FPTEMP(%a6),%fp0 |write result to fp0rtsovfl:tstb L_SCR1(%a6)beqs sovl_posorw #0x8000,%d1sovl_pos:movew FPTEMP(%a6),ETEMP(%a6) |result in ETEMPmovel FPTEMP_HI(%a6),ETEMP_HI(%a6)movel FPTEMP_LO(%a6),ETEMP_LO(%a6)bra t_ovfl2denorm:tstb L_SCR1(%a6)beqs den_posorw #0x8000,%d1den_pos:tstl FPTEMP_HI(%a6) |check j bitblts nden_exit |if set, not denormmovew %d1,ETEMP(%a6) |input expected in ETEMPmovel FPTEMP_HI(%a6),ETEMP_HI(%a6)movel FPTEMP_LO(%a6),ETEMP_LO(%a6)orl #unfl_bit,USER_FPSR(%a6) |set unflleal ETEMP(%a6),%a0bra t_resdnrmnden_exit:movew %d1,FPTEMP(%a6) |result in FPTEMPfmovel USER_FPCR(%a6),%FPCRfmovex FPTEMP(%a6),%fp0 |write result to fp0rts|| Source is negative. Add the src to the dest exponent.| (The result exponent will be reduced). The result can be| denormalized.|src_neg:addl %d0,%d1 |add src to destbeqs denorm |if zero, result is denormblts fix_dnrm |if negative, result is| ;needing denormalizationtstb L_SCR1(%a6)beqs sneg_posorw #0x8000,%d1sneg_pos:movew %d1,FPTEMP(%a6) |result in FPTEMPfmovel USER_FPCR(%a6),%FPCRfmovex FPTEMP(%a6),%fp0 |write result to fp0rts|| The result exponent is below denorm value. Test for catastrophic| underflow and force zero if true. If not, try to shift the| mantissa right until a zero exponent exists.|fix_dnrm:cmpiw #0xffc0,%d1 |lower bound for normalizationblt fix_unfl |if lower, catastrophic unflmovew %d1,%d0 |use d0 for expmovel %d2,-(%a7) |free d2 for normmovel FPTEMP_HI(%a6),%d1movel FPTEMP_LO(%a6),%d2clrl L_SCR2(%a6)fix_loop:addw #1,%d0 |drive d0 to 0lsrl #1,%d1 |while shifting theroxrl #1,%d2 |mantissa to the rightbccs no_carryst L_SCR2(%a6) |use L_SCR2 to capture inexno_carry:tstw %d0 |it is finished whenblts fix_loop |d0 is zero or the mantissatstb L_SCR2(%a6)beqs tst_zeroorl #unfl_inx_mask,USER_FPSR(%a6)| ;set unfl, aunfl, ainex|| Test for zero. If zero, simply use fmove to return +/- zero| to the fpu.|tst_zero:clrw FPTEMP_EX(%a6)tstb L_SCR1(%a6) |test for signbeqs tst_conorw #0x8000,FPTEMP_EX(%a6) |set sign bittst_con:movel %d1,FPTEMP_HI(%a6)movel %d2,FPTEMP_LO(%a6)movel (%a7)+,%d2tstl %d1bnes not_zerotstl FPTEMP_LO(%a6)bnes not_zero|| Result is zero. Check for rounding mode to set lsb. If the| mode is rp, and the zero is positive, return smallest denorm.| If the mode is rm, and the zero is negative, return smallest| negative denorm.|btstb #5,FPCR_MODE(%a6) |test if rm or rpbeqs no_dirbtstb #4,FPCR_MODE(%a6) |check which onebeqs zer_rmzer_rp:tstb L_SCR1(%a6) |check signbnes no_dir |if set, neg op, no incmovel #1,FPTEMP_LO(%a6) |set lsbbras sm_dnrmzer_rm:tstb L_SCR1(%a6) |check signbeqs no_dir |if clr, neg op, no incmovel #1,FPTEMP_LO(%a6) |set lsborl #neg_mask,USER_FPSR(%a6) |set Nbras sm_dnrmno_dir:fmovel USER_FPCR(%a6),%FPCRfmovex FPTEMP(%a6),%fp0 |use fmove to set cc'srts|| The rounding mode changed the zero to a smallest denorm. Call| t_resdnrm with exceptional operand in ETEMP.|sm_dnrm:movel FPTEMP_EX(%a6),ETEMP_EX(%a6)movel FPTEMP_HI(%a6),ETEMP_HI(%a6)movel FPTEMP_LO(%a6),ETEMP_LO(%a6)leal ETEMP(%a6),%a0bra t_resdnrm|| Result is still denormalized.|not_zero:orl #unfl_mask,USER_FPSR(%a6) |set unfltstb L_SCR1(%a6) |check for signbeqs fix_exitorl #neg_mask,USER_FPSR(%a6) |set Nfix_exit:bras sm_dnrm|| The result has underflowed to zero. Return zero and set| unfl, aunfl, and ainex.|fix_unfl:orl #unfl_inx_mask,USER_FPSR(%a6)btstb #5,FPCR_MODE(%a6) |test if rm or rpbeqs no_dir2btstb #4,FPCR_MODE(%a6) |check which onebeqs zer_rm2zer_rp2:tstb L_SCR1(%a6) |check signbnes no_dir2 |if set, neg op, no incclrl FPTEMP_EX(%a6)clrl FPTEMP_HI(%a6)movel #1,FPTEMP_LO(%a6) |set lsbbras sm_dnrm |return smallest denormzer_rm2:tstb L_SCR1(%a6) |check signbeqs no_dir2 |if clr, neg op, no incmovew #0x8000,FPTEMP_EX(%a6)clrl FPTEMP_HI(%a6)movel #1,FPTEMP_LO(%a6) |set lsborl #neg_mask,USER_FPSR(%a6) |set Nbra sm_dnrm |return smallest denormno_dir2:tstb L_SCR1(%a6)bges pos_zeroneg_zero:clrl FP_SCR1(%a6) |clear the exceptional operandclrl FP_SCR1+4(%a6) |for gen_except.clrl FP_SCR1+8(%a6)fmoves #0x80000000,%fp0rtspos_zero:clrl FP_SCR1(%a6) |clear the exceptional operandclrl FP_SCR1+4(%a6) |for gen_except.clrl FP_SCR1+8(%a6)fmoves #0x00000000,%fp0rts|| The destination is a denormalized number. It must be handled| by first shifting the bits in the mantissa until it is normalized,| then adding the remainder of the source to the exponent.|dst_dnrm:moveml %d2/%d3,-(%a7)movew FPTEMP_EX(%a6),%d1movel FPTEMP_HI(%a6),%d2movel FPTEMP_LO(%a6),%d3dst_loop:tstl %d2 |test for normalized resultblts dst_norm |exit loop if sotstl %d0 |otherwise, test shift countbeqs dst_fin |if zero, shifting is donesubil #1,%d0 |dec srclsll #1,%d3roxll #1,%d2bras dst_loop|| Destination became normalized. Simply add the remaining| portion of the src to the exponent.|dst_norm:addw %d0,%d1 |dst is normalized; add srctstb L_SCR1(%a6)beqs dnrm_posorl #0x8000,%d1dnrm_pos:movemw %d1,FPTEMP_EX(%a6)moveml %d2,FPTEMP_HI(%a6)moveml %d3,FPTEMP_LO(%a6)fmovel USER_FPCR(%a6),%FPCRfmovex FPTEMP(%a6),%fp0moveml (%a7)+,%d2/%d3rts|| Destination remained denormalized. Call t_excdnrm with| exceptional operand in ETEMP.|dst_fin:tstb L_SCR1(%a6) |check for signbeqs dst_exitorl #neg_mask,USER_FPSR(%a6) |set Norl #0x8000,%d1dst_exit:movemw %d1,ETEMP_EX(%a6)moveml %d2,ETEMP_HI(%a6)moveml %d3,ETEMP_LO(%a6)orl #unfl_mask,USER_FPSR(%a6) |set unflmoveml (%a7)+,%d2/%d3leal ETEMP(%a6),%a0bra t_resdnrm|| Source is outside of 2^14 range. Test the sign and branch| to the appropriate exception handler.|src_out:tstb L_SCR1(%a6)beqs scro_posorl #0x8000,%d1scro_pos:movel FPTEMP_HI(%a6),ETEMP_HI(%a6)movel FPTEMP_LO(%a6),ETEMP_LO(%a6)tstw ETEMP(%a6)blts res_negres_pos:movew %d1,ETEMP(%a6) |result in ETEMPbra t_ovfl2res_neg:movew %d1,ETEMP(%a6) |result in ETEMPleal ETEMP(%a6),%a0bra t_unfl|end
