   This file documents NASM, the Netwide Assembler: an assembler
targetting the Intel x86 series of processors, with portable source.

   Copyright 2002 The NASM Development Team

   All rights reserved. This document is redistributable under the
licence given in the file "COPYING" distributed in the NASM archive.

B.4.68. `FADD', `FADDP': Floating-Point Addition
------------------------------------------------

     FADD mem32                    ; D8 /0                [8086,FPU]
     FADD mem64                    ; DC /0                [8086,FPU]

     FADD fpureg                   ; D8 C0+r              [8086,FPU]
     FADD ST0,fpureg               ; D8 C0+r              [8086,FPU]

     FADD TO fpureg                ; DC C0+r              [8086,FPU]
     FADD fpureg,ST0               ; DC C0+r              [8086,FPU]

     FADDP fpureg                  ; DE C0+r              [8086,FPU]
     FADDP fpureg,ST0              ; DE C0+r              [8086,FPU]

   * `FADD', given one operand, adds the operand to `ST0' and stores
     the result back in `ST0'. If the operand has the `TO' modifier,
     the result is stored in the register given rather than in `ST0'.

   * `FADDP' performs the same function as `FADD TO', but pops the
     register stack after storing the result.

   The given two-operand forms are synonyms for the one-operand forms.

   To add an integer value to `ST0', use the c{FIADD} instruction
(see Section B.4.80)

B.4.69. `FBLD', `FBSTP': BCD Floating-Point Load and Store
----------------------------------------------------------

     FBLD mem80                    ; DF /4                [8086,FPU]
     FBSTP mem80                   ; DF /6                [8086,FPU]

   `FBLD' loads an 80-bit (ten-byte) packed binary-coded decimal number
from the given memory address, converts it to a real, and pushes it on
the register stack. `FBSTP' stores the value of `ST0', in packed BCD,
at the given address and then pops the register stack.

B.4.70. `FCHS': Floating-Point Change Sign
------------------------------------------

     FCHS                          ; D9 E0                [8086,FPU]

   `FCHS' negates the number in `ST0', by inverting the sign bit:
negative numbers become positive, and vice versa.

B.4.71. `FCLEX', `FNCLEX': Clear Floating-Point Exceptions
----------------------------------------------------------

     FCLEX                         ; 9B DB E2             [8086,FPU]
     FNCLEX                        ; DB E2                [8086,FPU]

   `FCLEX' clears any floating-point exceptions which may be pending.
`FNCLEX' does the same thing but doesn't wait for previous floating-
point operations (including the _handling_ of pending exceptions) to
finish first.

B.4.72. `FCMOVcc': Floating-Point Conditional Move
--------------------------------------------------

     FCMOVB fpureg                 ; DA C0+r              [P6,FPU]
     FCMOVB ST0,fpureg             ; DA C0+r              [P6,FPU]

     FCMOVE fpureg                 ; DA C8+r              [P6,FPU]
     FCMOVE ST0,fpureg             ; DA C8+r              [P6,FPU]

     FCMOVBE fpureg                ; DA D0+r              [P6,FPU]
     FCMOVBE ST0,fpureg            ; DA D0+r              [P6,FPU]

     FCMOVU fpureg                 ; DA D8+r              [P6,FPU]
     FCMOVU ST0,fpureg             ; DA D8+r              [P6,FPU]

     FCMOVNB fpureg                ; DB C0+r              [P6,FPU]
     FCMOVNB ST0,fpureg            ; DB C0+r              [P6,FPU]

     FCMOVNE fpureg                ; DB C8+r              [P6,FPU]
     FCMOVNE ST0,fpureg            ; DB C8+r              [P6,FPU]

     FCMOVNBE fpureg               ; DB D0+r              [P6,FPU]
     FCMOVNBE ST0,fpureg           ; DB D0+r              [P6,FPU]

     FCMOVNU fpureg                ; DB D8+r              [P6,FPU]
     FCMOVNU ST0,fpureg            ; DB D8+r              [P6,FPU]

   The `FCMOV' instructions perform conditional move operations: each of
them moves the contents of the given register into `ST0' if its
condition is satisfied, and does nothing if not.

   The conditions are not the same as the standard condition codes used
with conditional jump instructions. The conditions `B', `BE', `NB',
`NBE', `E' and `NE' are exactly as normal, but none of the other
standard ones are supported. Instead, the condition `U' and its
counterpart `NU' are provided; the `U' condition is satisfied if the
last two floating-point numbers compared were _unordered_, i.e. they
were not equal but neither one could be said to be greater than the
other, for example if they were NaNs. (The flag state which signals
this is the setting of the parity flag: so the `U' condition is
notionally equivalent to `PE', and `NU' is equivalent to `PO'.)

   The `FCMOV' conditions test the main processor's status flags, not
the FPU status flags, so using `FCMOV' directly after `FCOM' will not
work. Instead, you should either use `FCOMI' which writes directly to
the main CPU flags word, or use `FSTSW' to extract the FPU flags.

   Although the `FCMOV' instructions are flagged `P6' above, they may
not be supported by all Pentium Pro processors; the `CPUID' instruction
(see Section B.4.34) will return a bit which indicates whether
conditional moves are supported.

B.4.73. `FCOM', `FCOMP', `FCOMPP', `FCOMI', `FCOMIP': Floating-Point Compare
----------------------------------------------------------------------------

     FCOM mem32                    ; D8 /2                [8086,FPU]
     FCOM mem64                    ; DC /2                [8086,FPU]
     FCOM fpureg                   ; D8 D0+r              [8086,FPU]
     FCOM ST0,fpureg               ; D8 D0+r              [8086,FPU]

     FCOMP mem32                   ; D8 /3                [8086,FPU]
     FCOMP mem64                   ; DC /3                [8086,FPU]
     FCOMP fpureg                  ; D8 D8+r              [8086,FPU]
     FCOMP ST0,fpureg              ; D8 D8+r              [8086,FPU]

     FCOMPP                        ; DE D9                [8086,FPU]

     FCOMI fpureg                  ; DB F0+r              [P6,FPU]
     FCOMI ST0,fpureg              ; DB F0+r              [P6,FPU]

     FCOMIP fpureg                 ; DF F0+r              [P6,FPU]
     FCOMIP ST0,fpureg             ; DF F0+r              [P6,FPU]

   `FCOM' compares `ST0' with the given operand, and sets the FPU flags
accordingly. `ST0' is treated as the left-hand side of the comparison,
so that the carry flag is set (for a `less-than' result) if `ST0' is
less than the given operand.

   `FCOMP' does the same as `FCOM', but pops the register stack
afterwards. `FCOMPP' compares `ST0' with `ST1' and then pops the
register stack twice.

   `FCOMI' and `FCOMIP' work like the corresponding forms of `FCOM' and
`FCOMP', but write their results directly to the CPU flags register
rather than the FPU status word, so they can be immediately followed by
conditional jump or conditional move instructions.

   The `FCOM' instructions differ from the `FUCOM' instructions (see
Section B.4.108) only in the way they handle quiet NaNs: `FUCOM' will
handle them silently and set the condition code flags to an `unordered'
result, whereas `FCOM' will generate an exception.

B.4.74. `FCOS': Cosine
----------------------

     FCOS                          ; D9 FF                [386,FPU]

   `FCOS' computes the cosine of `ST0' (in radians), and stores the
result in `ST0'. The absolute value of `ST0' must be less than 2**63.

   See also `FSINCOS' (see Section B.4.100).

B.4.75. `FDECSTP': Decrement Floating-Point Stack Pointer
---------------------------------------------------------

     FDECSTP                       ; D9 F6                [8086,FPU]

   `FDECSTP' decrements the `top' field in the floating-point status
word. This has the effect of rotating the FPU register stack by one, as
if the contents of `ST7' had been pushed on the stack. See also
`FINCSTP' (see Section B.4.85).

B.4.76. `FxDISI', `FxENI': Disable and Enable Floating-Point Interrupts
-----------------------------------------------------------------------

     FDISI                         ; 9B DB E1             [8086,FPU]
     FNDISI                        ; DB E1                [8086,FPU]

     FENI                          ; 9B DB E0             [8086,FPU]
     FNENI                         ; DB E0                [8086,FPU]

   `FDISI' and `FENI' disable and enable floating-point interrupts.
These instructions are only meaningful on original 8087 processors: the
287 and above treat them as no-operation instructions.

   `FNDISI' and `FNENI' do the same thing as `FDISI' and `FENI'
respectively, but without waiting for the floating-point processor to
finish what it was doing first.

B.4.77. `FDIV', `FDIVP', `FDIVR', `FDIVRP': Floating-Point Division
-------------------------------------------------------------------

     FDIV mem32                    ; D8 /6                [8086,FPU]
     FDIV mem64                    ; DC /6                [8086,FPU]

     FDIV fpureg                   ; D8 F0+r              [8086,FPU]
     FDIV ST0,fpureg               ; D8 F0+r              [8086,FPU]

     FDIV TO fpureg                ; DC F8+r              [8086,FPU]
     FDIV fpureg,ST0               ; DC F8+r              [8086,FPU]

     FDIVR mem32                   ; D8 /0                [8086,FPU]
     FDIVR mem64                   ; DC /0                [8086,FPU]

     FDIVR fpureg                  ; D8 F8+r              [8086,FPU]
     FDIVR ST0,fpureg              ; D8 F8+r              [8086,FPU]

     FDIVR TO fpureg               ; DC F0+r              [8086,FPU]
     FDIVR fpureg,ST0              ; DC F0+r              [8086,FPU]

     FDIVP fpureg                  ; DE F8+r              [8086,FPU]
     FDIVP fpureg,ST0              ; DE F8+r              [8086,FPU]

     FDIVRP fpureg                 ; DE F0+r              [8086,FPU]
     FDIVRP fpureg,ST0             ; DE F0+r              [8086,FPU]

   * `FDIV' divides `ST0' by the given operand and stores the result
     back in `ST0', unless the `TO' qualifier is given, in which case
     it divides the given operand by `ST0' and stores the result in the
     operand.

   * `FDIVR' does the same thing, but does the division the other way
     up: so if `TO' is not given, it divides the given operand by `ST0'
     and stores the result in `ST0', whereas if `TO' is given it
     divides `ST0' by its operand and stores the result in the operand.

   * `FDIVP' operates like `FDIV TO', but pops the register stack once
     it has finished.

   * `FDIVRP' operates like `FDIVR TO', but pops the register stack
     once it has finished.

   For FP/Integer divisions, see `FIDIV' (see Section B.4.82).

B.4.78. `FEMMS': Faster Enter/Exit of the MMX or floating-point state
---------------------------------------------------------------------

     FEMMS                         ; 0F 0E           [PENT,3DNOW]

   `FEMMS' can be used in place of the `EMMS' instruction on processors
which support the 3DNow! instruction set. Following execution of
`FEMMS', the state of the `MMX/FP' registers is undefined, and this
allows a faster context switch between `FP' and `MMX' instructions. The
`FEMMS' instruction can also be used _before_ executing `MMX'
instructions

B.4.79. `FFREE': Flag Floating-Point Register as Unused
-------------------------------------------------------

     FFREE fpureg                  ; DD C0+r              [8086,FPU]
     FFREEP fpureg                 ; DF C0+r              [286,FPU,UNDOC]

   `FFREE' marks the given register as being empty.

   `FFREEP' marks the given register as being empty, and then pops the
register stack.

B.4.80. `FIADD': Floating-Point/Integer Addition
------------------------------------------------

     FIADD mem16                   ; DE /0                [8086,FPU]
     FIADD mem32                   ; DA /0                [8086,FPU]

   `FIADD' adds the 16-bit or 32-bit integer stored in the given memory
location to `ST0', storing the result in `ST0'.

B.4.81. `FICOM', `FICOMP': Floating-Point/Integer Compare
---------------------------------------------------------

     FICOM mem16                   ; DE /2                [8086,FPU]
     FICOM mem32                   ; DA /2                [8086,FPU]

     FICOMP mem16                  ; DE /3                [8086,FPU]
     FICOMP mem32                  ; DA /3                [8086,FPU]

   `FICOM' compares `ST0' with the 16-bit or 32-bit integer stored in
the given memory location, and sets the FPU flags accordingly.
`FICOMP' does the same, but pops the register stack afterwards.

B.4.82. `FIDIV', `FIDIVR': Floating-Point/Integer Division
----------------------------------------------------------

     FIDIV mem16                   ; DE /6                [8086,FPU]
     FIDIV mem32                   ; DA /6                [8086,FPU]

     FIDIVR mem16                  ; DE /7                [8086,FPU]
     FIDIVR mem32                  ; DA /7                [8086,FPU]

   `FIDIV' divides `ST0' by the 16-bit or 32-bit integer stored in the
given memory location, and stores the result in `ST0'.  `FIDIVR' does
the division the other way up: it divides the integer by `ST0', but
still stores the result in `ST0'.

B.4.83. `FILD', `FIST', `FISTP': Floating-Point/Integer Conversion
------------------------------------------------------------------

     FILD mem16                    ; DF /0                [8086,FPU]
     FILD mem32                    ; DB /0                [8086,FPU]
     FILD mem64                    ; DF /5                [8086,FPU]

     FIST mem16                    ; DF /2                [8086,FPU]
     FIST mem32                    ; DB /2                [8086,FPU]

     FISTP mem16                   ; DF /3                [8086,FPU]
     FISTP mem32                   ; DB /3                [8086,FPU]
     FISTP mem64                   ; DF /7                [8086,FPU]

   `FILD' loads an integer out of a memory location, converts it to a
real, and pushes it on the FPU register stack. `FIST' converts `ST0' to
an integer and stores that in memory; `FISTP' does the same as `FIST',
but pops the register stack afterwards.

B.4.84. `FIMUL': Floating-Point/Integer Multiplication
------------------------------------------------------

     FIMUL mem16                   ; DE /1                [8086,FPU]
     FIMUL mem32                   ; DA /1                [8086,FPU]

   `FIMUL' multiplies `ST0' by the 16-bit or 32-bit integer stored in
the given memory location, and stores the result in `ST0'.

B.4.85. `FINCSTP': Increment Floating-Point Stack Pointer
---------------------------------------------------------

     FINCSTP                       ; D9 F7                [8086,FPU]

   `FINCSTP' increments the `top' field in the floating-point status
word. This has the effect of rotating the FPU register stack by one, as
if the register stack had been popped; however, unlike the popping of
the stack performed by many FPU instructions, it does not flag the new
`ST7' (previously `ST0') as empty. See also `FDECSTP' (see Section B.4.75).

B.4.86. `FINIT', `FNINIT': Initialise Floating-Point Unit
---------------------------------------------------------

     FINIT                         ; 9B DB E3             [8086,FPU]
     FNINIT                        ; DB E3                [8086,FPU]

   `FINIT' initialises the FPU to its default state. It flags all
registers as empty, without actually change their values, clears the
top of stack pointer. `FNINIT' does the same, without first waiting for
pending exceptions to clear.

B.4.87. `FISUB': Floating-Point/Integer Subtraction
---------------------------------------------------

     FISUB mem16                   ; DE /4                [8086,FPU]
     FISUB mem32                   ; DA /4                [8086,FPU]

     FISUBR mem16                  ; DE /5                [8086,FPU]
     FISUBR mem32                  ; DA /5                [8086,FPU]

   `FISUB' subtracts the 16-bit or 32-bit integer stored in the given
memory location from `ST0', and stores the result in `ST0'.  `FISUBR'
does the subtraction the other way round, i.e. it subtracts `ST0' from
the given integer, but still stores the result in `ST0'.

B.4.88. `FLD': Floating-Point Load
----------------------------------

     FLD mem32                     ; D9 /0                [8086,FPU]
     FLD mem64                     ; DD /0                [8086,FPU]
     FLD mem80                     ; DB /5                [8086,FPU]
     FLD fpureg                    ; D9 C0+r              [8086,FPU]

   `FLD' loads a floating-point value out of the given register or
memory location, and pushes it on the FPU register stack.

B.4.89. `FLDxx': Floating-Point Load Constants
----------------------------------------------

     FLD1                          ; D9 E8                [8086,FPU]
     FLDL2E                        ; D9 EA                [8086,FPU]
     FLDL2T                        ; D9 E9                [8086,FPU]
     FLDLG2                        ; D9 EC                [8086,FPU]
     FLDLN2                        ; D9 ED                [8086,FPU]
     FLDPI                         ; D9 EB                [8086,FPU]
     FLDZ                          ; D9 EE                [8086,FPU]

   These instructions push specific standard constants on the FPU
register stack.

      Instruction    Constant pushed

      FLD1           1
      FLDL2E         base-2 logarithm of e
      FLDL2T         base-2 log of 10
      FLDLG2         base-10 log of 2
      FLDLN2         base-e log of 2
      FLDPI          pi
      FLDZ           zero

B.4.90. `FLDCW': Load Floating-Point Control Word
-------------------------------------------------

     FLDCW mem16                   ; D9 /5                [8086,FPU]

   `FLDCW' loads a 16-bit value out of memory and stores it into the FPU
control word (governing things like the rounding mode, the precision,
and the exception masks). See also `FSTCW' (see Section B.4.103). If
exceptions are enabled and you don't want to generate one, use `FCLEX'
or `FNCLEX' (see Section B.4.71) before loading the new control
word.

B.4.91. `FLDENV': Load Floating-Point Environment
-------------------------------------------------

     FLDENV mem                    ; D9 /4                [8086,FPU]

   `FLDENV' loads the FPU operating environment (control word, status
word, tag word, instruction pointer, data pointer and last opcode) from
memory. The memory area is 14 or 28 bytes long, depending on the CPU
mode at the time. See also `FSTENV' (see Section B.4.104).

B.4.92. `FMUL', `FMULP': Floating-Point Multiply
------------------------------------------------

     FMUL mem32                    ; D8 /1                [8086,FPU]
     FMUL mem64                    ; DC /1                [8086,FPU]

     FMUL fpureg                   ; D8 C8+r              [8086,FPU]
     FMUL ST0,fpureg               ; D8 C8+r              [8086,FPU]

     FMUL TO fpureg                ; DC C8+r              [8086,FPU]
     FMUL fpureg,ST0               ; DC C8+r              [8086,FPU]

     FMULP fpureg                  ; DE C8+r              [8086,FPU]
     FMULP fpureg,ST0              ; DE C8+r              [8086,FPU]

   `FMUL' multiplies `ST0' by the given operand, and stores the result
in `ST0', unless the `TO' qualifier is used in which case it stores the
result in the operand. `FMULP' performs the same operation as `FMUL
TO', and then pops the register stack.

B.4.93. `FNOP': Floating-Point No Operation
-------------------------------------------

     FNOP                          ; D9 D0                [8086,FPU]

   `FNOP' does nothing.

B.4.94. `FPATAN', `FPTAN': Arctangent and Tangent
-------------------------------------------------

     FPATAN                        ; D9 F3                [8086,FPU]
     FPTAN                         ; D9 F2                [8086,FPU]

   `FPATAN' computes the arctangent, in radians, of the result of
dividing `ST1' by `ST0', stores the result in `ST1', and pops the
register stack. It works like the C `atan2' function, in that changing
the sign of both `ST0' and `ST1' changes the output value by pi (so it
performs true rectangular-to-polar coordinate conversion, with `ST1'
being the Y coordinate and `ST0' being the X coordinate, not merely an
arctangent).

   `FPTAN' computes the tangent of the value in `ST0' (in radians), and
stores the result back into `ST0'.

   The absolute value of `ST0' must be less than 2**63.

B.4.95. `FPREM', `FPREM1': Floating-Point Partial Remainder
-----------------------------------------------------------

     FPREM                         ; D9 F8                [8086,FPU]
     FPREM1                        ; D9 F5                [386,FPU]

   These instructions both produce the remainder obtained by dividing
`ST0' by `ST1'. This is calculated, notionally, by dividing `ST0' by
`ST1', rounding the result to an integer, multiplying by `ST1' again,
and computing the value which would need to be added back on to the
result to get back to the original value in `ST0'.

   The two instructions differ in the way the notional round-to-integer
operation is performed. `FPREM' does it by rounding towards zero, so
that the remainder it returns always has the same sign as the original
value in `ST0'; `FPREM1' does it by rounding to the nearest integer, so
that the remainder always has at most half the magnitude of `ST1'.

   Both instructions calculate _partial_ remainders, meaning that they
may not manage to provide the final result, but might leave intermediate
results in `ST0' instead. If this happens, they will set the C2 flag in
the FPU status word; therefore, to calculate a remainder, you should
repeatedly execute `FPREM' or `FPREM1' until C2 becomes clear.

B.4.96. `FRNDINT': Floating-Point Round to Integer
--------------------------------------------------

     FRNDINT                       ; D9 FC                [8086,FPU]

   `FRNDINT' rounds the contents of `ST0' to an integer, according to
the current rounding mode set in the FPU control word, and stores the
result back in `ST0'.

B.4.97. `FSAVE', `FRSTOR': Save/Restore Floating-Point State
------------------------------------------------------------

     FSAVE mem                     ; 9B DD /6             [8086,FPU]
     FNSAVE mem                    ; DD /6                [8086,FPU]

     FRSTOR mem                    ; DD /4                [8086,FPU]

   `FSAVE' saves the entire floating-point unit state, including all the
information saved by `FSTENV' (see Section B.4.104) plus the
contents of all the registers, to a 94 or 108 byte area of memory
(depending on the CPU mode). `FRSTOR' restores the floating-point state
from the same area of memory.

   `FNSAVE' does the same as `FSAVE', without first waiting for pending
floating-point exceptions to clear.

B.4.98. `FSCALE': Scale Floating-Point Value by Power of Two
------------------------------------------------------------

     FSCALE                        ; D9 FD                [8086,FPU]

   `FSCALE' scales a number by a power of two: it rounds `ST1' towards
zero to obtain an integer, then multiplies `ST0' by two to the power of
that integer, and stores the result in `ST0'.

B.4.99. `FSETPM': Set Protected Mode
------------------------------------

     FSETPM                        ; DB E4                [286,FPU]

   This instruction initialises protected mode on the 287 floating-point
coprocessor. It is only meaningful on that processor: the 387 and above
treat the instruction as a no-operation.

B.4.100. `FSIN', `FSINCOS': Sine and Cosine
-------------------------------------------

     FSIN                          ; D9 FE                [386,FPU]
     FSINCOS                       ; D9 FB                [386,FPU]

   `FSIN' calculates the sine of `ST0' (in radians) and stores the
result in `ST0'. `FSINCOS' does the same, but then pushes the cosine of
the same value on the register stack, so that the sine ends up in `ST1'
and the cosine in `ST0'. `FSINCOS' is faster than executing `FSIN' and
`FCOS' (see Section B.4.74) in succession.

   The absolute value of `ST0' must be less than 2**63.

B.4.101. `FSQRT': Floating-Point Square Root
--------------------------------------------

     FSQRT                         ; D9 FA                [8086,FPU]

   `FSQRT' calculates the square root of `ST0' and stores the result in
`ST0'.

B.4.102. `FST', `FSTP': Floating-Point Store
--------------------------------------------

     FST mem32                     ; D9 /2                [8086,FPU]
     FST mem64                     ; DD /2                [8086,FPU]
     FST fpureg                    ; DD D0+r              [8086,FPU]

     FSTP mem32                    ; D9 /3                [8086,FPU]
     FSTP mem64                    ; DD /3                [8086,FPU]
     FSTP mem80                    ; DB /7                [8086,FPU]
     FSTP fpureg                   ; DD D8+r              [8086,FPU]

   `FST' stores the value in `ST0' into the given memory location or
other FPU register. `FSTP' does the same, but then pops the register
stack.

B.4.103. `FSTCW': Store Floating-Point Control Word
---------------------------------------------------

     FSTCW mem16                   ; 9B D9 /7             [8086,FPU]
     FNSTCW mem16                  ; D9 /7                [8086,FPU]

   `FSTCW' stores the `FPU' control word (governing things like the
rounding mode, the precision, and the exception masks) into a 2-byte
memory area. See also `FLDCW' (see Section B.4.90).

   `FNSTCW' does the same thing as `FSTCW', without first waiting for
pending floating-point exceptions to clear.

B.4.104. `FSTENV': Store Floating-Point Environment
---------------------------------------------------

     FSTENV mem                    ; 9B D9 /6             [8086,FPU]
     FNSTENV mem                   ; D9 /6                [8086,FPU]

   `FSTENV' stores the `FPU' operating environment (control word,
status word, tag word, instruction pointer, data pointer and last
opcode) into memory. The memory area is 14 or 28 bytes long, depending
on the CPU mode at the time. See also `FLDENV' (see Section B.4.91).

   `FNSTENV' does the same thing as `FSTENV', without first waiting for
pending floating-point exceptions to clear.

B.4.105. `FSTSW': Store Floating-Point Status Word
--------------------------------------------------

     FSTSW mem16                   ; 9B DD /7             [8086,FPU]
     FSTSW AX                      ; 9B DF E0             [286,FPU]

     FNSTSW mem16                  ; DD /7                [8086,FPU]
     FNSTSW AX                     ; DF E0                [286,FPU]

   `FSTSW' stores the `FPU' status word into `AX' or into a 2- byte
memory area.

   `FNSTSW' does the same thing as `FSTSW', without first waiting for
pending floating-point exceptions to clear.

B.4.106. `FSUB', `FSUBP', `FSUBR', `FSUBRP': Floating-Point Subtract
--------------------------------------------------------------------

     FSUB mem32                    ; D8 /4                [8086,FPU]
     FSUB mem64                    ; DC /4                [8086,FPU]

     FSUB fpureg                   ; D8 E0+r              [8086,FPU]
     FSUB ST0,fpureg               ; D8 E0+r              [8086,FPU]

     FSUB TO fpureg                ; DC E8+r              [8086,FPU]
     FSUB fpureg,ST0               ; DC E8+r              [8086,FPU]

     FSUBR mem32                   ; D8 /5                [8086,FPU]
     FSUBR mem64                   ; DC /5                [8086,FPU]

     FSUBR fpureg                  ; D8 E8+r              [8086,FPU]
     FSUBR ST0,fpureg              ; D8 E8+r              [8086,FPU]

     FSUBR TO fpureg               ; DC E0+r              [8086,FPU]
     FSUBR fpureg,ST0              ; DC E0+r              [8086,FPU]

     FSUBP fpureg                  ; DE E8+r              [8086,FPU]
     FSUBP fpureg,ST0              ; DE E8+r              [8086,FPU]

     FSUBRP fpureg                 ; DE E0+r              [8086,FPU]
     FSUBRP fpureg,ST0             ; DE E0+r              [8086,FPU]

   * `FSUB' subtracts the given operand from `ST0' and stores the
     result back in `ST0', unless the `TO' qualifier is given, in which
     case it subtracts `ST0' from the given operand and stores the
     result in the operand.

   * `FSUBR' does the same thing, but does the subtraction the other way
     up: so if `TO' is not given, it subtracts `ST0' from the given
     operand and stores the result in `ST0', whereas if `TO' is given
     it subtracts its operand from `ST0' and stores the result in the
     operand.

   * `FSUBP' operates like `FSUB TO', but pops the register stack once
     it has finished.

   * `FSUBRP' operates like `FSUBR TO', but pops the register stack
     once it has finished.

B.4.107. `FTST': Test `ST0' Against Zero
----------------------------------------

     FTST                          ; D9 E4                [8086,FPU]

   `FTST' compares `ST0' with zero and sets the FPU flags accordingly.
`ST0' is treated as the left-hand side of the comparison, so that a
`less-than' result is generated if `ST0' is negative.

B.4.108. `FUCOMxx': Floating-Point Unordered Compare
----------------------------------------------------

     FUCOM fpureg                  ; DD E0+r              [386,FPU]
     FUCOM ST0,fpureg              ; DD E0+r              [386,FPU]

     FUCOMP fpureg                 ; DD E8+r              [386,FPU]
     FUCOMP ST0,fpureg             ; DD E8+r              [386,FPU]

     FUCOMPP                       ; DA E9                [386,FPU]

     FUCOMI fpureg                 ; DB E8+r              [P6,FPU]
     FUCOMI ST0,fpureg             ; DB E8+r              [P6,FPU]

     FUCOMIP fpureg                ; DF E8+r              [P6,FPU]
     FUCOMIP ST0,fpureg            ; DF E8+r              [P6,FPU]

   * `FUCOM' compares `ST0' with the given operand, and sets the FPU
     flags accordingly. `ST0' is treated as the left-hand side of the
     comparison, so that the carry flag is set (for a `less-than'
     result) if `ST0' is less than the given operand.

   * `FUCOMP' does the same as `FUCOM', but pops the register stack
     afterwards. `FUCOMPP' compares `ST0' with `ST1' and then pops the
     register stack twice.

   * `FUCOMI' and `FUCOMIP' work like the corresponding forms of
     `FUCOM' and `FUCOMP', but write their results directly to the CPU
     flags register rather than the FPU status word, so they can be
     immediately followed by conditional jump or conditional move
     instructions.

   The `FUCOM' instructions differ from the `FCOM' instructions (see
Section B.4.73) only in the way they handle quiet NaNs: `FUCOM' will
handle them silently and set the condition code flags to an `unordered'
result, whereas `FCOM' will generate an exception.

B.4.109. `FXAM': Examine Class of Value in `ST0'
------------------------------------------------

     FXAM                          ; D9 E5                [8086,FPU]

   `FXAM' sets the FPU flags `C3', `C2' and `C0' depending on the type
of value stored in `ST0':

      Register contents     Flags

      Unsupported format    000
      NaN                   001
      Finite number         010
      Infinity              011
      Zero                  100
      Empty register        101
      Denormal              110

   Additionally, the `C1' flag is set to the sign of the number.

B.4.110. `FXCH': Floating-Point Exchange
----------------------------------------

     FXCH                          ; D9 C9                [8086,FPU]
     FXCH fpureg                   ; D9 C8+r              [8086,FPU]
     FXCH fpureg,ST0               ; D9 C8+r              [8086,FPU]
     FXCH ST0,fpureg               ; D9 C8+r              [8086,FPU]

   `FXCH' exchanges `ST0' with a given FPU register. The no-operand
form exchanges `ST0' with `ST1'.

B.4.111. `FXRSTOR': Restore `FP', `MMX' and `SSE' State
-------------------------------------------------------

     FXRSTOR memory                ; 0F AE /1               [P6,SSE,FPU]

   The `FXRSTOR' instruction reloads the `FPU', `MMX' and `SSE' state
(environment and registers), from the 512 byte memory area defined by
the source operand. This data should have been written by a previous
`FXSAVE'.

B.4.112. `FXSAVE': Store `FP', `MMX' and `SSE' State
----------------------------------------------------

     FXSAVE memory                 ; 0F AE /0         [P6,SSE,FPU]

   `FXSAVE'The FXSAVE instruction writes the current `FPU', `MMX' and
`SSE' technology states (environment and registers), to the 512 byte
memory area defined by the destination operand. It does this without
checking for pending unmasked floating-point exceptions (similar to the
operation of `FNSAVE').

   Unlike the `FSAVE/FNSAVE' instructions, the processor retains the
contents of the `FPU', `MMX' and `SSE' state in the processor after the
state has been saved. This instruction has been optimised to maximize
floating-point save performance.

B.4.113. `FXTRACT': Extract Exponent and Significand
----------------------------------------------------

     FXTRACT                       ; D9 F4                [8086,FPU]

   `FXTRACT' separates the number in `ST0' into its exponent and
significand (mantissa), stores the exponent back into `ST0', and then
pushes the significand on the register stack (so that the significand
ends up in `ST0', and the exponent in `ST1').

B.4.114. `FYL2X', `FYL2XP1': Compute Y times Log2(X) or Log2(X+1)
-----------------------------------------------------------------

     FYL2X                         ; D9 F1                [8086,FPU]
     FYL2XP1                       ; D9 F9                [8086,FPU]

   `FYL2X' multiplies `ST1' by the base-2 logarithm of `ST0', stores
the result in `ST1', and pops the register stack (so that the result
ends up in `ST0'). `ST0' must be non-zero and positive.

   `FYL2XP1' works the same way, but replacing the base-2 log of `ST0'
with that of `ST0' plus one. This time, `ST0' must have magnitude no
greater than 1 minus half the square root of two.

B.4.115. `HLT': Halt Processor
------------------------------

     HLT                           ; F4                   [8086,PRIV]

   `HLT' puts the processor into a halted state, where it will perform
no more operations until restarted by an interrupt or a reset.

   On the 286 and later processors, this is a privileged instruction.

B.4.116. `IBTS': Insert Bit String
----------------------------------

     IBTS r/m16,reg16              ; o16 0F A7 /r         [386,UNDOC]
     IBTS r/m32,reg32              ; o32 0F A7 /r         [386,UNDOC]

   The implied operation of this instruction is:

     IBTS r/m16,AX,CL,reg16
     IBTS r/m32,EAX,CL,reg32

   Writes a bit string from the source operand to the destination. `CL'
indicates the number of bits to be copied, from the low bits of the
source.  `(E)AX' indicates the low order bit offset in the destination
that is written to. For example, if `CL' is set to 4 and `AX' (for
16-bit code) is set to 5, bits 0-3 of `src' will be copied to bits 5-8
of `dst'. This instruction is very poorly documented, and I have been
unable to find any official source of documentation on it.

   `IBTS' is supported only on the early Intel 386s, and conflicts with
the opcodes for `CMPXCHG486' (on early Intel 486s). NASM supports it
only for completeness. Its counterpart is `XBTS' (see Section B.4.332).

B.4.117. `IDIV': Signed Integer Divide
--------------------------------------

     IDIV r/m8                     ; F6 /7                [8086]
     IDIV r/m16                    ; o16 F7 /7            [8086]
     IDIV r/m32                    ; o32 F7 /7            [386]

   `IDIV' performs signed integer division. The explicit operand
provided is the divisor; the dividend and destination operands are
implicit, in the following way:

   * For `IDIV r/m8', `AX' is divided by the given operand; the
     quotient is stored in `AL' and the remainder in `AH'.

   * For `IDIV r/m16', `DX:AX' is divided by the given operand; the
     quotient is stored in `AX' and the remainder in `DX'.

   * For `IDIV r/m32', `EDX:EAX' is divided by the given operand; the
     quotient is stored in `EAX' and the remainder in `EDX'.

   Unsigned integer division is performed by the `DIV' instruction: see
Section B.4.59.

B.4.118. `IMUL': Signed Integer Multiply
----------------------------------------

     IMUL r/m8                     ; F6 /5                [8086]
     IMUL r/m16                    ; o16 F7 /5            [8086]
     IMUL r/m32                    ; o32 F7 /5            [386]

     IMUL reg16,r/m16              ; o16 0F AF /r         [386]
     IMUL reg32,r/m32              ; o32 0F AF /r         [386]

     IMUL reg16,imm8               ; o16 6B /r ib         [186]
     IMUL reg16,imm16              ; o16 69 /r iw         [186]
     IMUL reg32,imm8               ; o32 6B /r ib         [386]
     IMUL reg32,imm32              ; o32 69 /r id         [386]

     IMUL reg16,r/m16,imm8         ; o16 6B /r ib         [186]
     IMUL reg16,r/m16,imm16        ; o16 69 /r iw         [186]
     IMUL reg32,r/m32,imm8         ; o32 6B /r ib         [386]
     IMUL reg32,r/m32,imm32        ; o32 69 /r id         [386]

   `IMUL' performs signed integer multiplication. For the single-operand
form, the other operand and destination are implicit, in the following
way:

   * For `IMUL r/m8', `AL' is multiplied by the given operand; the
     product is stored in `AX'.

   * For `IMUL r/m16', `AX' is multiplied by the given operand; the
     product is stored in `DX:AX'.

   * For `IMUL r/m32', `EAX' is multiplied by the given operand; the
     product is stored in `EDX:EAX'.

   The two-operand form multiplies its two operands and stores the
result in the destination (first) operand. The three-operand form
multiplies its last two operands and stores the result in the first
operand.

   The two-operand form with an immediate second operand is in fact a
shorthand for the three-operand form, as can be seen by examining the
opcode descriptions: in the two-operand form, the code `/r' takes both
its register and `r/m' parts from the same operand (the first one).

   In the forms with an 8-bit immediate operand and another longer
source operand, the immediate operand is considered to be signed, and
is sign- extended to the length of the other source operand. In these
cases, the `BYTE' qualifier is necessary to force NASM to generate this
form of the instruction.

   Unsigned integer multiplication is performed by the `MUL'
instruction: see Section B.4.184.

B.4.119. `IN': Input from I/O Port
----------------------------------

     IN AL,imm8                    ; E4 ib                [8086]
     IN AX,imm8                    ; o16 E5 ib            [8086]
     IN EAX,imm8                   ; o32 E5 ib            [386]
     IN AL,DX                      ; EC                   [8086]
     IN AX,DX                      ; o16 ED               [8086]
     IN EAX,DX                     ; o32 ED               [386]

   `IN' reads a byte, word or doubleword from the specified I/O port,
and stores it in the given destination register. The port number may be
specified as an immediate value if it is between 0 and 255, and
otherwise must be stored in `DX'. See also `OUT' (see Section B.4.194).

B.4.120. `INC': Increment Integer
---------------------------------

     INC reg16                     ; o16 40+r             [8086]
     INC reg32                     ; o32 40+r             [386]
     INC r/m8                      ; FE /0                [8086]
     INC r/m16                     ; o16 FF /0            [8086]
     INC r/m32                     ; o32 FF /0            [386]

   `INC' adds 1 to its operand. It does _not_ affect the carry flag: to
affect the carry flag, use `ADD something,1' (see Section B.4.3).
`INC' affects all the other flags according to the result.

   This instruction can be used with a `LOCK' prefix to allow atomic
execution.

   See also `DEC' (see Section B.4.58).

B.4.121. `INSB', `INSW', `INSD': Input String from I/O Port
-----------------------------------------------------------

     INSB                          ; 6C                   [186]
     INSW                          ; o16 6D               [186]
     INSD                          ; o32 6D               [386]

   `INSB' inputs a byte from the I/O port specified in `DX' and stores
it at `[ES:DI]' or `[ES:EDI]'. It then increments or decrements
(depending on the direction flag: increments if the flag is clear,
decrements if it is set) `DI' or `EDI'.

   The register used is `DI' if the address size is 16 bits, and `EDI'
if it is 32 bits. If you need to use an address size not equal to the
current `BITS' setting, you can use an explicit `a16' or `a32' prefix.

   Segment override prefixes have no effect for this instruction: the
use of `ES' for the load from `[DI]' or `[EDI]' cannot be overridden.

   `INSW' and `INSD' work in the same way, but they input a word or a
doubleword instead of a byte, and increment or decrement the addressing
register by 2 or 4 instead of 1.

   The `REP' prefix may be used to repeat the instruction `CX' (or
`ECX' - again, the address size chooses which) times.

   See also `OUTSB', `OUTSW' and `OUTSD' (see Section B.4.195).

B.4.122. `INT': Software Interrupt
----------------------------------

     INT imm8                      ; CD ib                [8086]

   `INT' causes a software interrupt through a specified vector number
from 0 to 255.

   The code generated by the `INT' instruction is always two bytes long:
although there are short forms for some `INT' instructions, NASM does
not generate them when it sees the `INT' mnemonic. In order to generate
single-byte breakpoint instructions, use the `INT3' or `INT1'
instructions (see Section B.4.123) instead.

B.4.123. `INT3', `INT1', `ICEBP', `INT01': Breakpoints
------------------------------------------------------

     INT1                          ; F1                   [P6]
     ICEBP                         ; F1                   [P6]
     INT01                         ; F1                   [P6]

     INT3                          ; CC                   [8086]
     INT03                         ; CC                   [8086]

   `INT1' and `INT3' are short one-byte forms of the instructions `INT
1' and `INT 3' (see Section B.4.122). They perform a similar
function to their longer counterparts, but take up less code space.
They are used as breakpoints by debuggers.

   * `INT1', and its alternative synonyms `INT01' and `ICEBP', is an
     instruction used by in-circuit emulators (ICEs). It is present,
     though not documented, on some processors down to the 286, but is
     only documented for the Pentium Pro. `INT3' is the instruction
     normally used as a breakpoint by debuggers.

   * `INT3', and its synonym `INT03', is not precisely equivalent to
     `INT 3': the short form, since it is designed to be used as a
     breakpoint, bypasses the normal `IOPL' checks in virtual-8086 mode,
     and also does not go through interrupt redirection.

B.4.124. `INTO': Interrupt if Overflow
--------------------------------------

     INTO                          ; CE                   [8086]

   `INTO' performs an `INT 4' software interrupt (see Section B.4.122)
if and only if the overflow flag is set.