********************************************************************** * Floating Point Package 22/1/86 * * written by R.Soja, Motorola; modified for MC6801 by Tom Rogers * ********************************************************************** * All floating point routines use * * two, 3-byte operands located in RAM at OP1,OP2 * * Each is organised as: 7 bit exponent + 1 sign bit (2's complement)* * 15 bit mantissa + 1 sign bit * * (15 bit positive notation) * * Sign bit is always is always MSBit * * * * Routines implemented: * * 1. Addition MAD (FADD) OP1+OP2 * * 2. Subtraction MSB (FSUB) OP1-OP2 * * 3. Division MDV (FDIV) OP1/OP2 * * 4. Multiplication MML (FMUL) OP1*OP2 * * * * On exit from routine, OP1 contains result, OP2 is destroyed * * * * Two conversion routines are included: * * FLOATINT converts FP number in OP1 to unsigned integer in ACCD * * INTFLOAT converts unsigned integer in ACCD to FP number in OP1 * * An integer rounding subroutine (ROUND) is also included. * ********************************************************************** * * Note that NO ORG staements are included, as this package is intended to be * appended as a subroutine package to a main calling program. * RAM variables: * MANT1 RMB 2 OP1 EXP1 RMB 1 MANT2 RMB 2 OP2 EXP2 RMB 1 TEMP1 RMB 2 used by routines TEMP2 RMB 2 Y RMB 2 substitute Y register QUOT RMB 2 used by FDIV * * FP routines: MAD EQU * OP1 + OP2 => OP1 FADD EQU * BSR ALIGN BVS FADDEX If exponent difference too great, return. LDAA MANT1 Put sign bit of mantissa 1 in X reg. ANDA #$80 JSR XGDX LDAA MANT1 EORA MANT2 BMI SUBMANT If signs are same BSR GETABS then add positive parts of mantissas. ADDD MANT2 BPL FADD1 if MSBit of result set, then result has INC EXP1 overflowed, so increment exponent, while BVC FADD2 limiting value to upper bound. DEC EXP1 LDD #$7FFF BRA FADD1 FADD2 LSRD FADD1 STX MANT2 Save sign bit STD MANT1 and result, prior to JSR NORM normalising it. FADDEX RTS Return to calling program segment. SUBMANT BSR GETABS If signs are different, SUBD MANT2 then subtract positive parts of mantissas. BSR CONVFP Change 2s compl result to floating point format BRA FADD1 and store result (X contains corrected sign bit) * GETABS LDAA MANT2 Clear sign bits in MANT2 ANDA #$7F STAA MANT2 LDD MANT1 and MANT1 in ACCD ANDA #$7F RTS * MSB EQU * OP1 - OP2 => OP1 FSUB EQU * LDAA MANT2 ADDA #$80 Negate sign of mantissa 2 STAA MANT2 and perform addition BRA FADD * ALIGN CLRA LDAB EXP1 SUBB EXP2 BPL POS If EXP1 OP1 FDIV EQU * LDD MANT2 BEQ MAXRES Trap divide by 0 LDAA MANT1 EORA MANT2 BMI FDIV1 If signs are same CLR Y then result sign is positive CLR Y+1 ( Y has result sign.) BRA FDIV2 FDIV1 LDX #$8000 STX Y else result sign is negative. FDIV2 LDAB EXP1 SUBB EXP2 BVC FDIV3 If V bit set then its an under/overflow, so STAA MANT1 ! update result sign BCC MINRES ! If C bit clear then force result to min limit BRA MAXRES ! else force result to max limit, retaining sign FDIV3 STAB EXP1 Save result exponent LDX #16 Initialize shift counter JSR GETABS +ive part of MANT1 in D, +ive part of MANT2 in it COMPARE SUBD MANT2 Dividend minus divisor BCS RESTORE Borrow so need to restore dividend SEC else no borrow so set carry BRA SHIFT and go shift into quotient. RESTORE ADDD MANT2 Add divisor back to dividend CLC prep to shift a 0 SHIFT ROL QUOT+1 Shift 0 or 1 into quotient ROL QUOT LSLD Shift dividend left DEX All division done? BNE COMPARE not yet LDD QUOT else done so get quotient BPL FDIV4 If quot sign bit already clear, wrap up LSRD else open up sign bit INC EXP1 adjusting exponent. FDIV4 ADDD Y Update sign bit BRA NORM3 Ck. for -0, store result and return * MAXRES STAA TEMP1 Store A. LDAA MANT1 Maximise MSbyte of mantissa, retaining sign. ORAA #$7F STAA MANT1 LDAA TEMP1 Restore A. LDD #$FF7F Maximise LSbyte of mantissa, and exponent. STD MANT1+1 RTS * MINRES CLRA Result = 0 CLRB STD MANT1 CLR EXP1 RTS * MML EQU * OP1 * OP2 => OP1 FMUL EQU * LDAB EXP1 First, add exponents. ADDB EXP2 BVC FMUL1 If V bit is set then its an under/overflow, so STAA MANT1 ! update result sign BCS MINRES ! If C bit set then force result to min limit BRA MAXRES ! else force result to max limit, retaining sign FMUL1 STAB EXP1 Store result exponent. LDAA MANT1 Evaluate result sign, and EORA MANT2 put it in X reg JSR XGDX STAA TEMP1 Store A. LDAA MANT1 Make both operands positive ANDA #$7F STAA MANT1 LDAA MANT2 ANDA #$7F STAA MANT2 LDAA TEMP1 Restore A. BSR CONVFPI Convert MANT1,MANT2 to unsigned integer format * !and return with result sign + MANT1 in Y reg LDAA MANT1 multiply MSbytes of mantissas. LDAB MANT2 MUL JSR XGDX Save 1st partial result in X LDAA MANT1+1 Cross multiply. LDAB MANT2 MUL ADCA #0 Round up and TAB CLRA restore weighting of partial result (in ACCD) STX MANT1 Add 1st and 2nd partial results ADDD MANT1 JSR XGDX Store updated partial result. STD TEMP1 Store D. LDD Y Restore MANT1 STD MANT1 LDD TEMP1 Restore D. LDAA MANT1 Cross multiply again. LDAB MANT2+1 MUL ADCA #0 Round up again. TAB CLRA Correctly weighted 3rd partial result now in ACCD STX MANT1 so add it to stored partial result. ADDD MANT1 BSR CONVIFP Convert integer in ACCD to FP format,and store. * Multiplication of LS bytes is unnecessary, as * the result will always overflow if both non-zero. RTS Return to calling program. * CONVFPI EQU * Enter with +ive MANT1,MANT2: result sign in X reg LSL MANT1+1 De-normalise both operands. ROL MANT1 LSL MANT2+1 ROL MANT2 LDD MANT1 CPX #0 Add result sign bit to ACCD BPL FPI1 ORAB #1 FPI1 JSR XGDY and save result sign+operand 1 in Y. RTS * CONVIFP EQU * LDX #0 STX MANT2 STD MANT1 Temporarily store result. JSR XGDY Move result sign bit LSRD ROR MANT2 to MANT2 before LDD MANT1 LSRD JSR NORM normalising result mantissa. IFP2 RTS Return with result stored in MANT1. * FLOATINT EQU * CLRB LDAA EXP1 If exponent <= 0 BGT FLTINT1 then clear ACCD and return. CLRA RTS FLTINT1 CLRA else LSL MANT1+1 adjust mantissa, destroying sign bit ROL MANT1 FLTINT2 LSL MANT1+1 then move mantissa into ACCD ROL MANT1 ROLB ROLA DEC EXP1 BNE FLTINT2 until exponent = 0 RTS * ROUND TST MANT1 Call IMMEDIATELY after FLOATINT if to be used. BPL ROUNDEX MANT1 has "leftover precision." ASL MANT1 If MSB of MANT1 is set, fraction >= .5 BPL ROUNDEX If next MSB set, fraction >= .75 ADDD #1 so increment D & return ROUNDEX RTS else just return. * INTFLOAT EQU * On entry, unsigned integer in ACCD LDX #0 Initialise result mantissa STX MANT1 CLR EXP1 and exponent. INTFLT1 LSRD Move integer to F.P. mantissa ROR MANT1 ROR MANT1+1 INC EXP1 adjusting exponent with every shift. CMPA #0 BNE INTFLT1 CMPB #0 BNE INTFLT1 When no more bits in ACCD ROR MANT1 clear sign bit as integer was always >=0 ROR MANT1+1 RTS * XGDX STD TEMP1 Store D STX TEMP2 and X. LDD TEMP2 Load D with X LDX TEMP1 and X with D. XGDXEX RTS * XGDY STD TEMP1 D in TEMP1 LDD Y Move Y STD TEMP2 to TEMP2. LDD TEMP1 Move D/TEMP1 STD Y to Y. LDD TEMP2 Put Y into D. XGDYEX RTS