📄 util.s
字号:
/* util.s - Motorola 68040 FP utility routines (EXC) *//* Copyright 1991-1993 Wind River Systems, Inc. */ .data .globl _copyright_wind_river .long _copyright_wind_river/*modification history--------------------01f,21jul93,kdl added .text (SPR #2372).01e,23aug92,jcf changed bxxx to jxx.01d,26may92,rrr the tree shuffle01c,10jan92,kdl general cleanup.01b,17dec91,kdl put in changes from Motorola v3.7 (FPSP v2.1): handle implied precision in __x_ovf_r_k; comment-out __x_check_force routine.01a,15aug91,kdl original version, from Motorola FPSP v2.0; changed {byte,word,long}_d{0-7} labels to avoid confusion when converting to mit format.*//*DESCRIPTION utilsa 3.3 4/26/91 This file contains routines used by other programs. __x_ovf_res: used by overflow to force the correct result. __x_ovf_r_k, __x_ovf_r_x2, __x_ovf_r_x3 are derivatives of this routine. __x_get_fline: get user's opcode word __x_g_dfmtou: returns the destination format. __x_g_opcls: returns the opclass of the float instruction. __x_g_rndpr: returns the rounding precision. __x_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 8NOMANUAL*/#include "fpsp040E.h"| xref __x_mem_read .globl __x_g_dfmtou .globl __x_g_opcls .globl __x_g_rndpr .globl __x_get_fline .globl __x_reg_dest|| Final result table for __x_ovf_res. Note that the negative counterparts| are unnecessary as __x_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| .globl __x_check_force|| __x_check_force --- check the rounding precision of the instruction|| This entry point is used by the exception handlers.|| Check the CMDREG1B or CMDREG3B command word to decide the rounding| precision of the instruction.|| Input: rounding precision in a6@(USER_FPCR).| Output: a6@(USER_FPCR) is possibly modified to reflect the| rounding precision of the instruction.| Register Usage: d0 is scratch register.|__x_check_force:| btst #E3,a6@(E_BYTE) | check for nu exception| jeq e1_exc | it is cu exception|e3_exc:| movew a6@(CMDREG3B),d0 | get the command word| andiw #0x00000060,d0 | clear all bits except 6 and 5| cmpil #0x00000040,d0| jeq f_sgl | force precision is single| cmpil #0x00000060,d0| jeq f_dbl | force precision is double| movew a6@(CMDREG3B),d0 | get the command word again| andil #0x7f,d0 | clear all except operation| cmpil #0x33,d0| jeq f_sglmd | fsglmul or fsgldiv| cmpil #0x30,d0| jeq f_sglmd| rts|e1_exc:| movew a6@(CMDREG1B),d0 | get command word| andil #0x00000044,d0 | clear all bits except 6 and 2| cmpil #0x00000040,d0| jeq f_sgl | the instruction is force single| cmpil #0x00000044,d0| jeq f_dbl | the instruction is force double| movew a6@(CMDREG1B),d0 | again get the command word| andil #0x0000007f,d0 | clear all except the op code| cmpil #0x00000027,d0| jeq f_sglmd | fsglmul| cmpil #0x00000024,d0| jeq f_sglmd | fsgldiv| rts|f_sgl:| andib #0x3f,a6@(fpcr_MODE) | single precision| orib #0x40,a6@(fpcr_MODE)| rts|f_dbl:| andib #0x3f,a6@(fpcr_MODE)| orib #0x80,a6@(fpcr_MODE)| rts|f_sglmd:| andib #0x3f,a6@(fpcr_MODE)| rts|| __x_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)| .text .globl __x_ovf_r_k__x_ovf_r_k: lea a6@(ETEMP),a0 | a0 points to source operand bclr #sign_bit,a6@(ETEMP_EX) sne a6@(ETEMP_SGN) | convert to internal IEEE format|| __x_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 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. .globl __x_ovf_r_x2__x_ovf_r_x2: btst #E3,a6@(E_BYTE) | check for nu exception jeq ovf_e1_exc | it is cu exceptionovf_e3_exc: movew a6@(CMDREG3B),d0 | get the command word andiw #0x00000060,d0 | clear all bits except 6 and 5 cmpil #0x00000040,d0 jeq ovff_sgl | force precision is single cmpil #0x00000060,d0 jeq ovff_dbl | force precision is double movew a6@(CMDREG3B),d0 | get the command word again andil #0x7f,d0 | clear all except operation cmpil #0x33,d0 jeq ovf_fsgl | fsglmul or fsgldiv cmpil #0x30,d0 jeq ovf_fsgl jra ovf_fpcr | instruction is none of the above| | use fpcrovf_e1_exc: movew a6@(CMDREG1B),d0 | get command word andil #0x00000044,d0 | clear all bits except 6 and 2 cmpil #0x00000040,d0 jeq ovff_sgl | the instruction is force single cmpil #0x00000044,d0 jeq ovff_dbl | the instruction is force double movew a6@(CMDREG1B),d0 | again get the command word andil #0x0000007f,d0 | clear all except the op code cmpil #0x00000027,d0 jeq ovf_fsgl | fsglmul cmpil #0x00000024,d0 jeq ovf_fsgl | fsgldiv jra ovf_fpcr | none of the above, use fpcr||| Inst is either fsgldiv or fsglmul. Force extended precision.|ovf_fsgl: clrl d0 jra __x_ovf_resovff_sgl: movel #0x00000001,d0 | set single jra __x_ovf_resovff_dbl: movel #0x00000002,d0 | set double jra __x_ovf_res|| The precision is in the fpcr.|ovf_fpcr: bfextu a6@(fpcr_MODE){#0:#2},d0 | set round precision jra __x_ovf_res||| __x_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.| .globl __x_ovf_r_x3__x_ovf_r_x3: bsrl __x_g_dfmtou | get dest fmt in d0{1:0}| | for fmovout, the destination format| | is the rounding precision|| __x_ovf_res --- overflow result calculation|| Input:| a0 points to operand in internal extended format| Output:| a0 points to result in internal extended format| .globl __x_ovf_res__x_ovf_res: lsll #2,d0 | move round precision to d0{3:2} bfextu a6@(fpcr_MODE){#2:#2},d1 | set round mode orl d1,d0 | index is fmt:mode in d0{3:0} lea tblovfl,a1 | load a1 with table address movel a1@(d0:w:4),a1 | use d0 as index to the table jmp a1@ | go to the correct routine||case DEST_FMT = EXT|EXT_RN: lea EXT_PINF,a1 | answer is +/- infinity bset #inf_bit,a6@(FPSR_CC) jra set_sign | now go set the signEXT_RZ: lea EXT_PLRG,a1 | answer is +/- large number jra set_sign | now go set the signEXT_RM: tstb a0@(LOCAL_SGN) | if negative overflow jeq e_rm_pose_rm_neg: lea EXT_PINF,a1 | answer is negative infinity orl #neginf_mask,a6@(USER_FPSR) jra end_ovfre_rm_pos: lea EXT_PLRG,a1 | answer is large positive number jra end_ovfrEXT_RP: tstb a0@(LOCAL_SGN) | if negative overflow jeq e_rp_pose_rp_neg: lea EXT_PLRG,a1 | answer is large negative number bset #neg_bit,a6@(FPSR_CC) jra end_ovfre_rp_pos: lea EXT_PINF,a1 | answer is positive infinity bset #inf_bit,a6@(FPSR_CC) jra end_ovfr||case DEST_FMT = DBL|DBL_RN: lea EXT_PINF,a1 | answer is +/- infinity bset #inf_bit,a6@(FPSR_CC) jra set_signDBL_RZ: lea DBL_PLRG,a1 | answer is +/- large number jra set_sign | now go set the signDBL_RM: tstb a0@(LOCAL_SGN) | if negative overflow jeq d_rm_posd_rm_neg: lea EXT_PINF,a1 | answer is negative infinity orl #neginf_mask,a6@(USER_FPSR) jra end_ovfr | inf is same for all precisions (ext,dbl,sgl)d_rm_pos: lea DBL_PLRG,a1 | answer is large positive number jra end_ovfrDBL_RP: tstb a0@(LOCAL_SGN) | if negative overflow jeq d_rp_posd_rp_neg: lea DBL_PLRG,a1 | answer is large negative number bset #neg_bit,a6@(FPSR_CC) jra end_ovfrd_rp_pos: lea EXT_PINF,a1 | answer is positive infinity bset #inf_bit,a6@(FPSR_CC) jra end_ovfr||case DEST_FMT = SGL|SGL_RN: lea EXT_PINF,a1 | answer is +/- infinity bset #inf_bit,a6@(FPSR_CC) jra set_signSGL_RZ: lea SGL_PLRG,a1 | anwer is +/- large number jra set_signSGL_RM: tstb a0@(LOCAL_SGN) | if negative overflow jeq s_rm_poss_rm_neg: lea EXT_PINF,a1 | answer is negative infinity orl #neginf_mask,a6@(USER_FPSR) jra end_ovfrs_rm_pos: lea SGL_PLRG,a1 | answer is large positive number jra end_ovfrSGL_RP: tstb a0@(LOCAL_SGN) | if negative overflow jeq s_rp_poss_rp_neg: lea SGL_PLRG,a1 | answer is large negative number bset #neg_bit,a6@(FPSR_CC) jra end_ovfrs_rp_pos: lea EXT_PINF,a1 | answer is postive infinity bset #inf_bit,a6@(FPSR_CC) jra end_ovfrset_sign: tstb a0@(LOCAL_SGN) | if negative overflow jeq end_ovfrneg_sign: bset #neg_bit,a6@(FPSR_CC)end_ovfr: movew a1@(LOCAL_EX),a0@(LOCAL_EX) | do not overwrite sign movel a1@(LOCAL_HI),a0@(LOCAL_HI) movel a1@(LOCAL_LO),a0@(LOCAL_LO) rts|| ERROR|error: rts|| __x_get_fline --- get f-line opcode of interrupted instruction|| Returns opcode in the low word of d0.|__x_get_fline: movel a6@(USER_fpi),a0 | opcode address movel #0,a7@- | reserve a word on the stack lea a7@(2),a1 | point to low word of temporary movel #2,d0 | count bsrl __x_mem_read movel a7@+,d0 rts|| __x_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -