mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 00:14:25 +00:00
220 lines
9.6 KiB
ArmAsm
220 lines
9.6 KiB
ArmAsm
ttl fast floating point add/subtract (ffpadd/ffpsub)
|
||
***************************************
|
||
* (c) copyright 1980 by motorola inc. *
|
||
***************************************
|
||
|
||
*************************************************************
|
||
* ffpadd/ffpsub *
|
||
* fast floating point add/subtract *
|
||
* *
|
||
* ffpadd/ffpsub - fast floating point add and subtract *
|
||
* *
|
||
* input: *
|
||
* ffpadd *
|
||
* d6 - floating point addend *
|
||
* d7 - floating point adder *
|
||
* ffpsub *
|
||
* d6 - floating point subtrahend *
|
||
* d7 - floating point minuend *
|
||
* *
|
||
* output: *
|
||
* d7 - floating point add result *
|
||
* *
|
||
* condition codes: *
|
||
* n - result is negative *
|
||
* z - result is zero *
|
||
* v - overflow has occured *
|
||
* c - undefined *
|
||
* x - undefined *
|
||
* *
|
||
* registers d3 thru d5 are volatile *
|
||
* *
|
||
* code size: 228 bytes stack work area: 0 bytes *
|
||
* *
|
||
* notes: *
|
||
* 1) addend/subtrahend unaltered (d6). *
|
||
* 2) underflow returns zero and is unflagged. *
|
||
* 3) overflow returns the highest value with the *
|
||
* correct sign and the 'v' bit set in the ccr. *
|
||
* *
|
||
* time: (8 mhz no wait states assumed) *
|
||
* *
|
||
* composite average 20.625 microseconds *
|
||
* *
|
||
* add: arg1=0 7.75 microseconds *
|
||
* arg2=0 5.25 microseconds *
|
||
* *
|
||
* like signs 14.50 - 26.00 microseconds *
|
||
* average 18.00 microseconds *
|
||
* unlike signs 20.13 - 54.38 microceconds *
|
||
* average 22.00 microseconds *
|
||
* *
|
||
* subtract: arg1=0 4.25 microseconds *
|
||
* arg2=0 9.88 microseconds *
|
||
* *
|
||
* like signs 15.75 - 27.25 microseconds *
|
||
* average 19.25 microseconds *
|
||
* unlike signs 21.38 - 55.63 microseconds *
|
||
* average 23.25 microseconds *
|
||
* *
|
||
*************************************************************
|
||
page
|
||
ffpadd idnt 1,1 ffp add/subtract
|
||
|
||
xdef ffpadd,ffpsub entry points
|
||
xref ffpcpyrt copyright notice
|
||
|
||
section 9
|
||
|
||
************************
|
||
* subtract entry point *
|
||
************************
|
||
ffpsub move.b d6,d4 test arg1
|
||
beq.s fpart2 return arg2 if arg1 zero
|
||
eor.b #$80,d4 invert copied sign of arg1
|
||
bmi.s fpami1 branch arg1 minus
|
||
* + arg1
|
||
move.b d7,d5 copy and test arg2
|
||
bmi.s fpams branch arg2 minus
|
||
bne.s fpals branch positive not zero
|
||
bra.s fpart1 return arg1 since arg2 is zero
|
||
|
||
*******************
|
||
* add entry point *
|
||
*******************
|
||
ffpadd move.b d6,d4 test argument1
|
||
bmi.s fpami1 branch if arg1 minus
|
||
beq.s fpart2 return arg2 if zero
|
||
|
||
* + arg1
|
||
move.b d7,d5 test argument2
|
||
bmi.s fpams branch if mixed signs
|
||
beq.s fpart1 zero so return argument1
|
||
|
||
* +arg1 +arg2
|
||
* -arg1 -arg2
|
||
fpals sub.b d4,d5 test exponent magnitudes
|
||
bmi.s fpa2lt branch arg1 greater
|
||
move.b d7,d4 setup stronger s+exp in d4
|
||
|
||
* arg1exp <= arg2exp
|
||
cmp.b #24,d5 overbearing size
|
||
bcc.s fpart2 branch yes, return arg2
|
||
move.l d6,d3 copy arg1
|
||
clr.b d3 clean off sign+exponent
|
||
lsr.l d5,d3 shift to same magnitude
|
||
move.b #$80,d7 force carry if lsb-1 on
|
||
add.l d3,d7 add arguments
|
||
bcs.s fpa2gc branch if carry produced
|
||
fparsr move.b d4,d7 restore sign/exponent
|
||
rts return to caller
|
||
|
||
* add same sign overflow normalization
|
||
fpa2gc roxr.l #1,d7 shift carry back into result
|
||
add.b #1,d4 add one to exponent
|
||
bvs.s fpa2os branch overflow
|
||
bcc.s fparsr branch if no exponent overflow
|
||
fpa2os moveq #-1,d7 create all ones
|
||
sub.b #1,d4 back to highest exponent+sign
|
||
move.b d4,d7 replace in result
|
||
* or.b #$02,ccr show overflow occurred
|
||
dc.l $003c0002 ****assembler error****
|
||
rts return to caller
|
||
|
||
* return argument1
|
||
fpart1 move.l d6,d7 move in as result
|
||
move.b d4,d7 move in prepared sign+exponent
|
||
rts return to caller
|
||
|
||
* return argument2
|
||
fpart2 tst.b d7 test for returned value
|
||
rts return to caller
|
||
|
||
* -arg1exp > -arg2exp
|
||
* +arg1exp > +arg2exp
|
||
fpa2lt cmp.b #-24,d5 ? arguments within range
|
||
ble.s fpart1 nope, return larger
|
||
neg.b d5 change difference to positive
|
||
move.l d6,d3 setup larger value
|
||
clr.b d7 clean off sign+exponent
|
||
lsr.l d5,d7 shift to same magnitude
|
||
move.b #$80,d3 force carry if lsb-1 on
|
||
add.l d3,d7 add arguments
|
||
bcs.s fpa2gc branch if carry produced
|
||
move.b d4,d7 restore sign/exponent
|
||
rts return to caller
|
||
|
||
* -arg1
|
||
fpami1 move.b d7,d5 test arg2's sign
|
||
bmi.s fpals branch for like signs
|
||
beq.s fpart1 if zero return argument1
|
||
|
||
* -arg1 +arg2
|
||
* +arg1 -arg2
|
||
fpams moveq #-128,d3 create a carry mask ($80)
|
||
eor.b d3,d5 strip sign off arg2 s+exp copy
|
||
sub.b d4,d5 compare magnitudes
|
||
beq.s fpaeq branch equal magnitudes
|
||
bmi.s fpatlt branch if arg1 larger
|
||
* arg1 <= arg2
|
||
cmp.b #24,d5 compare magnitude difference
|
||
bcc.s fpart2 branch arg2 much bigger
|
||
move.b d7,d4 arg2 s+exp dominates
|
||
move.b d3,d7 setup carry on arg2
|
||
move.l d6,d3 copy arg1
|
||
fpamss clr.b d3 clear extraneous bits
|
||
lsr.l d5,d3 adjust for magnitude
|
||
sub.l d3,d7 subtract smaller from larger
|
||
bmi.s fparsr return final result if no overflow
|
||
|
||
* mixed signs normalize
|
||
fpanor move.b d4,d5 save correct sign
|
||
fpanrm clr.b d7 clear subtract residue
|
||
sub.b #1,d4 make up for first shift
|
||
cmp.l #$00007fff,d7 ? small enough for swap
|
||
bhi.s fpaxqn branch nope
|
||
swap.w d7 shift left 16 bits real fast
|
||
sub.b #16,d4 make up for 16 bit shift
|
||
fpaxqn add.l d7,d7 shift up one bit
|
||
dbmi d4,fpaxqn decrement and branch if positive
|
||
eor.b d4,d5 ? same sign
|
||
bmi.s fpazro branch underflow to zero
|
||
move.b d4,d7 restore sign/exponent
|
||
beq.s fpazro return zero if exponent underflowed
|
||
rts return to caller
|
||
|
||
* exponent underflowed - return zero
|
||
fpazro moveq.l #0,d7 create a true zero
|
||
rts return to caller
|
||
|
||
* arg1 > arg2
|
||
fpatlt cmp.b #-24,d5 ? arg1 >> arg2
|
||
ble.s fpart1 return it if so
|
||
neg.b d5 absolutize difference
|
||
move.l d7,d3 move arg2 as lower value
|
||
move.l d6,d7 set up arg1 as high
|
||
move.b #$80,d7 setup rounding bit
|
||
bra.s fpamss perform the addition
|
||
|
||
* equal magnitudes
|
||
fpaeq move.b d7,d5 save arg1 sign
|
||
exg.l d5,d4 swap arg2 with arg1 s+exp
|
||
move.b d6,d7 insure same low byte
|
||
sub.l d6,d7 obtain difference
|
||
beq.s fpazro return zero if identical
|
||
bpl.s fpanor branch if arg2 bigger
|
||
neg.l d7 correct difference to positive
|
||
move.b d5,d4 use arg2's sign + exponent
|
||
bra.s fpanrm and go normalize
|
||
|
||
end
|
||
|
||
|