// // SMPStaticAnalyzer.cpp // // This plugin performs the static analyses needed for the SMP project // (Software Memory Protection). // #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 <ua.hpp> #include "SMPStaticAnalyzer.h" #include "SMPDataFlowAnalysis.h" // Set to 1 for debugging output #define SMP_DEBUG 1 #define SMP_DEBUG2 1 // verbose #define SMP_DEBUG3 0 // verbose #define SMP_DEBUG_MEM 0 // print memory operands #define SMP_DEBUG_TYPE0 0 // Output instr info for OptType = 0 // Set to 1 when doing a binary search using SMP_DEBUG_COUNT to find // which function is causing a problem. #define SMP_BINARY_DEBUG 0 #define SMP_DEBUG_COUNT 356 // How many funcs to process in problem search int FuncsProcessed = 0; // Define optimization categories for instructions. int OptCategory[NN_last+1]; // Initialize the OptCategory[] array. void InitOptCategory(void); // Keep statistics on how many instructions we saw in each optimization // category, and how many optimizing annotations were emitted for // each category. int OptCount[LAST_OPT_CATEGORY + 1]; int AnnotationCount[LAST_OPT_CATEGORY + 1]; static 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" }; // The types of data objects based on their first operand flags. static char *DataTypes[] = { "VOID", "NUMHEX", "NUMDEC", "CHAR", "SEG", "OFFSET", "NUMBIN", "NUMOCT", "ENUM", "FORCED", "STRUCTOFFSET", "STACKVAR", "NUMFLOAT", "UNKNOWN", "UNKNOWN", "UNKNOWN", 0}; void IDAP_run(int); static int idaapi idp_callback(void *, int event_id, va_list va) { if (event_id == ph.auto_empty_finally) { // IDA analysis is done IDAP_run(0); qexit(0); } return 0; } int IDAP_init(void) { #if 0 // We are now calling from the SMP.idc script. // Skip this plugin if it was not specified by the user on the // command line. if (get_plugin_options("SMPStaticAnalyzer") == NULL) { msg("IDAP_init point 2.\n"); return PLUGIN_SKIP; } #endif // Ensure correct working environment. if ((inf.filetype != f_ELF) && (inf.filetype != f_PE)) { error("Executable format must be PE or ELF."); return PLUGIN_SKIP; } if (ph.id != PLFM_386) { error("Processor must be x86."); return PLUGIN_SKIP; } hook_to_notification_point(HT_IDP, idp_callback, NULL); InitOptCategory(); InitDFACategory(); return PLUGIN_KEEP; } // end of IDAP_init void IDAP_term(void) { unhook_from_notification_point(HT_IDP, idp_callback, NULL); return; } void IDAP_run(int arg) { segment_t *seg; char buf[MAXSTR]; ea_t ea; flags_t ObjFlags; bool ReadOnlyFlag; FILE *SymsFile; char FuncName[MAXSTR]; SMPFunction *CurrFunc = NULL; bool FuncsDumped = false; #if SMP_DEBUG msg("Beginning IDAP_run.\n"); #endif // Open the output file. SymsFile = qfopen("SMP.annot", "w"); if (NULL == SymsFile) { error("FATAL: Cannot open output file SMP.annot\n"); return; } (void) memset(OptCount, 0, sizeof(OptCount)); (void) memset(AnnotationCount, 0, sizeof(AnnotationCount)); // First, examine the data segments and print info about static // data, such as name/address/size. Do the same for functions in // code segments. // Loop through all segments. for (int SegIndex = 0; SegIndex < get_segm_qty(); ++SegIndex) { seg = getnseg(SegIndex); // We are only interested in the data segments of type // SEG_DATA, SEG_BSS and SEG_COMM. if ((seg->type == SEG_DATA) || (seg->type == SEG_BSS) || (seg->type == SEG_COMM)) { // Loop through each of the segments we are interested in, // examining all data objects (effective addresses). ReadOnlyFlag = ((seg->perm & SEGPERM_READ) && (!(seg->perm & SEGPERM_WRITE))); #if SMP_DEBUG msg("Starting data segment of type %d\n", seg->type); if (ReadOnlyFlag) { msg("Read-only data segment.\n"); } #endif ea = seg->startEA; while (ea < seg->endEA) { ObjFlags = get_flags_novalue(ea); // Only process head bytes of data objects, i.e. isData(). if (isData(ObjFlags)) { // Compute the size of the data object. ea_t NextEA = ea; do { NextEA = nextaddr(NextEA); } while ((NextEA < seg->endEA) && (!isHead(get_flags_novalue(NextEA)))); size_t ObjSize = (size_t) (NextEA - ea); // Get the data object name using its address. char *TrueName = get_true_name(BADADDR, ea, buf, sizeof(buf)); if (NULL == TrueName) { qstrncpy(buf, "SMP_dummy0", 12); } // Output the name, address, size, and type info. if (ReadOnlyFlag) { qfprintf(SymsFile, "%x %d OBJECT GLOBAL %s %s RO\n", ea, ObjSize, buf, DataTypes[get_optype_flags0(ObjFlags) >> 20]); } else { qfprintf(SymsFile, "%x %d OBJECT GLOBAL %s %s RW\n", ea, ObjSize, buf, DataTypes[get_optype_flags0(ObjFlags) >> 20]); } // Move on to next data object ea = NextEA; } else { ea = nextaddr(ea); } } // end while (ea < seg->endEA) } // end if (seg->type == SEG_DATA ...) else if (seg->type == SEG_CODE) { #if SMP_DEBUG msg("Starting code segment.\n"); #endif #if SMP_DEBUG2 if (!FuncsDumped) { for (size_t FuncIndex = 0; FuncIndex < get_func_qty(); ++FuncIndex) { func_t *FuncInfo = getn_func(FuncIndex); get_func_name(FuncInfo->startEA, FuncName, MAXSTR-1); msg("FuncName dump: %s\n", FuncName); } for (size_t ChunkIndex = 0; ChunkIndex < get_fchunk_qty(); ++ChunkIndex) { func_t *ChunkInfo = getn_fchunk((int) ChunkIndex); get_func_name(ChunkInfo->startEA, FuncName, MAXSTR-1); if (0 == strcmp(FuncName, "fflush")) { msg("fflush chunk: address %x", ChunkInfo->startEA); if (is_func_tail(ChunkInfo)) msg(" TAIL\n"); else msg(" ENTRY\n"); } else if ((0x81498f0 < ChunkInfo->startEA) && (0x8149cb6 > ChunkInfo->startEA)) { msg("Missing fflush chunk: %s %x", FuncName, ChunkInfo->startEA); if (is_func_tail(ChunkInfo)) msg(" TAIL\n"); else msg(" ENTRY\n"); } } // end for (size_t ChunkIndex = ...) func_t *FuncInfo = get_func(0x8149be0); if (NULL == FuncInfo) msg("No func at 0x8149be0\n"); else { get_func_name(FuncInfo->startEA, FuncName, MAXSTR-1); msg("Func at 0x8149be0: %s\n", FuncName); } FuncsDumped = true; } #endif for (size_t FuncIndex = 0; FuncIndex < get_func_qty(); ++FuncIndex) { func_t *FuncInfo = getn_func(FuncIndex); // If more than one SEG_CODE segment, only process // functions within the current segment. Don't know // if multiple code segments are possible, but // get_func_qty() is for the whole program, not just // the current segment. if (FuncInfo->startEA < seg->startEA) { // Already processed this func in earlier segment. continue; } else if (FuncInfo->startEA >= seg->endEA) { #if SMP_DEBUG2 get_func_name(FuncInfo->startEA, FuncName, MAXSTR-1); msg("Skipping function until we reach its segment: %s\n", FuncName); #endif break; } // Create a function object. if (NULL != CurrFunc){ delete CurrFunc; CurrFunc = NULL; } CurrFunc = new SMPFunction(FuncInfo); #if SMP_BINARY_DEBUG if (FuncsProcessed++ > SMP_DEBUG_COUNT) { get_func_name(FuncInfo->startEA, FuncName, MAXSTR-1); msg("Debug termination. FuncName = %s \n", FuncName); msg("Function startEA: %x endEA: %x \n", FuncInfo->startEA, FuncInfo->endEA); break; } #endif #if SMP_BINARY_DEBUG if (FuncsProcessed > SMP_DEBUG_COUNT) { get_func_name(FuncInfo->startEA, FuncName, MAXSTR-1); msg("Final FuncName: %s \n", FuncName); SMPBinaryDebug = true; } #endif CurrFunc->Analyze(); CurrFunc->EmitAnnotations(SymsFile); delete CurrFunc; CurrFunc = NULL; } // end for (size_t FuncIndex = 0; ...) } // end else if (seg->type === SEG_CODE) else { #if SMP_DEBUG msg("Not processing segment of type %d \n", seg->type); #endif } } // end for (int SegIndex = 0; ... ) for (int OptType = 0; OptType <= LAST_OPT_CATEGORY; ++OptType) { msg("Optimization Category Count %d: %d Annotations: %d\n", OptType, OptCount[OptType], AnnotationCount[OptType]); } qfclose(SymsFile); return; } // end IDAP_run() char IDAP_comment[] = "UVa SMP/NICECAP Project"; char IDAP_help[] = "Good luck"; char IDAP_name[] = "SMPStaticAnalyzer"; char IDAP_hotkey[] = "Alt-J"; plugin_t PLUGIN = { IDP_INTERFACE_VERSION, 0, IDAP_init, IDAP_term, IDAP_run, IDAP_comment, IDAP_help, IDAP_name, IDAP_hotkey }; // Initialize the OptCategory[] array to define how we emit // optimizing annotations. void InitOptCategory(void) { // Default category is 0, no optimization without knowing context. (void) memset(OptCategory, 0, sizeof(OptCategory)); // Category 1 instructions never need updating of their memory // metadata by the Memory Monitor SDT. Currently, this is because // these instructions only have effects on registers we do not maintain // metadata for, such as the EIP and the FLAGS, e.g. jumps, compares. // Category 2 instructions always have a result type of 'n' (number). // Category 3 instructions have a result type of 'n' (number) // whenever the second source operand is an immediate operand of type 'n'. // NOTE: MOV is only current example, and this will take some thought if // other examples arise. // Category 4 instructions have a result type identical to the 1st source operand type. // NOTE: This is currently set for single-operand instructions such as // INC, DEC. As a result, these are treated pretty much as if // they were category 1 instructions, as there is no metadata update, // unless the operand is a memory operand (i.e. mem or [reg]). // If new instructions are added to this category that are not single // operand and do require some updating, the category should be split. // Category 5 instructions have a result type identical to the 1st source operand // type whenever the 2nd source operand is an operand of type 'n'. // If the destination is memory, metadata still needs to be checked; if // not, no metadata check is needed, so it becomes category 1. // Category 6 instructions always have a result type of 'p' (pointer). // Category 7 instructions are category 2 instructions with two destinations, // such as multiply and divide instructions that affect EDX:EAX. There are // forms of these instructions that only have one destination, so they have // to be distinguished via the operand info. // Category 8 instructions implicitly write a numeric value to EDX:EAX, but // EDX and EAX are not listed as operands. RDTSC, RDPMC, RDMSR, and other // instructions that copy machine registers into EDX:EAX are category 8. // Category 9 instructions are floating point instructions that either // have a memory destination (treat as category 0) or a FP reg destination // (treat as category 1). // NOTE: The Memory Monitor SDT needs just three categories, corresponding // to categories 0, 1, and all others. For all categories > 1, the // annotation should tell the SDT exactly how to update its metadata. // For example, a division instruction will write type 'n' (NUM) as // the metadata for result registers EDX:EAX. So, the annotation should // list 'n', EDX, EAX, and a terminator of '/'. CWD (convert word to // doubleword) should have a list of 'n', EAX, '/'. OptCategory[NN_null] = 0; // Unknown Operation OptCategory[NN_aaa] = 2; // ASCII Adjust after Addition OptCategory[NN_aad] = 2; // ASCII Adjust AX before Division OptCategory[NN_aam] = 2; // ASCII Adjust AX after Multiply OptCategory[NN_aas] = 2; // ASCII Adjust AL after Subtraction OptCategory[NN_adc] = 5; // Add with Carry OptCategory[NN_add] = 5; // Add OptCategory[NN_and] = 0; // Logical AND OptCategory[NN_arpl] = 1; // Adjust RPL Field of Selector OptCategory[NN_bound] = 1; // Check Array Index Against Bounds OptCategory[NN_bsf] = 2; // Bit Scan Forward OptCategory[NN_bsr] = 2; // Bit Scan Reverse OptCategory[NN_bt] = 2; // Bit Test OptCategory[NN_btc] = 2; // Bit Test and Complement OptCategory[NN_btr] = 2; // Bit Test and Reset OptCategory[NN_bts] = 2; // Bit Test and Set OptCategory[NN_call] = 1; // Call Procedure OptCategory[NN_callfi] = 1; // Indirect Call Far Procedure OptCategory[NN_callni] = 1; // Indirect Call Near Procedure OptCategory[NN_cbw] = 2; // AL -> AX (with sign) ** No ops? OptCategory[NN_cwde] = 2; // AX -> EAX (with sign) ** OptCategory[NN_cdqe] = 2; // EAX -> RAX (with sign) ** OptCategory[NN_clc] = 1; // Clear Carry Flag OptCategory[NN_cld] = 1; // Clear Direction Flag OptCategory[NN_cli] = 1; // Clear Interrupt Flag OptCategory[NN_clts] = 1; // Clear Task-Switched Flag in CR0 OptCategory[NN_cmc] = 1; // Complement Carry Flag OptCategory[NN_cmp] = 1; // Compare Two Operands OptCategory[NN_cmps] = 1; // Compare Strings OptCategory[NN_cwd] = 2; // AX -> DX:AX (with sign) OptCategory[NN_cdq] = 2; // EAX -> EDX:EAX (with sign) OptCategory[NN_cqo] = 2; // RAX -> RDX:RAX (with sign) OptCategory[NN_daa] = 2; // Decimal Adjust AL after Addition OptCategory[NN_das] = 2; // Decimal Adjust AL after Subtraction OptCategory[NN_dec] = 4; // Decrement by 1 OptCategory[NN_div] = 7; // Unsigned Divide OptCategory[NN_enterw] = 0; // Make Stack Frame for Procedure Parameters ** OptCategory[NN_enter] = 0; // Make Stack Frame for Procedure Parameters ** OptCategory[NN_enterd] = 0; // Make Stack Frame for Procedure Parameters ** OptCategory[NN_enterq] = 0; // Make Stack Frame for Procedure Parameters ** OptCategory[NN_hlt] = 0; // Halt OptCategory[NN_idiv] = 7; // Signed Divide OptCategory[NN_imul] = 7; // Signed Multiply OptCategory[NN_in] = 0; // Input from Port ** OptCategory[NN_inc] = 4; // Increment by 1 OptCategory[NN_ins] = 2; // Input Byte(s) from Port to String ** OptCategory[NN_int] = 1; // Call to Interrupt Procedure OptCategory[NN_into] = 1; // Call to Interrupt Procedure if Overflow Flag = 1 OptCategory[NN_int3] = 1; // Trap to Debugger OptCategory[NN_iretw] = 1; // Interrupt Return OptCategory[NN_iret] = 1; // Interrupt Return OptCategory[NN_iretd] = 1; // Interrupt Return (use32) OptCategory[NN_iretq] = 1; // Interrupt Return (use64) OptCategory[NN_ja] = 1; // Jump if Above (CF=0 & ZF=0) OptCategory[NN_jae] = 1; // Jump if Above or Equal (CF=0) OptCategory[NN_jb] = 1; // Jump if Below (CF=1) OptCategory[NN_jbe] = 1; // Jump if Below or Equal (CF=1 | ZF=1) OptCategory[NN_jc] = 1; // Jump if Carry (CF=1) OptCategory[NN_jcxz] = 1; // Jump if CX is 0 OptCategory[NN_jecxz] = 1; // Jump if ECX is 0 OptCategory[NN_jrcxz] = 1; // Jump if RCX is 0 OptCategory[NN_je] = 1; // Jump if Equal (ZF=1) OptCategory[NN_jg] = 1; // Jump if Greater (ZF=0 & SF=OF) OptCategory[NN_jge] = 1; // Jump if Greater or Equal (SF=OF) OptCategory[NN_jl] = 1; // Jump if Less (SF!=OF) OptCategory[NN_jle] = 1; // Jump if Less or Equal (ZF=1 | SF!=OF) OptCategory[NN_jna] = 1; // Jump if Not Above (CF=1 | ZF=1) OptCategory[NN_jnae] = 1; // Jump if Not Above or Equal (CF=1) OptCategory[NN_jnb] = 1; // Jump if Not Below (CF=0) OptCategory[NN_jnbe] = 1; // Jump if Not Below or Equal (CF=0 & ZF=0) OptCategory[NN_jnc] = 1; // Jump if Not Carry (CF=0) OptCategory[NN_jne] = 1; // Jump if Not Equal (ZF=0) OptCategory[NN_jng] = 1; // Jump if Not Greater (ZF=1 | SF!=OF) OptCategory[NN_jnge] = 1; // Jump if Not Greater or Equal (ZF=1) OptCategory[NN_jnl] = 1; // Jump if Not Less (SF=OF) OptCategory[NN_jnle] = 1; // Jump if Not Less or Equal (ZF=0 & SF=OF) OptCategory[NN_jno] = 1; // Jump if Not Overflow (OF=0) OptCategory[NN_jnp] = 1; // Jump if Not Parity (PF=0) OptCategory[NN_jns] = 1; // Jump if Not Sign (SF=0) OptCategory[NN_jnz] = 1; // Jump if Not Zero (ZF=0) OptCategory[NN_jo] = 1; // Jump if Overflow (OF=1) OptCategory[NN_jp] = 1; // Jump if Parity (PF=1) OptCategory[NN_jpe] = 1; // Jump if Parity Even (PF=1) OptCategory[NN_jpo] = 1; // Jump if Parity Odd (PF=0) OptCategory[NN_js] = 1; // Jump if Sign (SF=1) OptCategory[NN_jz] = 1; // Jump if Zero (ZF=1) OptCategory[NN_jmp] = 1; // Jump OptCategory[NN_jmpfi] = 1; // Indirect Far Jump OptCategory[NN_jmpni] = 1; // Indirect Near Jump OptCategory[NN_jmpshort] = 1; // Jump Short (not used) OptCategory[NN_lahf] = 2; // Load Flags into AH Register OptCategory[NN_lar] = 2; // Load Access Rights Byte OptCategory[NN_lea] = 0; // Load Effective Address ** OptCategory[NN_leavew] = 0; // High Level Procedure Exit ** OptCategory[NN_leave] = 0; // High Level Procedure Exit ** OptCategory[NN_leaved] = 0; // High Level Procedure Exit ** OptCategory[NN_leaveq] = 0; // High Level Procedure Exit ** OptCategory[NN_lgdt] = 0; // Load Global Descriptor Table Register OptCategory[NN_lidt] = 0; // Load Interrupt Descriptor Table Register OptCategory[NN_lgs] = 6; // Load Full Pointer to GS:xx OptCategory[NN_lss] = 6; // Load Full Pointer to SS:xx OptCategory[NN_lds] = 6; // Load Full Pointer to DS:xx OptCategory[NN_les] = 6; // Load Full Pointer to ES:xx OptCategory[NN_lfs] = 6; // Load Full Pointer to FS:xx OptCategory[NN_lldt] = 0; // Load Local Descriptor Table Register OptCategory[NN_lmsw] = 1; // Load Machine Status Word OptCategory[NN_lock] = 1; // Assert LOCK# Signal Prefix OptCategory[NN_lods] = 0; // Load String OptCategory[NN_loopw] = 1; // Loop while ECX != 0 OptCategory[NN_loop] = 1; // Loop while CX != 0 OptCategory[NN_loopd] = 1; // Loop while ECX != 0 OptCategory[NN_loopq] = 1; // Loop while RCX != 0 OptCategory[NN_loopwe] = 1; // Loop while CX != 0 and ZF=1 OptCategory[NN_loope] = 1; // Loop while rCX != 0 and ZF=1 OptCategory[NN_loopde] = 1; // Loop while ECX != 0 and ZF=1 OptCategory[NN_loopqe] = 1; // Loop while RCX != 0 and ZF=1 OptCategory[NN_loopwne] = 1; // Loop while CX != 0 and ZF=0 OptCategory[NN_loopne] = 1; // Loop while rCX != 0 and ZF=0 OptCategory[NN_loopdne] = 1; // Loop while ECX != 0 and ZF=0 OptCategory[NN_loopqne] = 1; // Loop while RCX != 0 and ZF=0 OptCategory[NN_lsl] = 6; // Load Segment Limit OptCategory[NN_ltr] = 1; // Load Task Register OptCategory[NN_mov] = 3; // Move Data OptCategory[NN_movsp] = 3; // Move to/from Special Registers OptCategory[NN_movs] = 0; // Move Byte(s) from String to String OptCategory[NN_movsx] = 3; // Move with Sign-Extend OptCategory[NN_movzx] = 3; // Move with Zero-Extend OptCategory[NN_mul] = 7; // Unsigned Multiplication of AL or AX OptCategory[NN_neg] = 2; // Two's Complement Negation OptCategory[NN_nop] = 1; // No Operation OptCategory[NN_not] = 2; // One's Complement Negation OptCategory[NN_or] = 0; // Logical Inclusive OR OptCategory[NN_out] = 0; // Output to Port OptCategory[NN_outs] = 0; // Output Byte(s) to Port OptCategory[NN_pop] = 0; // Pop a word from the Stack OptCategory[NN_popaw] = 0; // Pop all General Registers OptCategory[NN_popa] = 0; // Pop all General Registers OptCategory[NN_popad] = 0; // Pop all General Registers (use32) OptCategory[NN_popaq] = 0; // Pop all General Registers (use64) OptCategory[NN_popfw] = 1; // Pop Stack into Flags Register ** OptCategory[NN_popf] = 1; // Pop Stack into Flags Register ** OptCategory[NN_popfd] = 1; // Pop Stack into Eflags Register ** OptCategory[NN_popfq] = 1; // Pop Stack into Rflags Register ** OptCategory[NN_push] = 0; // Push Operand onto the Stack OptCategory[NN_pushaw] = 0; // Push all General Registers OptCategory[NN_pusha] = 0; // Push all General Registers OptCategory[NN_pushad] = 0; // Push all General Registers (use32) OptCategory[NN_pushaq] = 0; // Push all General Registers (use64) OptCategory[NN_pushfw] = 0; // Push Flags Register onto the Stack OptCategory[NN_pushf] = 0; // Push Flags Register onto the Stack OptCategory[NN_pushfd] = 0; // Push Flags Register onto the Stack (use32) OptCategory[NN_pushfq] = 0; // Push Flags Register onto the Stack (use64) OptCategory[NN_rcl] = 2; // Rotate Through Carry Left OptCategory[NN_rcr] = 2; // Rotate Through Carry Right OptCategory[NN_rol] = 2; // Rotate Left OptCategory[NN_ror] = 2; // Rotate Right OptCategory[NN_rep] = 0; // Repeat String Operation OptCategory[NN_repe] = 0; // Repeat String Operation while ZF=1 OptCategory[NN_repne] = 0; // Repeat String Operation while ZF=0 OptCategory[NN_retn] = 0; // Return Near from Procedure OptCategory[NN_retf] = 0; // Return Far from Procedure OptCategory[NN_sahf] = 1; // Store AH into Flags Register OptCategory[NN_sal] = 2; // Shift Arithmetic Left OptCategory[NN_sar] = 2; // Shift Arithmetic Right OptCategory[NN_shl] = 2; // Shift Logical Left OptCategory[NN_shr] = 2; // Shift Logical Right OptCategory[NN_sbb] = 5; // Integer Subtraction with Borrow OptCategory[NN_scas] = 1; // Compare String OptCategory[NN_seta] = 2; // Set Byte if Above (CF=0 & ZF=0) OptCategory[NN_setae] = 2; // Set Byte if Above or Equal (CF=0) OptCategory[NN_setb] = 2; // Set Byte if Below (CF=1) OptCategory[NN_setbe] = 2; // Set Byte if Below or Equal (CF=1 | ZF=1) OptCategory[NN_setc] = 2; // Set Byte if Carry (CF=1) OptCategory[NN_sete] = 2; // Set Byte if Equal (ZF=1) OptCategory[NN_setg] = 2; // Set Byte if Greater (ZF=0 & SF=OF) OptCategory[NN_setge] = 2; // Set Byte if Greater or Equal (SF=OF) OptCategory[NN_setl] = 2; // Set Byte if Less (SF!=OF) OptCategory[NN_setle] = 2; // Set Byte if Less or Equal (ZF=1 | SF!=OF) OptCategory[NN_setna] = 2; // Set Byte if Not Above (CF=1 | ZF=1) OptCategory[NN_setnae] = 2; // Set Byte if Not Above or Equal (CF=1) OptCategory[NN_setnb] = 2; // Set Byte if Not Below (CF=0) OptCategory[NN_setnbe] = 2; // Set Byte if Not Below or Equal (CF=0 & ZF=0) OptCategory[NN_setnc] = 2; // Set Byte if Not Carry (CF=0) OptCategory[NN_setne] = 2; // Set Byte if Not Equal (ZF=0) OptCategory[NN_setng] = 2; // Set Byte if Not Greater (ZF=1 | SF!=OF) OptCategory[NN_setnge] = 2; // Set Byte if Not Greater or Equal (ZF=1) OptCategory[NN_setnl] = 2; // Set Byte if Not Less (SF=OF) OptCategory[NN_setnle] = 2; // Set Byte if Not Less or Equal (ZF=0 & SF=OF) OptCategory[NN_setno] = 2; // Set Byte if Not Overflow (OF=0) OptCategory[NN_setnp] = 2; // Set Byte if Not Parity (PF=0) OptCategory[NN_setns] = 2; // Set Byte if Not Sign (SF=0) OptCategory[NN_setnz] = 2; // Set Byte if Not Zero (ZF=0) OptCategory[NN_seto] = 2; // Set Byte if Overflow (OF=1) OptCategory[NN_setp] = 2; // Set Byte if Parity (PF=1) OptCategory[NN_setpe] = 2; // Set Byte if Parity Even (PF=1) OptCategory[NN_setpo] = 2; // Set Byte if Parity Odd (PF=0) OptCategory[NN_sets] = 2; // Set Byte if Sign (SF=1) OptCategory[NN_setz] = 2; // Set Byte if Zero (ZF=1) OptCategory[NN_sgdt] = 0; // Store Global Descriptor Table Register OptCategory[NN_sidt] = 0; // Store Interrupt Descriptor Table Register OptCategory[NN_shld] = 2; // Double Precision Shift Left OptCategory[NN_shrd] = 2; // Double Precision Shift Right OptCategory[NN_sldt] = 6; // Store Local Descriptor Table Register OptCategory[NN_smsw] = 2; // Store Machine Status Word OptCategory[NN_stc] = 1; // Set Carry Flag OptCategory[NN_std] = 1; // Set Direction Flag OptCategory[NN_sti] = 1; // Set Interrupt Flag OptCategory[NN_stos] = 0; // Store String OptCategory[NN_str] = 6; // Store Task Register OptCategory[NN_sub] = 5; // Integer Subtraction OptCategory[NN_test] = 1; // Logical Compare OptCategory[NN_verr] = 1; // Verify a Segment for Reading OptCategory[NN_verw] = 1; // Verify a Segment for Writing OptCategory[NN_wait] = 1; // Wait until BUSY# Pin is Inactive (HIGH) OptCategory[NN_xchg] = 0; // Exchange Register/Memory with Register OptCategory[NN_xlat] = 0; // Table Lookup Translation OptCategory[NN_xor] = 2; // Logical Exclusive OR // // 486 instructions // OptCategory[NN_cmpxchg] = 0; // Compare and Exchange OptCategory[NN_bswap] = 1; // Swap bytes in register OptCategory[NN_xadd] = 0; // t<-dest; dest<-src+dest; src<-t OptCategory[NN_invd] = 1; // Invalidate Data Cache OptCategory[NN_wbinvd] = 1; // Invalidate Data Cache (write changes) OptCategory[NN_invlpg] = 1; // Invalidate TLB entry // // Pentium instructions // OptCategory[NN_rdmsr] = 8; // Read Machine Status Register OptCategory[NN_wrmsr] = 1; // Write Machine Status Register OptCategory[NN_cpuid] = 8; // Get CPU ID OptCategory[NN_cmpxchg8b] = 0; // Compare and Exchange Eight Bytes OptCategory[NN_rdtsc] = 8; // Read Time Stamp Counter OptCategory[NN_rsm] = 1; // Resume from System Management Mode // // Pentium Pro instructions // OptCategory[NN_cmova] = 0; // Move if Above (CF=0 & ZF=0) OptCategory[NN_cmovb] = 0; // Move if Below (CF=1) OptCategory[NN_cmovbe] = 0; // Move if Below or Equal (CF=1 | ZF=1) OptCategory[NN_cmovg] = 0; // Move if Greater (ZF=0 & SF=OF) OptCategory[NN_cmovge] = 0; // Move if Greater or Equal (SF=OF) OptCategory[NN_cmovl] = 0; // Move if Less (SF!=OF) OptCategory[NN_cmovle] = 0; // Move if Less or Equal (ZF=1 | SF!=OF) OptCategory[NN_cmovnb] = 0; // Move if Not Below (CF=0) OptCategory[NN_cmovno] = 0; // Move if Not Overflow (OF=0) OptCategory[NN_cmovnp] = 0; // Move if Not Parity (PF=0) OptCategory[NN_cmovns] = 0; // Move if Not Sign (SF=0) OptCategory[NN_cmovnz] = 0; // Move if Not Zero (ZF=0) OptCategory[NN_cmovo] = 0; // Move if Overflow (OF=1) OptCategory[NN_cmovp] = 0; // Move if Parity (PF=1) OptCategory[NN_cmovs] = 0; // Move if Sign (SF=1) OptCategory[NN_cmovz] = 0; // Move if Zero (ZF=1) OptCategory[NN_fcmovb] = 1; // Floating Move if Below OptCategory[NN_fcmove] = 1; // Floating Move if Equal OptCategory[NN_fcmovbe] = 1; // Floating Move if Below or Equal OptCategory[NN_fcmovu] = 1; // Floating Move if Unordered OptCategory[NN_fcmovnb] = 1; // Floating Move if Not Below OptCategory[NN_fcmovne] = 1; // Floating Move if Not Equal OptCategory[NN_fcmovnbe] = 1; // Floating Move if Not Below or Equal OptCategory[NN_fcmovnu] = 1; // Floating Move if Not Unordered OptCategory[NN_fcomi] = 1; // FP Compare, result in EFLAGS OptCategory[NN_fucomi] = 1; // FP Unordered Compare, result in EFLAGS OptCategory[NN_fcomip] = 1; // FP Compare, result in EFLAGS, pop stack OptCategory[NN_fucomip] = 1; // FP Unordered Compare, result in EFLAGS, pop stack OptCategory[NN_rdpmc] = 8; // Read Performance Monitor Counter // // FPP instructuions // OptCategory[NN_fld] = 1; // Load Real ** Infer src is 'n' OptCategory[NN_fst] = 9; // Store Real OptCategory[NN_fstp] = 9; // Store Real and Pop OptCategory[NN_fxch] = 1; // Exchange Registers OptCategory[NN_fild] = 1; // Load Integer ** Infer src is 'n' OptCategory[NN_fist] = 0; // Store Integer OptCategory[NN_fistp] = 0; // Store Integer and Pop OptCategory[NN_fbld] = 1; // Load BCD OptCategory[NN_fbstp] = 1; // Store BCD and Pop OptCategory[NN_fadd] = 1; // Add Real OptCategory[NN_faddp] = 1; // Add Real and Pop OptCategory[NN_fiadd] = 1; // Add Integer OptCategory[NN_fsub] = 1; // Subtract Real OptCategory[NN_fsubp] = 1; // Subtract Real and Pop OptCategory[NN_fisub] = 1; // Subtract Integer OptCategory[NN_fsubr] = 1; // Subtract Real Reversed OptCategory[NN_fsubrp] = 1; // Subtract Real Reversed and Pop OptCategory[NN_fisubr] = 1; // Subtract Integer Reversed OptCategory[NN_fmul] = 1; // Multiply Real OptCategory[NN_fmulp] = 1; // Multiply Real and Pop OptCategory[NN_fimul] = 1; // Multiply Integer OptCategory[NN_fdiv] = 1; // Divide Real OptCategory[NN_fdivp] = 1; // Divide Real and Pop OptCategory[NN_fidiv] = 1; // Divide Integer OptCategory[NN_fdivr] = 1; // Divide Real Reversed OptCategory[NN_fdivrp] = 1; // Divide Real Reversed and Pop OptCategory[NN_fidivr] = 1; // Divide Integer Reversed OptCategory[NN_fsqrt] = 1; // Square Root OptCategory[NN_fscale] = 1; // Scale: st(0) <- st(0) * 2^st(1) OptCategory[NN_fprem] = 1; // Partial Remainder OptCategory[NN_frndint] = 1; // Round to Integer OptCategory[NN_fxtract] = 1; // Extract exponent and significand OptCategory[NN_fabs] = 1; // Absolute value OptCategory[NN_fchs] = 1; // Change Sign OptCategory[NN_fcom] = 1; // Compare Real OptCategory[NN_fcomp] = 1; // Compare Real and Pop OptCategory[NN_fcompp] = 1; // Compare Real and Pop Twice OptCategory[NN_ficom] = 1; // Compare Integer OptCategory[NN_ficomp] = 1; // Compare Integer and Pop OptCategory[NN_ftst] = 1; // Test OptCategory[NN_fxam] = 1; // Examine OptCategory[NN_fptan] = 1; // Partial tangent OptCategory[NN_fpatan] = 1; // Partial arctangent OptCategory[NN_f2xm1] = 1; // 2^x - 1 OptCategory[NN_fyl2x] = 1; // Y * lg2(X) OptCategory[NN_fyl2xp1] = 1; // Y * lg2(X+1) OptCategory[NN_fldz] = 1; // Load +0.0 OptCategory[NN_fld1] = 1; // Load +1.0 OptCategory[NN_fldpi] = 1; // Load PI=3.14... OptCategory[NN_fldl2t] = 1; // Load lg2(10) OptCategory[NN_fldl2e] = 1; // Load lg2(e) OptCategory[NN_fldlg2] = 1; // Load lg10(2) OptCategory[NN_fldln2] = 1; // Load ln(2) OptCategory[NN_finit] = 1; // Initialize Processor OptCategory[NN_fninit] = 1; // Initialize Processor (no wait) OptCategory[NN_fsetpm] = 1; // Set Protected Mode OptCategory[NN_fldcw] = 1; // Load Control Word OptCategory[NN_fstcw] = 0; // Store Control Word OptCategory[NN_fnstcw] = 0; // Store Control Word (no wait) OptCategory[NN_fstsw] = 2; // Store Status Word to memory or AX OptCategory[NN_fnstsw] = 2; // Store Status Word (no wait) to memory or AX OptCategory[NN_fclex] = 1; // Clear Exceptions OptCategory[NN_fnclex] = 1; // Clear Exceptions (no wait) OptCategory[NN_fstenv] = 0; // Store Environment OptCategory[NN_fnstenv] = 0; // Store Environment (no wait) OptCategory[NN_fldenv] = 1; // Load Environment OptCategory[NN_fsave] = 0; // Save State OptCategory[NN_fnsave] = 0; // Save State (no wait) OptCategory[NN_frstor] = 1; // Restore State ** infer src is 'n' OptCategory[NN_fincstp] = 1; // Increment Stack Pointer OptCategory[NN_fdecstp] = 1; // Decrement Stack Pointer OptCategory[NN_ffree] = 1; // Free Register OptCategory[NN_fnop] = 1; // No Operation OptCategory[NN_feni] = 1; // (8087 only) OptCategory[NN_fneni] = 1; // (no wait) (8087 only) OptCategory[NN_fdisi] = 1; // (8087 only) OptCategory[NN_fndisi] = 1; // (no wait) (8087 only) // // 80387 instructions // OptCategory[NN_fprem1] = 1; // Partial Remainder ( < half ) OptCategory[NN_fsincos] = 1; // t<-cos(st); st<-sin(st); push t OptCategory[NN_fsin] = 1; // Sine OptCategory[NN_fcos] = 1; // Cosine OptCategory[NN_fucom] = 1; // Compare Unordered Real OptCategory[NN_fucomp] = 1; // Compare Unordered Real and Pop OptCategory[NN_fucompp] = 1; // Compare Unordered Real and Pop Twice // // Instructions added 28.02.96 // OptCategory[NN_setalc] = 2; // Set AL to Carry Flag ** OptCategory[NN_svdc] = 0; // Save Register and Descriptor OptCategory[NN_rsdc] = 0; // Restore Register and Descriptor OptCategory[NN_svldt] = 0; // Save LDTR and Descriptor OptCategory[NN_rsldt] = 0; // Restore LDTR and Descriptor OptCategory[NN_svts] = 1; // Save TR and Descriptor OptCategory[NN_rsts] = 1; // Restore TR and Descriptor OptCategory[NN_icebp] = 1; // ICE Break Point OptCategory[NN_loadall] = 0; // Load the entire CPU state from ES:EDI // // MMX instructions // OptCategory[NN_emms] = 1; // Empty MMX state OptCategory[NN_movd] = 9; // Move 32 bits OptCategory[NN_movq] = 9; // Move 64 bits OptCategory[NN_packsswb] = 1; // Pack with Signed Saturation (Word->Byte) OptCategory[NN_packssdw] = 1; // Pack with Signed Saturation (Dword->Word) OptCategory[NN_packuswb] = 1; // Pack with Unsigned Saturation (Word->Byte) OptCategory[NN_paddb] = 1; // Packed Add Byte OptCategory[NN_paddw] = 1; // Packed Add Word OptCategory[NN_paddd] = 1; // Packed Add Dword OptCategory[NN_paddsb] = 1; // Packed Add with Saturation (Byte) OptCategory[NN_paddsw] = 1; // Packed Add with Saturation (Word) OptCategory[NN_paddusb] = 1; // Packed Add Unsigned with Saturation (Byte) OptCategory[NN_paddusw] = 1; // Packed Add Unsigned with Saturation (Word) OptCategory[NN_pand] = 1; // Bitwise Logical And OptCategory[NN_pandn] = 1; // Bitwise Logical And Not OptCategory[NN_pcmpeqb] = 1; // Packed Compare for Equal (Byte) OptCategory[NN_pcmpeqw] = 1; // Packed Compare for Equal (Word) OptCategory[NN_pcmpeqd] = 1; // Packed Compare for Equal (Dword) OptCategory[NN_pcmpgtb] = 1; // Packed Compare for Greater Than (Byte) OptCategory[NN_pcmpgtw] = 1; // Packed Compare for Greater Than (Word) OptCategory[NN_pcmpgtd] = 1; // Packed Compare for Greater Than (Dword) OptCategory[NN_pmaddwd] = 1; // Packed Multiply and Add OptCategory[NN_pmulhw] = 1; // Packed Multiply High OptCategory[NN_pmullw] = 1; // Packed Multiply Low OptCategory[NN_por] = 1; // Bitwise Logical Or OptCategory[NN_psllw] = 1; // Packed Shift Left Logical (Word) OptCategory[NN_pslld] = 1; // Packed Shift Left Logical (Dword) OptCategory[NN_psllq] = 1; // Packed Shift Left Logical (Qword) OptCategory[NN_psraw] = 1; // Packed Shift Right Arithmetic (Word) OptCategory[NN_psrad] = 1; // Packed Shift Right Arithmetic (Dword) OptCategory[NN_psrlw] = 1; // Packed Shift Right Logical (Word) OptCategory[NN_psrld] = 1; // Packed Shift Right Logical (Dword) OptCategory[NN_psrlq] = 1; // Packed Shift Right Logical (Qword) OptCategory[NN_psubb] = 1; // Packed Subtract Byte OptCategory[NN_psubw] = 1; // Packed Subtract Word OptCategory[NN_psubd] = 1; // Packed Subtract Dword OptCategory[NN_psubsb] = 1; // Packed Subtract with Saturation (Byte) OptCategory[NN_psubsw] = 1; // Packed Subtract with Saturation (Word) OptCategory[NN_psubusb] = 1; // Packed Subtract Unsigned with Saturation (Byte) OptCategory[NN_psubusw] = 1; // Packed Subtract Unsigned with Saturation (Word) OptCategory[NN_punpckhbw] = 1; // Unpack High Packed Data (Byte->Word) OptCategory[NN_punpckhwd] = 1; // Unpack High Packed Data (Word->Dword) OptCategory[NN_punpckhdq] = 1; // Unpack High Packed Data (Dword->Qword) OptCategory[NN_punpcklbw] = 1; // Unpack Low Packed Data (Byte->Word) OptCategory[NN_punpcklwd] = 1; // Unpack Low Packed Data (Word->Dword) OptCategory[NN_punpckldq] = 1; // Unpack Low Packed Data (Dword->Qword) OptCategory[NN_pxor] = 1; // Bitwise Logical Exclusive Or // // Undocumented Deschutes processor instructions // OptCategory[NN_fxsave] = 1; // Fast save FP context ** to where? OptCategory[NN_fxrstor] = 1; // Fast restore FP context ** from where? // Pentium II instructions OptCategory[NN_sysenter] = 1; // Fast Transition to System Call Entry Point OptCategory[NN_sysexit] = 1; // Fast Transition from System Call Entry Point // 3DNow! instructions OptCategory[NN_pavgusb] = 1; // Packed 8-bit Unsigned Integer Averaging OptCategory[NN_pfadd] = 1; // Packed Floating-Point Addition OptCategory[NN_pfsub] = 1; // Packed Floating-Point Subtraction OptCategory[NN_pfsubr] = 1; // Packed Floating-Point Reverse Subtraction OptCategory[NN_pfacc] = 1; // Packed Floating-Point Accumulate OptCategory[NN_pfcmpge] = 1; // Packed Floating-Point Comparison, Greater or Equal OptCategory[NN_pfcmpgt] = 1; // Packed Floating-Point Comparison, Greater OptCategory[NN_pfcmpeq] = 1; // Packed Floating-Point Comparison, Equal OptCategory[NN_pfmin] = 1; // Packed Floating-Point Minimum OptCategory[NN_pfmax] = 1; // Packed Floating-Point Maximum OptCategory[NN_pi2fd] = 1; // Packed 32-bit Integer to Floating-Point OptCategory[NN_pf2id] = 1; // Packed Floating-Point to 32-bit Integer OptCategory[NN_pfrcp] = 1; // Packed Floating-Point Reciprocal Approximation OptCategory[NN_pfrsqrt] = 1; // Packed Floating-Point Reciprocal Square Root Approximation OptCategory[NN_pfmul] = 1; // Packed Floating-Point Multiplication OptCategory[NN_pfrcpit1] = 1; // Packed Floating-Point Reciprocal First Iteration Step OptCategory[NN_pfrsqit1] = 1; // Packed Floating-Point Reciprocal Square Root First Iteration Step OptCategory[NN_pfrcpit2] = 1; // Packed Floating-Point Reciprocal Second Iteration Step OptCategory[NN_pmulhrw] = 1; // Packed Floating-Point 16-bit Integer Multiply with rounding OptCategory[NN_femms] = 1; // Faster entry/exit of the MMX or floating-point state OptCategory[NN_prefetch] = 1; // Prefetch at least a 32-byte line into L1 data cache OptCategory[NN_prefetchw] = 1; // Prefetch processor cache line into L1 data cache (mark as modified) // Pentium III instructions OptCategory[NN_addps] = 1; // Packed Single-FP Add OptCategory[NN_addss] = 1; // Scalar Single-FP Add OptCategory[NN_andnps] = 1; // Bitwise Logical And Not for Single-FP OptCategory[NN_andps] = 1; // Bitwise Logical And for Single-FP OptCategory[NN_cmpps] = 1; // Packed Single-FP Compare OptCategory[NN_cmpss] = 1; // Scalar Single-FP Compare OptCategory[NN_comiss] = 1; // Scalar Ordered Single-FP Compare and Set EFLAGS OptCategory[NN_cvtpi2ps] = 1; // Packed signed INT32 to Packed Single-FP conversion OptCategory[NN_cvtps2pi] = 1; // Packed Single-FP to Packed INT32 conversion OptCategory[NN_cvtsi2ss] = 1; // Scalar signed INT32 to Single-FP conversion OptCategory[NN_cvtss2si] = 2; // Scalar Single-FP to signed INT32 conversion OptCategory[NN_cvttps2pi] = 1; // Packed Single-FP to Packed INT32 conversion (truncate) OptCategory[NN_cvttss2si] = 2; // Scalar Single-FP to signed INT32 conversion (truncate) OptCategory[NN_divps] = 1; // Packed Single-FP Divide OptCategory[NN_divss] = 1; // Scalar Single-FP Divide OptCategory[NN_ldmxcsr] = 1; // Load Streaming SIMD Extensions Technology Control/Status Register OptCategory[NN_maxps] = 1; // Packed Single-FP Maximum OptCategory[NN_maxss] = 1; // Scalar Single-FP Maximum OptCategory[NN_minps] = 1; // Packed Single-FP Minimum OptCategory[NN_minss] = 1; // Scalar Single-FP Minimum OptCategory[NN_movaps] = 9; // Move Aligned Four Packed Single-FP ** infer memsrc 'n'? OptCategory[NN_movhlps] = 1; // Move High to Low Packed Single-FP OptCategory[NN_movhps] = 1; // Move High Packed Single-FP OptCategory[NN_movlhps] = 1; // Move Low to High Packed Single-FP OptCategory[NN_movlps] = 1; // Move Low Packed Single-FP OptCategory[NN_movmskps] = 1; // Move Mask to Register OptCategory[NN_movss] = 9; // Move Scalar Single-FP OptCategory[NN_movups] = 9; // Move Unaligned Four Packed Single-FP OptCategory[NN_mulps] = 1; // Packed Single-FP Multiply OptCategory[NN_mulss] = 1; // Scalar Single-FP Multiply OptCategory[NN_orps] = 1; // Bitwise Logical OR for Single-FP Data OptCategory[NN_rcpps] = 1; // Packed Single-FP Reciprocal OptCategory[NN_rcpss] = 1; // Scalar Single-FP Reciprocal OptCategory[NN_rsqrtps] = 1; // Packed Single-FP Square Root Reciprocal OptCategory[NN_rsqrtss] = 1; // Scalar Single-FP Square Root Reciprocal OptCategory[NN_shufps] = 1; // Shuffle Single-FP OptCategory[NN_sqrtps] = 1; // Packed Single-FP Square Root OptCategory[NN_sqrtss] = 1; // Scalar Single-FP Square Root OptCategory[NN_stmxcsr] = 0; // Store Streaming SIMD Extensions Technology Control/Status Register ** Infer dest is 'n' OptCategory[NN_subps] = 1; // Packed Single-FP Subtract OptCategory[NN_subss] = 1; // Scalar Single-FP Subtract OptCategory[NN_ucomiss] = 1; // Scalar Unordered Single-FP Compare and Set EFLAGS OptCategory[NN_unpckhps] = 1; // Unpack High Packed Single-FP Data OptCategory[NN_unpcklps] = 1; // Unpack Low Packed Single-FP Data OptCategory[NN_xorps] = 1; // Bitwise Logical XOR for Single-FP Data OptCategory[NN_pavgb] = 1; // Packed Average (Byte) OptCategory[NN_pavgw] = 1; // Packed Average (Word) OptCategory[NN_pextrw] = 2; // Extract Word OptCategory[NN_pinsrw] = 1; // Insert Word OptCategory[NN_pmaxsw] = 1; // Packed Signed Integer Word Maximum OptCategory[NN_pmaxub] = 1; // Packed Unsigned Integer Byte Maximum OptCategory[NN_pminsw] = 1; // Packed Signed Integer Word Minimum OptCategory[NN_pminub] = 1; // Packed Unsigned Integer Byte Minimum OptCategory[NN_pmovmskb] = 1; // Move Byte Mask to Integer OptCategory[NN_pmulhuw] = 1; // Packed Multiply High Unsigned OptCategory[NN_psadbw] = 1; // Packed Sum of Absolute Differences OptCategory[NN_pshufw] = 1; // Packed Shuffle Word OptCategory[NN_maskmovq] = 0; // Byte Mask write ** Infer dest is 'n' OptCategory[NN_movntps] = 0; // Move Aligned Four Packed Single-FP Non Temporal * infer dest is 'n' OptCategory[NN_movntq] = 0; // Move 64 Bits Non Temporal ** Infer dest is 'n' OptCategory[NN_prefetcht0] = 1; // Prefetch to all cache levels OptCategory[NN_prefetcht1] = 1; // Prefetch to all cache levels OptCategory[NN_prefetcht2] = 1; // Prefetch to L2 cache OptCategory[NN_prefetchnta] = 1; // Prefetch to L1 cache OptCategory[NN_sfence] = 1; // Store Fence // Pentium III Pseudo instructions OptCategory[NN_cmpeqps] = 1; // Packed Single-FP Compare EQ OptCategory[NN_cmpltps] = 1; // Packed Single-FP Compare LT OptCategory[NN_cmpleps] = 1; // Packed Single-FP Compare LE OptCategory[NN_cmpunordps] = 1; // Packed Single-FP Compare UNORD OptCategory[NN_cmpneqps] = 1; // Packed Single-FP Compare NOT EQ OptCategory[NN_cmpnltps] = 1; // Packed Single-FP Compare NOT LT OptCategory[NN_cmpnleps] = 1; // Packed Single-FP Compare NOT LE OptCategory[NN_cmpordps] = 1; // Packed Single-FP Compare ORDERED OptCategory[NN_cmpeqss] = 1; // Scalar Single-FP Compare EQ OptCategory[NN_cmpltss] = 1; // Scalar Single-FP Compare LT OptCategory[NN_cmpless] = 1; // Scalar Single-FP Compare LE OptCategory[NN_cmpunordss] = 1; // Scalar Single-FP Compare UNORD OptCategory[NN_cmpneqss] = 1; // Scalar Single-FP Compare NOT EQ OptCategory[NN_cmpnltss] = 1; // Scalar Single-FP Compare NOT LT OptCategory[NN_cmpnless] = 1; // Scalar Single-FP Compare NOT LE OptCategory[NN_cmpordss] = 1; // Scalar Single-FP Compare ORDERED // AMD K7 instructions // Revisit AMD if we port to it. OptCategory[NN_pf2iw] = 0; // Packed Floating-Point to Integer with Sign Extend OptCategory[NN_pfnacc] = 0; // Packed Floating-Point Negative Accumulate OptCategory[NN_pfpnacc] = 0; // Packed Floating-Point Mixed Positive-Negative Accumulate OptCategory[NN_pi2fw] = 0; // Packed 16-bit Integer to Floating-Point OptCategory[NN_pswapd] = 0; // Packed Swap Double Word // Undocumented FP instructions (thanks to norbert.juffa@adm.com) OptCategory[NN_fstp1] = 9; // Alias of Store Real and Pop OptCategory[NN_fcom2] = 1; // Alias of Compare Real OptCategory[NN_fcomp3] = 1; // Alias of Compare Real and Pop OptCategory[NN_fxch4] = 1; // Alias of Exchange Registers OptCategory[NN_fcomp5] = 1; // Alias of Compare Real and Pop OptCategory[NN_ffreep] = 1; // Free Register and Pop OptCategory[NN_fxch7] = 1; // Alias of Exchange Registers OptCategory[NN_fstp8] = 9; // Alias of Store Real and Pop OptCategory[NN_fstp9] = 9; // Alias of Store Real and Pop // Pentium 4 instructions OptCategory[NN_addpd] = 1; // Add Packed Double-Precision Floating-Point Values OptCategory[NN_addsd] = 1; // Add Scalar Double-Precision Floating-Point Values OptCategory[NN_andnpd] = 1; // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values OptCategory[NN_andpd] = 1; // Bitwise Logical AND of Packed Double-Precision Floating-Point Values OptCategory[NN_clflush] = 1; // Flush Cache Line OptCategory[NN_cmppd] = 1; // Compare Packed Double-Precision Floating-Point Values OptCategory[NN_cmpsd] = 1; // Compare Scalar Double-Precision Floating-Point Values OptCategory[NN_comisd] = 1; // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS OptCategory[NN_cvtdq2pd] = 1; // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values OptCategory[NN_cvtdq2ps] = 1; // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values OptCategory[NN_cvtpd2dq] = 1; // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers OptCategory[NN_cvtpd2pi] = 1; // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers OptCategory[NN_cvtpd2ps] = 1; // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values OptCategory[NN_cvtpi2pd] = 1; // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values OptCategory[NN_cvtps2dq] = 1; // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers OptCategory[NN_cvtps2pd] = 1; // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values OptCategory[NN_cvtsd2si] = 2; // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer OptCategory[NN_cvtsd2ss] = 1; // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value OptCategory[NN_cvtsi2sd] = 1; // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value OptCategory[NN_cvtss2sd] = 1; // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value OptCategory[NN_cvttpd2dq] = 1; // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers OptCategory[NN_cvttpd2pi] = 1; // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers OptCategory[NN_cvttps2dq] = 1; // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers OptCategory[NN_cvttsd2si] = 2; // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer OptCategory[NN_divpd] = 1; // Divide Packed Double-Precision Floating-Point Values OptCategory[NN_divsd] = 1; // Divide Scalar Double-Precision Floating-Point Values OptCategory[NN_lfence] = 1; // Load Fence OptCategory[NN_maskmovdqu] = 0; // Store Selected Bytes of Double Quadword ** Infer dest is 'n' OptCategory[NN_maxpd] = 1; // Return Maximum Packed Double-Precision Floating-Point Values OptCategory[NN_maxsd] = 1; // Return Maximum Scalar Double-Precision Floating-Point Value OptCategory[NN_mfence] = 1; // Memory Fence OptCategory[NN_minpd] = 1; // Return Minimum Packed Double-Precision Floating-Point Values OptCategory[NN_minsd] = 1; // Return Minimum Scalar Double-Precision Floating-Point Value OptCategory[NN_movapd] = 9; // Move Aligned Packed Double-Precision Floating-Point Values ** Infer dest is 'n' OptCategory[NN_movdq2q] = 1; // Move Quadword from XMM to MMX Register OptCategory[NN_movdqa] = 9; // Move Aligned Double Quadword ** Infer dest is 'n' OptCategory[NN_movdqu] = 9; // Move Unaligned Double Quadword ** Infer dest is 'n' OptCategory[NN_movhpd] = 9; // Move High Packed Double-Precision Floating-Point Values ** Infer dest is 'n' OptCategory[NN_movlpd] = 9; // Move Low Packed Double-Precision Floating-Point Values ** Infer dest is 'n' OptCategory[NN_movmskpd] = 2; // Extract Packed Double-Precision Floating-Point Sign Mask OptCategory[NN_movntdq] = 0; // Store Double Quadword Using Non-Temporal Hint OptCategory[NN_movnti] = 0; // Store Doubleword Using Non-Temporal Hint OptCategory[NN_movntpd] = 0; // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint OptCategory[NN_movq2dq] = 1; // Move Quadword from MMX to XMM Register OptCategory[NN_movsd] = 9; // Move Scalar Double-Precision Floating-Point Values OptCategory[NN_movupd] = 9; // Move Unaligned Packed Double-Precision Floating-Point Values OptCategory[NN_mulpd] = 1; // Multiply Packed Double-Precision Floating-Point Values OptCategory[NN_mulsd] = 1; // Multiply Scalar Double-Precision Floating-Point Values OptCategory[NN_orpd] = 1; // Bitwise Logical OR of Double-Precision Floating-Point Values OptCategory[NN_paddq] = 1; // Add Packed Quadword Integers OptCategory[NN_pause] = 1; // Spin Loop Hint OptCategory[NN_pmuludq] = 1; // Multiply Packed Unsigned Doubleword Integers OptCategory[NN_pshufd] = 1; // Shuffle Packed Doublewords OptCategory[NN_pshufhw] = 1; // Shuffle Packed High Words OptCategory[NN_pshuflw] = 1; // Shuffle Packed Low Words OptCategory[NN_pslldq] = 1; // Shift Double Quadword Left Logical OptCategory[NN_psrldq] = 1; // Shift Double Quadword Right Logical OptCategory[NN_psubq] = 1; // Subtract Packed Quadword Integers OptCategory[NN_punpckhqdq] = 1; // Unpack High Data OptCategory[NN_punpcklqdq] = 1; // Unpack Low Data OptCategory[NN_shufpd] = 1; // Shuffle Packed Double-Precision Floating-Point Values OptCategory[NN_sqrtpd] = 1; // Compute Square Roots of Packed Double-Precision Floating-Point Values OptCategory[NN_sqrtsd] = 1; // Compute Square Rootof Scalar Double-Precision Floating-Point Value OptCategory[NN_subpd] = 1; // Subtract Packed Double-Precision Floating-Point Values OptCategory[NN_subsd] = 1; // Subtract Scalar Double-Precision Floating-Point Values OptCategory[NN_ucomisd] = 1; // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS OptCategory[NN_unpckhpd] = 1; // Unpack and Interleave High Packed Double-Precision Floating-Point Values OptCategory[NN_unpcklpd] = 1; // Unpack and Interleave Low Packed Double-Precision Floating-Point Values OptCategory[NN_xorpd] = 1; // Bitwise Logical OR of Double-Precision Floating-Point Values // AMD syscall/sysret instructions NOTE: not AMD, found in Intel manual OptCategory[NN_syscall] = 1; // Low latency system call OptCategory[NN_sysret] = 1; // Return from system call // AMD64 instructions NOTE: not AMD, found in Intel manual OptCategory[NN_swapgs] = 1; // Exchange GS base with KernelGSBase MSR // New Pentium instructions (SSE3) OptCategory[NN_movddup] = 9; // Move One Double-FP and Duplicate OptCategory[NN_movshdup] = 9; // Move Packed Single-FP High and Duplicate OptCategory[NN_movsldup] = 9; // Move Packed Single-FP Low and Duplicate // Missing AMD64 instructions NOTE: also found in Intel manual OptCategory[NN_movsxd] = 2; // Move with Sign-Extend Doubleword OptCategory[NN_cmpxchg16b] = 0; // Compare and Exchange 16 Bytes // SSE3 instructions OptCategory[NN_addsubpd] = 1; // Add /Sub packed DP FP numbers OptCategory[NN_addsubps] = 1; // Add /Sub packed SP FP numbers OptCategory[NN_haddpd] = 1; // Add horizontally packed DP FP numbers OptCategory[NN_haddps] = 1; // Add horizontally packed SP FP numbers OptCategory[NN_hsubpd] = 1; // Sub horizontally packed DP FP numbers OptCategory[NN_hsubps] = 1; // Sub horizontally packed SP FP numbers OptCategory[NN_monitor] = 1; // Set up a linear address range to be monitored by hardware OptCategory[NN_mwait] = 1; // Wait until write-back store performed within the range specified by the MONITOR instruction OptCategory[NN_fisttp] = 2; // Store ST in intXX (chop) and pop OptCategory[NN_lddqu] = 0; // Load unaligned integer 128-bit // SSSE3 instructions OptCategory[NN_psignb] = 1; // Packed SIGN Byte OptCategory[NN_psignw] = 1; // Packed SIGN Word OptCategory[NN_psignd] = 1; // Packed SIGN Doubleword OptCategory[NN_pshufb] = 1; // Packed Shuffle Bytes OptCategory[NN_pmulhrsw] = 1; // Packed Multiply High with Round and Scale OptCategory[NN_pmaddubsw] = 1; // Multiply and Add Packed Signed and Unsigned Bytes OptCategory[NN_phsubsw] = 1; // Packed Horizontal Subtract and Saturate OptCategory[NN_phaddsw] = 1; // Packed Horizontal Add and Saturate OptCategory[NN_phaddw] = 1; // Packed Horizontal Add Word OptCategory[NN_phaddd] = 1; // Packed Horizontal Add Doubleword OptCategory[NN_phsubw] = 1; // Packed Horizontal Subtract Word OptCategory[NN_phsubd] = 1; // Packed Horizontal Subtract Doubleword OptCategory[NN_palignr] = 1; // Packed Align Right OptCategory[NN_pabsb] = 1; // Packed Absolute Value Byte OptCategory[NN_pabsw] = 1; // Packed Absolute Value Word OptCategory[NN_pabsd] = 1; // Packed Absolute Value Doubleword // VMX instructions OptCategory[NN_vmcall] = 1; // Call to VM Monitor OptCategory[NN_vmclear] = 0; // Clear Virtual Machine Control Structure OptCategory[NN_vmlaunch] = 1; // Launch Virtual Machine OptCategory[NN_vmresume] = 1; // Resume Virtual Machine OptCategory[NN_vmptrld] = 6; // Load Pointer to Virtual Machine Control Structure OptCategory[NN_vmptrst] = 0; // Store Pointer to Virtual Machine Control Structure OptCategory[NN_vmread] = 0; // Read Field from Virtual Machine Control Structure OptCategory[NN_vmwrite] = 0; // Write Field from Virtual Machine Control Structure OptCategory[NN_vmxoff] = 1; // Leave VMX Operation OptCategory[NN_vmxon] = 1; // Enter VMX Operation OptCategory[NN_last] = 1; return; } // end InitOptCategory()