Chapter Fourteen (Part 4)
|Table of Content||
Chapter Fourteen (Part 6)
FLOATING POINT ARITHMETIC (Part 5)
188.8.131.52 - The FCOM FCOMP and FCOMPP Instructions
184.108.40.206 - The FUCOM FUCOMP and FUCOMPP Instructions
220.127.116.11 - The FTST Instruction
18.104.22.168 - The FXAM Instruction
14.4.8 - Constant Instructions
14.4.9 - Transcendental Instructions
22.214.171.124 - The F2XM1 Instruction
126.96.36.199 - The FSIN FCOS and FSINCOS Instructions
188.8.131.52 - The FPTAN Instruction
184.108.40.206 - The FPATAN Instruction
220.127.116.11 - The FYL2X and FYL2XP1 Instructions
- Miscellaneous instructions
18.104.22.168 - The FINIT and FNINIT Instructions
22.214.171.124 - The FWAIT Instruction
126.96.36.199 - The FLDCW and FSTCW Instructions
188.8.131.52 - The FCLEX and FNCLEX Instructions
184.108.40.206 - The FLDENV FSTENV and FNSTENV Instructions
220.127.116.11 - The FSAVE FNSAVE and FRSTOR Instructions
18.104.22.168 - The FSTSW and FNSTSW Instructions
22.214.171.124 - The FINCSTP and FDECSTP Instructions
126.96.36.199 - The FNOP Instruction
188.8.131.52 - The FFREE Instruction
14.4.11 - Integer Operations
The 80x87 provides several instructions for comparing real
fucompp instructions compare the two values on the
top of stack and set the condition codes appropriately. The
compares the value on the top of stack with zero. The
fxam instrution checks
the value on tos and reports sign
and tag information.
most programs test the condition code bits
immediately after a comparison. Unfortunately
there are no conditional jump instructions
that branch based on the FPU condition codes. Instead
you can use the
instruction to copy the floating point status register (see "The FPU Status
Register") into the
ax register; then you can use the
instruction to copy the
ah register into the 80x86's condition code bits.
After doing this
you can can use the conditional jump instructions to test some
condition. This technique copies
C0 into the carry flag
the parity flag
C3 into the zero flag. The
does not copy
C1 into any of the 80x86's flag bits.
sahf instruction does not copy any
80x87 processor status bits into the sign or overflow flags
you cannot use the
jle instructions. Instead
instructions when testing the results of a floating point comparison. Yes
conditional jumps normally test unsigned values and floating point numbers are signed
use the unsigned conditional branches anyway; the
instructions set the 80x86 flags register to use the unsigned jumps.
184.108.40.206 The FCOM FCOMP and FCOMPP Instructions
st(0) to the specified operand and set the corresponding
80x87 condition code bits based on the result of the comparison. The legal forms for these
fcom fcomp fcompp fcom st(i) fcomp st(i) fcom mem fcomp mem
With no operands
st(1) and set the
processor flags accordingly. In addition
the stack and
fcompp pops both
With a single register operand
st(0) against the specified register.
Fcomp also pops
after the comparison.
With a 32 or 64 bit memory operand
fcomp instructions convert the memory variable to an 80 bit extended
precision value and then compare
st(0) against this value
condition code bits accordingly.
Fcomp also pops
st(0) after the
These instructions set
C2 (which winds up in
the parity flag) if the two operands are not comparable (e.g.
NaN). If it is possible for
an illegal floating point value to wind up in a comparison
you should check the parity
flag for an error before checking the desired condition.
These instructions set the stack fault bit if there aren't
two items on the top of the register stack. They set the denormalized exception bit if
either or both operands are denormalized. They set the invalid operation flag if either or
both operands are quite NaNs. These instructions always clear the
220.127.116.11 The FUCOM FUCOMP and FUCOMPP Instructions
These instructions are similar to the fcom fcomp and fcompp instructions although they only allow the following forms:
fucom fucomp fucompp fucom st(i) fucomp st(i)
The difference between fcom/fcomp/fcompp and fucom/fucomp/fucompp is relatively minor. The fcom/fcomp/fcompp instructions set the invalid operation exception bit if you compare two NaNs. The fucom/fucomp/fucompp instructions do not. In all other cases these two sets of instructions behave identically.
18.104.22.168 The FTST Instruction
ftst instruction compares the value in
against 0.0. It behaves just like the
fcom instruction would if
contained 0.0. Note that this instruction does not differentiate -0.0 from +0.0. If the
st(0) is either of these values
ftst will set
denote equality. If you need to differentiate -0.0 from +0.0
instruction. Note that this instruction does not pop
st(0) off the stack.
22.214.171.124 The FXAM Instruction
fxam instruction examines the value in
and reports the results in the condition code bits (see "The FPU Status
Register" for details on how fxam sets these bits). This instruction does not pop
off the stack.
14.4.8 Constant Instructions
The 80x87 FPU provides several instructions that let you load commonly used constants onto the FPU's register stack. These instructions set the stack fault invalid operation and C1 flags if a stack overflow occurs; they do not otherwise affect the FPU flags. The specific instructions in this category include:
fldz ;Pushes +0.0. fld1 ;Pushes +1.0. fldp ;Pushes p. fldl2t ;Pushes log2(10). fldl2e ;Pushes log2(e). fldlg2 ;Pushes log10(2). fldln2 ;Pushes ln(2).
14.4.9 Transcendental Instructions
The 80387 and later FPUs provide eight transcendental (log and trigonometric) instructions to compute a partial tangent partial arctangent 2x-1 y * log2(x) and y * log2(x+1). Using various algebraic identities it is easy to compute most of the other common transcendental functions using these instructions.
126.96.36.199 The F2XM1 Instruction
computes 2st(0)-1. The value in
st(0)must be in the range -1.0
st(0)is out of range
f2xm1generates an undefined result but raises no exceptions. The computed value replaces the value in
; Compute 10x using the identity: 10x = 2x*lg(10) (lg = log2). fld x fldl2t fmul f2xm1 fld1 fadd
f2xm1 computes (2**x) - 1
why the code above adds 1.0 to the result at the end of the computation.
188.8.131.52 The FSIN FCOS and FSINCOS Instructions
These instructions pop the value off the top of the
register stack and compute the sine
and push the result(s) back onto the
fsincos pushes the sine followed by the cosine of the original
hence it leaves cos(
st(0) and sin(
These instructions assume
st(0) specifies an
angle in radians and this angle must be in the range -2**63 <
+2**63. If the original operand is out of range
these instructions set the
flag and leave
st(0) unchanged. You can use the fprem1 instruction
divisor of 2pi to reduce the operand to a reasonable range.
These instructions set the stack fault/
and invalid operation flags according to the result of
184.108.40.206 The FPTAN Instruction
computes the tangent of
st(0)and pushes this value and then it pushes 1.0 onto the stack. Like the
fcosinstructions the value of
st(0)is assumed to be in radians and must be in the range -2**63<
st(0)<+2**63. If the value is outside this range fptan sets
C2to indicate that the conversion did not take place. As with the
fsincosinstructions you can use the
fprem1instruction to reduce this operand to a reasonable range using a divisor of 2pi.
If the argument is invalid (i.e.
zero or pi radians
which causes a division by zero) the result is undefined and this instruction raises no
Fptan will set the stack fault
C1 bits as required by the operation.
220.127.116.11 The FPATAN Instruction
This instruction expects two values on the top of stack. It pops them and computes the following:
st(0) = tan-1( st(1) / st(0) )
The resulting value is the arctangent of the ratio on the
stack expressed in radians. If you have a value you wish to compute the tangent of
to create the appropriate ratio and then execute the
This instruction affects the stack fault/
and invalid operation bits if an problem occurs during the
computation. It sets the
C1 condition code bit if it has to round the result.
18.104.22.168 The FYL2X and FYL2XP1 Instructions
st(1) * log2(
Fyl2x requires that
be greater than zero
st(0) to be in the range:
is useful for computing logs to bases other than two;
fyl2xp1is useful for computing compound interest maintaining the maximum precision during computation.
Fyl2x can affect all the exception flags.
denotes rounding if there is not other error
stack overflow/underflow if the stack fault
bit is set.
fyl2xp1 instruction does not affect the
overflow or zero divide exception flags. These exceptions occur when
very small or zero. Since
fyl2xp1 adds one to
computing the function
this condition never holds.
Fyl2xp1 affects the other
flags in a manner identical to
14.4.10 Miscellaneous instructions
The 80x87 FPU includes several additional instructions
which control the FPU
and let you test or set various status
bits. These instructions include
frstpm are active only on FPUs earlier than the 80387
so we will not consider them here.
Many of these instructions have two forms. The first form
is Fxxxx and the second form is FNxxxx. The version without the "N" emits an
instruction prior to opcode (which is standard for most coprocessor instructions). The
version with the "N" does not emit the
fwait opcode ("N"
stands for no wait).
22.214.171.124 The FINIT and FNINIT Instructions
finit instruction intializes the FPU for
proper operation. Your applications should execute this instruction before executing any
other FPU instructions. This instruction initializes the control register to 37Fh (see
"The FPU Control Register")
the status register to zero (see "The FPU
Status Register") and the tag word to 0FFFFh. The other registers are unaffected.
126.96.36.199 The FWAIT Instruction
fwait instruction pauses the system until
any currently executing FPU instruction completes. This is required because the FPU on the
80486sx and earlier CPU/FPU combinations can execute instructions in parallel with the
any FPU instruction which reads or writes memory could suffer from a data
hazard if the main CPU accesses that same memory location before the FPU reads or writes
that location. The
fwait instruction lets you synchronize the operation of
the FPU by waiting until the completion of the current FPU instruction. This resolves the
data hazard by
inserting an explict "stall" into the execution
188.8.131.52 The FLDCW and FSTCW Instructions
require a single 16 bit memory operand:
fldcw mem_16 fstcw mem_16
These two instructions load the control register (see
"The FPU Control Register") from a memory location (
fldcw) or store
the control word to a 16 bit memory location (
When using the
fldcw instruction to turn on
one of the exceptions
if the corresponding exception flag is set when you enable that
the FPU will generate an immediate interrupt before the CPU executes the next
you should use the fclex instruction to clear any pending
interrupts before changing the FPU exception enable bits.
184.108.40.206 The FCLEX and FNCLEX Instructions
clear all exception bits the stack fault bit
and the busy flag in the FPU status register
(see "The FPU Status Register").
220.127.116.11 The FLDENV FSTENV and FNSTENV Instructions
fstenv mem_14b fnstenv mem_14b fldenv mem_14b
fstenv/fnstenv instructions store a
14-byte FPU environment record to the memory operand specified. When operating in real
mode (the only mode this text considers)
the environment record takes the form:
You must execute the
instructions with the CPU interrupts disabled. Furthermore
you should always ensure that
the FPU is not busy before executing this instruction. This is easily accomplished by
using the following code:
pushf ;Preserve I flag. cli ;Disable interrupts. fstenv mem_14b ;Implicit wait for not busy. fwait ;Wait for operation to finish. popf ;Restore I flag.
fldenv instruction loads the FPU
environment from the specified memory operand. Note that this instruction lets you load
the the status word. There is no explicit instruction like
18.104.22.168 The FSAVE FNSAVE and FRSTOR Instructions
fsave mem_94b fnsave mem_94b frstor mem_94b
These instructions save and restore the state of the FPU.
This includes saving all the internal control
and data registers. The destination
fsave/fnsave (source location for
frstor) must be
94 bytes long. The first 14 bytes correspond to the environment record the
fstenv instructions use; the remaining 80 bytes hold the data from the
FPU register stack written out as
reloads the environment record and floating point registers from the specified memory
instructions are mainly intended for task switching. You can also use
frstor as a "push all" and "pop all" sequence to
preserve the state of the FPU.
interrupts should be disabled while saving or restoring the FPU state.
Otherwise another interrupt service routine could manipulate the FPU registers and
invalidate the operation of the
operation. The following code properly protects the environment data while saving and
restore the FPU status:
; Preserve the FPU state assume di points at the environment ; record in memory. pushf cli fsave [si] fwait popf . . . pushf cli frstor [si] fwait popf
22.214.171.124 The FSTSW and FNSTSW Instructions
fstsw ax fnstsw ax fstsw mem_16 fnstsw mem_16
These instructions store the FPU status register (see
"The FPU Status Register") into a 16 bit memory location or the
register. These instructions are unusual in the sense that they can copy an FPU value into
one of the 80x86 general purpose registers. Of course
the whole purpose behind allowing
the transfer of the status register into ax is to allow the CPU to easily test the
condition code register with the sahf instruction.
126.96.36.199 The FINCSTP and FDECSTP Instructions
instructions do not take any operands. They simply increment and decrement the stack
pointer bits (mod 8) in the FPU status register. These two instructions clear the C1 flag
but do not otherwise affect the condition code bits in the FPU status register.
188.8.131.52 The FNOP Instruction
fnop instruction is simply an alias for
st(0). It performs no other operation on the FPU.
184.108.40.206 The FFREE Instruction
This instruction modifies the tag bits for register i in the tags register to mark the specified register as emtpy. The value is unaffected by this instruction but the FPU will no longer be able to access that data (without resetting the appropriate tag bits).
14.4.11 Integer Operations
The 80x87 FPUs provide special instructions that combine integer to extended precision conversion along with various arithmetic and comparison operations. These instructions are the following:
fiadd int fisub int fisubr int fimul int fidiv int fidivr int ficom int ficomp int
These instructions convert their 16 or 32 bit integer operands to an 80 bit extended precision floating point value and then use this value as the source operand for the specified operation. These instructions use st(0) as the destination operand.
Chapter Fourteen: Floating Point
Arithmetics (Part 5)
28 SEP 1996