diff options
Diffstat (limited to 'c/src/lib/libcpu/m68k/m68040/fpsp/util.S')
-rw-r--r-- | c/src/lib/libcpu/m68k/m68040/fpsp/util.S | 750 |
1 files changed, 0 insertions, 750 deletions
diff --git a/c/src/lib/libcpu/m68k/m68040/fpsp/util.S b/c/src/lib/libcpu/m68k/m68040/fpsp/util.S deleted file mode 100644 index 38e13db8b7..0000000000 --- a/c/src/lib/libcpu/m68k/m68040/fpsp/util.S +++ /dev/null @@ -1,750 +0,0 @@ -#include "fpsp-namespace.h" -// -// -// 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.defs" - - |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. -// ;+inf -EXT_PINF: .long 0x7fff0000,0x00000000,0x00000000,0x00000000 -// ;largest +ext -EXT_PLRG: .long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 -// ;largest magnitude +sgl in ext -SGL_PLRG: .long 0x407e0000,0xffffff00,0x00000000,0x00000000 -// ;largest magnitude +dbl in ext -DBL_PLRG: .long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 -// ;largest -ext - -tblovfl: - .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_k -ovf_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_x2 -ovf_r_x2: - btstb #E3,E_BYTE(%a6) //check for nu exception - beql ovf_e1_exc //it is cu exception -ovf_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 FPCR -ovf_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_res - -ovff_sgl: - movel #0x00000001,%d0 //set single - bra ovf_res -ovff_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_x3 -ovf_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_res -ovf_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 sign -EXT_RM: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs e_rm_pos -e_rm_neg: - leal EXT_PINF,%a1 //answer is negative infinity - orl #neginf_mask,USER_FPSR(%a6) - bra end_ovfr -e_rm_pos: - leal EXT_PLRG,%a1 //answer is large positive number - bra end_ovfr -EXT_RP: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs e_rp_pos -e_rp_neg: - leal EXT_PLRG,%a1 //answer is large negative number - bsetb #neg_bit,FPSR_CC(%a6) - bra end_ovfr -e_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_sign -DBL_RZ: - leal DBL_PLRG,%a1 //answer is +/- large number - bra set_sign //now go set the sign -DBL_RM: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs d_rm_pos -d_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_ovfr -DBL_RP: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs d_rp_pos -d_rp_neg: - leal DBL_PLRG,%a1 //answer is large negative number - bsetb #neg_bit,FPSR_CC(%a6) - bra end_ovfr -d_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_sign -SGL_RZ: - leal SGL_PLRG,%a1 //answer is +/- large number - bras set_sign -SGL_RM: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs s_rm_pos -s_rm_neg: - leal EXT_PINF,%a1 //answer is negative infinity - orl #neginf_mask,USER_FPSR(%a6) - bras end_ovfr -s_rm_pos: - leal SGL_PLRG,%a1 //answer is large positive number - bras end_ovfr -SGL_RP: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs s_rp_pos -s_rp_neg: - leal SGL_PLRG,%a1 //answer is large negative number - bsetb #neg_bit,FPSR_CC(%a6) - bras end_ovfr -s_rp_pos: - leal EXT_PINF,%a1 //answer is positive infinity - bsetb #inf_bit,FPSR_CC(%a6) - bras end_ovfr - -set_sign: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs end_ovfr -neg_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 - rts -op_0x0: - btstb #E3,E_BYTE(%a6) - beql unf_e1_exc //branch to e1 underflow -unf_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_fpcr -unf_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 - cmpil #0x00400000,%d0 - beql unff_sgl //force single - cmpil #0x00440000,%d0 //force double - beql unff_dbl - movel CMDREG1B(%a6),%d0 //get the command word again - andil #0x007f0000,%d0 //clear all bits except the operation - cmpil #0x00270000,%d0 - beql unf_fsgl //fsglmul - cmpil #0x00240000,%d0 - beql unf_fsgl //fsgldiv - bra unf_fpcr - -// -// Convert to return format. The values from cmdreg3b and the return -// values are: -// cmdreg3b return precision -// -------- ------ --------- -// 00,01 0 ext -// 10 1 sgl -// 11 2 dbl -// Force single -// -unff_sgl: - movel #1,%d0 //return 1 - rts -// -// Force double -// -unff_dbl: - movel #2,%d0 //return 2 - rts -// -// Force extended -// -unf_fsgl: - movel #0,%d0 - rts -// -// Get rounding precision set in FPCR{7:6}. -// -unf_fpcr: - movel USER_FPCR(%a6),%d0 //rounding precision bits in d0{7:6} - bfextu %d0{#24:#2},%d0 //move the rounding prec bits to d0{1:0} - rts -// -// g_opcls --- put opclass in d0{2:0} -// -g_opcls: - btstb #E3,E_BYTE(%a6) - beqs opc_1b //if set, go to cmdreg1b -opc_3b: - clrl %d0 //if E3, only opclass 0x0 is possible - rts -opc_1b: - movel CMDREG1B(%a6),%d0 - bfextu %d0{#0:#3},%d0 //shift opclass bits d0{31:29} to d0{2:0} - rts -// -// g_dfmtou --- put destination format in d0{1:0} -// -// If E1, the format is from cmdreg1b{12:10} -// If E3, the format is extended. -// -// Dest. Fmt. -// extended 010 -> 00 -// single 001 -> 01 -// double 101 -> 10 -// -g_dfmtou: - btstb #E3,E_BYTE(%a6) - beqs op011 - clrl %d0 //if E1, size is always ext - rts -op011: - movel CMDREG1B(%a6),%d0 - bfextu %d0{#3:#3},%d0 //dest fmt from cmdreg1b{12:10} - cmpb #1,%d0 //check for single - bnes not_sgl - movel #1,%d0 - rts -not_sgl: - cmpb #5,%d0 //check for double - bnes not_dbl - movel #2,%d0 - rts -not_dbl: - clrl %d0 //must be extended - rts - -// -// -// Final result table for unf_sub. Note that the negative counterparts -// are unnecessary as unf_sub always returns the sign separately from -// the exponent. -// ;+zero -EXT_PZRO: .long 0x00000000,0x00000000,0x00000000,0x00000000 -// ;+zero -SGL_PZRO: .long 0x3f810000,0x00000000,0x00000000,0x00000000 -// ;+zero -DBL_PZRO: .long 0x3c010000,0x00000000,0x00000000,0x00000000 -// ;smallest +ext denorm -EXT_PSML: .long 0x00000000,0x00000000,0x00000001,0x00000000 -// ;smallest +sgl denorm -SGL_PSML: .long 0x3f810000,0x00000100,0x00000000,0x00000000 -// ;smallest +dbl denorm -DBL_PSML: .long 0x3c010000,0x00000000,0x00000800,0x00000000 -// -// UNF_SUB --- underflow result calculation -// -// Input: -// d0 contains round precision -// a0 points to input operand in the internal extended format -// -// Output: -// a0 points to correct internal extended precision result. -// - -tblunf: - .long uEXT_RN - .long uEXT_RZ - .long uEXT_RM - .long uEXT_RP - .long uSGL_RN - .long uSGL_RZ - .long uSGL_RM - .long uSGL_RP - .long uDBL_RN - .long uDBL_RZ - .long uDBL_RM - .long uDBL_RP - .long uDBL_RN - .long uDBL_RZ - .long uDBL_RM - .long uDBL_RP - - .global unf_sub -unf_sub: - 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 tblunf,%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 -// -uEXT_RN: - leal EXT_PZRO,%a1 //answer is +/- zero - bsetb #z_bit,FPSR_CC(%a6) - bra uset_sign //now go set the sign -uEXT_RZ: - leal EXT_PZRO,%a1 //answer is +/- zero - bsetb #z_bit,FPSR_CC(%a6) - bra uset_sign //now go set the sign -uEXT_RM: - tstb LOCAL_SGN(%a0) //if negative underflow - beqs ue_rm_pos -ue_rm_neg: - leal EXT_PSML,%a1 //answer is negative smallest denorm - bsetb #neg_bit,FPSR_CC(%a6) - bra end_unfr -ue_rm_pos: - leal EXT_PZRO,%a1 //answer is positive zero - bsetb #z_bit,FPSR_CC(%a6) - bra end_unfr -uEXT_RP: - tstb LOCAL_SGN(%a0) //if negative underflow - beqs ue_rp_pos -ue_rp_neg: - leal EXT_PZRO,%a1 //answer is negative zero - oril #negz_mask,USER_FPSR(%a6) - bra end_unfr -ue_rp_pos: - leal EXT_PSML,%a1 //answer is positive smallest denorm - bra end_unfr -// -//case DEST_FMT = DBL -// -uDBL_RN: - leal DBL_PZRO,%a1 //answer is +/- zero - bsetb #z_bit,FPSR_CC(%a6) - bra uset_sign -uDBL_RZ: - leal DBL_PZRO,%a1 //answer is +/- zero - bsetb #z_bit,FPSR_CC(%a6) - bra uset_sign //now go set the sign -uDBL_RM: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs ud_rm_pos -ud_rm_neg: - leal DBL_PSML,%a1 //answer is smallest denormalized negative - bsetb #neg_bit,FPSR_CC(%a6) - bra end_unfr -ud_rm_pos: - leal DBL_PZRO,%a1 //answer is positive zero - bsetb #z_bit,FPSR_CC(%a6) - bra end_unfr -uDBL_RP: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs ud_rp_pos -ud_rp_neg: - leal DBL_PZRO,%a1 //answer is negative zero - oril #negz_mask,USER_FPSR(%a6) - bra end_unfr -ud_rp_pos: - leal DBL_PSML,%a1 //answer is smallest denormalized negative - bra end_unfr -// -//case DEST_FMT = SGL -// -uSGL_RN: - leal SGL_PZRO,%a1 //answer is +/- zero - bsetb #z_bit,FPSR_CC(%a6) - bras uset_sign -uSGL_RZ: - leal SGL_PZRO,%a1 //answer is +/- zero - bsetb #z_bit,FPSR_CC(%a6) - bras uset_sign -uSGL_RM: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs us_rm_pos -us_rm_neg: - leal SGL_PSML,%a1 //answer is smallest denormalized negative - bsetb #neg_bit,FPSR_CC(%a6) - bras end_unfr -us_rm_pos: - leal SGL_PZRO,%a1 //answer is positive zero - bsetb #z_bit,FPSR_CC(%a6) - bras end_unfr -uSGL_RP: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs us_rp_pos -us_rp_neg: - leal SGL_PZRO,%a1 //answer is negative zero - oril #negz_mask,USER_FPSR(%a6) - bras end_unfr -us_rp_pos: - leal SGL_PSML,%a1 //answer is smallest denormalized positive - bras end_unfr - -uset_sign: - tstb LOCAL_SGN(%a0) //if negative overflow - beqs end_unfr -uneg_sign: - bsetb #neg_bit,FPSR_CC(%a6) - -end_unfr: - movew LOCAL_EX(%a1),LOCAL_EX(%a0) //be careful not to overwrite sign - movel LOCAL_HI(%a1),LOCAL_HI(%a0) - movel LOCAL_LO(%a1),LOCAL_LO(%a0) - rts -// -// reg_dest --- write byte, word, or long data to Dn -// -// -// Input: -// L_SCR1: Data -// d1: data size and dest register number formatted as: -// -// 32 5 4 3 2 1 0 -// ----------------------------------------------- -// | 0 | Size | Dest Reg # | -// ----------------------------------------------- -// -// Size is: -// 0 - Byte -// 1 - Word -// 2 - Long/Single -// -pregdst: - .long byte_d0 - .long byte_d1 - .long byte_d2 - .long byte_d3 - .long byte_d4 - .long byte_d5 - .long byte_d6 - .long byte_d7 - .long word_d0 - .long word_d1 - .long word_d2 - .long word_d3 - .long word_d4 - .long word_d5 - .long word_d6 - .long word_d7 - .long long_d0 - .long long_d1 - .long long_d2 - .long long_d3 - .long long_d4 - .long long_d5 - .long long_d6 - .long long_d7 - -reg_dest: - leal pregdst,%a0 - movel %a0@(%d1:l:4),%a0 - jmp (%a0) - -byte_d0: - moveb L_SCR1(%a6),USER_D0+3(%a6) - rts -byte_d1: - moveb L_SCR1(%a6),USER_D1+3(%a6) - rts -byte_d2: - moveb L_SCR1(%a6),%d2 - rts -byte_d3: - moveb L_SCR1(%a6),%d3 - rts -byte_d4: - moveb L_SCR1(%a6),%d4 - rts -byte_d5: - moveb L_SCR1(%a6),%d5 - rts -byte_d6: - moveb L_SCR1(%a6),%d6 - rts -byte_d7: - moveb L_SCR1(%a6),%d7 - rts -word_d0: - movew L_SCR1(%a6),USER_D0+2(%a6) - rts -word_d1: - movew L_SCR1(%a6),USER_D1+2(%a6) - rts -word_d2: - movew L_SCR1(%a6),%d2 - rts -word_d3: - movew L_SCR1(%a6),%d3 - rts -word_d4: - movew L_SCR1(%a6),%d4 - rts -word_d5: - movew L_SCR1(%a6),%d5 - rts -word_d6: - movew L_SCR1(%a6),%d6 - rts -word_d7: - movew L_SCR1(%a6),%d7 - rts -long_d0: - movel L_SCR1(%a6),USER_D0(%a6) - rts -long_d1: - movel L_SCR1(%a6),USER_D1(%a6) - rts -long_d2: - movel L_SCR1(%a6),%d2 - rts -long_d3: - movel L_SCR1(%a6),%d3 - rts -long_d4: - movel L_SCR1(%a6),%d4 - rts -long_d5: - movel L_SCR1(%a6),%d5 - rts -long_d6: - movel L_SCR1(%a6),%d6 - rts -long_d7: - movel L_SCR1(%a6),%d7 - rts - |end |