Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102/libf/ffplog.s
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

162 lines
7.3 KiB
ArmAsm

ttl fast floating point log (ffplog)
***************************************
* (c) copyright 1981 by motorola inc. *
***************************************
*************************************************
* ffplog *
* fast floating point logorithm *
* *
* input: d7 - input argument *
* *
* output: d7 - logorithmic result to base e *
* *
* all other registers totally transparent *
* *
* code size: 184 bytes stack work: 38 bytes *
* *
* condition codes: *
* z - set if the result is zero *
* n - set if result in is negative *
* v - set if invalid negative argument *
* or zero argument *
* c - undefined *
* x - undefined *
* *
* *
* notes: *
* 1) spot checks show errors bounded by *
* 5 x 10**-8. *
* 2) negative arguments are illegal and cause*
* the "v" bit to be set and the absolute *
* value used instead. *
* 3) a zero argument returns the largest *
* negative value possible with the "v" bit*
* set. *
* *
* time: (8mhz no wait states assumed) *
* *
* times are very data sensitive with *
* samples ranging from 170 to 556 *
* microseconds *
* *
*************************************************
page
ffplog idnt 1,2 ffp log
opt pcs
section 9
xdef ffplog entry point
xref ffphthet hypertangent table
xref ffpadd,ffpdiv,ffpsub,ffpmul2 arithmetic primitives
xref ffptnorm transcendental normalize routine
xref ffpcpyrt copyright stub
fpone equ $80000041 floating value for one
log2 equ $b1721840 log(2) = .6931471805
**************
* log entry *
**************
* insure argument positive
ffplog tst.b d7 ? test sign
beq.s fplzro branch argument zero
bpl.s fplok branch alright
* argument is negative - use the absolute value and set the "v" bit
and.b #$7f,d7 take absolute value
bsr.s fplok find log(abs(x))
*psetv or.b #$02,ccr set overflow bit
fpsetv dc.l $003c0002 ***assembler error***
rts return to caller
* argument is zero - return largest negative number with "v" bit
fplzro move.l #-1,d7 return largest negative
bra fpsetv return with "v" bit set
* save work registers and strip exponent off
fplok movem.l d1-d6/a0,-(sp) save all work registers
move.b d7,-(sp) save original exponent
move.b #64+1,d7 force between 1 and 2
move.l #fpone,d6 load up a one
move.l d7,d2 copy argument
bsr ffpadd create arg+1
exg.l d7,d2 swap result with argument
bsr ffpsub create arg-1
move.l d2,d6 prepare for divide
bsr ffpdiv result is (arg-1)/(arg+1)
beq.s fplnocr zero so cordic not needed
* convert to bin(31,29) precision
sub.b #64+3,d7 adjust exponent
neg.b d7 for shift necessary
cmp.b #31,d7 ? insure not too small
bls.s fplshf no, go shift
move.l #0,d7 force to zero
fplshf lsr.l d7,d7 shift to bin(31,29) precision
*****************************************
* cordic calculation registers: *
* d1 - loop count a0 - table pointer *
* d2 - shift count *
* d3 - y' d5 - y *
* d4 - x' d6 - z *
* d7 - x *
*****************************************
move.l #0,d6 z=0
move.l #1<<29,d5 y=1
lea ffphthet,a0 to inverse hyperbolic tangent table
move.l #22,d1 loop 23 times
move.l #1,d2 prime shift counter
bra.s cordic enter cordic loop
* cordic loop
fplpls asr.l d2,d4 shift(x')
sub.l d4,d5 y = y - x'
add.l (a0),d6 z = z + hypertan(i)
cordic move.l d7,d4 x' = x
move.l d5,d3 y' = y
asr.l d2,d3 shift(y')
fplnlp sub.l d3,d7 x = x - y'
bpl.s fplpls branch negative
move.l d4,d7 restore x
add.l #4,a0 to next table entry
add.b #1,d2 increment shift count
lsr.l #1,d3 shift(y')
dbra d1,fplnlp and loop until done
* now convert to float and add exponent*log(2) for final result
move.l #0,d7 default zero if too small
bsr ffptnorm float z
beq.s fplnocr branch if too small
add.b #1,d6 times two
move.l d6,d7 setup in d7 in case exp=0
fplnocr move.l d7,d2 save result
move.l #0,d6 prepare original exponent load
move.b (sp)+,d6 load it back
sub.b #64+1,d6 convert exponent to binary
beq.s fplzpr branch zero partial here
move.b d6,d1 save sign byte
bpl.s fplpos branch positive value
neg.b d6 force positive
fplpos ror.l #8,d6 prepare to convert to integer
move.l #$47,d5 setup exponent mask
fplnorm add.l d6,d6 shift to left
dbmi d5,fplnorm exp-1 and branch if not normalized
move.b d5,d6 fix in exponent
and.b #$80,d1 extract sign
or.b d1,d6 insert sign in
move.l #log2,d7 multiply exponent by log(2)
bsr ffpmul2 multiply d6 and d7
move.l d2,d6 now add cordic result
bsr ffpadd for final answer
fplzpr movem.l (sp)+,d1-d6/a0 restore registers
rts return to caller
end