// // SMPDataFlowAnalysis.cpp // // This module contains common types an helper classes needed for the // SMP project (Software Memory Protection). // #include <list> #include <set> #include <vector> #include <algorithm> #include <cstring> #include <pro.h> #include <assert.h> #include <ida.hpp> #include <idp.hpp> #include <allins.hpp> #include <auto.hpp> #include <bytes.hpp> #include <funcs.hpp> #include <intel.hpp> #include <loader.hpp> #include <lines.hpp> #include <name.hpp> #include "SMPDataFlowAnalysis.h" #include "SMPStaticAnalyzer.h" // Set to 1 for debugging output #define SMP_DEBUG 1 #define SMP_DEBUG2 0 // verbose #define SMP_DEBUG3 0 // verbose #define SMP_DEBUG_CONTROLFLOW 0 // tells what processing stage is entered #define SMP_DEBUG_XOR 0 #define SMP_DEBUG_CHUNKS 1 // tracking down tail chunks for functions #define SMP_DEBUG_FRAMEFIXUP 0 #define SMP_DEBUG_DATAFLOW 0 // Compute LVA/SSA or not? Turn it off for NICECAP demo on 31-JAN-2008 #define SMP_COMPUTE_LVA_SSA 0 char *RegNames[R_of + 1] = { "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "SPL", "BPL", "SIL", "DIL", "EIP", "ES", "CS", "SS", "DS", "FS", "GS", "CF", "ZF", "SF", "OF" }; // Define instruction categories for data flow analysis. SMPitype DFACategory[NN_last+1]; // Define which instructions define and use the CPU flags. bool SMPDefsFlags[NN_last + 1]; bool SMPUsesFlags[NN_last + 1]; // Get the size in bytes of the data type of an operand. size_t GetOpDataSize(op_t DataOp) { size_t DataSize; switch (DataOp.dtyp) { case dt_byte: DataSize = 1; break; case dt_word: DataSize = 2; break; case dt_dword: case dt_float: case dt_code: case dt_unicode: case dt_string: DataSize = 4; break; case dt_double: case dt_qword: DataSize = 8; break; case dt_packreal: DataSize = 12; break; case dt_byte16: DataSize = 16; break; case dt_fword: DataSize = 6; break; case dt_3byte: DataSize = 3; break; default: msg("WARNING: unexpected data type %d in GetOpDataSize().\n", DataOp.dtyp); DataSize = 4; break; } return DataSize; } // end of GetOpDataSize() // We need to make subword registers equal to their containing registers when we // do comparisons, so that we will realize that register EAX is killed by a prior DEF // of register AL, for example, and vice versa. To keep sets ordered strictly, // we also have to make AL and AH be equal to each other as well as equal to EAX. #define FIRST_x86_SUBWORD_REG R_al #define LAST_x86_SUBWORD_REG R_bh bool MDLessReg(const ushort Reg1, const ushort Reg2) { bool FirstSubword = ((Reg1 >= FIRST_x86_SUBWORD_REG) && (Reg1 <= LAST_x86_SUBWORD_REG)); bool SecondSubword = ((Reg2 >= FIRST_x86_SUBWORD_REG) && (Reg2 <= LAST_x86_SUBWORD_REG)); ushort SReg1 = Reg1; ushort SReg2 = Reg2; if (FirstSubword) { // See enumeration RegNo in intel.hpp. if (SReg1 < 20) // AL, CL, DL or BL SReg1 -= 16; else // AH, CH, DH or BH SReg1 -= 20; } if (SecondSubword) { if (SReg2 < 20) SReg2 -= 16; else SReg2 -= 20; } return (SReg1 < SReg2); } // end of MDLessReg() // In SSA computations, we are storing the GlobalNames index into the op_t fields // n, offb, and offo. This function extracts an unsigned int from these three 8-bit // fields. unsigned int ExtractGlobalIndex(op_t GlobalOp) { unsigned int index = 0; index |= (((unsigned int) GlobalOp.offo) & 0x000000ff); index <<= 8; index |= (((unsigned int) GlobalOp.offb) & 0x000000ff); index <<= 8; index |= (((unsigned int) GlobalOp.n) & 0x000000ff); return index; } void SetGlobalIndex(op_t *TempOp, size_t index) { TempOp->n = (char) (index & 0x000000ff); TempOp->offb = (char) ((index & 0x0000ff00) >> 8); TempOp->offo = (char) ((index & 0x00ff0000) >> 16); return; } // DEBUG Print DEF and/or USE for an operand. void PrintDefUse(ulong feature, int OpNum) { // CF_ macros number the operands from 1 to 6, while OpNum // is a 0 to 5 index into the insn_t.Operands[] array. // OpNum == -1 is a signal that this is a DEF or USE or VarKillSet etc. // operand and not an instruction operand. if (-1 == OpNum) return; switch (OpNum) { case 0: if (feature & CF_CHG1) msg(" DEF"); if (feature & CF_USE1) msg(" USE"); break; case 1: if (feature & CF_CHG2) msg(" DEF"); if (feature & CF_USE2) msg(" USE"); break; case 2: if (feature & CF_CHG3) msg(" DEF"); if (feature & CF_USE3) msg(" USE"); break; case 3: if (feature & CF_CHG4) msg(" DEF"); if (feature & CF_USE4) msg(" USE"); break; case 4: if (feature & CF_CHG5) msg(" DEF"); if (feature & CF_USE5) msg(" USE"); break; case 5: if (feature & CF_CHG6) msg(" DEF"); if (feature & CF_USE6) msg(" USE"); break; } return; } // end PrintDefUse() // DEBUG print SIB info for an operand. void PrintSIB(op_t Opnd) { int BaseReg = sib_base(Opnd); short IndexReg = sib_index(Opnd); int ScaleFactor = sib_scale(Opnd); #define NAME_LEN 5 char BaseName[NAME_LEN] = {'N', 'o', 'n', 'e', '\0'}; char IndexName[NAME_LEN] = {'N', 'o', 'n', 'e', '\0'}; #if 1 if (!((BaseReg == R_bp) && (Opnd.type == o_mem))) // EBP can be SIB code for NO BASE REG #endif qstrncpy(BaseName, RegNames[BaseReg], NAME_LEN - 1); if (IndexReg != R_sp) { // SIB code for NO INDEX REG qstrncpy(IndexName, RegNames[IndexReg], NAME_LEN -1); } msg(" Base %s Index %s Scale %d", BaseName, IndexName, ScaleFactor); } // end PrintSIB() // Debug: print one operand from an instruction or DEF or USE list. void PrintOneOperand(op_t Opnd, ulong features, int OpNum) { if (Opnd.type == o_void) return; else if (Opnd.type == o_mem) { msg(" Operand %d : memory : addr: %x", OpNum, Opnd.addr); PrintDefUse(features, OpNum); if (Opnd.hasSIB) { PrintSIB(Opnd); } } else if (Opnd.type == o_phrase) { msg(" Operand %d : memory phrase :", OpNum); PrintDefUse(features, OpNum); if (Opnd.hasSIB) { // has SIB info PrintSIB(Opnd); } else { // no SIB info ushort BaseReg = Opnd.phrase; msg(" reg %s", RegNames[BaseReg]); } if (Opnd.addr != 0) { msg(" \n WARNING: addr for o_phrase type: %d\n", Opnd.addr); } } else if (Opnd.type == o_displ) { msg(" Operand %d : memory displ :", OpNum); ea_t offset = Opnd.addr; PrintDefUse(features, OpNum); if (Opnd.hasSIB) { PrintSIB(Opnd); msg(" displ %d", offset); } else { ushort BaseReg = Opnd.reg; msg(" reg %s displ %d", RegNames[BaseReg], offset); } } else if (Opnd.type == o_reg) { msg(" Operand %d : register %s", OpNum, RegNames[Opnd.reg]); PrintDefUse(features, OpNum); } else if (Opnd.type == o_imm) { msg(" Operand %d : immed", OpNum); PrintDefUse(features, OpNum); } else if (Opnd.type == o_far) { msg(" Operand %d : FarPtrImmed", OpNum); msg(" addr: %x", Opnd.addr); PrintDefUse(features, OpNum); } else if (Opnd.type == o_near) { msg(" Operand %d : NearPtrImmed", OpNum); msg(" addr: %x", Opnd.addr); PrintDefUse(features, OpNum); } else { msg(" Operand %d : unknown", OpNum); PrintDefUse(features, OpNum); } if (!(Opnd.showed())) msg(" HIDDEN "); return; } // end of PrintOneOperand() // Print an operand that has no features flags or operand position number, such // as the op_t types found in lists and sets throughout the blocks, phi functions, etc. void PrintListOperand(op_t Opnd, int SSANum) { if (Opnd.type == o_void) return; else if (Opnd.type == o_mem) { msg(" Operand : memory : addr: %x", Opnd.addr); if (Opnd.hasSIB) { PrintSIB(Opnd); } } else if (Opnd.type == o_phrase) { msg(" Operand : memory phrase :"); if (Opnd.hasSIB) { // has SIB info PrintSIB(Opnd); } else { // no SIB info ushort BaseReg = Opnd.phrase; msg(" reg %s", RegNames[BaseReg]); } if (Opnd.addr != 0) { msg(" \n WARNING: addr for o_phrase type: %d\n", Opnd.addr); } } else if (Opnd.type == o_displ) { msg(" Operand : memory displ :"); ea_t offset = Opnd.addr; if (Opnd.hasSIB) { PrintSIB(Opnd); msg(" displ %d", offset); } else { ushort BaseReg = Opnd.reg; msg(" reg %s displ %d", RegNames[BaseReg], offset); } } else if (Opnd.type == o_reg) { msg(" Operand : register: %s", RegNames[Opnd.reg]); } else if (Opnd.type == o_imm) { msg(" Operand : immed %d", Opnd.value); } else if (Opnd.type == o_far) { msg(" Operand : FarPtrImmed addr: %x", Opnd.addr); } else if (Opnd.type == o_near) { msg(" Operand : NearPtrImmed addr: %x", Opnd.addr); } else { msg(" Operand : unknown"); } msg(" SSANum: %d ", SSANum); if (!(Opnd.showed())) msg(" HIDDEN "); return; } // end of PrintListOperand() // MACHINE DEPENDENT: Is operand type a known type that we want to analyze? bool MDKnownOperandType(op_t TempOp) { return ((TempOp.type >= o_reg) && (TempOp.type <= o_near)); } // ***************************************************************** // Class DefOrUse // ***************************************************************** // Default constructor to make the compilers happy. DefOrUse::DefOrUse(void) { this->OpType = UNINIT; this->SSANumber = -2; return; } // Constructor. DefOrUse::DefOrUse(op_t Ref, SMPOperandType Type, int SSASub) { this->Operand = Ref; this->OpType = Type; this->SSANumber = SSASub; return; } // Copy constructor. DefOrUse::DefOrUse(const DefOrUse &CopyIn) { *this = CopyIn; return; } // Assignment operator for copy constructor use. DefOrUse &DefOrUse::operator=(const DefOrUse &rhs) { this->Operand = rhs.Operand; this->OpType = rhs.OpType; this->SSANumber = rhs.SSANumber; return *this; } // Debug printing. void DefOrUse::Dump(void) const { PrintListOperand(this->Operand, this->SSANumber); if (this->OpType == NUMERIC) msg("N "); else if (this->OpType == POINTER) msg("P "); else if (this->OpType == UNKNOWN) msg("U "); // Don't write anything for UNINIT OpType return; } // end of DefOrUse::Dump() // ***************************************************************** // Class DefOrUseList // ***************************************************************** // Default constructor. DefOrUseList::DefOrUseList(void) { return; } // Set a Def or Use into the list, along with its type. void DefOrUseList::SetRef(op_t Ref, SMPOperandType Type, int SSASub) { DefOrUse CurrRef(Ref, Type, SSASub); this->Refs.push_back(CurrRef); return; } // Get a reference by index. DefOrUse DefOrUseList::GetRef(size_t index) const { return Refs[index]; } // Change the SSA subscript for a reference. void DefOrUseList::SetSSANum(size_t index, int NewSSASub) { this->Refs[index].SetSSANum(NewSSASub); return; } // Change the operand type for a reference. void DefOrUseList::SetType(size_t index, SMPOperandType Type) { this->Refs[index].SetType(Type); return; } // Debug printing. void DefOrUseList::Dump(void) const { for (size_t index = 0; index < this->Refs.size(); ++index) { Refs[index].Dump(); } msg("\n"); return; } // Erase duplicate entries, in case SMPInstr::MDFixupDefUseLists() adds one. void DefOrUseList::EraseDuplicates(void) { set<op_t, LessOp> TempRefs; // Use STL set to find duplicates set<op_t, LessOp>::iterator TempIter; vector<DefOrUse>::iterator RefIter; RefIter = this->Refs.begin(); while (RefIter != this->Refs.end()) { TempIter = TempRefs.find(RefIter->GetOp()); if (TempIter == TempRefs.end()) { // not already in set TempRefs.insert(RefIter->GetOp()); ++RefIter; } else { // found it in set already RefIter = this->Refs.erase(RefIter); } } return; } // end of DefOrUseList::EraseDuplicates() // ***************************************************************** // Class SMPPhiFunction // ***************************************************************** // Constructor SMPPhiFunction::SMPPhiFunction(int GlobIndex, const DefOrUse &Def) { this->index = GlobIndex; this->DefName = Def; return; } // Add a phi item to the list void SMPPhiFunction::PushBack(DefOrUse Ref) { this->SubscriptedOps.SetRef(Ref.GetOp(), Ref.GetType(), Ref.GetSSANum()); return; } // Set the SSA number of the defined variable. void SMPPhiFunction::SetSSADef(int NewSSASub) { this->DefName.SetSSANum(NewSSASub); return; } // Set the SSA number of the input variable. void SMPPhiFunction::SetSSARef(size_t index, int NewSSASub) { this->SubscriptedOps.SetSSANum(index, NewSSASub); return; } // Debug printing. void SMPPhiFunction::Dump(void) const { msg(" DEF: "); this->DefName.Dump(); msg(" USEs: "); this->SubscriptedOps.Dump(); return; } // ***************************************************************** // Class SMPDefUseChain // ***************************************************************** // Constructors SMPDefUseChain::SMPDefUseChain(void) { this->SSAName.type = o_void; this->RefInstrs.push_back(BADADDR); return; } SMPDefUseChain::SMPDefUseChain(op_t Name, ea_t Def) { this->SSAName = Name; this->RefInstrs.push_back(Def); return; } // Set the variable name. void SMPDefUseChain::SetName(op_t Name) { this->SSAName = Name; return; } // Set the DEF instruction. void SMPDefUseChain::SetDef(ea_t Def) { this->RefInstrs[0] = Def; return; } // Push a USE onto the list void SMPDefUseChain::PushUse(ea_t Use) { this->RefInstrs.push_back(Use); return; } // DEBUG dump. void SMPDefUseChain::Dump(int SSANum) { msg("DEF-USE chain for: "); PrintListOperand(this->SSAName, SSANum); if (this->RefInstrs.size() < 1) { msg(" no references.\n"); return; } msg("\n DEF: %x USEs: ", this->RefInstrs.at(0)); size_t index; for (index = 1; index < this->RefInstrs.size(); ++index) msg("%x ", this->RefInstrs.at(index)); msg("\n"); return; } // end of SMPDefUseChain::Dump() // ***************************************************************** // Class SMPDUChainArray // ***************************************************************** SMPDUChainArray::SMPDUChainArray(void) { this->SSAName.type = o_void; return; } SMPDUChainArray::SMPDUChainArray(op_t Name) { this->SSAName = Name; return; } void SMPDUChainArray::SetName(op_t Name) { this->SSAName = Name; return; } // DEBUG dump. void SMPDUChainArray::Dump(void) { size_t index; for (index = 0; index < this->DUChains.size(); ++index) { this->DUChains.at(index).Dump((int) index); } return; } // ***************************************************************** // Class SMPCompleteDUChains // ***************************************************************** // DEBUG dump. void SMPCompleteDUChains::Dump(void) { size_t index; for (index = 0; index < this->ChainsByName.size(); ++index) { this->ChainsByName.at(index).Dump(); } return; } // end of SMPCompleteDUChains::Dump() // Initialize the DFACategory[] array to define instruction classes // for the purposes of data flow analysis. void InitDFACategory(void) { // Default category is 0, not the start or end of a basic block. (void) memset(DFACategory, 0, sizeof(DFACategory)); DFACategory[NN_call] = CALL; // Call Procedure DFACategory[NN_callfi] = INDIR_CALL; // Indirect Call Far Procedure DFACategory[NN_callni] = INDIR_CALL; // Indirect Call Near Procedure DFACategory[NN_hlt] = HALT; // Halt DFACategory[NN_int] = CALL; // Call to Interrupt Procedure DFACategory[NN_into] = CALL; // Call to Interrupt Procedure if Overflow Flag = 1 DFACategory[NN_int3] = CALL; // Trap to Debugger DFACategory[NN_iretw] = RETURN; // Interrupt Return DFACategory[NN_iret] = RETURN; // Interrupt Return DFACategory[NN_iretd] = RETURN; // Interrupt Return (use32) DFACategory[NN_iretq] = RETURN; // Interrupt Return (use64) DFACategory[NN_ja] = COND_BRANCH; // Jump if Above (CF=0 & ZF=0) DFACategory[NN_jae] = COND_BRANCH; // Jump if Above or Equal (CF=0) DFACategory[NN_jb] = COND_BRANCH; // Jump if Below (CF=1) DFACategory[NN_jbe] = COND_BRANCH; // Jump if Below or Equal (CF=1 | ZF=1) DFACategory[NN_jc] = COND_BRANCH; // Jump if Carry (CF=1) DFACategory[NN_jcxz] = COND_BRANCH; // Jump if CX is 0 DFACategory[NN_jecxz] = COND_BRANCH; // Jump if ECX is 0 DFACategory[NN_jrcxz] = COND_BRANCH; // Jump if RCX is 0 DFACategory[NN_je] = COND_BRANCH; // Jump if Equal (ZF=1) DFACategory[NN_jg] = COND_BRANCH; // Jump if Greater (ZF=0 & SF=OF) DFACategory[NN_jge] = COND_BRANCH; // Jump if Greater or Equal (SF=OF) DFACategory[NN_jl] = COND_BRANCH; // Jump if Less (SF!=OF) DFACategory[NN_jle] = COND_BRANCH; // Jump if Less or Equal (ZF=1 | SF!=OF) DFACategory[NN_jna] = COND_BRANCH; // Jump if Not Above (CF=1 | ZF=1) DFACategory[NN_jnae] = COND_BRANCH; // Jump if Not Above or Equal (CF=1) DFACategory[NN_jnb] = COND_BRANCH; // Jump if Not Below (CF=0) DFACategory[NN_jnbe] = COND_BRANCH; // Jump if Not Below or Equal (CF=0 & ZF=0) DFACategory[NN_jnc] = COND_BRANCH; // Jump if Not Carry (CF=0) DFACategory[NN_jne] = COND_BRANCH; // Jump if Not Equal (ZF=0) DFACategory[NN_jng] = COND_BRANCH; // Jump if Not Greater (ZF=1 | SF!=OF) DFACategory[NN_jnge] = COND_BRANCH; // Jump if Not Greater or Equal (ZF=1) DFACategory[NN_jnl] = COND_BRANCH; // Jump if Not Less (SF=OF) DFACategory[NN_jnle] = COND_BRANCH; // Jump if Not Less or Equal (ZF=0 & SF=OF) DFACategory[NN_jno] = COND_BRANCH; // Jump if Not Overflow (OF=0) DFACategory[NN_jnp] = COND_BRANCH; // Jump if Not Parity (PF=0) DFACategory[NN_jns] = COND_BRANCH; // Jump if Not Sign (SF=0) DFACategory[NN_jnz] = COND_BRANCH; // Jump if Not Zero (ZF=0) DFACategory[NN_jo] = COND_BRANCH; // Jump if Overflow (OF=1) DFACategory[NN_jp] = COND_BRANCH; // Jump if Parity (PF=1) DFACategory[NN_jpe] = COND_BRANCH; // Jump if Parity Even (PF=1) DFACategory[NN_jpo] = COND_BRANCH; // Jump if Parity Odd (PF=0) DFACategory[NN_js] = COND_BRANCH; // Jump if Sign (SF=1) DFACategory[NN_jz] = COND_BRANCH; // Jump if Zero (ZF=1) DFACategory[NN_jmp] = JUMP; // Jump DFACategory[NN_jmpfi] = INDIR_JUMP; // Indirect Far Jump DFACategory[NN_jmpni] = INDIR_JUMP; // Indirect Near Jump DFACategory[NN_jmpshort] = JUMP; // Jump Short (only in 64-bit mode) DFACategory[NN_loopw] = COND_BRANCH; // Loop while ECX != 0 DFACategory[NN_loop] = COND_BRANCH; // Loop while CX != 0 DFACategory[NN_loopd] = COND_BRANCH; // Loop while ECX != 0 DFACategory[NN_loopq] = COND_BRANCH; // Loop while RCX != 0 DFACategory[NN_loopwe] = COND_BRANCH; // Loop while CX != 0 and ZF=1 DFACategory[NN_loope] = COND_BRANCH; // Loop while rCX != 0 and ZF=1 DFACategory[NN_loopde] = COND_BRANCH; // Loop while ECX != 0 and ZF=1 DFACategory[NN_loopqe] = COND_BRANCH; // Loop while RCX != 0 and ZF=1 DFACategory[NN_loopwne] = COND_BRANCH; // Loop while CX != 0 and ZF=0 DFACategory[NN_loopne] = COND_BRANCH; // Loop while rCX != 0 and ZF=0 DFACategory[NN_loopdne] = COND_BRANCH; // Loop while ECX != 0 and ZF=0 DFACategory[NN_loopqne] = COND_BRANCH; // Loop while RCX != 0 and ZF=0 DFACategory[NN_retn] = RETURN; // Return Near from Procedure DFACategory[NN_retf] = RETURN; // Return Far from Procedure // // Pentium instructions // DFACategory[NN_rsm] = HALT; // Resume from System Management Mode // Pentium II instructions DFACategory[NN_sysenter] = CALL; // Fast Transition to System Call Entry Point DFACategory[NN_sysexit] = CALL; // Fast Transition from System Call Entry Point // AMD syscall/sysret instructions NOTE: not AMD, found in Intel manual DFACategory[NN_syscall] = CALL; // Low latency system call DFACategory[NN_sysret] = CALL; // Return from system call // VMX instructions DFACategory[NN_vmcall] = INDIR_CALL; // Call to VM Monitor return; } // end InitDFACategory() // Initialize the SMPDefsFlags[] array to define how we emit // optimizing annotations. void InitSMPDefsFlags(void) { // Default value is true. Many instructions set the flags. (void) memset(SMPDefsFlags, true, sizeof(SMPDefsFlags)); SMPDefsFlags[NN_null] = false; // Unknown Operation SMPDefsFlags[NN_bound] = false; // Check Array Index Against Bounds SMPDefsFlags[NN_call] = false; // Call Procedure SMPDefsFlags[NN_callfi] = false; // Indirect Call Far Procedure SMPDefsFlags[NN_callni] = false; // Indirect Call Near Procedure SMPDefsFlags[NN_cbw] = false; // AL -> AX (with sign) SMPDefsFlags[NN_cwde] = false; // AX -> EAX (with sign) SMPDefsFlags[NN_cdqe] = false; // EAX -> RAX (with sign) SMPDefsFlags[NN_clts] = false; // Clear Task-Switched Flag in CR0 SMPDefsFlags[NN_cwd] = false; // AX -> DX:AX (with sign) SMPDefsFlags[NN_cdq] = false; // EAX -> EDX:EAX (with sign) SMPDefsFlags[NN_cqo] = false; // RAX -> RDX:RAX (with sign) SMPDefsFlags[NN_enterw] = false; // Make Stack Frame for Procedure Parameters SMPDefsFlags[NN_enter] = false; // Make Stack Frame for Procedure Parameters SMPDefsFlags[NN_enterd] = false; // Make Stack Frame for Procedure Parameters SMPDefsFlags[NN_enterq] = false; // Make Stack Frame for Procedure Parameters SMPDefsFlags[NN_hlt] = false; // Halt SMPDefsFlags[NN_in] = false; // Input from Port SMPDefsFlags[NN_ins] = false; // Input Byte(s) from Port to String SMPDefsFlags[NN_iretw] = false; // Interrupt Return SMPDefsFlags[NN_iret] = false; // Interrupt Return SMPDefsFlags[NN_iretd] = false; // Interrupt Return (use32) SMPDefsFlags[NN_iretq] = false; // Interrupt Return (use64) SMPDefsFlags[NN_ja] = false; // Jump if Above (CF=0 & ZF=0) SMPDefsFlags[NN_jae] = false; // Jump if Above or Equal (CF=0) SMPDefsFlags[NN_jb] = false; // Jump if Below (CF=1) SMPDefsFlags[NN_jbe] = false; // Jump if Below or Equal (CF=1 | ZF=1) SMPDefsFlags[NN_jc] = false; // Jump if Carry (CF=1) SMPDefsFlags[NN_jcxz] = false; // Jump if CX is 0 SMPDefsFlags[NN_jecxz] = false; // Jump if ECX is 0 SMPDefsFlags[NN_jrcxz] = false; // Jump if RCX is 0 SMPDefsFlags[NN_je] = false; // Jump if Equal (ZF=1) SMPDefsFlags[NN_jg] = false; // Jump if Greater (ZF=0 & SF=OF) SMPDefsFlags[NN_jge] = false; // Jump if Greater or Equal (SF=OF) SMPDefsFlags[NN_jl] = false; // Jump if Less (SF!=OF) SMPDefsFlags[NN_jle] = false; // Jump if Less or Equal (ZF=1 | SF!=OF) SMPDefsFlags[NN_jna] = false; // Jump if Not Above (CF=1 | ZF=1) SMPDefsFlags[NN_jnae] = false; // Jump if Not Above or Equal (CF=1) SMPDefsFlags[NN_jnb] = false; // Jump if Not Below (CF=0) SMPDefsFlags[NN_jnbe] = false; // Jump if Not Below or Equal (CF=0 & ZF=0) SMPDefsFlags[NN_jnc] = false; // Jump if Not Carry (CF=0) SMPDefsFlags[NN_jne] = false; // Jump if Not Equal (ZF=0) SMPDefsFlags[NN_jng] = false; // Jump if Not Greater (ZF=1 | SF!=OF) SMPDefsFlags[NN_jnge] = false; // Jump if Not Greater or Equal (ZF=1) SMPDefsFlags[NN_jnl] = false; // Jump if Not Less (SF=OF) SMPDefsFlags[NN_jnle] = false; // Jump if Not Less or Equal (ZF=0 & SF=OF) SMPDefsFlags[NN_jno] = false; // Jump if Not Overflow (OF=0) SMPDefsFlags[NN_jnp] = false; // Jump if Not Parity (PF=0) SMPDefsFlags[NN_jns] = false; // Jump if Not Sign (SF=0) SMPDefsFlags[NN_jnz] = false; // Jump if Not Zero (ZF=0) SMPDefsFlags[NN_jo] = false; // Jump if Overflow (OF=1) SMPDefsFlags[NN_jp] = false; // Jump if Parity (PF=1) SMPDefsFlags[NN_jpe] = false; // Jump if Parity Even (PF=1) SMPDefsFlags[NN_jpo] = false; // Jump if Parity Odd (PF=0) SMPDefsFlags[NN_js] = false; // Jump if Sign (SF=1) SMPDefsFlags[NN_jz] = false; // Jump if Zero (ZF=1) SMPDefsFlags[NN_jmp] = false; // Jump SMPDefsFlags[NN_jmpfi] = false; // Indirect Far Jump SMPDefsFlags[NN_jmpni] = false; // Indirect Near Jump SMPDefsFlags[NN_jmpshort] = false; // Jump Short (not used) SMPDefsFlags[NN_lahf] = false; // Load Flags into AH Register SMPDefsFlags[NN_lea] = false; // Load Effective Address SMPDefsFlags[NN_leavew] = false; // High Level Procedure Exit SMPDefsFlags[NN_leave] = false; // High Level Procedure Exit SMPDefsFlags[NN_leaved] = false; // High Level Procedure Exit SMPDefsFlags[NN_leaveq] = false; // High Level Procedure Exit SMPDefsFlags[NN_lgdt] = false; // Load Global Descriptor Table Register SMPDefsFlags[NN_lidt] = false; // Load Interrupt Descriptor Table Register SMPDefsFlags[NN_lgs] = false; // Load Full Pointer to GS:xx SMPDefsFlags[NN_lss] = false; // Load Full Pointer to SS:xx SMPDefsFlags[NN_lds] = false; // Load Full Pointer to DS:xx SMPDefsFlags[NN_les] = false; // Load Full Pointer to ES:xx SMPDefsFlags[NN_lfs] = false; // Load Full Pointer to FS:xx SMPDefsFlags[NN_loopwe] = false; // Loop while CX != 0 and ZF=1 SMPDefsFlags[NN_loope] = false; // Loop while rCX != 0 and ZF=1 SMPDefsFlags[NN_loopde] = false; // Loop while ECX != 0 and ZF=1 SMPDefsFlags[NN_loopqe] = false; // Loop while RCX != 0 and ZF=1 SMPDefsFlags[NN_loopwne] = false; // Loop while CX != 0 and ZF=0 SMPDefsFlags[NN_loopne] = false; // Loop while rCX != 0 and ZF=0 SMPDefsFlags[NN_loopdne] = false; // Loop while ECX != 0 and ZF=0 SMPDefsFlags[NN_loopqne] = false; // Loop while RCX != 0 and ZF=0 SMPDefsFlags[NN_ltr] = false; // Load Task Register SMPDefsFlags[NN_mov] = false; // Move Data SMPDefsFlags[NN_movsp] = false; // Move to/from Special Registers SMPDefsFlags[NN_movs] = false; // Move Byte(s) from String to String SMPDefsFlags[NN_movsx] = false; // Move with Sign-Extend SMPDefsFlags[NN_movzx] = false; // Move with Zero-Extend SMPDefsFlags[NN_nop] = false; // No Operation SMPDefsFlags[NN_out] = false; // Output to Port SMPDefsFlags[NN_outs] = false; // Output Byte(s) to Port SMPDefsFlags[NN_pop] = false; // Pop a word from the Stack SMPDefsFlags[NN_popaw] = false; // Pop all General Registers SMPDefsFlags[NN_popa] = false; // Pop all General Registers SMPDefsFlags[NN_popad] = false; // Pop all General Registers (use32) SMPDefsFlags[NN_popaq] = false; // Pop all General Registers (use64) SMPDefsFlags[NN_push] = false; // Push Operand onto the Stack SMPDefsFlags[NN_pushaw] = false; // Push all General Registers SMPDefsFlags[NN_pusha] = false; // Push all General Registers SMPDefsFlags[NN_pushad] = false; // Push all General Registers (use32) SMPDefsFlags[NN_pushaq] = false; // Push all General Registers (use64) SMPDefsFlags[NN_pushfw] = false; // Push Flags Register onto the Stack SMPDefsFlags[NN_pushf] = false; // Push Flags Register onto the Stack SMPDefsFlags[NN_pushfd] = false; // Push Flags Register onto the Stack (use32) SMPDefsFlags[NN_pushfq] = false; // Push Flags Register onto the Stack (use64) SMPDefsFlags[NN_rep] = false; // Repeat String Operation SMPDefsFlags[NN_repe] = false; // Repeat String Operation while ZF=1 SMPDefsFlags[NN_repne] = false; // Repeat String Operation while ZF=0 SMPDefsFlags[NN_retn] = false; // Return Near from Procedure SMPDefsFlags[NN_retf] = false; // Return Far from Procedure SMPDefsFlags[NN_shl] = false; // Shift Logical Left SMPDefsFlags[NN_shr] = false; // Shift Logical Right SMPDefsFlags[NN_seta] = false; // Set Byte if Above (CF=0 & ZF=0) SMPDefsFlags[NN_setae] = false; // Set Byte if Above or Equal (CF=0) SMPDefsFlags[NN_setb] = false; // Set Byte if Below (CF=1) SMPDefsFlags[NN_setbe] = false; // Set Byte if Below or Equal (CF=1 | ZF=1) SMPDefsFlags[NN_setc] = false; // Set Byte if Carry (CF=1) SMPDefsFlags[NN_sete] = false; // Set Byte if Equal (ZF=1) SMPDefsFlags[NN_setg] = false; // Set Byte if Greater (ZF=0 & SF=OF) SMPDefsFlags[NN_setge] = false; // Set Byte if Greater or Equal (SF=OF) SMPDefsFlags[NN_setl] = false; // Set Byte if Less (SF!=OF) SMPDefsFlags[NN_setle] = false; // Set Byte if Less or Equal (ZF=1 | SF!=OF) SMPDefsFlags[NN_setna] = false; // Set Byte if Not Above (CF=1 | ZF=1) SMPDefsFlags[NN_setnae] = false; // Set Byte if Not Above or Equal (CF=1) SMPDefsFlags[NN_setnb] = false; // Set Byte if Not Below (CF=0) SMPDefsFlags[NN_setnbe] = false; // Set Byte if Not Below or Equal (CF=0 & ZF=0) SMPDefsFlags[NN_setnc] = false; // Set Byte if Not Carry (CF=0) SMPDefsFlags[NN_setne] = false; // Set Byte if Not Equal (ZF=0) SMPDefsFlags[NN_setng] = false; // Set Byte if Not Greater (ZF=1 | SF!=OF) SMPDefsFlags[NN_setnge] = false; // Set Byte if Not Greater or Equal (ZF=1) SMPDefsFlags[NN_setnl] = false; // Set Byte if Not Less (SF=OF) SMPDefsFlags[NN_setnle] = false; // Set Byte if Not Less or Equal (ZF=0 & SF=OF) SMPDefsFlags[NN_setno] = false; // Set Byte if Not Overflow (OF=0) SMPDefsFlags[NN_setnp] = false; // Set Byte if Not Parity (PF=0) SMPDefsFlags[NN_setns] = false; // Set Byte if Not Sign (SF=0) SMPDefsFlags[NN_setnz] = false; // Set Byte if Not Zero (ZF=0) SMPDefsFlags[NN_seto] = false; // Set Byte if Overflow (OF=1) SMPDefsFlags[NN_setp] = false; // Set Byte if Parity (PF=1) SMPDefsFlags[NN_setpe] = false; // Set Byte if Parity Even (PF=1) SMPDefsFlags[NN_setpo] = false; // Set Byte if Parity Odd (PF=0) SMPDefsFlags[NN_sets] = false; // Set Byte if Sign (SF=1) SMPDefsFlags[NN_setz] = false; // Set Byte if Zero (ZF=1) SMPDefsFlags[NN_sgdt] = false; // Store Global Descriptor Table Register SMPDefsFlags[NN_sidt] = false; // Store Interrupt Descriptor Table Register SMPDefsFlags[NN_sldt] = false; // Store Local Descriptor Table Register SMPDefsFlags[NN_str] = false; // Store Task Register SMPDefsFlags[NN_wait] = false; // Wait until BUSY# Pin is Inactive (HIGH) SMPDefsFlags[NN_xchg] = false; // Exchange Register/Memory with Register // // 486 instructions // SMPDefsFlags[NN_bswap] = false; // Swap bytes in register SMPDefsFlags[NN_invd] = false; // Invalidate Data Cache SMPDefsFlags[NN_wbinvd] = false; // Invalidate Data Cache (write changes) SMPDefsFlags[NN_invlpg] = false; // Invalidate TLB entry // // Pentium instructions // SMPDefsFlags[NN_rdmsr] = false; // Read Machine Status Register SMPDefsFlags[NN_wrmsr] = false; // Write Machine Status Register SMPDefsFlags[NN_cpuid] = false; // Get CPU ID SMPDefsFlags[NN_rdtsc] = false; // Read Time Stamp Counter // // Pentium Pro instructions // SMPDefsFlags[NN_cmova] = false; // Move if Above (CF=0 & ZF=0) SMPDefsFlags[NN_cmovb] = false; // Move if Below (CF=1) SMPDefsFlags[NN_cmovbe] = false; // Move if Below or Equal (CF=1 | ZF=1) SMPDefsFlags[NN_cmovg] = false; // Move if Greater (ZF=0 & SF=OF) SMPDefsFlags[NN_cmovge] = false; // Move if Greater or Equal (SF=OF) SMPDefsFlags[NN_cmovl] = false; // Move if Less (SF!=OF) SMPDefsFlags[NN_cmovle] = false; // Move if Less or Equal (ZF=1 | SF!=OF) SMPDefsFlags[NN_cmovnb] = false; // Move if Not Below (CF=0) SMPDefsFlags[NN_cmovno] = false; // Move if Not Overflow (OF=0) SMPDefsFlags[NN_cmovnp] = false; // Move if Not Parity (PF=0) SMPDefsFlags[NN_cmovns] = false; // Move if Not Sign (SF=0) SMPDefsFlags[NN_cmovnz] = false; // Move if Not Zero (ZF=0) SMPDefsFlags[NN_cmovo] = false; // Move if Overflow (OF=1) SMPDefsFlags[NN_cmovp] = false; // Move if Parity (PF=1) SMPDefsFlags[NN_cmovs] = false; // Move if Sign (SF=1) SMPDefsFlags[NN_cmovz] = false; // Move if Zero (ZF=1) SMPDefsFlags[NN_fcmovb] = false; // Floating Move if Below SMPDefsFlags[NN_fcmove] = false; // Floating Move if Equal SMPDefsFlags[NN_fcmovbe] = false; // Floating Move if Below or Equal SMPDefsFlags[NN_fcmovu] = false; // Floating Move if Unordered SMPDefsFlags[NN_fcmovnb] = false; // Floating Move if Not Below SMPDefsFlags[NN_fcmovne] = false; // Floating Move if Not Equal SMPDefsFlags[NN_fcmovnbe] = false; // Floating Move if Not Below or Equal SMPDefsFlags[NN_fcmovnu] = false; // Floating Move if Not Unordered SMPDefsFlags[NN_rdpmc] = false; // Read Performance Monitor Counter // // FPP instructuions // SMPDefsFlags[NN_fld] = false; // Load Real SMPDefsFlags[NN_fst] = false; // Store Real SMPDefsFlags[NN_fstp] = false; // Store Real and Pop SMPDefsFlags[NN_fxch] = false; // Exchange Registers SMPDefsFlags[NN_fild] = false; // Load Integer SMPDefsFlags[NN_fist] = false; // Store Integer SMPDefsFlags[NN_fistp] = false; // Store Integer and Pop SMPDefsFlags[NN_fbld] = false; // Load BCD SMPDefsFlags[NN_fbstp] = false; // Store BCD and Pop SMPDefsFlags[NN_fadd] = false; // Add Real SMPDefsFlags[NN_faddp] = false; // Add Real and Pop SMPDefsFlags[NN_fiadd] = false; // Add Integer SMPDefsFlags[NN_fsub] = false; // Subtract Real SMPDefsFlags[NN_fsubp] = false; // Subtract Real and Pop SMPDefsFlags[NN_fisub] = false; // Subtract Integer SMPDefsFlags[NN_fsubr] = false; // Subtract Real Reversed SMPDefsFlags[NN_fsubrp] = false; // Subtract Real Reversed and Pop SMPDefsFlags[NN_fisubr] = false; // Subtract Integer Reversed SMPDefsFlags[NN_fmul] = false; // Multiply Real SMPDefsFlags[NN_fmulp] = false; // Multiply Real and Pop SMPDefsFlags[NN_fimul] = false; // Multiply Integer SMPDefsFlags[NN_fdiv] = false; // Divide Real SMPDefsFlags[NN_fdivp] = false; // Divide Real and Pop SMPDefsFlags[NN_fidiv] = false; // Divide Integer SMPDefsFlags[NN_fdivr] = false; // Divide Real Reversed SMPDefsFlags[NN_fdivrp] = false; // Divide Real Reversed and Pop SMPDefsFlags[NN_fidivr] = false; // Divide Integer Reversed SMPDefsFlags[NN_fsqrt] = false; // Square Root SMPDefsFlags[NN_fscale] = false; // Scale: st(0) <- st(0) * 2^st(1) SMPDefsFlags[NN_fprem] = false; // Partial Remainder SMPDefsFlags[NN_frndint] = false; // Round to Integer SMPDefsFlags[NN_fxtract] = false; // Extract exponent and significand SMPDefsFlags[NN_fabs] = false; // Absolute value SMPDefsFlags[NN_fchs] = false; // Change Sign SMPDefsFlags[NN_ficom] = false; // Compare Integer SMPDefsFlags[NN_ficomp] = false; // Compare Integer and Pop SMPDefsFlags[NN_ftst] = false; // Test SMPDefsFlags[NN_fxam] = false; // Examine SMPDefsFlags[NN_fptan] = false; // Partial tangent SMPDefsFlags[NN_fpatan] = false; // Partial arctangent SMPDefsFlags[NN_f2xm1] = false; // 2^x - 1 SMPDefsFlags[NN_fyl2x] = false; // Y * lg2(X) SMPDefsFlags[NN_fyl2xp1] = false; // Y * lg2(X+1) SMPDefsFlags[NN_fldz] = false; // Load +0.0 SMPDefsFlags[NN_fld1] = false; // Load +1.0 SMPDefsFlags[NN_fldpi] = false; // Load PI=3.14... SMPDefsFlags[NN_fldl2t] = false; // Load lg2(10) SMPDefsFlags[NN_fldl2e] = false; // Load lg2(e) SMPDefsFlags[NN_fldlg2] = false; // Load lg10(2) SMPDefsFlags[NN_fldln2] = false; // Load ln(2) SMPDefsFlags[NN_finit] = false; // Initialize Processor SMPDefsFlags[NN_fninit] = false; // Initialize Processor (no wait) SMPDefsFlags[NN_fsetpm] = false; // Set Protected Mode SMPDefsFlags[NN_fldcw] = false; // Load Control Word SMPDefsFlags[NN_fstcw] = false; // Store Control Word SMPDefsFlags[NN_fnstcw] = false; // Store Control Word (no wait) SMPDefsFlags[NN_fstsw] = false; // Store Status Word to memory or AX SMPDefsFlags[NN_fnstsw] = false; // Store Status Word (no wait) to memory or AX SMPDefsFlags[NN_fclex] = false; // Clear Exceptions SMPDefsFlags[NN_fnclex] = false; // Clear Exceptions (no wait) SMPDefsFlags[NN_fstenv] = false; // Store Environment SMPDefsFlags[NN_fnstenv] = false; // Store Environment (no wait) SMPDefsFlags[NN_fldenv] = false; // Load Environment SMPDefsFlags[NN_fsave] = false; // Save State SMPDefsFlags[NN_fnsave] = false; // Save State (no wait) SMPDefsFlags[NN_frstor] = false; // Restore State SMPDefsFlags[NN_fincstp] = false; // Increment Stack Pointer SMPDefsFlags[NN_fdecstp] = false; // Decrement Stack Pointer SMPDefsFlags[NN_ffree] = false; // Free Register SMPDefsFlags[NN_fnop] = false; // No Operation SMPDefsFlags[NN_feni] = false; // (8087 only) SMPDefsFlags[NN_fneni] = false; // (no wait) (8087 only) SMPDefsFlags[NN_fdisi] = false; // (8087 only) SMPDefsFlags[NN_fndisi] = false; // (no wait) (8087 only) // // 80387 instructions // SMPDefsFlags[NN_fprem1] = false; // Partial Remainder ( < half ) SMPDefsFlags[NN_fsincos] = false; // t<-cos(st); st<-sin(st); push t SMPDefsFlags[NN_fsin] = false; // Sine SMPDefsFlags[NN_fcos] = false; // Cosine SMPDefsFlags[NN_fucom] = false; // Compare Unordered Real SMPDefsFlags[NN_fucomp] = false; // Compare Unordered Real and Pop SMPDefsFlags[NN_fucompp] = false; // Compare Unordered Real and Pop Twice // // Instructions added 28.02.96 // SMPDefsFlags[NN_svdc] = false; // Save Register and Descriptor SMPDefsFlags[NN_rsdc] = false; // Restore Register and Descriptor SMPDefsFlags[NN_svldt] = false; // Save LDTR and Descriptor SMPDefsFlags[NN_rsldt] = false; // Restore LDTR and Descriptor SMPDefsFlags[NN_svts] = false; // Save TR and Descriptor SMPDefsFlags[NN_rsts] = false; // Restore TR and Descriptor SMPDefsFlags[NN_icebp] = false; // ICE Break Point // // MMX instructions // SMPDefsFlags[NN_emms] = false; // Empty MMX state SMPDefsFlags[NN_movd] = false; // Move 32 bits SMPDefsFlags[NN_movq] = false; // Move 64 bits SMPDefsFlags[NN_packsswb] = false; // Pack with Signed Saturation (Word->Byte) SMPDefsFlags[NN_packssdw] = false; // Pack with Signed Saturation (Dword->Word) SMPDefsFlags[NN_packuswb] = false; // Pack with Unsigned Saturation (Word->Byte) SMPDefsFlags[NN_paddb] = false; // Packed Add Byte SMPDefsFlags[NN_paddw] = false; // Packed Add Word SMPDefsFlags[NN_paddd] = false; // Packed Add Dword SMPDefsFlags[NN_paddsb] = false; // Packed Add with Saturation (Byte) SMPDefsFlags[NN_paddsw] = false; // Packed Add with Saturation (Word) SMPDefsFlags[NN_paddusb] = false; // Packed Add Unsigned with Saturation (Byte) SMPDefsFlags[NN_paddusw] = false; // Packed Add Unsigned with Saturation (Word) SMPDefsFlags[NN_pand] = false; // Bitwise Logical And SMPDefsFlags[NN_pandn] = false; // Bitwise Logical And Not SMPDefsFlags[NN_pcmpeqb] = false; // Packed Compare for Equal (Byte) SMPDefsFlags[NN_pcmpeqw] = false; // Packed Compare for Equal (Word) SMPDefsFlags[NN_pcmpeqd] = false; // Packed Compare for Equal (Dword) SMPDefsFlags[NN_pcmpgtb] = false; // Packed Compare for Greater Than (Byte) SMPDefsFlags[NN_pcmpgtw] = false; // Packed Compare for Greater Than (Word) SMPDefsFlags[NN_pcmpgtd] = false; // Packed Compare for Greater Than (Dword) SMPDefsFlags[NN_pmaddwd] = false; // Packed Multiply and Add SMPDefsFlags[NN_pmulhw] = false; // Packed Multiply High SMPDefsFlags[NN_pmullw] = false; // Packed Multiply Low SMPDefsFlags[NN_por] = false; // Bitwise Logical Or SMPDefsFlags[NN_psllw] = false; // Packed Shift Left Logical (Word) SMPDefsFlags[NN_pslld] = false; // Packed Shift Left Logical (Dword) SMPDefsFlags[NN_psllq] = false; // Packed Shift Left Logical (Qword) SMPDefsFlags[NN_psraw] = false; // Packed Shift Right Arithmetic (Word) SMPDefsFlags[NN_psrad] = false; // Packed Shift Right Arithmetic (Dword) SMPDefsFlags[NN_psrlw] = false; // Packed Shift Right Logical (Word) SMPDefsFlags[NN_psrld] = false; // Packed Shift Right Logical (Dword) SMPDefsFlags[NN_psrlq] = false; // Packed Shift Right Logical (Qword) SMPDefsFlags[NN_psubb] = false; // Packed Subtract Byte SMPDefsFlags[NN_psubw] = false; // Packed Subtract Word SMPDefsFlags[NN_psubd] = false; // Packed Subtract Dword SMPDefsFlags[NN_psubsb] = false; // Packed Subtract with Saturation (Byte) SMPDefsFlags[NN_psubsw] = false; // Packed Subtract with Saturation (Word) SMPDefsFlags[NN_psubusb] = false; // Packed Subtract Unsigned with Saturation (Byte) SMPDefsFlags[NN_psubusw] = false; // Packed Subtract Unsigned with Saturation (Word) SMPDefsFlags[NN_punpckhbw] = false; // Unpack High Packed Data (Byte->Word) SMPDefsFlags[NN_punpckhwd] = false; // Unpack High Packed Data (Word->Dword) SMPDefsFlags[NN_punpckhdq] = false; // Unpack High Packed Data (Dword->Qword) SMPDefsFlags[NN_punpcklbw] = false; // Unpack Low Packed Data (Byte->Word) SMPDefsFlags[NN_punpcklwd] = false; // Unpack Low Packed Data (Word->Dword) SMPDefsFlags[NN_punpckldq] = false; // Unpack Low Packed Data (Dword->Qword) SMPDefsFlags[NN_pxor] = false; // Bitwise Logical Exclusive Or // // Undocumented Deschutes processor instructions // SMPDefsFlags[NN_fxsave] = false; // Fast save FP context SMPDefsFlags[NN_fxrstor] = false; // Fast restore FP context // Pentium II instructions SMPDefsFlags[NN_sysexit] = false; // Fast Transition from System Call Entry Point // 3DNow! instructions SMPDefsFlags[NN_pavgusb] = false; // Packed 8-bit Unsigned Integer Averaging SMPDefsFlags[NN_pfadd] = false; // Packed Floating-Point Addition SMPDefsFlags[NN_pfsub] = false; // Packed Floating-Point Subtraction SMPDefsFlags[NN_pfsubr] = false; // Packed Floating-Point Reverse Subtraction SMPDefsFlags[NN_pfacc] = false; // Packed Floating-Point Accumulate SMPDefsFlags[NN_pfcmpge] = false; // Packed Floating-Point Comparison, Greater or Equal SMPDefsFlags[NN_pfcmpgt] = false; // Packed Floating-Point Comparison, Greater SMPDefsFlags[NN_pfcmpeq] = false; // Packed Floating-Point Comparison, Equal SMPDefsFlags[NN_pfmin] = false; // Packed Floating-Point Minimum SMPDefsFlags[NN_pfmax] = false; // Packed Floating-Point Maximum SMPDefsFlags[NN_pi2fd] = false; // Packed 32-bit Integer to Floating-Point SMPDefsFlags[NN_pf2id] = false; // Packed Floating-Point to 32-bit Integer SMPDefsFlags[NN_pfrcp] = false; // Packed Floating-Point Reciprocal Approximation SMPDefsFlags[NN_pfrsqrt] = false; // Packed Floating-Point Reciprocal Square Root Approximation SMPDefsFlags[NN_pfmul] = false; // Packed Floating-Point Multiplication SMPDefsFlags[NN_pfrcpit1] = false; // Packed Floating-Point Reciprocal First Iteration Step SMPDefsFlags[NN_pfrsqit1] = false; // Packed Floating-Point Reciprocal Square Root First Iteration Step SMPDefsFlags[NN_pfrcpit2] = false; // Packed Floating-Point Reciprocal Second Iteration Step SMPDefsFlags[NN_pmulhrw] = false; // Packed Floating-Point 16-bit Integer Multiply with rounding SMPDefsFlags[NN_femms] = false; // Faster entry/exit of the MMX or floating-point state SMPDefsFlags[NN_prefetch] = false; // Prefetch at least a 32-byte line into L1 data cache SMPDefsFlags[NN_prefetchw] = false; // Prefetch processor cache line into L1 data cache (mark as modified) // Pentium III instructions SMPDefsFlags[NN_addps] = false; // Packed Single-FP Add SMPDefsFlags[NN_addss] = false; // Scalar Single-FP Add SMPDefsFlags[NN_andnps] = false; // Bitwise Logical And Not for Single-FP SMPDefsFlags[NN_andps] = false; // Bitwise Logical And for Single-FP SMPDefsFlags[NN_cmpps] = false; // Packed Single-FP Compare SMPDefsFlags[NN_cmpss] = false; // Scalar Single-FP Compare SMPDefsFlags[NN_cvtpi2ps] = false; // Packed signed INT32 to Packed Single-FP conversion SMPDefsFlags[NN_cvtps2pi] = false; // Packed Single-FP to Packed INT32 conversion SMPDefsFlags[NN_cvtsi2ss] = false; // Scalar signed INT32 to Single-FP conversion SMPDefsFlags[NN_cvtss2si] = false; // Scalar Single-FP to signed INT32 conversion SMPDefsFlags[NN_cvttps2pi] = false; // Packed Single-FP to Packed INT32 conversion (truncate) SMPDefsFlags[NN_cvttss2si] = false; // Scalar Single-FP to signed INT32 conversion (truncate) SMPDefsFlags[NN_divps] = false; // Packed Single-FP Divide SMPDefsFlags[NN_divss] = false; // Scalar Single-FP Divide SMPDefsFlags[NN_ldmxcsr] = false; // Load Streaming SIMD Extensions Technology Control/Status Register SMPDefsFlags[NN_maxps] = false; // Packed Single-FP Maximum SMPDefsFlags[NN_maxss] = false; // Scalar Single-FP Maximum SMPDefsFlags[NN_minps] = false; // Packed Single-FP Minimum SMPDefsFlags[NN_minss] = false; // Scalar Single-FP Minimum SMPDefsFlags[NN_movaps] = false; // Move Aligned Four Packed Single-FP SMPDefsFlags[NN_movhlps] = false; // Move High to Low Packed Single-FP SMPDefsFlags[NN_movhps] = false; // Move High Packed Single-FP SMPDefsFlags[NN_movlhps] = false; // Move Low to High Packed Single-FP SMPDefsFlags[NN_movlps] = false; // Move Low Packed Single-FP SMPDefsFlags[NN_movmskps] = false; // Move Mask to Register SMPDefsFlags[NN_movss] = false; // Move Scalar Single-FP SMPDefsFlags[NN_movups] = false; // Move Unaligned Four Packed Single-FP SMPDefsFlags[NN_mulps] = false; // Packed Single-FP Multiply SMPDefsFlags[NN_mulss] = false; // Scalar Single-FP Multiply SMPDefsFlags[NN_orps] = false; // Bitwise Logical OR for Single-FP Data SMPDefsFlags[NN_rcpps] = false; // Packed Single-FP Reciprocal SMPDefsFlags[NN_rcpss] = false; // Scalar Single-FP Reciprocal SMPDefsFlags[NN_rsqrtps] = false; // Packed Single-FP Square Root Reciprocal SMPDefsFlags[NN_rsqrtss] = false; // Scalar Single-FP Square Root Reciprocal SMPDefsFlags[NN_shufps] = false; // Shuffle Single-FP SMPDefsFlags[NN_sqrtps] = false; // Packed Single-FP Square Root SMPDefsFlags[NN_sqrtss] = false; // Scalar Single-FP Square Root SMPDefsFlags[NN_stmxcsr] = false; // Store Streaming SIMD Extensions Technology Control/Status Register SMPDefsFlags[NN_subps] = false; // Packed Single-FP Subtract SMPDefsFlags[NN_subss] = false; // Scalar Single-FP Subtract SMPDefsFlags[NN_unpckhps] = false; // Unpack High Packed Single-FP Data SMPDefsFlags[NN_unpcklps] = false; // Unpack Low Packed Single-FP Data SMPDefsFlags[NN_xorps] = false; // Bitwise Logical XOR for Single-FP Data SMPDefsFlags[NN_pavgb] = false; // Packed Average (Byte) SMPDefsFlags[NN_pavgw] = false; // Packed Average (Word) SMPDefsFlags[NN_pextrw] = false; // Extract Word SMPDefsFlags[NN_pinsrw] = false; // Insert Word SMPDefsFlags[NN_pmaxsw] = false; // Packed Signed Integer Word Maximum SMPDefsFlags[NN_pmaxub] = false; // Packed Unsigned Integer Byte Maximum SMPDefsFlags[NN_pminsw] = false; // Packed Signed Integer Word Minimum SMPDefsFlags[NN_pminub] = false; // Packed Unsigned Integer Byte Minimum SMPDefsFlags[NN_pmovmskb] = false; // Move Byte Mask to Integer SMPDefsFlags[NN_pmulhuw] = false; // Packed Multiply High Unsigned SMPDefsFlags[NN_psadbw] = false; // Packed Sum of Absolute Differences SMPDefsFlags[NN_pshufw] = false; // Packed Shuffle Word SMPDefsFlags[NN_maskmovq] = false; // Byte Mask write SMPDefsFlags[NN_movntps] = false; // Move Aligned Four Packed Single-FP Non Temporal SMPDefsFlags[NN_movntq] = false; // Move 64 Bits Non Temporal SMPDefsFlags[NN_prefetcht0] = false; // Prefetch to all cache levels SMPDefsFlags[NN_prefetcht1] = false; // Prefetch to all cache levels SMPDefsFlags[NN_prefetcht2] = false; // Prefetch to L2 cache SMPDefsFlags[NN_prefetchnta] = false; // Prefetch to L1 cache SMPDefsFlags[NN_sfence] = false; // Store Fence // Pentium III Pseudo instructions SMPDefsFlags[NN_cmpeqps] = false; // Packed Single-FP Compare EQ SMPDefsFlags[NN_cmpltps] = false; // Packed Single-FP Compare LT SMPDefsFlags[NN_cmpleps] = false; // Packed Single-FP Compare LE SMPDefsFlags[NN_cmpunordps] = false; // Packed Single-FP Compare UNORD SMPDefsFlags[NN_cmpneqps] = false; // Packed Single-FP Compare NOT EQ SMPDefsFlags[NN_cmpnltps] = false; // Packed Single-FP Compare NOT LT SMPDefsFlags[NN_cmpnleps] = false; // Packed Single-FP Compare NOT LE SMPDefsFlags[NN_cmpordps] = false; // Packed Single-FP Compare ORDERED SMPDefsFlags[NN_cmpeqss] = false; // Scalar Single-FP Compare EQ SMPDefsFlags[NN_cmpltss] = false; // Scalar Single-FP Compare LT SMPDefsFlags[NN_cmpless] = false; // Scalar Single-FP Compare LE SMPDefsFlags[NN_cmpunordss] = false; // Scalar Single-FP Compare UNORD SMPDefsFlags[NN_cmpneqss] = false; // Scalar Single-FP Compare NOT EQ SMPDefsFlags[NN_cmpnltss] = false; // Scalar Single-FP Compare NOT LT SMPDefsFlags[NN_cmpnless] = false; // Scalar Single-FP Compare NOT LE SMPDefsFlags[NN_cmpordss] = false; // Scalar Single-FP Compare ORDERED // AMD K7 instructions // Revisit AMD if we port to it. SMPDefsFlags[NN_pf2iw] = false; // Packed Floating-Point to Integer with Sign Extend SMPDefsFlags[NN_pfnacc] = false; // Packed Floating-Point Negative Accumulate SMPDefsFlags[NN_pfpnacc] = false; // Packed Floating-Point Mixed Positive-Negative Accumulate SMPDefsFlags[NN_pi2fw] = false; // Packed 16-bit Integer to Floating-Point SMPDefsFlags[NN_pswapd] = false; // Packed Swap Double Word // Undocumented FP instructions (thanks to norbert.juffa@adm.com) SMPDefsFlags[NN_fstp1] = false; // Alias of Store Real and Pop SMPDefsFlags[NN_fxch4] = false; // Alias of Exchange Registers SMPDefsFlags[NN_ffreep] = false; // Free Register and Pop SMPDefsFlags[NN_fxch7] = false; // Alias of Exchange Registers SMPDefsFlags[NN_fstp8] = false; // Alias of Store Real and Pop SMPDefsFlags[NN_fstp9] = false; // Alias of Store Real and Pop // Pentium 4 instructions SMPDefsFlags[NN_addpd] = false; // Add Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_addsd] = false; // Add Scalar Double-Precision Floating-Point Values SMPDefsFlags[NN_andnpd] = false; // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_andpd] = false; // Bitwise Logical AND of Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_clflush] = false; // Flush Cache Line SMPDefsFlags[NN_cmppd] = false; // Compare Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_cmpsd] = false; // Compare Scalar Double-Precision Floating-Point Values SMPDefsFlags[NN_cvtdq2pd] = false; // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values SMPDefsFlags[NN_cvtdq2ps] = false; // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_cvtpd2dq] = false; // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers SMPDefsFlags[NN_cvtpd2pi] = false; // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers SMPDefsFlags[NN_cvtpd2ps] = false; // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values SMPDefsFlags[NN_cvtpi2pd] = false; // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_cvtps2dq] = false; // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers SMPDefsFlags[NN_cvtps2pd] = false; // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_cvtsd2si] = false; // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer SMPDefsFlags[NN_cvtsd2ss] = false; // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value SMPDefsFlags[NN_cvtsi2sd] = false; // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value SMPDefsFlags[NN_cvtss2sd] = false; // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value SMPDefsFlags[NN_cvttpd2dq] = false; // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers SMPDefsFlags[NN_cvttpd2pi] = false; // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers SMPDefsFlags[NN_cvttps2dq] = false; // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers SMPDefsFlags[NN_cvttsd2si] = false; // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer SMPDefsFlags[NN_divpd] = false; // Divide Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_divsd] = false; // Divide Scalar Double-Precision Floating-Point Values SMPDefsFlags[NN_lfence] = false; // Load Fence SMPDefsFlags[NN_maskmovdqu] = false; // Store Selected Bytes of Double Quadword SMPDefsFlags[NN_maxpd] = false; // Return Maximum Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_maxsd] = false; // Return Maximum Scalar Double-Precision Floating-Point Value SMPDefsFlags[NN_mfence] = false; // Memory Fence SMPDefsFlags[NN_minpd] = false; // Return Minimum Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_minsd] = false; // Return Minimum Scalar Double-Precision Floating-Point Value SMPDefsFlags[NN_movapd] = false; // Move Aligned Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_movdq2q] = false; // Move Quadword from XMM to MMX Register SMPDefsFlags[NN_movdqa] = false; // Move Aligned Double Quadword SMPDefsFlags[NN_movdqu] = false; // Move Unaligned Double Quadword SMPDefsFlags[NN_movhpd] = false; // Move High Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_movlpd] = false; // Move Low Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_movmskpd] = false; // Extract Packed Double-Precision Floating-Point Sign Mask SMPDefsFlags[NN_movntdq] = false; // Store Double Quadword Using Non-Temporal Hint SMPDefsFlags[NN_movnti] = false; // Store Doubleword Using Non-Temporal Hint SMPDefsFlags[NN_movntpd] = false; // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint SMPDefsFlags[NN_movq2dq] = false; // Move Quadword from MMX to XMM Register SMPDefsFlags[NN_movsd] = false; // Move Scalar Double-Precision Floating-Point Values SMPDefsFlags[NN_movupd] = false; // Move Unaligned Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_mulpd] = false; // Multiply Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_mulsd] = false; // Multiply Scalar Double-Precision Floating-Point Values SMPDefsFlags[NN_orpd] = false; // Bitwise Logical OR of Double-Precision Floating-Point Values SMPDefsFlags[NN_paddq] = false; // Add Packed Quadword Integers SMPDefsFlags[NN_pause] = false; // Spin Loop Hint SMPDefsFlags[NN_pmuludq] = false; // Multiply Packed Unsigned Doubleword Integers SMPDefsFlags[NN_pshufd] = false; // Shuffle Packed Doublewords SMPDefsFlags[NN_pshufhw] = false; // Shuffle Packed High Words SMPDefsFlags[NN_pshuflw] = false; // Shuffle Packed Low Words SMPDefsFlags[NN_pslldq] = false; // Shift Double Quadword Left Logical SMPDefsFlags[NN_psrldq] = false; // Shift Double Quadword Right Logical SMPDefsFlags[NN_psubq] = false; // Subtract Packed Quadword Integers SMPDefsFlags[NN_punpckhqdq] = false; // Unpack High Data SMPDefsFlags[NN_punpcklqdq] = false; // Unpack Low Data SMPDefsFlags[NN_shufpd] = false; // Shuffle Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_sqrtpd] = false; // Compute Square Roots of Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_sqrtsd] = false; // Compute Square Rootof Scalar Double-Precision Floating-Point Value SMPDefsFlags[NN_subpd] = false; // Subtract Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_subsd] = false; // Subtract Scalar Double-Precision Floating-Point Values SMPDefsFlags[NN_unpckhpd] = false; // Unpack and Interleave High Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_unpcklpd] = false; // Unpack and Interleave Low Packed Double-Precision Floating-Point Values SMPDefsFlags[NN_xorpd] = false; // Bitwise Logical OR of Double-Precision Floating-Point Values // AMD syscall/sysret instructions NOTE: not AMD, found in Intel manual // AMD64 instructions NOTE: not AMD, found in Intel manual SMPDefsFlags[NN_swapgs] = false; // Exchange GS base with KernelGSBase MSR // New Pentium instructions (SSE3) SMPDefsFlags[NN_movddup] = false; // Move One Double-FP and Duplicate SMPDefsFlags[NN_movshdup] = false; // Move Packed Single-FP High and Duplicate SMPDefsFlags[NN_movsldup] = false; // Move Packed Single-FP Low and Duplicate // Missing AMD64 instructions NOTE: also found in Intel manual SMPDefsFlags[NN_movsxd] = false; // Move with Sign-Extend Doubleword // SSE3 instructions SMPDefsFlags[NN_addsubpd] = false; // Add /Sub packed DP FP numbers SMPDefsFlags[NN_addsubps] = false; // Add /Sub packed SP FP numbers SMPDefsFlags[NN_haddpd] = false; // Add horizontally packed DP FP numbers SMPDefsFlags[NN_haddps] = false; // Add horizontally packed SP FP numbers SMPDefsFlags[NN_hsubpd] = false; // Sub horizontally packed DP FP numbers SMPDefsFlags[NN_hsubps] = false; // Sub horizontally packed SP FP numbers SMPDefsFlags[NN_monitor] = false; // Set up a linear address range to be monitored by hardware SMPDefsFlags[NN_mwait] = false; // Wait until write-back store performed within the range specified by the MONITOR instruction SMPDefsFlags[NN_fisttp] = false; // Store ST in intXX (chop) and pop SMPDefsFlags[NN_lddqu] = false; // Load unaligned integer 128-bit // SSSE3 instructions SMPDefsFlags[NN_psignb] = false; // Packed SIGN Byte SMPDefsFlags[NN_psignw] = false; // Packed SIGN Word SMPDefsFlags[NN_psignd] = false; // Packed SIGN Doubleword SMPDefsFlags[NN_pshufb] = false; // Packed Shuffle Bytes SMPDefsFlags[NN_pmulhrsw] = false; // Packed Multiply High with Round and Scale SMPDefsFlags[NN_pmaddubsw] = false; // Multiply and Add Packed Signed and Unsigned Bytes SMPDefsFlags[NN_phsubsw] = false; // Packed Horizontal Subtract and Saturate SMPDefsFlags[NN_phaddsw] = false; // Packed Horizontal Add and Saturate SMPDefsFlags[NN_phaddw] = false; // Packed Horizontal Add Word SMPDefsFlags[NN_phaddd] = false; // Packed Horizontal Add Doubleword SMPDefsFlags[NN_phsubw] = false; // Packed Horizontal Subtract Word SMPDefsFlags[NN_phsubd] = false; // Packed Horizontal Subtract Doubleword SMPDefsFlags[NN_palignr] = false; // Packed Align Right SMPDefsFlags[NN_pabsb] = false; // Packed Absolute Value Byte SMPDefsFlags[NN_pabsw] = false; // Packed Absolute Value Word SMPDefsFlags[NN_pabsd] = false; // Packed Absolute Value Doubleword // VMX instructions SMPDefsFlags[NN_last] = false; return; } // end InitSMPDefsFlags() // Initialize the SMPUsesFlags[] array to define how we emit // optimizing annotations. void InitSMPUsesFlags(void) { // Default value is false. Few instructions use the flags. (void) memset(SMPUsesFlags, false, sizeof(SMPUsesFlags)); SMPUsesFlags[NN_null] = true; // Unknown Operation #if 1 SMPUsesFlags[NN_aaa] = true; // ASCII adjust after addition SMPUsesFlags[NN_aas] = true; // ASCII adjust after subtraction #endif SMPUsesFlags[NN_adc] = true; // Add with Carry SMPUsesFlags[NN_cmps] = true; // Compare Strings (uses DF direction flag) SMPUsesFlags[NN_into] = true; // Call to Interrupt Procedure if Overflow Flag = 1 SMPUsesFlags[NN_ja] = true; // Jump if Above (CF=0 & ZF=0) SMPUsesFlags[NN_jae] = true; // Jump if Above or Equal (CF=0) SMPUsesFlags[NN_jb] = true; // Jump if Below (CF=1) SMPUsesFlags[NN_jbe] = true; // Jump if Below or Equal (CF=1 | ZF=1) SMPUsesFlags[NN_jc] = true; // Jump if Carry (CF=1) SMPUsesFlags[NN_jcxz] = true; // Jump if CX is 0 SMPUsesFlags[NN_jecxz] = true; // Jump if ECX is 0 SMPUsesFlags[NN_jrcxz] = true; // Jump if RCX is 0 SMPUsesFlags[NN_je] = true; // Jump if Equal (ZF=1) SMPUsesFlags[NN_jg] = true; // Jump if Greater (ZF=0 & SF=OF) SMPUsesFlags[NN_jge] = true; // Jump if Greater or Equal (SF=OF) SMPUsesFlags[NN_jl] = true; // Jump if Less (SF!=OF) SMPUsesFlags[NN_jle] = true; // Jump if Less or Equal (ZF=1 | SF!=OF) SMPUsesFlags[NN_jna] = true; // Jump if Not Above (CF=1 | ZF=1) SMPUsesFlags[NN_jnae] = true; // Jump if Not Above or Equal (CF=1) SMPUsesFlags[NN_jnb] = true; // Jump if Not Below (CF=0) SMPUsesFlags[NN_jnbe] = true; // Jump if Not Below or Equal (CF=0 & ZF=0) SMPUsesFlags[NN_jnc] = true; // Jump if Not Carry (CF=0) SMPUsesFlags[NN_jne] = true; // Jump if Not Equal (ZF=0) SMPUsesFlags[NN_jng] = true; // Jump if Not Greater (ZF=1 | SF!=OF) SMPUsesFlags[NN_jnge] = true; // Jump if Not Greater or Equal (ZF=1) SMPUsesFlags[NN_jnl] = true; // Jump if Not Less (SF=OF) SMPUsesFlags[NN_jnle] = true; // Jump if Not Less or Equal (ZF=0 & SF=OF) SMPUsesFlags[NN_jno] = true; // Jump if Not Overflow (OF=0) SMPUsesFlags[NN_jnp] = true; // Jump if Not Parity (PF=0) SMPUsesFlags[NN_jns] = true; // Jump if Not Sign (SF=0) SMPUsesFlags[NN_jnz] = true; // Jump if Not Zero (ZF=0) SMPUsesFlags[NN_jo] = true; // Jump if Overflow (OF=1) SMPUsesFlags[NN_jp] = true; // Jump if Parity (PF=1) SMPUsesFlags[NN_jpe] = true; // Jump if Parity Even (PF=1) SMPUsesFlags[NN_jpo] = true; // Jump if Parity Odd (PF=0) SMPUsesFlags[NN_js] = true; // Jump if Sign (SF=1) SMPUsesFlags[NN_jz] = true; // Jump if Zero (ZF=1) SMPUsesFlags[NN_lahf] = true; // Load Flags into AH Register SMPUsesFlags[NN_loopwe] = true; // Loop while CX != 0 and ZF=1 SMPUsesFlags[NN_loope] = true; // Loop while rCX != 0 and ZF=1 SMPUsesFlags[NN_loopde] = true; // Loop while ECX != 0 and ZF=1 SMPUsesFlags[NN_loopqe] = true; // Loop while RCX != 0 and ZF=1 SMPUsesFlags[NN_loopwne] = true; // Loop while CX != 0 and ZF=0 SMPUsesFlags[NN_loopne] = true; // Loop while rCX != 0 and ZF=0 SMPUsesFlags[NN_loopdne] = true; // Loop while ECX != 0 and ZF=0 SMPUsesFlags[NN_loopqne] = true; // Loop while RCX != 0 and ZF=0 SMPUsesFlags[NN_pushfw] = true; // Push Flags Register onto the Stack SMPUsesFlags[NN_pushf] = true; // Push Flags Register onto the Stack SMPUsesFlags[NN_pushfd] = true; // Push Flags Register onto the Stack (use32) SMPUsesFlags[NN_pushfq] = true; // Push Flags Register onto the Stack (use64) SMPUsesFlags[NN_repe] = true; // Repeat String Operation while ZF=1 SMPUsesFlags[NN_repne] = true; // Repeat String Operation while ZF=0 #if 0 SMPUsesFlags[NN_sahf] = true; // Store AH into Flags Register SMPUsesFlags[NN_shl] = true; // Shift Logical Left SMPUsesFlags[NN_shr] = true; // Shift Logical Right #endif SMPUsesFlags[NN_sbb] = true; // Integer Subtraction with Borrow SMPUsesFlags[NN_scas] = true; // Compare String (uses DF direction flag) SMPUsesFlags[NN_seta] = true; // Set Byte if Above (CF=0 & ZF=0) SMPUsesFlags[NN_setae] = true; // Set Byte if Above or Equal (CF=0) SMPUsesFlags[NN_setb] = true; // Set Byte if Below (CF=1) SMPUsesFlags[NN_setbe] = true; // Set Byte if Below or Equal (CF=1 | ZF=1) SMPUsesFlags[NN_setc] = true; // Set Byte if Carry (CF=1) SMPUsesFlags[NN_sete] = true; // Set Byte if Equal (ZF=1) SMPUsesFlags[NN_setg] = true; // Set Byte if Greater (ZF=0 & SF=OF) SMPUsesFlags[NN_setge] = true; // Set Byte if Greater or Equal (SF=OF) SMPUsesFlags[NN_setl] = true; // Set Byte if Less (SF!=OF) SMPUsesFlags[NN_setle] = true; // Set Byte if Less or Equal (ZF=1 | SF!=OF) SMPUsesFlags[NN_setna] = true; // Set Byte if Not Above (CF=1 | ZF=1) SMPUsesFlags[NN_setnae] = true; // Set Byte if Not Above or Equal (CF=1) SMPUsesFlags[NN_setnb] = true; // Set Byte if Not Below (CF=0) SMPUsesFlags[NN_setnbe] = true; // Set Byte if Not Below or Equal (CF=0 & ZF=0) SMPUsesFlags[NN_setnc] = true; // Set Byte if Not Carry (CF=0) SMPUsesFlags[NN_setne] = true; // Set Byte if Not Equal (ZF=0) SMPUsesFlags[NN_setng] = true; // Set Byte if Not Greater (ZF=1 | SF!=OF) SMPUsesFlags[NN_setnge] = true; // Set Byte if Not Greater or Equal (ZF=1) SMPUsesFlags[NN_setnl] = true; // Set Byte if Not Less (SF=OF) SMPUsesFlags[NN_setnle] = true; // Set Byte if Not Less or Equal (ZF=0 & SF=OF) SMPUsesFlags[NN_setno] = true; // Set Byte if Not Overflow (OF=0) SMPUsesFlags[NN_setnp] = true; // Set Byte if Not Parity (PF=0) SMPUsesFlags[NN_setns] = true; // Set Byte if Not Sign (SF=0) SMPUsesFlags[NN_setnz] = true; // Set Byte if Not Zero (ZF=0) SMPUsesFlags[NN_seto] = true; // Set Byte if Overflow (OF=1) SMPUsesFlags[NN_setp] = true; // Set Byte if Parity (PF=1) SMPUsesFlags[NN_setpe] = true; // Set Byte if Parity Even (PF=1) SMPUsesFlags[NN_setpo] = true; // Set Byte if Parity Odd (PF=0) SMPUsesFlags[NN_sets] = true; // Set Byte if Sign (SF=1) SMPUsesFlags[NN_setz] = true; // Set Byte if Zero (ZF=1) SMPUsesFlags[NN_stos] = true; // Store String // // 486 instructions // // // Pentium instructions // SMPUsesFlags[NN_cpuid] = true; // Get CPU ID #if 0 SMPUsesFlags[NN_cmpxchg8b] = true; // Compare and Exchange Eight Bytes #endif // // Pentium Pro instructions // SMPUsesFlags[NN_cmova] = true; // Move if Above (CF=0 & ZF=0) SMPUsesFlags[NN_cmovb] = true; // Move if Below (CF=1) SMPUsesFlags[NN_cmovbe] = true; // Move if Below or Equal (CF=1 | ZF=1) SMPUsesFlags[NN_cmovg] = true; // Move if Greater (ZF=0 & SF=OF) SMPUsesFlags[NN_cmovge] = true; // Move if Greater or Equal (SF=OF) SMPUsesFlags[NN_cmovl] = true; // Move if Less (SF!=OF) SMPUsesFlags[NN_cmovle] = true; // Move if Less or Equal (ZF=1 | SF!=OF) SMPUsesFlags[NN_cmovnb] = true; // Move if Not Below (CF=0) SMPUsesFlags[NN_cmovno] = true; // Move if Not Overflow (OF=0) SMPUsesFlags[NN_cmovnp] = true; // Move if Not Parity (PF=0) SMPUsesFlags[NN_cmovns] = true; // Move if Not Sign (SF=0) SMPUsesFlags[NN_cmovnz] = true; // Move if Not Zero (ZF=0) SMPUsesFlags[NN_cmovo] = true; // Move if Overflow (OF=1) SMPUsesFlags[NN_cmovp] = true; // Move if Parity (PF=1) SMPUsesFlags[NN_cmovs] = true; // Move if Sign (SF=1) SMPUsesFlags[NN_cmovz] = true; // Move if Zero (ZF=1) SMPUsesFlags[NN_fcmovb] = true; // Floating Move if Below SMPUsesFlags[NN_fcmove] = true; // Floating Move if Equal SMPUsesFlags[NN_fcmovbe] = true; // Floating Move if Below or Equal SMPUsesFlags[NN_fcmovu] = true; // Floating Move if Unordered SMPUsesFlags[NN_fcmovnb] = true; // Floating Move if Not Below SMPUsesFlags[NN_fcmovne] = true; // Floating Move if Not Equal SMPUsesFlags[NN_fcmovnbe] = true; // Floating Move if Not Below or Equal SMPUsesFlags[NN_fcmovnu] = true; // Floating Move if Not Unordered // // FPP instructions // // // 80387 instructions // // // Instructions added 28.02.96 // SMPUsesFlags[NN_setalc] = true; // Set AL to Carry Flag // // MMX instructions // // // Undocumented Deschutes processor instructions // // Pentium II instructions // 3DNow! instructions // Pentium III instructions // Pentium III Pseudo instructions // AMD K7 instructions // Revisit AMD if we port to it. // Undocumented FP instructions (thanks to norbert.juffa@adm.com) // Pentium 4 instructions // AMD syscall/sysret instructions NOTE: not AMD, found in Intel manual // AMD64 instructions NOTE: not AMD, found in Intel manual // New Pentium instructions (SSE3) // Missing AMD64 instructions NOTE: also found in Intel manual // SSE3 instructions // SSSE3 instructions // VMX instructions SMPUsesFlags[NN_last] = false; return; } // end InitSMPUsesFlags()