I have two problems to solve in x87 ASM and I'm a little confused by it, could anyone suggest some ideas?
Equation: 1-(x/y)
Background: X and Y are always positive floating point numbers, but the result of the calculation can be either positive or negative. This is part of a wider calculation which always results in a positive number.
Problem 1: Either X or Y can be zero (and both can be zero simultaneously). Divide by zero is bad. However if either value is zero, I want the final result to be "1" (i.e. Fld1, pop any unnecessary numbers and then move on)
Problem 2: The result must always fall between -1 and +1. If the result is above 1 or below -1, I just want to replace the result with 1. (I.e. In the case of 1-(35/0.01).)
So far I have the following:
fld dword [y] ; Check if either number is 0
fmul dword [x] ;
Fldz
fcomip st(1),st(0)
je exit_1 ; If result is zero jump outta here
fld dword [y] ; Otherwise load the floats
fld dword [x]
fdivp ; Do X/Y
fld1
fsubrp ; 1 - X/Y
????? ; Need some code here to check result is between -1 and 1. If not, replace the result with "1" every time.
.exit_1
fld1 ; Use 1 as the result for the next calculation
jump to_next_calc
In order to the value of
1 - x/yto go below -1,x/y > 2, meaning that you can early exit withHaving
=also handles the case ofx==0 and y==0, where as the>handles the case ofx>0 and y==0.Then proceed normally and the output is limited to
[-1 .. 1]automatically.The multiplication of
yby two can be theoretically speeded up by adding 1 to the exponent - given that the number is not denormal, inf, or nan, and does not overflow...