/* This assembly file contains various support routines that are used throughout the libraries. The C runtime library Gordon A. Sterling Created on 1/12/90 */ #include "lib_glob.h" #include "dbl_glob.h" #include "flt_glob.h" .SEGMENT/CODE Code_Space_Name; .FILE RTL_FILENAME; /* This routine performs a floating point division in the current precision mode of the processor. Calling Parameters F12 contains the Denominator F11 contains the value 2.0; F7 contains the Numerator Return Registers F7 contains the Quotient Altered Registers F0, F7, F12 Cycle Count 8 cycles */ .GLOBAL ___float_divide; ___float_divide:F0=RECIPS F12; /*Get 4 bit seed R0=1/D*/ F12=F0*F12; /*D' = D*R0*/ F7=F0*F7, F0=F11-F12; /*F0=R1=2-D', F7=N*R0*/ F12=F0*F12; /*F12=D'=D'*R1*/ F7=F0*F7, F0=F11-F12; /*F7=N*R0*R1, F0=R2=2-D'*/ RTS (DB), F12=F0*F12; /*F12=D'=D'*R2*/ F7=F0*F7, F0=F11-F12; /*F7=N*R0*R1*R2, F0=R3=2-D'*/ F7=F0*F7; /*F12=N*R0*R1*R2*R3*/ /* This routine performs a double (or long double) to floating point conversion in the current precision mode of the processor Calling Parameters F0 contains upper word (|s|EXP|mantissa) F1 contains lower word ( LSBs of mantissa) Return Registers F0 contains floating point result Altered Registers F0, F1, F2, F3 Cycle Count 12 Cycles */ .GLOBAL ___lib_ldtof, ___lib_dtof; ___lib_ldtof: ___lib_dtof: R2=0x3F800000; /*Need a one to start*/ R3=FEXT R0 BY 0:20; /*Extract upper mantissa to R2*/ R2=R2 OR LSHIFT R3 BY 3; /*Shift into float mantissa*/ R3=FEXT R1 BY 9:23; /*Extract lower mantissa to R3*/ R1=-43; /*Relative exponent*/ F3=FLOAT R3 BY R1; /*Place into float format*/ F1=F2+F3; /*Determine mantissa of result*/ R2=FEXT R0 BY 20:11; /*Extract biased exponent*/ R3=D_EXP_BIAS; /*Get bias of double exponent*/ RTS (DB), F1=F1 COPYSIGN F0;/*Copy sign of result*/ R2=R2-R3; /*Get unbiased exponent*/ F0=SCALB F1 BY R2; /*Set exponent of result*/ /* This routine performs a floating point to double or long double conversion in the current precision mode of the processor Calling Parameters F0 contains floating point value Return Registers F0 contains MSW of double value (|s|EXP|mantissa) F1 contains LSW of double value (lower mantissa) Altered Registers F0, F1, F2, F3 Cycle Count 16 Cycles */ .GLOBAL ___lib_ftold, ___lib_ftod; ___lib_ftold: ___lib_ftod: R3=LOGB F0; /*Get exponent of float*/ R2=-R3; /*Prepare to zero exponent*/ F0=SCALB F0 BY R2, R1=R0; /*Zero exponent*/ IF EQ RTS (DB); /*Input == 0, so output=0*/ R2=D_EXP_BIAS; /*Get bias for a double*/ R3=R2+R3; /*Compute biased exp for double*/ R1=LSHIFT R3 BY 20; /*Position exponent bits*/ F1=F1 COPYSIGN F0; /*Place sign bit*/ F0=ABS F0; /*Clear sign bit*/ R2=FEXT R0 BY 3:20; /*Place upper mantissa bits*/ R1=R1 OR R2; /*Place into double word*/ R2=0x7FFFFFF8; /*Mask out everything but mant*/ R2=R0 AND R2; /*Lower mantissa bits only*/ R3=51; /*Relative exponent of lower mant*/ RTS (DB), F0=F0-F2; /*Compute remainder*/ R1=FIX F0 BY R3, R0=R1; /*Place lower mantissa*/ R1=LSHIFT R1 BY 1; /*Upshift lower mant to unsigned*/ /* This routine performs a double precision multiply on its two arguments. Calling Parameters R12 = |s|EXP|mantissa| of X R13 = mantissa of X R14 = |s|EXP|mantissa| of Y R15 = mantissa of Y Return registers F0 = |s|EXP|mantissa of (X*Y) F1 = mantissa of (X*Y) Altered registers R0, R1, R2, R3 MRF Cycle Count */ .GLOBAL ___lib_dmult; ___lib_dmult: R3=BCLR R12 BY 31; /* Shut off sign bit for -0 */ R3=R3 OR R13; /* Check for a zero input */ IF EQ JUMP (PC, zero_result); /* Zero result so return */ R3=BCLR R14 BY 31; /* Shut off sign bit for -0 */ R3=R3 OR R15; /* Check for a zero input */ IF EQ JUMP (PC, zero_result); /* Zero result, so return */ R0=LSHIFT R15 BY 11; /*Move LSW up, zero lower*/ R1=LSHIFT R13 BY 11; MRF=R0*R1 (UUF); R2=MR1F; MR0F=R2; R2=MR2F; MR1F=R2; R2=LSHIFT R15 by -21; /*Move LSW into place*/ R3=LSHIFT R13 BY -21; R2=R2 OR LSHIFT R14 BY 11; R3=R3 OR LSHIFT R12 BY 11; /*Move MSW into place 1.31*/ R2=BSET R2 BY 31; /*Set hidden bit*/ R3=BSET R3 BY 31; MRF=MRF+R0*R3 (UUF); MRF=MRF+R1*R2 (UUF); R0=MR1F; MR0F=R0; R0=MR2F; MR1F=R0; MRF=MRF+R2*R3 (UUF); R0=0x00000001; /* We need to do rounding here */ R1=0x00000100; /* so we are going to add 1/2LSB*/ MRF=MRF+R0*R1 (UUF); /* to the number we just created*/ R0=LSHIFT R14 BY -20; /*Extract exponent*/ R1=LSHIFT R12 BY -20; R0=BCLR R0 BY 11; /*Clear sign bit*/ R1=BCLR R1 BY 11; R0=R0+R1; /*Add exponents*/ R1=D_EXP_BIAS; /*Remove bias of exponent*/ R0=R0-R1; IF MV JUMP (PC, large_prod); /*Product overflow*/ /* okay, now a little thinking... we've got a number which should be 1<=x<2. If it is, then we just clear it's most significant bit and shift it 11 bits to the right. This is equivalent to shifting 11 bits and then clearing bit 20. Now if the number isn't 1<=x<2, we know that the number x<1. We've got to figure out how many bits we need to shift it to the left in order to get it 1<=x<2. If we use the exp function on it, it returns the opposite of (the number of leading zeroes -1), call this "y". So, if we shift the number (-y)+1 to the left, then we'll be "normalized". Thus, if we shift 11 to the right (=-11 to the left) then (-y)+1 to the left, we've ended up shifting -11-y+1 to the left. So, watch this... */ R1=MR1F; /*Get MSW of product*/ R3=-11; /*Base shift if no overflow*/ R1=PASS R1, R2=M5; /* is MSb of x set */ IF GE R2=EXP R1; /* if not then we'll need to adjust */ IF GE R2=R2-1; /* to get y-1 =(-y)+1 */ R3=R3-R2; /*Compute actual shift value*/ R1=LSHIFT R1 BY R3; /*Shift MSW into place*/ R1=BCLR R1 BY 20; /*Remove hidden bit*/ R0=R0+R2; /*Adjust exp for non-normalized number*/ R0=R0+1; /*Increment exponent*/ R1=R1 OR LSHIFT R0 BY 20; /*Move exponent into place*/ R0=R14 XOR R12; /*Compute sign bit*/ BTST R0 BY 31; /*Test sign bit*/ IF NOT SZ R1=BSET R1 BY 31; /*Set sign bit of result*/ R0=MR0F; R1=LSHIFT R0 BY R3, R0=R1; /*Shift LSW*/ R2=32; RTS (DB), R3=R3+R2; R2=MR1F; R1=R1 OR LSHIFT R2 BY R3; large_prod: RTS; /* In this case, one of the arguments is zero. We need to return a */ /* zero, with the proper sign. */ zero_result: RTS (DB), R1=R1-R1; /* Zero out LSW of result */ R3=R12 XOR R14, R0=R1; /* Compute sign of product */ IF LT R0=BSET R0 BY 31; /* Set sign bit of result */ /* This routine performs a double precision addition (or subtraction) of its two arguments. Calling Parameters R12 = |s|EXP|mantissa| of X R13 = mantissa of X R14 = |s|EXP|mantissa| of Y R15 = mantissa of Y Return registers F0 = |s|EXP|mantissa of (X op Y) F1 = mantissa of (X op Y) Altered registers R0, R1, R2, R3, R4, R5 Cycle Count */ .GLOBAL ___lib_dadd, ___lib_dsub; ___lib_dsub: R12=BTGL R12 BY 31; /*Invert sign of Y*/ ___lib_dadd: R3=FEXT R12 BY 20:11; /*Get biased exponent*/ R2=FEXT R14 BY 20:11; /*Get biased exp of Y*/ R1=R2-R3; /*Test for greater value*/ IF GE JUMP (PC, shift_x_op); /*Y bigger, so shift X*/ swap_ops: R14=PASS R12, R12=R14; /*Swap MSWs*/ R15=PASS R13, R13=R15; /*Swap LSWs*/ R1=-R1; shift_x_op: R1=-R1; /*Invert difference for shift*/ R3=LSHIFT R13 BY R1; /*Downshift X mantissa by diff*/ R4=FEXT R12 BY 0:20; /*Extract MSBs of X mantissa*/ R4=BSET R4 BY 20; /*Make implict 1 explicit*/ R2=LSHIFT R4 BY R1; /*Downshift X MS mantissa by diff*/ R0=32; /*Need to OR in LSBs of MS mantissa*/ R1=R1+R0; /*Compute new shift value*/ R3=R3 OR LSHIFT R4 BY R1; /*Place upper bits*/ R12=PASS R12, R4=dm_0; /*Test for sign of X*/ IF GE JUMP (PC, extract_y_mant); /*X is postive, figure Y*/ invert_x: R3=-R3; /*Invert LSW of shifted X mant*/ NOP; /*CHIP ANOMALY: Late carry*/ R2=R4-R2+CI-1; /*Invert MSW of shifted X mant*/ extract_y_mant: R0=FEXT R14 BY 0:20; /*Extract MSBs of mantissa*/ R0=BSET R0 BY 20; /*Make implicit 1 explicit!*/ R14=PASS R14, R1=R15; /*Test for sign of Y*/ IF GE JUMP (PC, add_core); /*Y is positive*/ invert_y: R1=-R1; /*Invert LSW of Y mantissa*/ NOP; /*CHIP ANOMALY: Late carry*/ R0=R4-R0+CI-1; /*Invert MSW of Y mantissa*/ add_core: R1=R1+R3, R5=dm_0; /*Add LSWs, Sign of result*/ NOP; /*CHIP ANOMALY: Late carry*/ R0=R0+R2+CI; /*Add MSWs*/ normalize: IF GE JUMP (PC, check_MSW); invert_result: F5=-1.0; /*Sign of result*/ R1=-R1; /*Invert LSW*/ NOP; /*CHIP ANOMALY: Late carry*/ R0=R4-R0+CI-1; /*Invert MSW*/ check_MSW: IF EQ JUMP (PC, small_result); /*All zeros in MSW*/ R2=EXP R0; /*Check for redundant bits*/ R2=-R2; /*Invert for shift*/ R0=LSHIFT R0 BY R2; /*Move into position*/ R4=LSHIFT R1 BY R2; /*Move LSBs for later*/ R3=32; /*Shift to lower word*/ R3=R2-R3; R0=R0 OR LSHIFT R1 BY R3; R1=FEXT R14 BY 20:11; /*Extract exponent*/ R4=R1-R2, R1=R4; /*Add normalizing amount*/ R2=10; /*Scale for 11.21 number*/ R4=R4+R2; /*Adjust final exponent*/ R0=BCLR R0 BY 30; /*Make explicit 1 implicit!*/ R2=LSHIFT R0 BY -10; /*Place MSW mantissa*/ R1=LSHIFT R1 BY -10; /*Place LSW mantissa*/ R1=R1 OR LSHIFT R0 BY 22; /*Place MS of LSW mantissa*/ place_exp_sign: RTS (DB); R2=R2 OR LSHIFT R4 BY 20; /*Place exponent*/ F0=F2 COPYSIGN F5; /*Place sign bit*/ small_result: R1=LSHIFT R1 BY -1; /*Shift unsigned value down*/ R2=R2-R2, R4=R0; /*Set both R2 and R4 to zero*/ R1=PASS R1; /*Test for zero result*/ IF EQ JUMP (PC, place_exp_sign); /*Zero result, set sign bit*/ R2=EXP R1; /*Test for redundant bits*/ R2=-R2; /*Invert for shift*/ R0=R0 OR LSHIFT R1 BY R2; /*Normalize word*/ R1=FEXT R14 BY 20:11; /*Extract exponent*/ R4=R1-R2, R1=R4; /*Add normalizing amount*/ R2=-21; /*Add scale for small number */ R4=R4+R2; /*Adjust final exponent*/ JUMP (PC, place_exp_sign) (DB); /*Complete result*/ R0=BCLR R0 BY 30; /*Make explicit 1 implicit!*/ R2=LSHIFT R0 BY -10; /*Place MSW mantissa*/ /* This routine performs a double (or long double) to integer conversion in the current precision mode of the processor Calling Parameters F0 contains upper word (|s|EXP|mantissa) F1 contains lower word ( LSBs of mantissa) Return Registers R0 contains floating point result Altered Registers F0, F1, F2, F3 Cycle Count 13 Cycles */ .GLOBAL ___lib_ldtoi, ___lib_dtoi; ___lib_ldtoi: ___lib_dtoi: R2=FEXT R0 BY 20:11; /* Get biased exponent */ R3=D_EXP_BIAS; /* Get exponent bias */ R2=R2-R3; /* Compute exponent */ R3=52; /* Integer bias */ R2=R2-R3; /* Compute shift amount */ R1=LSHIFT R1 BY R2; /* Shift lower mantissa */ R3=32; /* Upper word bias */ R3=R2+R3; /* Compute upper shift */ R2=FEXT R0 BY 0:20; /* Get upper mantissa */ R2=BSET R2 BY 20; /* Set hidden bit */ RTS (DB), R1=R1 OR LSHIFT R2 BY R3;/* Move mantissa to int*/ R1=PASS R0, R0=R1; /* Check sign of input */ IF LT R0=-R0; /* Set sign of output */ /* This routine performs a double (or long double) to unsigned integer conversion in the current precision mode of the processor Calling Parameters F0 contains upper word (|s|EXP|mantissa) F1 contains lower word ( LSBs of mantissa) Return Registers R0 contains unsigned integer Altered Registers F0, F1, F2, F3, F4 Cycle Count 15 Cycles */ .GLOBAL ___lib_ldtoui, ___lib_dtoui; ___lib_ldtoui: ___lib_dtoui: R4=MODE1; BIT SET MODE1 32768; /*Set TRUNCATE mode*/ BIT CLR MODE1 65536; /*Set to 40-BIT mode*/ R2=0x3F800000; /*Need a one to start*/ R3=FEXT R0 BY 0:20; /*Extract upper mantissa to R2*/ R2=R2 OR LSHIFT R3 BY 3; /*Shift into float mantissa*/ R3=FEXT R1 BY 9:23; /*Extract lower mantissa to R3*/ R1=-43; /*Relative exponent*/ F3=FLOAT R3 BY R1; /*Place into float format*/ F1=F2+F3; /*Determine mantissa of result*/ R2=FEXT R0 BY 20:11; /*Extract biased exponent*/ R3=D_EXP_BIAS; /*Get bias of double exponent*/ RTS (DB), R2=R2-R3; /*Get unbiased exponent*/ R0=FIX F1 BY R2; /*Set exponent of result*/ MODE1=R4; /* This routine performs a integer to double or long double conversion in the current precision mode of the processor Calling Parameters R0 contains integer value Return Registers F0 contains MSW of double value (|s|EXP|mantissa) F1 contains LSW of double value (lower mantissa) Altered Registers F0, F1, F2, F3 Cycle Count 17 Cycles */ .GLOBAL ___lib_itold, ___lib_itod; ___lib_itold: ___lib_itod: F0=FLOAT R0, R1=R0; /*First get float version*/ IF EQ RTS (DB); /*Input == 0, so output=0*/ R3=LOGB F0; /*Get exponent of float*/ R2=-R3; /*Prepare to zero exponent*/ F0=SCALB F0 BY R2; /*Zero exponent*/ R2=D_EXP_BIAS; /*Get bias for a double*/ R3=R2+R3; /*Compute biased exp for double*/ R1=LSHIFT R3 BY 20; /*Position exponent bits*/ F1=F1 COPYSIGN F0; /*Place sign bit*/ F0=ABS F0; /*Clear sign bit*/ R2=FEXT R0 BY 3:20; /*Place upper mantissa bits*/ R1=R1 OR R2; /*Place into double word*/ R2=0x7FFFFFF8; /*Mask out everything but mant*/ R2=R0 AND R2; /*Lower mantissa bits only*/ R3=51; /*Relative exponent of lower mant*/ RTS (DB), F0=F0-F2; /*Compute remainder*/ R1=FIX F0 BY R3, R0=R1; /*Place lower mantissa*/ R1=LSHIFT R1 BY 1; /*Upshift lower mant to unsigned*/ /* This routine performs a double (or long double) to integer conversion in the current precision mode of the processor Calling Parameters F0 contains upper word (|s|EXP|mantissa) F1 contains lower word ( LSBs of mantissa) Return Registers R0 contains floating point result Altered Registers F0, F1, F2, F3 Cycle Count 12 Cycles */ .GLOBAL ___lib_ldtox, ___lib_dtox; ___lib_ldtox: ___lib_dtox: R2=0x3F800000; /*Need a one to start*/ R3=FEXT R0 BY 0:20; /*Extract upper mantissa to R2*/ R2=R2 OR LSHIFT R3 BY 3; /*Shift into float mantissa*/ R3=FEXT R1 BY 9:23; /*Extract lower mantissa to R3*/ R1=-43; /*Relative exponent*/ F3=FLOAT R3 BY R1; /*Place into float format*/ F1=F2+F3; /*Determine mantissa of result*/ R2=FEXT R0 BY 20:11; /*Extract biased exponent*/ R3=D_EXP_BIAS; /*Get bias of double exponent*/ F1=F1 COPYSIGN F0; /*Copy sign of result*/ R0=-31; /*Scale for fract/float*/ RTS (DB), R2=R2-R3; /*Get unbiased exponent*/ R2=R2+R0; /*Adjust for fractional value*/ R0=FIX F1 BY R2; /*Set exponent of result*/ /* This routine performs a fractional to double or long double conversion in the current precision mode of the processor Calling Parameters R0 contains integer value Return Registers F0 contains MSW of double value (|s|EXP|mantissa) F1 contains LSW of double value (lower mantissa) Altered Registers F0, F1, F2, F3 Cycle Count 17 Cycles */ .GLOBAL ___lib_xtold, ___lib_xtod; ___lib_xtold: ___lib_xtod: R1=-31; /*Scale for fract to float*/ F0=FLOAT R0 BY R1, R1=R0; /*First get float version*/ IF EQ RTS (DB); /*Input==0, so output=0*/ R3=LOGB F0; /*Get exponent of float*/ R2=-R3; /*Prepare to zero exponent*/ F0=SCALB F0 BY R2; /*Zero exponent*/ R2=D_EXP_BIAS; /*Get bias for a double*/ R3=R2+R3; /*Compute biased exp for double*/ R1=LSHIFT R3 BY 20; /*Position exponent bits*/ F1=F1 COPYSIGN F0; /*Place sign bit*/ F0=ABS F0; /*Clear sign bit*/ R2=FEXT R0 BY 3:20; /*Place upper mantissa bits*/ R1=R1 OR R2; /*Place into double word*/ R2=0x7FFFFFF8; /*Mask out everything but mant*/ R2=R0 AND R2; /*Lower mantissa bits only*/ R3=51; /*Relative exponent of lower mant*/ RTS (DB), F0=F0-F2; /*Compute remainder*/ R1=FIX F0 BY R3, R0=R1; /*Place lower mantissa*/ R1=LSHIFT R1 BY 1; /*Upshift lower mant to unsigned*/ .ENDSEG;