FCMOV Flags: FP Conditional MOVE data +-+-+-+-+-+-+-+-+-+ +----------+----------+ |O|D|I|T|S|Z|A|P|C| | 1101101n | 11cccrrr | +-+-+-+-+-+-+-+-+-+ +----------+----------+ | | | | | | | | | | | Dn | xx | +-+-+-+-+-+-+-+-+-+ +----------+----------+
FCMOVcc ST, STi
n=0 DA C0 + i FCMOVB ST, STi ; Move if Below DA C8 + i FCMOVE ST, STi ; Move if Equal DA D0 + i FCMOVBE ST, STi ; Move if Below or Equal DA D8 + i FCMOVU ST, STi ; Move if Unordered n=1 DB C0 + i FCMOVNB ST, STi ; Move if Not Below DB C8 + i FCMOVNE ST, STi ; Move if Not Equal DB D0 + i FCMOVNBE ST, STi ; Move if Not Below or Equal DB D8 + i FCMOVNU ST, STi ; Move if Not Unordered
FCMOV { TEMP0 = STi; /* Both operands are read to detect an underflow */ TEMP1 = ST0; /* condition before proceeding. */ IF condition { ST0 = STi; }
The FCMOV instruction performs a similar function as CMOV. FCMOV check a condition in the integer flags (EFLAGS) and moves data to the stack top (ST0) if the condition is met. In addition to six integer conditions, two floating point conditions may also be tested. The two floating point conditions checked are Ordered and Unordered which result from FCOM and FTST operations. Conditional move assignments for other conditions, such as denormalized numbers must use the traditional technique of using FSTSW, and integer test instruction, and branching. See Table 1 for a list of all of the condition FCMOV may use.
From the operational description given above, it is clear that the operation unconditionally reads both operands, regardless of the test condition. The purpose of reading both operands is to detect an underflow condition. If reading either operand would generate an underflow exception, then that exception is signaled before the condition is checked. FCMOV will never cause an overflow exception.
Table 1 -- FCMOV condition codes
Normally, no FPU flags are affected by FCMOV. However, if an exception occurs, then the FPU flags are affected as follows:
FSW.C1 will be set to indicate a stack underflow condition (U#). The FTW field will correspond to the top of stack, and ST0 will be marked FULL (unless there was an unmasked stack underflow exception). See Table 2 for a description of FCMOV stack exception behavior.
Table 2 -- FCMOV Stack Exception Characteristics
The FCMOV opcodes are newly defined for P6, however don't always produce an invalid opcode exception (#UD) on previous x86 processors. The encodings for FCMOV produce an invalid opcode exception on the Pentium and Intel486 processors, but are ignored, and treated like an FNOP by the Intel387 math coprocessor. Behavior for the 8087 and 80287 math coprocessors is undefined.
IS
Exception 7 (#NM) if EM or TS is set in CR0.
Exception 7 (#NM) if EM or TS is set in CR0.
Exception 7 (#NM) if EM or TS is set in CR0.
The first example shows a normal stream of instructions which would be used to perform a conditional move in an Intel386-compatible manner. The second example replaces this code with use of the FCMOV instruction. Then the third example combines the use of the new FCOMI instruction and FCMOV to perform the same function in a very efficient manner. Note: these code examples don't attempt to take into account the possibility of unordered numbers. If unordered numbers must be accommodated, then more code is required.
FCOM ST0, ST1 ; Floating point compare FNSTSW AX ; Store floating point flags in AX (no wait) SAHF ; Move AH to integer flags register JB Continue ; Branch if we don't replace ST0 FXCH ST0, ST1 ; Exchange ST0 and ST1 Continue:
FCOM ST0, ST1 ; Floating point compare FNSTSW AX ; Store floating point flags in AX (no wait) SAHF ; Move AH to integer flags register FCMOVNB ST0, ST1 ; Conditionally move ST0 and ST1 if not below
FCOMI ST0, ST1 ; Compare and move results to integer flags FCMOVNB ST0, ST1 ; Conditionally move ST0 and ST1 if not below
Get description of [AAM] [AAD] [UMOV] [LOADALL] New P6 OpCodes [CMOV] [FCOMI] [RDPMC] [INT01] [SALC] [UD2]