$in_range:
Such a solution is inefficient since the FSTSW instruction is serializing with respect to all x87/3DNow!/MMX instructions and should thus be avoided (see the section “Floating-Point Compare Instructions” on page 98). Use of FSTSW in the above fashion slows down the common path through the code.
Instead, it is advisable to check the argument before one of the trigonometric instructions is invoked.
Example 2 (Preferred):
FLD QWORD PTR [x] ;argument
FLD DWORD PTR [two_to_the_63] ;2^63
FCOMIP ST,ST(1) ;argument <= 2^63 ?
JBE $in_range ;Yes, It is in range.
CALL $reduce_range ;reduce argument in ST(0) to < 2^63 $in_range:
FSIN;compute sine (in-range argument ; guaranteed)
Check Argument Range of Trigonometric Instructions

AMD Athlon™ Processor x86 Code Optimization

22007E/0 — November 1999

If an “argument out of range” is detected, a range reduction subroutine is invoked which reduces the argument to less than 2^63 before the instruction is attempted again. While an argument > 2^63 is unusual, it often indicates a problem elsewhere in the code and the code may completely fail in the absence of a properly guarded trigonometric instruction. For example, in the case of FSIN or FCOS generated from a sin() or cos() function invocation in the HLL, the downstream code might reasonably expect that the returned result is in the range [-1,1].

A naive solution for guarding a trigonometric instruction may check the C2 bit in the FPU status word after each FSIN, FCOS, FPTAN, and FSINCOS instruction, and take appropriate action if it is set (indicating an argument out of range).

Example 1 (Avoid):

FLD

QWORD PTR [x] ;argument

 

FSIN

 

;compute sine

 

FSTSW

AX

;store FPU status word to AX

TEST

AX, 0400h

;is the C2 bit set?

 

JZ

$in_range

;nope, argument was

in range, all OK

CALL

$reduce_range ;reduce argument in

ST(0) to < 2^63

FSIN

 

;compute sine (in-range argument

 

 

; guaranteed)

 

104

Page 120
Image 120
AMD x86 manual 104