URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [fpsp040/] [x_unfl.S] - Rev 1765
Compare with Previous | Blame | View Log
|| x_unfl.sa 3.4 7/1/91|| fpsp_unfl --- FPSP handler for underflow exception|| Trap disabled results| For 881/2 compatibility, sw must denormalize the intermediate| result, then store the result. Denormalization is accomplished| by taking the intermediate result (which is always normalized) and| shifting the mantissa right while incrementing the exponent until| it is equal to the denormalized exponent for the destination| format. After denormalization, the result is rounded to the| destination format.|| Trap enabled results| All trap disabled code applies. In addition the exceptional| operand needs to made available to the user with a bias of $6000| added to the exponent.|| 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.X_UNFL: |idnt 2,1 | Motorola 040 Floating Point Software Package|section 8.include "fpsp.h"|xref denorm|xref round|xref store|xref g_rndpr|xref g_opcls|xref g_dfmtou|xref real_unfl|xref real_inex|xref fpsp_done|xref b1238_fix.global fpsp_unflfpsp_unfl:link %a6,#-LOCAL_SIZEfsave -(%a7)moveml %d0-%d1/%a0-%a1,USER_DA(%a6)fmovemx %fp0-%fp3,USER_FP0(%a6)fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)|bsrl unf_res |denormalize, round & store interm op|| If underflow exceptions are not enabled, check for inexact| exception|btstb #unfl_bit,FPCR_ENABLE(%a6)beqs ck_inexbtstb #E3,E_BYTE(%a6)beqs no_e3_1|| Clear dirty bit on dest resister in the frame before branching| to b1238_fix.|bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg nobclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bitbsrl b1238_fix |test for bug1238 casemovel USER_FPSR(%a6),FPSR_SHADOW(%a6)orl #sx_mask,E_BYTE(%a6)no_e3_1:moveml USER_DA(%a6),%d0-%d1/%a0-%a1fmovemx USER_FP0(%a6),%fp0-%fp3fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiarfrestore (%a7)+unlk %a6bral real_unfl|| It is possible to have either inex2 or inex1 exceptions with the| unfl. If the inex enable bit is set in the FPCR, and either| inex2 or inex1 occurred, we must clean up and branch to the| real inex handler.|ck_inex:moveb FPCR_ENABLE(%a6),%d0andb FPSR_EXCEPT(%a6),%d0andib #0x3,%d0beqs unfl_done|| Inexact enabled and reported, and we must take an inexact exception|take_inex:btstb #E3,E_BYTE(%a6)beqs no_e3_2|| Clear dirty bit on dest resister in the frame before branching| to b1238_fix.|bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg nobclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bitbsrl b1238_fix |test for bug1238 casemovel USER_FPSR(%a6),FPSR_SHADOW(%a6)orl #sx_mask,E_BYTE(%a6)no_e3_2:moveb #INEX_VEC,EXC_VEC+1(%a6)moveml USER_DA(%a6),%d0-%d1/%a0-%a1fmovemx USER_FP0(%a6),%fp0-%fp3fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiarfrestore (%a7)+unlk %a6bral real_inexunfl_done:bclrb #E3,E_BYTE(%a6)beqs e1_set |if set then branch|| Clear dirty bit on dest resister in the frame before branching| to b1238_fix.|bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg nobclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bitbsrl b1238_fix |test for bug1238 casemovel USER_FPSR(%a6),FPSR_SHADOW(%a6)orl #sx_mask,E_BYTE(%a6)moveml USER_DA(%a6),%d0-%d1/%a0-%a1fmovemx USER_FP0(%a6),%fp0-%fp3fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiarfrestore (%a7)+unlk %a6bral fpsp_donee1_set:moveml USER_DA(%a6),%d0-%d1/%a0-%a1fmovemx USER_FP0(%a6),%fp0-%fp3fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiarunlk %a6bral fpsp_done|| unf_res --- underflow result calculation|unf_res:bsrl g_rndpr |returns RND_PREC in d0 0=ext,| ;1=sgl, 2=dbl| ;we need the RND_PREC in the| ;upper word for roundmovew #0,-(%a7)movew %d0,-(%a7) |copy RND_PREC to stack||| If the exception bit set is E3, the exceptional operand from the| fpu is in WBTEMP; else it is in FPTEMP.|btstb #E3,E_BYTE(%a6)beqs unf_E1unf_E3:lea WBTEMP(%a6),%a0 |a0 now points to operand|| Test for fsgldiv and fsglmul. If the inst was one of these, then| force the precision to extended for the denorm routine. Use| the user's precision for the round routine.|movew CMDREG3B(%a6),%d1 |check for fsgldiv or fsglmulandiw #0x7f,%d1cmpiw #0x30,%d1 |check for sgldivbeqs unf_sglcmpiw #0x33,%d1 |check for sglmulbnes unf_cont |if not, use fpcr prec in roundunf_sgl:clrl %d0movew #0x1,(%a7) |override g_rndpr precision| ;force singlebras unf_contunf_E1:lea FPTEMP(%a6),%a0 |a0 now points to operandunf_cont:bclrb #sign_bit,LOCAL_EX(%a0) |clear sign bitsne LOCAL_SGN(%a0) |store signbsrl denorm |returns denorm, a0 points to it|| WARNING:| ;d0 has guard,round sticky bit| ;make sure that it is not corrupted| ;before it reaches the round subroutine| ;also ensure that a0 isn't corrupted|| Set up d1 for round subroutine d1 contains the PREC/MODE| information respectively on upper/lower register halves.|bfextu FPCR_MODE(%a6){#2:#2},%d1 |get mode from FPCR| ;mode in lower d1addl (%a7)+,%d1 |merge PREC/MODE|| WARNING: a0 and d0 are assumed to be intact between the denorm and| round subroutines. All code between these two subroutines| must not corrupt a0 and d0.||| Perform Round| Input: a0 points to input operand| d0{31:29} has guard, round, sticky| d1{01:00} has rounding mode| d1{17:16} has rounding precision| Output: a0 points to rounded operand|bsrl round |returns rounded denorm at (a0)|| Differentiate between store to memory vs. store to register|unf_store:bsrl g_opcls |returns opclass in d0{2:0}cmpib #0x3,%d0bnes not_opc011|| At this point, a store to memory is pending|opc011:bsrl g_dfmtoutstb %d0beqs ext_opc011 |If extended, do not subtract| ;If destination format is sgl/dbl,tstb LOCAL_HI(%a0) |If rounded result is normal,don't| ;subtractbmis ext_opc011subqw #1,LOCAL_EX(%a0) |account for denorm bias vs.| ;normalized bias| ; normalized denormalized| ;single $7f $7e| ;double $3ff $3fe|ext_opc011:bsrl store |stores to memorybras unf_done |finish up|| At this point, a store to a float register is pending|not_opc011:bsrl store |stores to float register| ;a0 is not corrupted on a store to a| ;float register.|| Set the condition codes according to result|tstl LOCAL_HI(%a0) |check upper mantissabnes ck_sgntstl LOCAL_LO(%a0) |check lower mantissabnes ck_sgnbsetb #z_bit,FPSR_CC(%a6) |set condition codes if zerock_sgn:btstb #sign_bit,LOCAL_EX(%a0) |check the sign bitbeqs unf_donebsetb #neg_bit,FPSR_CC(%a6)|| Finish.|unf_done:btstb #inex2_bit,FPSR_EXCEPT(%a6)beqs no_aunflbsetb #aunfl_bit,FPSR_AEXCEPT(%a6)no_aunfl:rts|end
