The CS Stuff

;***************************************************************************
;* "exp" - 8-bit negative exponential
;* This subroutine takes the exponential of negative op1i.opt1f
;* The result is placed in resi.resf
;* The program requires the use of mpy16um
;***************************************************************************
;;ln2 = .69314718056 --> (8bit) 176.75231043
.equ ln2 = 0xB1
;1/ln2 = 1.44269504089 = 1 + 112.87235427 = 0x01.71
;the linear interpolation of 2^x, 0<x<1
.equ p1 = 0xC1 ; .7568 --> slope corresponding to x = .25 = 0x40, y = 1.1892
.equ p2 = 0xD3 ; .8284 --> slope corresponding to x = .5 = 0x80, y = 1.4142
.equ p3 = 0xE8 ; .9091 --> slope corresponding to x = .75 = 0xC0, y = 1.6818
.equ p4 = 0x00; 1 --> slope corresponding to x = 1, y =2
exp: mov save1, XbaseEi ; saves the inputs
mov save2, XbaseEf
mov save3, base
mov save4, iln2i
mov save5, iln2f
mov XbaseEi, op1i
clr resi ;sets the output to 0
clr resf
;check to make sure there isn't an underflow
cpi XbaseEi, 0x08
brge end_e
;multiply x by 1/ln2
ldi iln2i, 0x01
ldi iln2f, 0x71
mov op1i, XbaseEi
mov op2i, iln2i
mov op2f, iln2f
rcall mpy16u
;convert the integer part
ldi base, 0x80 ;divides by 2 for each integer value of x
tst resi
breq frac_part
loop: lsr base ;div by 2
dec resi
tst resi ;=0?
brne loop
frac_part: ;convert the fractional part
ldi iln2f, 0x00
sub iln2f, resf ;1-decimal part of x
clr XbaseEi
;check the range
ldi XbaseEf, p1
cpi iln2f, 0x40
brlo zoiks ;if x<.25, slope = p1
ldi XbaseEf, p2
cpi iln2f, 0x80
brlo zoiks ;if x<.5, slope = p2
ldi XbaseEf, p3
cpi iln2f, 0xC0
brlo zoiks ;if x<.75, slope = p3
ldi XbaseEi, 0x01
ldi XbaseEf, p4 ;if x==.75, slope = 1.p4
zoiks: clr op2i
mov op2f, iln2f
mov op1i,XbaseEi
mov op1f,XbaseEf
rcall mpy16u ;x*slope
inc resi ;x*slope+1, to fit linear interp of 2^x, -1<x<0
mov op2i, resi
mov op2f, resf
clr iln2i
mov op1i, iln2i
mov op1f, base
rcall mpy16u ;2^integer*(liner interp of decimal)
end_e:
ret
;***************** resi.resf = e^x, -8<x<0

16-bit, fixed point binary exponential:
The idea for this algorithm is to convert the exponential from base-e to base-2. This is done by dividing the exponent by the natural logarithm of 2. The resulting value is the 2^x needed to get the same value as the original exponential. This number can be broken down into a integer and a fractional part. The integer part represents 2^-int(x), which is a simple right shift (it is a right shift since, in this case, it is always a negative exponential—if it were a positive, it would be a left shift). The fractional part of the new exponent is used compared to a linear interpolation (of 5 points) of the 2^x function for 0 < x < 1. The results from this interpolation is then multiplied by the right-shifted value from before to get the combined base-two exponential which approximates the original exponential function. The code for the algorithm is given to right. The graph to the right compares this method to e^x for -6 < x < 0. It is clear that this not a bad approximation at all.