123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- |
- | 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
- |
- | For details on the license for this file, please see the
- | file, README, in this same directory.
- |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_resdnrm
- SRC_BNDS: .short 0x3fff,0x400c
- |
- | This entry point is used by the unimplemented instruction exception
- | handler.
- |
- |
- |
- | FSCALE
- |
- .global sscale
- sscale:
- fmovel #0,%fpcr |clr user enabled exc
- clrl %d1
- movew FPTEMP(%a6),%d1 |get dest exponent
- smi L_SCR1(%a6) |use L_SCR1 to hold sign
- andil #0x7fff,%d1 |strip sign
- movew ETEMP(%a6),%d0 |check src bounds
- andiw #0x7fff,%d0 |clr sign bit
- cmp2w SRC_BNDS,%d0
- bccs src_in
- cmpiw #0x400c,%d0 |test for too large
- bge src_out
- |
- | The source input is below 1, so we check for denormalized numbers
- | and set unfl.
- |
- src_small:
- moveb DTAG(%a6),%d0
- andib #0xe0,%d0
- tstb %d0
- beqs no_denorm
- st STORE_FLG(%a6) |dest already contains result
- orl #unfl_mask,USER_FPSR(%a6) |set UNFL
- den_done:
- leal FPTEMP(%a6),%a0
- bra t_resdnrm
- no_denorm:
- fmovel USER_FPCR(%a6),%FPCR
- fmovex FPTEMP(%a6),%fp0 |simply return dest
- rts
- |
- | 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 int
- fmovel #rz_mode,%fpcr |force rz for src conversion
- fmovel %fp0,%d0 |int src to d0
- fmovel #0,%FPSR |clr status from above
- tstw ETEMP(%a6) |check src sign
- blt 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 denorm
- beq dst_dnrm
- addl %d0,%d1 |add src to dest exp
- beqs denorm |if zero, result is denorm
- cmpil #0x7fff,%d1 |test for overflow
- bges ovfl
- tstb L_SCR1(%a6)
- beqs spos_pos
- orw #0x8000,%d1
- spos_pos:
- movew %d1,FPTEMP(%a6) |result in FPTEMP
- fmovel USER_FPCR(%a6),%FPCR
- fmovex FPTEMP(%a6),%fp0 |write result to fp0
- rts
- ovfl:
- tstb L_SCR1(%a6)
- beqs sovl_pos
- orw #0x8000,%d1
- sovl_pos:
- movew FPTEMP(%a6),ETEMP(%a6) |result in ETEMP
- movel FPTEMP_HI(%a6),ETEMP_HI(%a6)
- movel FPTEMP_LO(%a6),ETEMP_LO(%a6)
- bra t_ovfl2
- denorm:
- tstb L_SCR1(%a6)
- beqs den_pos
- orw #0x8000,%d1
- den_pos:
- tstl FPTEMP_HI(%a6) |check j bit
- blts nden_exit |if set, not denorm
- movew %d1,ETEMP(%a6) |input expected in ETEMP
- movel FPTEMP_HI(%a6),ETEMP_HI(%a6)
- movel FPTEMP_LO(%a6),ETEMP_LO(%a6)
- orl #unfl_bit,USER_FPSR(%a6) |set unfl
- leal ETEMP(%a6),%a0
- bra t_resdnrm
- nden_exit:
- movew %d1,FPTEMP(%a6) |result in FPTEMP
- fmovel USER_FPCR(%a6),%FPCR
- fmovex FPTEMP(%a6),%fp0 |write result to fp0
- rts
- |
- | 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 dest
- beqs denorm |if zero, result is denorm
- blts fix_dnrm |if negative, result is
- | ;needing denormalization
- tstb L_SCR1(%a6)
- beqs sneg_pos
- orw #0x8000,%d1
- sneg_pos:
- movew %d1,FPTEMP(%a6) |result in FPTEMP
- fmovel USER_FPCR(%a6),%FPCR
- fmovex FPTEMP(%a6),%fp0 |write result to fp0
- rts
- |
- | 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 normalization
- blt fix_unfl |if lower, catastrophic unfl
- movew %d1,%d0 |use d0 for exp
- movel %d2,-(%a7) |free d2 for norm
- movel FPTEMP_HI(%a6),%d1
- movel FPTEMP_LO(%a6),%d2
- clrl L_SCR2(%a6)
- fix_loop:
- addw #1,%d0 |drive d0 to 0
- lsrl #1,%d1 |while shifting the
- roxrl #1,%d2 |mantissa to the right
- bccs no_carry
- st L_SCR2(%a6) |use L_SCR2 to capture inex
- no_carry:
- tstw %d0 |it is finished when
- blts fix_loop |d0 is zero or the mantissa
- tstb L_SCR2(%a6)
- beqs tst_zero
- orl #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 sign
- beqs tst_con
- orw #0x8000,FPTEMP_EX(%a6) |set sign bit
- tst_con:
- movel %d1,FPTEMP_HI(%a6)
- movel %d2,FPTEMP_LO(%a6)
- movel (%a7)+,%d2
- tstl %d1
- bnes not_zero
- tstl 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 rp
- beqs no_dir
- btstb #4,FPCR_MODE(%a6) |check which one
- beqs zer_rm
- zer_rp:
- tstb L_SCR1(%a6) |check sign
- bnes no_dir |if set, neg op, no inc
- movel #1,FPTEMP_LO(%a6) |set lsb
- bras sm_dnrm
- zer_rm:
- tstb L_SCR1(%a6) |check sign
- beqs no_dir |if clr, neg op, no inc
- movel #1,FPTEMP_LO(%a6) |set lsb
- orl #neg_mask,USER_FPSR(%a6) |set N
- bras sm_dnrm
- no_dir:
- fmovel USER_FPCR(%a6),%FPCR
- fmovex FPTEMP(%a6),%fp0 |use fmove to set cc's
- rts
- |
- | 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),%a0
- bra t_resdnrm
- |
- | Result is still denormalized.
- |
- not_zero:
- orl #unfl_mask,USER_FPSR(%a6) |set unfl
- tstb L_SCR1(%a6) |check for sign
- beqs fix_exit
- orl #neg_mask,USER_FPSR(%a6) |set N
- fix_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 rp
- beqs no_dir2
- btstb #4,FPCR_MODE(%a6) |check which one
- beqs zer_rm2
- zer_rp2:
- tstb L_SCR1(%a6) |check sign
- bnes no_dir2 |if set, neg op, no inc
- clrl FPTEMP_EX(%a6)
- clrl FPTEMP_HI(%a6)
- movel #1,FPTEMP_LO(%a6) |set lsb
- bras sm_dnrm |return smallest denorm
- zer_rm2:
- tstb L_SCR1(%a6) |check sign
- beqs no_dir2 |if clr, neg op, no inc
- movew #0x8000,FPTEMP_EX(%a6)
- clrl FPTEMP_HI(%a6)
- movel #1,FPTEMP_LO(%a6) |set lsb
- orl #neg_mask,USER_FPSR(%a6) |set N
- bra sm_dnrm |return smallest denorm
- no_dir2:
- tstb L_SCR1(%a6)
- bges pos_zero
- neg_zero:
- clrl FP_SCR1(%a6) |clear the exceptional operand
- clrl FP_SCR1+4(%a6) |for gen_except.
- clrl FP_SCR1+8(%a6)
- fmoves #0x80000000,%fp0
- rts
- pos_zero:
- clrl FP_SCR1(%a6) |clear the exceptional operand
- clrl FP_SCR1+4(%a6) |for gen_except.
- clrl FP_SCR1+8(%a6)
- fmoves #0x00000000,%fp0
- rts
- |
- | 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),%d1
- movel FPTEMP_HI(%a6),%d2
- movel FPTEMP_LO(%a6),%d3
- dst_loop:
- tstl %d2 |test for normalized result
- blts dst_norm |exit loop if so
- tstl %d0 |otherwise, test shift count
- beqs dst_fin |if zero, shifting is done
- subil #1,%d0 |dec src
- lsll #1,%d3
- roxll #1,%d2
- bras 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 src
- tstb L_SCR1(%a6)
- beqs dnrm_pos
- orl #0x8000,%d1
- dnrm_pos:
- movemw %d1,FPTEMP_EX(%a6)
- moveml %d2,FPTEMP_HI(%a6)
- moveml %d3,FPTEMP_LO(%a6)
- fmovel USER_FPCR(%a6),%FPCR
- fmovex FPTEMP(%a6),%fp0
- moveml (%a7)+,%d2/%d3
- rts
- |
- | Destination remained denormalized. Call t_excdnrm with
- | exceptional operand in ETEMP.
- |
- dst_fin:
- tstb L_SCR1(%a6) |check for sign
- beqs dst_exit
- orl #neg_mask,USER_FPSR(%a6) |set N
- orl #0x8000,%d1
- dst_exit:
- movemw %d1,ETEMP_EX(%a6)
- moveml %d2,ETEMP_HI(%a6)
- moveml %d3,ETEMP_LO(%a6)
- orl #unfl_mask,USER_FPSR(%a6) |set unfl
- moveml (%a7)+,%d2/%d3
- leal ETEMP(%a6),%a0
- bra 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_pos
- orl #0x8000,%d1
- scro_pos:
- movel FPTEMP_HI(%a6),ETEMP_HI(%a6)
- movel FPTEMP_LO(%a6),ETEMP_LO(%a6)
- tstw ETEMP(%a6)
- blts res_neg
- res_pos:
- movew %d1,ETEMP(%a6) |result in ETEMP
- bra t_ovfl2
- res_neg:
- movew %d1,ETEMP(%a6) |result in ETEMP
- leal ETEMP(%a6),%a0
- bra t_unfl
- |end
|