From b985b1dc4daaa888cdd61346d50e39edbdec0fe6 Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Thu, 13 Dec 2007 16:14:58 +0000
Subject: [PATCH] Starting over.

---
 .gitattributes        |    1 -
 SMPStaticAnalyzer.cpp | 1629 -----------------------------------------
 2 files changed, 1630 deletions(-)
 delete mode 100644 SMPStaticAnalyzer.cpp

diff --git a/.gitattributes b/.gitattributes
index c533adcb..df0eef64 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -3,6 +3,5 @@
 /README.txt -text
 /SMP-analyze.sh -text
 /SMP.idc -text
-/SMPStaticAnalyzer.cpp -text
 /makefile -text
 /plugin.script -text
diff --git a/SMPStaticAnalyzer.cpp b/SMPStaticAnalyzer.cpp
deleted file mode 100644
index 4fcf8b9e..00000000
--- a/SMPStaticAnalyzer.cpp
+++ /dev/null
@@ -1,1629 +0,0 @@
-//
-// 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>
-
-// Set to 1 for debugging output
-#define SMP_DEBUG 1
-#define SMP_DEBUG2 0   // verbose
-#define SMP_DEBUG3 0   // verbose
-#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
-
-
-// Define optimization categories for instructions.
-static int OptCategory[NN_last+1];
-// Initialize the OptCategory[] array.
-void InitOptCategory(void);
-
-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" 
-	};
-
-// Print out the destination operand list for the instruction, given
-//  the OptCategory for the instruction as a hint.
-char *DestString(insn_t, int, char *);
-
-#define LAST_OPT_CATEGORY  9
-static char *OptExplanation[LAST_OPT_CATEGORY + 1] =
-	{ "NoOpt", "NoMetaUpdate", "AlwaysNUM", "NUMVia2ndSrcIMMEDNUM",
-	  "Always1stSrc", "1stSrcVia2ndSrcIMMEDNUM", "AlwaysPtr",
-	  "AlwaysNUM", "AlwaysNUM", "NUMViaFPRegDest"
-	};
-
-void IDAP_run(int);
-
-// Is the destination operand a memory reference?
-bool IsDestMemoryOperand(insn_t Inst) {
-	if (Inst.Operands[0].type == o_void)
-		return false;
-	else
-		return ((Inst.Operands[0].type == o_mem)
-				|| (Inst.Operands[0].type == o_phrase)
-				|| (Inst.Operands[0].type == o_displ));
-}
-
-// Is the source operand a memory reference?
-bool IsSrcMemoryOperand(insn_t Inst) {
-	if (Inst.Operands[1].type == o_void)
-		return false;
-	else
-		return ((Inst.Operands[1].type == o_mem)
-				|| (Inst.Operands[1].type == o_phrase)
-				|| (Inst.Operands[1].type == o_displ));
-}
-
-// 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.
-	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 (BaseReg != R_bp) { // SIB code for NO BASE REG
-		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 operands for Inst.
-void PrintOperands(insn_t Inst) {
-	op_t Opnd;
-	ulong CanonicalFeatures = Inst.get_canon_feature();
-	for (int i = 0; i < UA_MAXOP; ++i) {
-		Opnd = Inst.Operands[i];
-		if (Opnd.type == o_void)
-			continue;
-		else if (Opnd.type == o_mem) {
-			msg(" Operand %d : memory : addr: %x", i, Opnd.addr);
-			PrintDefUse(CanonicalFeatures, i);
-			if (Opnd.hasSIB) { // has SIB info
-				PrintSIB(Opnd);
-			}
-		}
-		else if (Opnd.type == o_phrase) {
-			msg(" Operand %d : memory phrase :", i);
-			PrintDefUse(CanonicalFeatures, i);
-			if (Opnd.hasSIB) { // has SIB info
-				PrintSIB(Opnd);
-			}
-			else { // no SIB info
-				ushort IndexReg = Opnd.phrase;
-				msg(" reg %s", RegNames[IndexReg]);
-			}
-		}
-		else if (Opnd.type == o_displ) {
-			ushort IndexReg = Opnd.phrase;
-			ea_t offset = Opnd.addr;
-			msg(" Operand %d : memory displ : reg %s displ %d", i,
-				RegNames[IndexReg], offset);
-			PrintDefUse(CanonicalFeatures, i);
-			if (Opnd.hasSIB)
-				msg(" \n WARNING: SIB for o_displ type");
-		}
-		else if (Opnd.type == o_reg) {
-			msg(" Operand %d : register", i);
-			msg(" regno: %d", Opnd.reg);
-			PrintDefUse(CanonicalFeatures, i);
-		}
-		else if (Opnd.type == o_imm) {
-			msg(" Operand %d : immed", i);
-			PrintDefUse(CanonicalFeatures, i);
-		}
-		else if (Opnd.type == o_far) {
-			msg(" Operand %d : FarPtrImmed", i);
-			PrintDefUse(CanonicalFeatures, i);
-		}
-		else if (Opnd.type == o_near) {
-			msg(" Operand %d : NearPtrImmed", i);
-			PrintDefUse(CanonicalFeatures, i);
-		}
-		else {
-			msg(" Operand %d : unknown", i);
-			PrintDefUse(CanonicalFeatures, i);
-		}
-		if (!(Opnd.showed()))
-			msg(" HIDDEN ");
-	}
-	msg(" \n");
-	return;
-}
-
-// Emit annotations for constants used as ptr offsets from EBP or
-//  ESP into the stack frame. Only pay attention to EBP-relative
-//  offsets if EBP is being used as a frame pointer (UseFP == true).
-void AnnotateStackConstants(bool UseFP, insn_t Inst, char *disasm, FILE *AnnotFile) {
-	op_t Opnd;
-	for (int i = 0; i < UA_MAXOP; ++i) {
-		Opnd = Inst.Operands[i];
-		if (Opnd.type == o_displ) {
-			ea_t offset = Opnd.addr;
-			if (Opnd.hasSIB && (0 != offset)) {
-				int BaseReg = sib_base(Opnd);
-				short IndexReg = sib_index(Opnd);
-#define NAME_LEN 5
-				if (BaseReg == R_sp) { // EBP cannot be base reg in SIB
-					// ESP-relative constant offset
-					qfprintf(AnnotFile,
-							"%x %d PTRIMMEDESP STACK %d %s\n",
-							Inst.ea, Inst.size, offset, disasm);
-				}
-				else if (IndexReg == R_bp) { // ESP cannot be index reg
-					// EBP-relative constant offset
-					qfprintf(AnnotFile,
-							"%x %d PTRIMMEDEBP STACK %d %s\n",
-							Inst.ea, Inst.size, offset, disasm);
-				}
-			}
-			else {
-				int BaseReg = Opnd.reg;
-				if (offset != 0) { // Don't annotate zero ???
-					if (UseFP && (R_bp == BaseReg)) {
-						// EBP-relative constant offset
-						qfprintf(AnnotFile,
-							"%x %d PTRIMMEDEBP STACK %d %s\n",
-							Inst.ea, Inst.size, offset, disasm);
-					}
-					else if (R_sp == BaseReg) {
-						// ESP-relative constant offset
-						qfprintf(AnnotFile,
-							"%x %d PTRIMMEDESP STACK %d %s\n",
-							Inst.ea, Inst.size, offset, disasm);
-					}
-				}
-			} // end (if Opnd.hasSIB ... else ... )
-		} // end if (Opnd.type == o_displ)
-	} // end for all operands
-	return;
-} // end AnnotateStackConstants()
-
-// Does the instruction whose flags are in F have a numeric type
-//   as the second source operand?
-// NOTE: We can only analyze immediate values now, using a heuristic
-//   that values in the range +/- 8K are numeric and others are
-//   probably addresses. When data flow analyses are implemented,
-//   we will be able to analyze many non-immediate operands.
-#define IMMEDNUM_LOWER -8191
-#define IMMEDNUM_UPPER 8191
-bool IsSecondOperandNumeric(flags_t F, insn_t Instr, char *disasm) {
-	bool SecondOpImm = (Instr.Operands[1].type == o_imm);
-	signed long TempImm;
-
-	if (SecondOpImm) {
-		TempImm = (signed long) Instr.Operands[1].value;
-	}
-
-#if SMP_DEBUG
-	if (SecondOpImm && (0 > TempImm)) {
-#if 0
-		msg("Negative immediate: %d Hex: %x ASM: %s\n", TempImm,
-			Instr.Operands[1].value, disasm);
-#endif
-	}
-	else if ((!SecondOpImm) && (Instr.Operands[1].type == o_imm)) {
-		msg("Problem with flags on immediate src operand: %s\n", disasm);
-	}
-#endif
-
-	return (SecondOpImm && (TempImm > IMMEDNUM_LOWER)
-		&& (TempImm < IMMEDNUM_UPPER));
-} // end IsSecondoperandNumeric()
-
-// Is the instruction the one that allocates space on the
-//  stack for the local variables of size LocSize?
-bool IsFrameAllocInstr(insn_t Instr, asize_t LocSize) {
-	// The frame allocating instruction should look like:
-	//   sub esp,48   or   add esp,-64   etc.
-	if ((Instr.itype == NN_sub) || (Instr.itype == NN_add)) {
-		if ((Instr.Operands[0].type == o_reg)
-			&& (Instr.Operands[0].reg == R_sp)) {
-			// We know that an addition or subtraction is being
-			// performed on the stack pointer. This should not be
-			// possible within the prologue except at the stack
-			// frame allocation instruction, so return true. We
-			// could be more robust in this analysis in the future. **!!**
-			return true;
-		}
-	}
-	return false;
-} // end IsFrameAllocInstr()
-
-// Get the stack frame info so we can emit stack
-//  annotations when we reach the stack allocation
-//  instruction that sets aside space for local vars.
-// Return the address of the instruction at which these
-//  annotations should be emitted. This should normally
-//  be an instruction such as:  sub esp,48
-//  However, for a function with no local variables at all,
-//  we will need to determine which instruction should be
-//  considered to be the final instruction of the function
-//  prologue and return its address.
-ea_t GetStackFrameInfo(func_t *FuncInfo, char *FuncName,
-					   asize_t &LocalVarsSize, ushort &CalleeSavedRegsSize,
-					   int &ReturnAddressSize, asize_t &IncomingArgsSize) {
-	// member_t *FrameMember;
-	// struc_t *FrameStruct = get_frame(FuncInfo);
-
-	// The sizes of the three regions of the stack frame other than the
-	//  return address are stored in the function structure.
-	LocalVarsSize = FuncInfo->frsize;
-	CalleeSavedRegsSize = FuncInfo->frregs;
-	IncomingArgsSize = FuncInfo->argsize;
-
-	// The return address size can be obtained in a machine independent
-	//  way by calling get_frame_retsize(). 
-	ReturnAddressSize = get_frame_retsize(FuncInfo);
-
-	// Now, if LocalVarsSize is not zero, we need to find the instruction
-	//  in the function prologue that allocates space on the stack for
-	//  local vars. This code could be made more robust in the future
-	//  by matching LocalVarsSize to the immediate value in the allocation
-	//  instruction. **!!**
-	if (0 < LocalVarsSize) {
-		for (ea_t addr = FuncInfo->startEA; addr < FuncInfo->endEA;
-			addr = get_item_end(addr)) {
-			flags_t InstrFlags = getFlags(addr);
-			if (isHead(InstrFlags) && isCode(InstrFlags)) {
-				ua_ana0(addr);
-				if (IsFrameAllocInstr(cmd, LocalVarsSize)) {
-					return addr;
-				}
-			}
-		}
-		// Could not find the frame allocating instruction.  Bad.
-		// Emit diagnostic and return the first instruction in the
-		// function.
-		msg("ERROR: Could not find stack frame allocation in %s\n",
-			FuncName);
-		return FuncInfo->startEA;
-	}
-	// else LocalVarsSize was zero, meaning that we need to search for the
-	//   end of the function prologue code and emit stack frame annotations
-	//   from that address (i.e. this function returns that address). We
-	//   will approximate this by finding the end of the sequence of PUSH
-	//   instructions at the beginning of the function. The last PUSH
-	//   instruction should be the last callee-save-reg instruction. We can
-	//   make this more robust in the future by making sure that we do not
-	//   count a PUSH of anything other than a register. **!!**
-	else {
-		ea_t SaveAddr = FuncInfo->startEA;
-		for (ea_t addr = FuncInfo->startEA; addr < FuncInfo->endEA;
-			addr = get_item_end(addr)) {
-			flags_t InstrFlags = getFlags(addr);
-			if (isHead(InstrFlags) && isCode(InstrFlags)) {
-				ua_ana0(addr);
-				if (cmd.itype == NN_push) {
-					SaveAddr = addr;
-				}
-				else {
-					return SaveAddr;
-				}
-			}
-		}
-		// If we reach this spot, we have a function composed entirely
-		//  of PUSH instructions, with not even a return instruction.
-		// Very bad news!
-		msg("FATAL ERROR in StaticAnalyzer::GetStackFrameInfo\n");
-		return SaveAddr;
-	} // end if (0 < LocalVarsSize) ... else ...
-} // end GetStackFrameInfo()
-
-// Emit the annotations describing the regions of the stack frame.
-void EmitStackFrameAnnotations(ea_t addr, insn_t Instr, char *disasm,
-				    FILE *AnnotFile,
-					asize_t LocalVarsSize, ushort CalleeSavedRegsSize,
-					int RetAddrSize, asize_t IncomingArgsSize) {
-	if (0 < IncomingArgsSize)
-		qfprintf(AnnotFile, "%x %d INARGS STACK esp + %d %s \n",
-				addr, IncomingArgsSize,
-				(LocalVarsSize + CalleeSavedRegsSize + RetAddrSize),
-				disasm);
-	if (0 < RetAddrSize)
-		qfprintf(AnnotFile, "%x %d MEMORYHOLE STACK esp + %d ReturnAddress \n",
-				addr, RetAddrSize, (LocalVarsSize + CalleeSavedRegsSize));
-	if (0 < CalleeSavedRegsSize)
-		qfprintf(AnnotFile, "%x %d MEMORYHOLE STACK esp + %d CalleeSavedRegs \n",
-				addr, CalleeSavedRegsSize, LocalVarsSize);
-	if (0 < LocalVarsSize)
-		qfprintf(AnnotFile, "%x %d LOCALFRAME STACK esp + %d LocalVars \n",
-				addr, LocalVarsSize, 0);
-	return;
-} // end EmitStackFrameAnnotations() 
-
-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) {
-	// Skip this plugin if it was not specified by the user on the
-	//  command line.
-	if (get_plugin_options("SMPStaticAnalyzer") == NULL) {
-		return PLUGIN_SKIP;
-	}
-	// 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();
-	return PLUGIN_KEEP;
-}
-
-void IDAP_term(void) {
-	unhook_from_notification_point(HT_IDP, idp_callback, NULL);
-	return;
-}
-
-void IDAP_run(int arg) {
-	// The types of data objects based on their first operand flags.
-	char *DataTypes[] = { "VOID", "NUMHEX", "NUMDEC", "CHAR",
-		"SEG", "OFFSET", "NUMBIN", "NUMOCT", "ENUM", "FORCED", 
-		"STRUCTOFFSET", "STACKVAR", "NUMFLOAT", "UNKNOWN", 
-		"UNKNOWN", "UNKNOWN", 0};
-
-	segment_t *seg;
-	char buf[MAXSTR];
-	ea_t ea;
-	flags_t ObjFlags;
-	bool ReadOnlyFlag;
-	FILE *SymsFile;
-	int OptCount[LAST_OPT_CATEGORY + 1];
-	int AnnotationCount[LAST_OPT_CATEGORY + 1];
-
-#if SMP_DEBUG
-    int FuncsProcessed = 0;
-	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
-			for (size_t FuncIndex = 0; FuncIndex < get_func_qty(); ++FuncIndex) {
-				func_t *FuncInfo = getn_func(FuncIndex);
-				char FuncName[MAXSTR];
-				size_t FuncSize = FuncInfo->endEA - FuncInfo->startEA;
-				bool UseBP = (0 != (FuncInfo->flags & (FUNC_FRAME | FUNC_BOTTOMBP)));
-				bool StaticFunc = (0 != (FuncInfo->flags & FUNC_STATIC));
-				asize_t LocalVarsSize;
-				ushort CalleeSavedRegsSize;
-				int RetAddrSize;
-				asize_t IncomingArgsSize;
-				ea_t LocalVarsAllocInstr;
-				// 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)
-					|| (FuncInfo->endEA > seg->endEA)) {
-					continue;
-				}
-				// Get the function name
-				get_func_name(FuncInfo->startEA, FuncName, sizeof(FuncName)-1);
-				
-				if (StaticFunc) {
-					qfprintf(SymsFile,
-						"%x %d FUNC LOCAL  %s ", FuncInfo->startEA,
-						FuncSize, FuncName);
-				}
-				else {
-					qfprintf(SymsFile,
-						"%x %d FUNC GLOBAL %s ", FuncInfo->startEA,
-						FuncSize, FuncName);
-				}
-				if (UseBP) {
-					qfprintf(SymsFile, "USEFP ");
-				}
-				else {
-					qfprintf(SymsFile, "NOFP ");
-				}
-				if (FuncInfo->does_return()) {
-					qfprintf(SymsFile, "\n");
-				}
-				else {
-					qfprintf(SymsFile, "NORET \n");
-				}
-
-#if SMP_BINARY_DEBUG
-				if (FuncsProcessed++ > SMP_DEBUG_COUNT) {
-					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) {
-					msg("Final FuncName:  %s \n", FuncName);
-				}
-#endif
-				// Get the stack frame info so we can emit stack
-				//  annotations when we reach the stack allocation
-				//  instruction that sets aside space for local vars.
-				LocalVarsAllocInstr = GetStackFrameInfo(FuncInfo, FuncName,
-					LocalVarsSize, CalleeSavedRegsSize, RetAddrSize,
-					IncomingArgsSize);
-				// Loop through all instructions in the function.
-				// Output optimization annotations for those
-				//  instructions that do not require full computation
-				//  of their memory metadata by the Memory Monitor SDT.
-				for (ea_t addr = FuncInfo->startEA; addr < FuncInfo->endEA;
-					  addr = get_item_end(addr)) {
-					flags_t InstrFlags = getFlags(addr);
-					if (isHead(InstrFlags) && isCode(InstrFlags)) {
-						char disasm[MAXSTR]; // disassembly text for instr
-						int OptType;  // OptCategory for current instr
-						bool MemDest; // memory destination operand?
-						bool SrcDest; // memory source operand?
-						bool SecondOperandNum; // numeric 2nd src operand?
-
-						// Fill cmd structure with disassembly of instr
-						//  and get the instr disassembly text.
-						ua_ana0(addr);
-						(void) generate_disasm_line(addr, disasm, sizeof(disasm) - 1);
-						// Remove interactive color-coding tags.
-						tag_remove(disasm, disasm, 0);
-#if SMP_BINARY_DEBUG
-						if (FuncsProcessed > SMP_DEBUG_COUNT) {
-							msg("Disasm:  %s \n", disasm);
-						}
-#endif
-
-						MemDest = IsDestMemoryOperand(cmd);
-						SrcDest = IsSrcMemoryOperand(cmd);
-						SecondOperandNum = IsSecondOperandNumeric(InstrFlags,
-							cmd, disasm);
-						// Get optimization category.
-						OptType = OptCategory[cmd.itype];
-						++OptCount[OptType]; // keep count for debugging info
-
-						// If this is the instruction which allocated space
-						//  for local variables, we want to emit annotations
-						//  describing the stack frame.
-						if (addr == LocalVarsAllocInstr) {
-							EmitStackFrameAnnotations(addr, cmd, disasm,
-								SymsFile, LocalVarsSize, CalleeSavedRegsSize,
-								RetAddrSize, IncomingArgsSize);
-						}
-
-#if SMP_DEBUG3
-						// if (MemDest || SrcDest) {
-						if (OptType >= 0) {
-							msg("OptType: %d %s", OptType, disasm);
-							PrintOperands(cmd);
-						}
-#endif
-
-						// Emit appropriate optimization annotations.
-						bool SDTInstrumentation = false;
-						switch (OptType) {
-							case 0:  // SDT will have to handle these
-								{
-#if SMP_DEBUG_TYPE0
-								  msg("OptType 0: %x  %s\n", addr, disasm);
-#endif
-								  SDTInstrumentation = true;
-								  break;
-								}
-
-							case 1:  // nothing for SDT to do
-								{ qfprintf(SymsFile, "%x %d INSTR LOCAL NoMetaUpdate %s \n",
-									addr, -1, disasm);
-								  ++AnnotationCount[OptType];
-								  break;
-								}
-
-							case 4:  // INC, DEC, etc.: no SDT work unless MemDest
-								{ if (MemDest || SrcDest) {
-									SDTInstrumentation = true;
-									break;  // treat as category 0
-								  }
-								  qfprintf(SymsFile, "%x %d INSTR LOCAL Always1stSrc %s \n",
-									addr, -1, disasm);
-								  ++AnnotationCount[OptType];
-								  break;
-								}
-
-							case 5: // ADD, etc.: If numeric 2nd src operand, no SDT work.
-								{ if (MemDest || SrcDest) {
-									SDTInstrumentation = true;
-									break;  // treat as category 0
-								  }
-								  if (SecondOperandNum) { // treat as category 1
-									  qfprintf(SymsFile, "%x %d INSTR LOCAL %s %s \n",
-										addr, -1, OptExplanation[OptType], disasm);
-									  ++AnnotationCount[OptType];
-								  }
-								  break;
-								}
-
-							case 6: // Only OS code should include these; problem for SDT
-								{ if (MemDest) {
-									SDTInstrumentation = true;
-									break;  // treat as category 0
-								  }
-								  qfprintf(SymsFile, "%x %d INSTR LOCAL AlwaysPTR %s \n",
-	
-								    addr, -OptType, disasm);
-								  ++AnnotationCount[OptType];
-								  break;
-								}
-
-							case 8: // Implicitly writes to EDX:EAX, always numeric.
-								{ qfprintf(SymsFile, "%x %d INSTR LOCAL n EDX EAX ZZ %s %s \n",
-									addr, -2, OptExplanation[OptType], disasm);
-								  ++AnnotationCount[OptType];
-								  SDTInstrumentation = true;
-								  break;
-								}
-
-							case 9:  // Either writes to FP reg (cat. 1) or memory (cat. 0)
-								{ if (MemDest) {
-#if SMP_DEBUG
-									  // MemDest seems to happen too much.
-									  msg("Floating point MemDest: %s \n",
-										  disasm);
-#endif
-									  SDTInstrumentation = true;
-									  break; // treat as category 0
-								  }
-								  qfprintf(SymsFile, "%x %d INSTR LOCAL %s %s \n",
-									addr, -1, OptExplanation[OptType], disasm);
-								  ++AnnotationCount[OptType];
-								  break;
-								}
-
-							default: // 2,3,7: Optimization possibilities depend on operands
-								{ 
-#if SMP_DEBUG2
-									if (OptType ==  3) {  // MOV instr class
-										if (MemDest) {
-											msg("MemDest on MOV: %s\n", disasm);
-										}
-										else if (!SecondOperandNum) {
-											msg("MOV: not 2nd op numeric: %s\n", disasm);
-											PrintOperands(cmd);
-										}
-									}
-#endif
-								  SDTInstrumentation = true;
-								  if (MemDest) break;  // treat as category 0
-								  if ((OptType == 2) || (OptType == 7) || SecondOperandNum) {
-									  qfprintf(SymsFile, "%x %d INSTR LOCAL n %s %s %s \n",
-										   addr, -2, DestString(cmd, OptType, disasm), 
-										OptExplanation[OptType], disasm);
-									  ++AnnotationCount[OptType];
-								  }
-								  break;
-								}
-						} // end switch (OptType)
-						// If mmStrata is going to have to deal with the
-						//  instruction, then we can annotate EBP and ESP
-						//  relative constant offsets. If we have emitted
-						//  an annotation of type -1, there is no point
-						//  in telling mmStrata about these constants.
-						if (SDTInstrumentation) {
-							AnnotateStackConstants(UseBP, cmd, disasm, SymsFile);
-						}
-					} // end if (isHead && isCode)
-				}  // end for (ea_t addr = FuncInfo->startEA; ...)
-			} // 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; ... )
-
-#if 0  // Segments produced slightly more useful data objects than names.
-	// Next, for comparison, loop through all names and print the
-	//  name, address, and size for all data objects.
-    size_t NumberOfNames = get_nlist_size();
-#if SMP_DEBUG
-	msg("Processing %d names. \n", NumberOfNames);
-#endif
-	for (int i = 0; i < (int) NumberOfNames; ++i) {
-        ea = get_nlist_ea(i);
-		ObjFlags = get_flags_novalue(ea);
-		if (isData(ObjFlags)) {
-		    // Compute the size of the data object.
-			ea_t NextEA = ea;
-			seg = getseg(ea);
-		    do {
-		       NextEA = nextaddr(NextEA);
-			} while ((NextEA < seg->endEA) && isTail(get_flags_novalue(NextEA)));
-		    size_t ObjSize = (size_t) (NextEA - ea);
-			// Get the data object name using its address.
-		    get_true_name(BADADDR, ea, buf, sizeof(buf));	
-		    // Output the name, address, size, and type info.
-		    qfprintf(SymsFile, 
-				"%x %d OBJECT GLOBAL %s  %s \n", ea, ObjSize,
-		  	    buf, DataTypes[get_optype_flags0(ObjFlags) >> 20]);
-		}
-	}  // end for (int i = 0; i < NumberOfNames; ...)
-#endif
-
-	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
-};
-
-// Print out the destination operand list for the instruction, given
-//  the OptCategory for the instruction as a hint.
-char *DestString(insn_t Instr, int OptType, char *disasm) {
-	static char DestList[MAXSTR];
-	if (OptType != 7) {
-		if (Instr.Operands[0].type != o_reg) {
-			msg("Problem: destination operand not memory and not reg: %d %d %s \n",
-				Instr.Operands[0].type, Instr.Operands[1].type, disasm);
-		}
-		else {
-			ushort DestReg = Instr.Operands[0].reg;
-			qstrncpy(DestList, RegNames[DestReg],
-					1 + strlen(RegNames[DestReg]));
-#if 1
-			qstrncat(DestList, " ZZ ", MAXSTR);
-#endif
-			return DestList;
-		}
-	}
-	else { // OptType 7 could have one or two destinations.
-		// NOTE: FIX later. Currently a clone of code above.     **
-#if SMP_DEBUG3
-		msg("OptType 7: %s\n", disasm);
-		PrintOperands(Instr);
-#endif
-		if (Instr.Operands[0].type != o_reg) {
-			msg("Problem: destination operand not memory and not reg: %d %d %s\n",
-				Instr.Operands[0].type, Instr.Operands[1].type, disasm);
-		}
-		else {
-			ushort DestReg = Instr.Operands[0].reg;
-			qstrncpy(DestList, RegNames[DestReg],
-					1 + strlen(RegNames[DestReg]));
-#if 1
-			qstrncat(DestList, " ZZ ", MAXSTR);
-#endif
-			return DestList;
-		}
-	}
-	DestList[0] = '\0';
-	return DestList;
-} // end of DestString()
-
-
-// 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;
-
-}
-- 
GitLab