📄 util.s
字号:
|| util.sa 3.7 7/29/91|| This file contains routines used by other programs.|| ovf_res: used by overflow to force the correct| result. ovf_r_k, ovf_r_x2, ovf_r_x3 are | derivatives of this routine.| get_fline: get user's opcode word| g_dfmtou: returns the destination format.| g_opcls: returns the opclass of the float instruction.| g_rndpr: returns the rounding precision. | reg_dest: write byte, word, or long data to Dn||| 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.|UTIL idnt 2,1 | Motorola 040 Floating Point Software Package |section 8 .include "fpsp.h" |xref mem_read .global g_dfmtou .global g_opcls .global g_rndpr .global get_fline .global reg_dest|| Final result table for ovf_res. Note that the negative counterparts| are unnecessary as ovf_res always returns the sign separately from| the exponent.| ;+infEXT_PINF: .long 0x7fff0000,0x00000000,0x00000000,0x00000000 | ;largest +extEXT_PLRG: .long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 | ;largest magnitude +sgl in extSGL_PLRG: .long 0x407e0000,0xffffff00,0x00000000,0x00000000 | ;largest magnitude +dbl in extDBL_PLRG: .long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 | ;largest -exttblovfl: .long EXT_RN .long EXT_RZ .long EXT_RM .long EXT_RP .long SGL_RN .long SGL_RZ .long SGL_RM .long SGL_RP .long DBL_RN .long DBL_RZ .long DBL_RM .long DBL_RP .long error .long error .long error .long error|| ovf_r_k --- overflow result calculation|| This entry point is used by kernel_ex. || This forces the destination precision to be extended|| Input: operand in ETEMP| Output: a result is in ETEMP (internal extended format)| .global ovf_r_kovf_r_k: lea ETEMP(%a6),%a0 |a0 points to source operand bclrb #sign_bit,ETEMP_EX(%a6) sne ETEMP_SGN(%a6) |convert to internal IEEE format|| ovf_r_x2 --- overflow result calculation|| This entry point used by x_ovfl. (opclass 0 and 2)|| Input a0 points to an operand in the internal extended format| Output a0 points to the result in the internal extended format|| This sets the round precision according to the user's FPCR unless the| instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul,| fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg.| If the instruction is fsgldiv of fsglmul, the rounding precision must be| extended. If the instruction is not fsgldiv or fsglmul but a force-| precision instruction, the rounding precision is then set to the force| precision. .global ovf_r_x2ovf_r_x2: btstb #E3,E_BYTE(%a6) |check for nu exception beql ovf_e1_exc |it is cu exceptionovf_e3_exc: movew CMDREG3B(%a6),%d0 |get the command word andiw #0x00000060,%d0 |clear all bits except 6 and 5 cmpil #0x00000040,%d0 beql ovff_sgl |force precision is single cmpil #0x00000060,%d0 beql ovff_dbl |force precision is double movew CMDREG3B(%a6),%d0 |get the command word again andil #0x7f,%d0 |clear all except operation cmpil #0x33,%d0 beql ovf_fsgl |fsglmul or fsgldiv cmpil #0x30,%d0 beql ovf_fsgl bra ovf_fpcr |instruction is none of the above| ;use FPCRovf_e1_exc: movew CMDREG1B(%a6),%d0 |get command word andil #0x00000044,%d0 |clear all bits except 6 and 2 cmpil #0x00000040,%d0 beql ovff_sgl |the instruction is force single cmpil #0x00000044,%d0 beql ovff_dbl |the instruction is force double movew CMDREG1B(%a6),%d0 |again get the command word andil #0x0000007f,%d0 |clear all except the op code cmpil #0x00000027,%d0 beql ovf_fsgl |fsglmul cmpil #0x00000024,%d0 beql ovf_fsgl |fsgldiv bra ovf_fpcr |none of the above, use FPCR| || Inst is either fsgldiv or fsglmul. Force extended precision.|ovf_fsgl: clrl %d0 bra ovf_resovff_sgl: movel #0x00000001,%d0 |set single bra ovf_resovff_dbl: movel #0x00000002,%d0 |set double bra ovf_res|| The precision is in the fpcr.|ovf_fpcr: bfextu FPCR_MODE(%a6){#0:#2},%d0 |set round precision bra ovf_res ||| ovf_r_x3 --- overflow result calculation|| This entry point used by x_ovfl. (opclass 3 only)|| Input a0 points to an operand in the internal extended format| Output a0 points to the result in the internal extended format|| This sets the round precision according to the destination size.| .global ovf_r_x3ovf_r_x3: bsr g_dfmtou |get dest fmt in d0{1:0}| ;for fmovout, the destination format| ;is the rounding precision|| ovf_res --- overflow result calculation|| Input:| a0 points to operand in internal extended format| Output:| a0 points to result in internal extended format| .global ovf_resovf_res: lsll #2,%d0 |move round precision to d0{3:2} bfextu FPCR_MODE(%a6){#2:#2},%d1 |set round mode orl %d1,%d0 |index is fmt:mode in d0{3:0} leal tblovfl,%a1 |load a1 with table address movel %a1@(%d0:l:4),%a1 |use d0 as index to the table jmp (%a1) |go to the correct routine||case DEST_FMT = EXT|EXT_RN: leal EXT_PINF,%a1 |answer is +/- infinity bsetb #inf_bit,FPSR_CC(%a6) bra set_sign |now go set the sign EXT_RZ: leal EXT_PLRG,%a1 |answer is +/- large number bra set_sign |now go set the signEXT_RM: tstb LOCAL_SGN(%a0) |if negative overflow beqs e_rm_pose_rm_neg: leal EXT_PINF,%a1 |answer is negative infinity orl #neginf_mask,USER_FPSR(%a6) bra end_ovfre_rm_pos: leal EXT_PLRG,%a1 |answer is large positive number bra end_ovfrEXT_RP: tstb LOCAL_SGN(%a0) |if negative overflow beqs e_rp_pose_rp_neg: leal EXT_PLRG,%a1 |answer is large negative number bsetb #neg_bit,FPSR_CC(%a6) bra end_ovfre_rp_pos: leal EXT_PINF,%a1 |answer is positive infinity bsetb #inf_bit,FPSR_CC(%a6) bra end_ovfr||case DEST_FMT = DBL|DBL_RN: leal EXT_PINF,%a1 |answer is +/- infinity bsetb #inf_bit,FPSR_CC(%a6) bra set_signDBL_RZ: leal DBL_PLRG,%a1 |answer is +/- large number bra set_sign |now go set the signDBL_RM: tstb LOCAL_SGN(%a0) |if negative overflow beqs d_rm_posd_rm_neg: leal EXT_PINF,%a1 |answer is negative infinity orl #neginf_mask,USER_FPSR(%a6) bra end_ovfr |inf is same for all precisions (ext,dbl,sgl)d_rm_pos: leal DBL_PLRG,%a1 |answer is large positive number bra end_ovfrDBL_RP: tstb LOCAL_SGN(%a0) |if negative overflow beqs d_rp_posd_rp_neg: leal DBL_PLRG,%a1 |answer is large negative number bsetb #neg_bit,FPSR_CC(%a6) bra end_ovfrd_rp_pos: leal EXT_PINF,%a1 |answer is positive infinity bsetb #inf_bit,FPSR_CC(%a6) bra end_ovfr||case DEST_FMT = SGL|SGL_RN: leal EXT_PINF,%a1 |answer is +/- infinity bsetb #inf_bit,FPSR_CC(%a6) bras set_signSGL_RZ: leal SGL_PLRG,%a1 |answer is +/- large number bras set_signSGL_RM: tstb LOCAL_SGN(%a0) |if negative overflow beqs s_rm_poss_rm_neg: leal EXT_PINF,%a1 |answer is negative infinity orl #neginf_mask,USER_FPSR(%a6) bras end_ovfrs_rm_pos: leal SGL_PLRG,%a1 |answer is large positive number bras end_ovfrSGL_RP: tstb LOCAL_SGN(%a0) |if negative overflow beqs s_rp_poss_rp_neg: leal SGL_PLRG,%a1 |answer is large negative number bsetb #neg_bit,FPSR_CC(%a6) bras end_ovfrs_rp_pos: leal EXT_PINF,%a1 |answer is positive infinity bsetb #inf_bit,FPSR_CC(%a6) bras end_ovfrset_sign: tstb LOCAL_SGN(%a0) |if negative overflow beqs end_ovfrneg_sign: bsetb #neg_bit,FPSR_CC(%a6)end_ovfr: movew LOCAL_EX(%a1),LOCAL_EX(%a0) |do not overwrite sign movel LOCAL_HI(%a1),LOCAL_HI(%a0) movel LOCAL_LO(%a1),LOCAL_LO(%a0) rts|| ERROR|error: rts|| get_fline --- get f-line opcode of interrupted instruction|| Returns opcode in the low word of d0.|get_fline: movel USER_FPIAR(%a6),%a0 |opcode address movel #0,-(%a7) |reserve a word on the stack leal 2(%a7),%a1 |point to low word of temporary movel #2,%d0 |count bsrl mem_read movel (%a7)+,%d0 rts|| g_rndpr --- put rounding precision in d0{1:0}| | valid return codes are:| 00 - extended | 01 - single| 10 - double|| begin| get rounding precision (cmdreg3b{6:5})| begin| case opclass = 011 (move out)| get destination format - this is the also the rounding precision|| case opclass = 0x0| if E3| *case RndPr(from cmdreg3b{6:5} = 11 then RND_PREC = DBL| *case RndPr(from cmdreg3b{6:5} = 10 then RND_PREC = SGL| case RndPr(from cmdreg3b{6:5} = 00 | 01| use precision from FPCR{7:6}| case 00 then RND_PREC = EXT| case 01 then RND_PREC = SGL| case 10 then RND_PREC = DBL| else E1| use precision in FPCR{7:6}| case 00 then RND_PREC = EXT| case 01 then RND_PREC = SGL| case 10 then RND_PREC = DBL| end|g_rndpr: bsr g_opcls |get opclass in d0{2:0} cmpw #0x0003,%d0 |check for opclass 011 bnes op_0x0|| For move out instructions (opclass 011) the destination format| is the same as the rounding precision. Pass results from g_dfmtou.| bsr g_dfmtou rtsop_0x0: btstb #E3,E_BYTE(%a6) beql unf_e1_exc |branch to e1 underflowunf_e3_exc: movel CMDREG3B(%a6),%d0 |rounding precision in d0{10:9} bfextu %d0{#9:#2},%d0 |move the rounding prec bits to d0{1:0} cmpil #0x2,%d0 beql unff_sgl |force precision is single cmpil #0x3,%d0 |force precision is double beql unff_dbl movew CMDREG3B(%a6),%d0 |get the command word again andil #0x7f,%d0 |clear all except operation cmpil #0x33,%d0 beql unf_fsgl |fsglmul or fsgldiv cmpil #0x30,%d0 beql unf_fsgl |fsgldiv or fsglmul bra unf_fpcrunf_e1_exc: movel CMDREG1B(%a6),%d0 |get 32 bits off the stack, 1st 16 bits| ;are the command word andil #0x00440000,%d0 |clear all bits except bits 6 and 2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -