URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libcpu/] [m68k/] [m68040/] [fpsp/] [util.S] - Rev 507
Go to most recent revision | Compare with Previous | Blame | View Log
//// $Id: util.S,v 1.2 2001-09-27 12:01:22 chris Exp $//// 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.// ;+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 operandbclrb #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 exceptionbeql ovf_e1_exc //it is cu exceptionovf_e3_exc:movew CMDREG3B(%a6),%d0 //get the command wordandiw #0x00000060,%d0 //clear all bits except 6 and 5cmpil #0x00000040,%d0beql ovff_sgl //force precision is singlecmpil #0x00000060,%d0beql ovff_dbl //force precision is doublemovew CMDREG3B(%a6),%d0 //get the command word againandil #0x7f,%d0 //clear all except operationcmpil #0x33,%d0beql ovf_fsgl //fsglmul or fsgldivcmpil #0x30,%d0beql ovf_fsglbra ovf_fpcr //instruction is none of the above// ;use FPCRovf_e1_exc:movew CMDREG1B(%a6),%d0 //get command wordandil #0x00000044,%d0 //clear all bits except 6 and 2cmpil #0x00000040,%d0beql ovff_sgl //the instruction is force singlecmpil #0x00000044,%d0beql ovff_dbl //the instruction is force doublemovew CMDREG1B(%a6),%d0 //again get the command wordandil #0x0000007f,%d0 //clear all except the op codecmpil #0x00000027,%d0beql ovf_fsgl //fsglmulcmpil #0x00000024,%d0beql ovf_fsgl //fsgldivbra ovf_fpcr //none of the above, use FPCR////// Inst is either fsgldiv or fsglmul. Force extended precision.//ovf_fsgl:clrl %d0bra ovf_resovff_sgl:movel #0x00000001,%d0 //set singlebra ovf_resovff_dbl:movel #0x00000002,%d0 //set doublebra ovf_res//// The precision is in the fpcr.//ovf_fpcr:bfextu FPCR_MODE(%a6){#0:#2},%d0 //set round precisionbra 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 modeorl %d1,%d0 //index is fmt:mode in d0{3:0}leal tblovfl,%a1 //load a1 with table addressmovel %a1@(%d0:l:4),%a1 //use d0 as index to the tablejmp (%a1) //go to the correct routine////case DEST_FMT = EXT//EXT_RN:leal EXT_PINF,%a1 //answer is +/- infinitybsetb #inf_bit,FPSR_CC(%a6)bra set_sign //now go set the signEXT_RZ:leal EXT_PLRG,%a1 //answer is +/- large numberbra set_sign //now go set the signEXT_RM:tstb LOCAL_SGN(%a0) //if negative overflowbeqs e_rm_pose_rm_neg:leal EXT_PINF,%a1 //answer is negative infinityorl #neginf_mask,USER_FPSR(%a6)bra end_ovfre_rm_pos:leal EXT_PLRG,%a1 //answer is large positive numberbra end_ovfrEXT_RP:tstb LOCAL_SGN(%a0) //if negative overflowbeqs e_rp_pose_rp_neg:leal EXT_PLRG,%a1 //answer is large negative numberbsetb #neg_bit,FPSR_CC(%a6)bra end_ovfre_rp_pos:leal EXT_PINF,%a1 //answer is positive infinitybsetb #inf_bit,FPSR_CC(%a6)bra end_ovfr////case DEST_FMT = DBL//DBL_RN:leal EXT_PINF,%a1 //answer is +/- infinitybsetb #inf_bit,FPSR_CC(%a6)bra set_signDBL_RZ:leal DBL_PLRG,%a1 //answer is +/- large numberbra set_sign //now go set the signDBL_RM:tstb LOCAL_SGN(%a0) //if negative overflowbeqs d_rm_posd_rm_neg:leal EXT_PINF,%a1 //answer is negative infinityorl #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 numberbra end_ovfrDBL_RP:tstb LOCAL_SGN(%a0) //if negative overflowbeqs d_rp_posd_rp_neg:leal DBL_PLRG,%a1 //answer is large negative numberbsetb #neg_bit,FPSR_CC(%a6)bra end_ovfrd_rp_pos:leal EXT_PINF,%a1 //answer is positive infinitybsetb #inf_bit,FPSR_CC(%a6)bra end_ovfr////case DEST_FMT = SGL//SGL_RN:leal EXT_PINF,%a1 //answer is +/- infinitybsetb #inf_bit,FPSR_CC(%a6)bras set_signSGL_RZ:leal SGL_PLRG,%a1 //answer is +/- large numberbras set_signSGL_RM:tstb LOCAL_SGN(%a0) //if negative overflowbeqs s_rm_poss_rm_neg:leal EXT_PINF,%a1 //answer is negative infinityorl #neginf_mask,USER_FPSR(%a6)bras end_ovfrs_rm_pos:leal SGL_PLRG,%a1 //answer is large positive numberbras end_ovfrSGL_RP:tstb LOCAL_SGN(%a0) //if negative overflowbeqs s_rp_poss_rp_neg:leal SGL_PLRG,%a1 //answer is large negative numberbsetb #neg_bit,FPSR_CC(%a6)bras end_ovfrs_rp_pos:leal EXT_PINF,%a1 //answer is positive infinitybsetb #inf_bit,FPSR_CC(%a6)bras end_ovfrset_sign:tstb LOCAL_SGN(%a0) //if negative overflowbeqs end_ovfrneg_sign:bsetb #neg_bit,FPSR_CC(%a6)end_ovfr:movew LOCAL_EX(%a1),LOCAL_EX(%a0) //do not overwrite signmovel 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 addressmovel #0,-(%a7) //reserve a word on the stackleal 2(%a7),%a1 //point to low word of temporarymovel #2,%d0 //countbsrl mem_readmovel (%a7)+,%d0rts//// 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 011bnes 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_dfmtourtsop_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,%d0beql unff_sgl //force precision is singlecmpil #0x3,%d0 //force precision is doublebeql unff_dblmovew CMDREG3B(%a6),%d0 //get the command word againandil #0x7f,%d0 //clear all except operationcmpil #0x33,%d0beql unf_fsgl //fsglmul or fsgldivcmpil #0x30,%d0beql unf_fsgl //fsgldiv or fsglmulbra unf_fpcrunf_e1_exc:movel CMDREG1B(%a6),%d0 //get 32 bits off the stack, 1st 16 bits// ;are the command wordandil #0x00440000,%d0 //clear all bits except bits 6 and 2cmpil #0x00400000,%d0beql unff_sgl //force singlecmpil #0x00440000,%d0 //force doublebeql unff_dblmovel CMDREG1B(%a6),%d0 //get the command word againandil #0x007f0000,%d0 //clear all bits except the operationcmpil #0x00270000,%d0beql unf_fsgl //fsglmulcmpil #0x00240000,%d0beql unf_fsgl //fsgldivbra 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 1rts//// Force double//unff_dbl:movel #2,%d0 //return 2rts//// Force extended//unf_fsgl:movel #0,%d0rts//// 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 cmdreg1bopc_3b:clrl %d0 //if E3, only opclass 0x0 is possiblertsopc_1b:movel CMDREG1B(%a6),%d0bfextu %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 op011clrl %d0 //if E1, size is always extrtsop011:movel CMDREG1B(%a6),%d0bfextu %d0{#3:#3},%d0 //dest fmt from cmdreg1b{12:10}cmpb #1,%d0 //check for singlebnes not_sglmovel #1,%d0rtsnot_sgl:cmpb #5,%d0 //check for doublebnes not_dblmovel #2,%d0rtsnot_dbl:clrl %d0 //must be extendedrts////// Final result table for unf_sub. Note that the negative counterparts// are unnecessary as unf_sub always returns the sign separately from// the exponent.// ;+zeroEXT_PZRO: .long 0x00000000,0x00000000,0x00000000,0x00000000// ;+zeroSGL_PZRO: .long 0x3f810000,0x00000000,0x00000000,0x00000000// ;+zeroDBL_PZRO: .long 0x3c010000,0x00000000,0x00000000,0x00000000// ;smallest +ext denormEXT_PSML: .long 0x00000000,0x00000000,0x00000001,0x00000000// ;smallest +sgl denormSGL_PSML: .long 0x3f810000,0x00000100,0x00000000,0x00000000// ;smallest +dbl denormDBL_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_subunf_sub:lsll #2,%d0 //move round precision to d0{3:2}bfextu FPCR_MODE(%a6){#2:#2},%d1 //set round modeorl %d1,%d0 //index is fmt:mode in d0{3:0}leal tblunf,%a1 //load a1 with table addressmovel %a1@(%d0:l:4),%a1 //use d0 as index to the tablejmp (%a1) //go to the correct routine////case DEST_FMT = EXT//uEXT_RN:leal EXT_PZRO,%a1 //answer is +/- zerobsetb #z_bit,FPSR_CC(%a6)bra uset_sign //now go set the signuEXT_RZ:leal EXT_PZRO,%a1 //answer is +/- zerobsetb #z_bit,FPSR_CC(%a6)bra uset_sign //now go set the signuEXT_RM:tstb LOCAL_SGN(%a0) //if negative underflowbeqs ue_rm_posue_rm_neg:leal EXT_PSML,%a1 //answer is negative smallest denormbsetb #neg_bit,FPSR_CC(%a6)bra end_unfrue_rm_pos:leal EXT_PZRO,%a1 //answer is positive zerobsetb #z_bit,FPSR_CC(%a6)bra end_unfruEXT_RP:tstb LOCAL_SGN(%a0) //if negative underflowbeqs ue_rp_posue_rp_neg:leal EXT_PZRO,%a1 //answer is negative zerooril #negz_mask,USER_FPSR(%a6)bra end_unfrue_rp_pos:leal EXT_PSML,%a1 //answer is positive smallest denormbra end_unfr////case DEST_FMT = DBL//uDBL_RN:leal DBL_PZRO,%a1 //answer is +/- zerobsetb #z_bit,FPSR_CC(%a6)bra uset_signuDBL_RZ:leal DBL_PZRO,%a1 //answer is +/- zerobsetb #z_bit,FPSR_CC(%a6)bra uset_sign //now go set the signuDBL_RM:tstb LOCAL_SGN(%a0) //if negative overflowbeqs ud_rm_posud_rm_neg:leal DBL_PSML,%a1 //answer is smallest denormalized negativebsetb #neg_bit,FPSR_CC(%a6)bra end_unfrud_rm_pos:leal DBL_PZRO,%a1 //answer is positive zerobsetb #z_bit,FPSR_CC(%a6)bra end_unfruDBL_RP:tstb LOCAL_SGN(%a0) //if negative overflowbeqs ud_rp_posud_rp_neg:leal DBL_PZRO,%a1 //answer is negative zerooril #negz_mask,USER_FPSR(%a6)bra end_unfrud_rp_pos:leal DBL_PSML,%a1 //answer is smallest denormalized negativebra end_unfr////case DEST_FMT = SGL//uSGL_RN:leal SGL_PZRO,%a1 //answer is +/- zerobsetb #z_bit,FPSR_CC(%a6)bras uset_signuSGL_RZ:leal SGL_PZRO,%a1 //answer is +/- zerobsetb #z_bit,FPSR_CC(%a6)bras uset_signuSGL_RM:tstb LOCAL_SGN(%a0) //if negative overflowbeqs us_rm_posus_rm_neg:leal SGL_PSML,%a1 //answer is smallest denormalized negativebsetb #neg_bit,FPSR_CC(%a6)bras end_unfrus_rm_pos:leal SGL_PZRO,%a1 //answer is positive zerobsetb #z_bit,FPSR_CC(%a6)bras end_unfruSGL_RP:tstb LOCAL_SGN(%a0) //if negative overflowbeqs us_rp_posus_rp_neg:leal SGL_PZRO,%a1 //answer is negative zerooril #negz_mask,USER_FPSR(%a6)bras end_unfrus_rp_pos:leal SGL_PSML,%a1 //answer is smallest denormalized positivebras end_unfruset_sign:tstb LOCAL_SGN(%a0) //if negative overflowbeqs end_unfruneg_sign:bsetb #neg_bit,FPSR_CC(%a6)end_unfr:movew LOCAL_EX(%a1),LOCAL_EX(%a0) //be careful not to overwrite signmovel 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_d7reg_dest:leal pregdst,%a0movel %a0@(%d1:l:4),%a0jmp (%a0)byte_d0:moveb L_SCR1(%a6),USER_D0+3(%a6)rtsbyte_d1:moveb L_SCR1(%a6),USER_D1+3(%a6)rtsbyte_d2:moveb L_SCR1(%a6),%d2rtsbyte_d3:moveb L_SCR1(%a6),%d3rtsbyte_d4:moveb L_SCR1(%a6),%d4rtsbyte_d5:moveb L_SCR1(%a6),%d5rtsbyte_d6:moveb L_SCR1(%a6),%d6rtsbyte_d7:moveb L_SCR1(%a6),%d7rtsword_d0:movew L_SCR1(%a6),USER_D0+2(%a6)rtsword_d1:movew L_SCR1(%a6),USER_D1+2(%a6)rtsword_d2:movew L_SCR1(%a6),%d2rtsword_d3:movew L_SCR1(%a6),%d3rtsword_d4:movew L_SCR1(%a6),%d4rtsword_d5:movew L_SCR1(%a6),%d5rtsword_d6:movew L_SCR1(%a6),%d6rtsword_d7:movew L_SCR1(%a6),%d7rtslong_d0:movel L_SCR1(%a6),USER_D0(%a6)rtslong_d1:movel L_SCR1(%a6),USER_D1(%a6)rtslong_d2:movel L_SCR1(%a6),%d2rtslong_d3:movel L_SCR1(%a6),%d3rtslong_d4:movel L_SCR1(%a6),%d4rtslong_d5:movel L_SCR1(%a6),%d5rtslong_d6:movel L_SCR1(%a6),%d6rtslong_d7:movel L_SCR1(%a6),%d7rts|end
Go to most recent revision | Compare with Previous | Blame | View Log
