//
// SMPDataFlowAnalysis.cpp
//
// This module contains common types an helper classes needed for the
//   SMP project (Software Memory Protection).
//

#include <list>
#include <set>
#include <vector>
#include <algorithm>

#include <cstring>

#include <pro.h>
#include <assert.h>
#include <ida.hpp>
#include <idp.hpp>
#include <allins.hpp>
#include <auto.hpp>
#include <bytes.hpp>
#include <funcs.hpp>
#include <intel.hpp>
#include <loader.hpp>
#include <lines.hpp>
#include <name.hpp>

#include "SMPDataFlowAnalysis.h"
#include "SMPStaticAnalyzer.h"

// Set to 1 for debugging output
#define SMP_DEBUG 1
#define SMP_DEBUG2 0   // verbose
#define SMP_DEBUG3 0   // verbose
#define SMP_DEBUG_CONTROLFLOW 0  // tells what processing stage is entered
#define SMP_DEBUG_XOR 0
#define SMP_DEBUG_CHUNKS 1  // tracking down tail chunks for functions
#define SMP_DEBUG_FRAMEFIXUP 0
#define SMP_DEBUG_DATAFLOW 0
#define SMP_DEBUG_OPERAND_TYPES 1  // leave on; should never happen

char *RegNames[R_of + 1] =
	{ "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI",
	  "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
	  "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH",
	  "SPL", "BPL", "SIL", "DIL", "EIP", "ES", "CS", "SS",
	  "DS", "FS", "GS", "CF", "ZF", "SF", "OF" 
	};

// Define instruction categories for data flow analysis.
SMPitype DFACategory[NN_last+1];
// Define instruction categories for data type analysis.
int SMPTypeCategory[NN_last+1];

// Define which instructions define and use the CPU flags.
bool SMPDefsFlags[NN_last + 1];
bool SMPUsesFlags[NN_last + 1];

// Get the size in bytes of the data type of an operand.
size_t GetOpDataSize(op_t DataOp) {
	size_t DataSize;
	switch (DataOp.dtyp) {
		case dt_byte:
			DataSize = 1;
			break;
		case dt_word:
			DataSize = 2;
			break;
		case dt_dword:
		case dt_float:
		case dt_code:
		case dt_unicode:
		case dt_string:
			DataSize = 4;
			break;
		case dt_double:
		case dt_qword:
			DataSize = 8;
			break;
		case dt_packreal:
			DataSize = 12;
			break;
		case dt_byte16:
			DataSize = 16;
			break;
		case dt_fword:
			DataSize = 6;
			break;
		case dt_3byte:
			DataSize = 3;
			break;
		default:
			msg("WARNING: unexpected data type %d in GetOpDataSize() :", DataOp.dtyp);
			PrintOperand(DataOp);
			msg("\n");
			DataSize = 4;
			break;
	}
	return DataSize;
} // end of GetOpDataSize()

// We need to make subword registers equal to their containing registers when we
//  do comparisons, so that we will realize that register EAX is killed by a prior DEF
//  of register AL, for example, and vice versa. To keep sets ordered strictly,
//  we also have to make AL and AH be equal to each other as well as equal to EAX.
#define FIRST_x86_SUBWORD_REG R_al
#define LAST_x86_SUBWORD_REG R_bh
bool MDLessReg(const ushort Reg1, const ushort Reg2) {
	ushort SReg1 = MDCanonicalizeSubReg(Reg1);
	ushort SReg2 = MDCanonicalizeSubReg(Reg2);
	return (SReg1 < SReg2);
} // end of MDLessReg()

ushort MDCanonicalizeSubReg(const ushort Reg1) {
	bool Subword = ((Reg1 >= FIRST_x86_SUBWORD_REG) && (Reg1 <= LAST_x86_SUBWORD_REG));
	ushort SReg1 = Reg1;

	if (Subword) {
		// See enumeration RegNo in intel.hpp.
		if (SReg1 < 20)  // AL, CL, DL or BL
			SReg1 -= 16;
		else             // AH, CH, DH or BH
			SReg1 -= 20;
	}
	return SReg1;
} // end of MDCanonicalizeSubReg()

// In SSA computations, we are storing the GlobalNames index into the op_t fields
//  n, offb, and offo. This function extracts an unsigned int from these three 8-bit
//  fields.
unsigned int ExtractGlobalIndex(op_t GlobalOp) {
	unsigned int index = 0;
	index |= (((unsigned int) GlobalOp.offo) & 0x000000ff);
	index <<= 8;
	index |= (((unsigned int) GlobalOp.offb) & 0x000000ff);
	index <<= 8;
	index |= (((unsigned int) GlobalOp.n) & 0x000000ff);
	return index;
}

void SetGlobalIndex(op_t *TempOp, size_t index) {
	TempOp->n = (char) (index & 0x000000ff);
	TempOp->offb = (char) ((index & 0x0000ff00) >> 8);
	TempOp->offo = (char) ((index & 0x00ff0000) >> 16);
	return;
}

// DEBUG Print DEF and/or USE for an operand.
void PrintDefUse(ulong feature, int OpNum) {
	// CF_ macros number the operands from 1 to 6, while OpNum
	//  is a 0 to 5 index into the insn_t.Operands[] array.
	// OpNum == -1 is a signal that this is a DEF or USE or VarKillSet etc.
	//  operand and not an instruction operand.
	if (-1 == OpNum)
		return;
	switch (OpNum) {
		case 0:
			if (feature & CF_CHG1)
				msg(" DEF");
			if (feature & CF_USE1)
				msg(" USE");
			break;
		case 1:
			if (feature & CF_CHG2)
				msg(" DEF");
			if (feature & CF_USE2)
				msg(" USE");
			break;
		case 2:
			if (feature & CF_CHG3)
				msg(" DEF");
			if (feature & CF_USE3)
				msg(" USE");
			break;
		case 3:
			if (feature & CF_CHG4)
				msg(" DEF");
			if (feature & CF_USE4)
				msg(" USE");
			break;
		case 4:
			if (feature & CF_CHG5)
				msg(" DEF");
			if (feature & CF_USE5)
				msg(" USE");
			break;
		case 5:
			if (feature & CF_CHG6)
				msg(" DEF");
			if (feature & CF_USE6)
				msg(" USE");
			break;
	}
	return;
} // end PrintDefUse()

// DEBUG print SIB info for an operand.
void PrintSIB(op_t Opnd) {
	int BaseReg = sib_base(Opnd);
	short IndexReg = sib_index(Opnd);
	int ScaleFactor = sib_scale(Opnd);
#define NAME_LEN 5
	char BaseName[NAME_LEN] = {'N', 'o', 'n', 'e', '\0'};
	char IndexName[NAME_LEN] = {'N', 'o', 'n', 'e', '\0'};
#if 1
	if (!((BaseReg == R_bp) && (Opnd.type == o_mem))) // EBP can be SIB code for NO BASE REG
#endif
		qstrncpy(BaseName, RegNames[BaseReg], NAME_LEN - 1);

	if (IndexReg != R_sp) { // SIB code for NO INDEX REG
		qstrncpy(IndexName, RegNames[IndexReg], NAME_LEN -1);
	}
	msg(" Base %s Index %s Scale %d", BaseName, IndexName, ScaleFactor);
} // end PrintSIB()

// Debug: print one operand from an instruction or DEF or USE list.
void PrintOneOperand(op_t Opnd, ulong features, int OpNum) { 
	if (Opnd.type != o_void) {
		PrintOperand(Opnd);
		PrintDefUse(features, OpNum);
	}
	return;
} // end of PrintOneOperand()

// Debug: print one operand.
void PrintOperand(op_t Opnd) { 
	if (Opnd.type == o_void)
		return;
	else if (Opnd.type == o_mem) {
		msg(" Operand: memory : addr: %x", Opnd.addr);
		if (Opnd.hasSIB) {
			PrintSIB(Opnd);
		}
	}
	else if (Opnd.type == o_phrase) {
		msg(" Operand: memory phrase :");
		if (Opnd.hasSIB) { // has SIB info
			PrintSIB(Opnd);
		}
		else { // no SIB info
			ushort BaseReg = Opnd.phrase;
			msg(" reg %s", RegNames[BaseReg]);
		}
		if (Opnd.addr != 0) {
			msg(" \n WARNING: addr for o_phrase type: %d\n", Opnd.addr);
		}
	}
	else if (Opnd.type == o_displ) {
		msg(" Operand: memory displ :");
		ea_t offset = Opnd.addr;
		if (Opnd.hasSIB) {
			PrintSIB(Opnd);
			msg(" displ %d", offset);
		}
		else {
			ushort BaseReg = Opnd.reg;
			msg(" reg %s displ %d", RegNames[BaseReg], offset);
		}
	}
	else if (Opnd.type == o_reg) {
		msg(" Operand: register %s", RegNames[Opnd.reg]);
	}
	else if (Opnd.type == o_imm) {
		msg(" Operand: immed %d", Opnd.value);
	}
	else if (Opnd.type == o_far) {
		msg(" Operand: FarPtrImmed addr: %x", Opnd.addr);
	}
	else if (Opnd.type == o_near) {
		msg(" Operand: NearPtrImmed addr: %x", Opnd.addr);
	}
	else if (Opnd.type == o_trreg) {
		msg(" Operand: TaskReg reg: %d", Opnd.reg);
	}
	else if (Opnd.type == o_dbreg) {
		msg(" Operand: DebugReg reg: %d", Opnd.reg);
	}
	else if (Opnd.type == o_crreg) {
		msg(" Operand: ControlReg reg: %d", Opnd.reg);
	}
	else if (Opnd.type == o_fpreg) {
		msg(" Operand: FloatReg reg: %d", Opnd.reg);
	}
	else if (Opnd.type == o_mmxreg) {
		msg(" Operand: MMXReg reg: %d", Opnd.reg);
	}
	else if (Opnd.type == o_xmmreg) {
		msg(" Operand: XMMReg reg: %d", Opnd.reg);
	}
	else {
		msg(" Operand: unknown");
	}
	if (!(Opnd.showed()))
		msg(" HIDDEN ");
	return;
} // end of PrintOperand()

// Print an operand that has no features flags or operand position number, such
//  as the op_t types found in lists and sets throughout the blocks, phi functions, etc.
void PrintListOperand(op_t Opnd, int SSANum) {
	if (Opnd.type != o_void) {
		PrintOperand(Opnd);
		msg(" SSANum: %d ", SSANum);
	}
	return;
} // end of PrintListOperand()

// MACHINE DEPENDENT: Is operand type a known type that we want to analyze?
bool MDKnownOperandType(op_t TempOp) {
	bool GoodOpType = ((TempOp.type >= o_reg) && (TempOp.type <= o_xmmreg));
#if SMP_DEBUG_OPERAND_TYPES
	if (!GoodOpType && (o_void != TempOp.type)) {
		msg("WARNING: Operand type %d \n", TempOp.type);
	}
#endif 
	return GoodOpType;
}

// *****************************************************************
// Class DefOrUse
// *****************************************************************

// Default constructor to make the compilers happy.
DefOrUse::DefOrUse(void) {
	this->OpType = UNINIT;
	this->SSANumber = -2;
	return;
}

// Constructor.
DefOrUse::DefOrUse(op_t Ref, SMPOperandType Type, int SSASub) {
	if (o_reg == Ref.type) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		Ref.reg = MDCanonicalizeSubReg(Ref.reg);
	}
	this->Operand = Ref;
	this->OpType = Type;
	this->SSANumber = SSASub;
	return;
}

// Copy constructor.
DefOrUse::DefOrUse(const DefOrUse &CopyIn) {
	*this = CopyIn;
	return;
}

// Assignment operator for copy constructor use.
DefOrUse &DefOrUse::operator=(const DefOrUse &rhs) {
	this->Operand = rhs.Operand;
	this->OpType = rhs.OpType;
	this->SSANumber = rhs.SSANumber;
	return *this;
}

// Debug printing.
void DefOrUse::Dump(void) const {
	PrintListOperand(this->Operand, this->SSANumber);
	if (this->OpType == NUMERIC)
		msg("N ");
	else if (this->OpType == CODEPTR)
		msg("C ");
	else if (this->OpType == POINTER)
		msg("P ");
	else if (this->OpType == STACKPTR)
		msg("S ");
	else if (this->OpType == GLOBALPTR)
		msg("G ");
	else if (this->OpType == HEAPPTR)
		msg("H ");
	else if (this->OpType == PTROFFSET)
		msg("O ");
	else if (this->OpType == UNKNOWN)
		msg("U ");
	// Don't write anything for UNINIT OpType
	return;
} // end of DefOrUse::Dump()

// *****************************************************************
// Class DefOrUseSet
// *****************************************************************

// Default constructor.
DefOrUseSet::DefOrUseSet(void) {
	return;
}

// Find the reference for a given operand type.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::FindRef(op_t SearchOp) {
	set<DefOrUse, LessDefUse>::iterator CurrRef;
	DefOrUse DummyRef(SearchOp);
	CurrRef = this->Refs.find(DummyRef);
	return CurrRef;
}

// Set a Def or Use into the list, along with its type.
void DefOrUseSet::SetRef(op_t Ref, SMPOperandType Type, int SSASub) {
	DefOrUse CurrRef(Ref, Type, SSASub);
	this->Refs.insert(CurrRef);
	return;
}

// Change the SSA subscript for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetSSANum(op_t CurrOp, int NewSSASub) {
	// To change a field within a set, we must grab a copy, change the copy,
	//  delete the old set member, and insert the updated copy as a new member.
	set<DefOrUse, LessDefUse>::iterator CurrRef = this->FindRef(CurrOp);
	assert(CurrRef != this->Refs.end());
	set<DefOrUse, LessDefUse>::iterator NextRef = CurrRef;
	++NextRef;
	DefOrUse NewCopy = (*CurrRef);
	NewCopy.SetSSANum(NewSSASub);
	this->Refs.erase(CurrRef);
	CurrRef = this->Refs.insert(NextRef, NewCopy);
	return CurrRef;
}

// Change the operand type for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetType(op_t CurrOp, SMPOperandType Type) {
	// To change a field within a set, we must grab a copy, change the copy,
	//  delete the old set member, and insert the updated copy as a new member.
	set<DefOrUse, LessDefUse>::iterator CurrRef = this->FindRef(CurrOp);
	assert(CurrRef != this->Refs.end());
#if 1
	if (o_imm == CurrOp.type) {
		if (UNINIT != CurrRef->GetType()) {
			msg("ERROR: Changing type of immediate to %d : ", Type);
			CurrRef->Dump();
			msg("\n");
		}
	}
#endif
	DefOrUse NewCopy = (*CurrRef);
	NewCopy.SetType(Type);
	this->Refs.erase(CurrRef);
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	InsertResult = this->Refs.insert(NewCopy);
	assert(InsertResult.second);
	CurrRef = InsertResult.first;
	return CurrRef;
}

// Debug printing.
void DefOrUseSet::Dump(void) {
	set<DefOrUse, LessDefUse>::iterator CurrRef;
	for (CurrRef = this->Refs.begin(); CurrRef != this->Refs.end(); ++CurrRef) {
		CurrRef->Dump();
	}
	msg("\n");
	return;
}


// *****************************************************************
// Class DefOrUseList
// *****************************************************************

// Default constructor.
DefOrUseList::DefOrUseList(void) {
	return;
}

// Set a Def or Use into the list, along with its type.
void DefOrUseList::SetRef(op_t Ref, SMPOperandType Type, int SSASub) {
	DefOrUse CurrRef(Ref, Type, SSASub);
	this->Refs.push_back(CurrRef);
	return;
}

// Get a reference by index.
DefOrUse DefOrUseList::GetRef(size_t index) const {
	return Refs[index];
}

// Change the SSA subscript for a reference.
void DefOrUseList::SetSSANum(size_t index, int NewSSASub) {
	this->Refs[index].SetSSANum(NewSSASub);
	return;
}

// Change the operand type for a reference.
void DefOrUseList::SetType(size_t index, SMPOperandType Type) {
	this->Refs[index].SetType(Type);
	return;
}

// Debug printing.
void DefOrUseList::Dump(void) const {
	for (size_t index = 0; index < this->Refs.size(); ++index) {
		Refs[index].Dump();
	}
	msg("\n");
	return;
}

// Erase duplicate entries, in case SMPInstr::MDFixupDefUseLists() adds one.
void DefOrUseList::EraseDuplicates(void) {
	set<op_t, LessOp> TempRefs; // Use STL set to find duplicates
	set<op_t, LessOp>::iterator TempIter;
	vector<DefOrUse>::iterator RefIter;

	RefIter = this->Refs.begin();
	while (RefIter != this->Refs.end()) {
		TempIter = TempRefs.find(RefIter->GetOp());
		if (TempIter == TempRefs.end()) { // not already in set
			TempRefs.insert(RefIter->GetOp());
			++RefIter;
		}
		else { // found it in set already
			RefIter = this->Refs.erase(RefIter);
		}
	}
	return;
} // end of DefOrUseList::EraseDuplicates()

// *****************************************************************
// Class SMPPhiFunction
// *****************************************************************

// Constructor
SMPPhiFunction::SMPPhiFunction(int GlobIndex, const DefOrUse &Def) {
	this->index = GlobIndex;
	this->DefName = Def;
	return;
}

// Add a phi item to the list
void SMPPhiFunction::PushBack(DefOrUse Ref) {
	this->SubscriptedOps.SetRef(Ref.GetOp(), Ref.GetType(), Ref.GetSSANum());
	return;
}

// Set the SSA number of the defined variable.
void SMPPhiFunction::SetSSADef(int NewSSASub) {
	this->DefName.SetSSANum(NewSSASub);
	return;
}

// Set the SSA number of the input variable.
void SMPPhiFunction::SetSSARef(size_t index, int NewSSASub) {
	this->SubscriptedOps.SetSSANum(index, NewSSASub);
	return;
}

// Set the type of the defined variable.
void SMPPhiFunction::SetDefType(SMPOperandType Type) {
	this->DefName.SetType(Type);
	return;
}

// Set the type of the input variable.
void SMPPhiFunction::SetRefType(size_t index, SMPOperandType Type) {
	this->SubscriptedOps.SetType(index, Type);
	return;
}

// Debug printing.
void SMPPhiFunction::Dump(void) const {
	msg(" DEF: ");
	this->DefName.Dump();
	msg(" USEs: ");
	this->SubscriptedOps.Dump();
	return;
}

// *****************************************************************
// Class SMPDefUseChain
// *****************************************************************

// Constructors
SMPDefUseChain::SMPDefUseChain(void) {
	this->SSAName.type = o_void;
	this->RefInstrs.push_back(BADADDR);
	return;
}

SMPDefUseChain::SMPDefUseChain(op_t Name, ea_t Def) {
	if (o_reg == Name.type) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		Name.reg = MDCanonicalizeSubReg(Name.reg);
	}
	this->SSAName = Name;
	this->RefInstrs.push_back(Def);
	return;
}

// Set the variable name.
void SMPDefUseChain::SetName(op_t Name) {
	if (o_reg == Name.type) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		Name.reg = MDCanonicalizeSubReg(Name.reg);
	}
	this->SSAName = Name;
	return;
}

// Set the DEF instruction.
void SMPDefUseChain::SetDef(ea_t Def) {
	this->RefInstrs[0] = Def;
	return;
}

// Push a USE onto the list
void SMPDefUseChain::PushUse(ea_t Use) {
	this->RefInstrs.push_back(Use);
	return;
}

// DEBUG dump.
void SMPDefUseChain::Dump(int SSANum) {
	msg("DEF-USE chain for: ");
	PrintListOperand(this->SSAName, SSANum);
	if (this->RefInstrs.size() < 1) {
		msg(" no references.\n");
		return;
	}
	msg("\n DEF: %x USEs: ", this->RefInstrs.at(0));
	size_t index;
	for (index = 1; index < this->RefInstrs.size(); ++index)
		msg("%x ", this->RefInstrs.at(index));
	msg("\n");
	return;
} // end of SMPDefUseChain::Dump()

// *****************************************************************
// Class SMPDUChainArray
// *****************************************************************
SMPDUChainArray::SMPDUChainArray(void) {
	this->SSAName.type = o_void;
	return;
}

SMPDUChainArray::SMPDUChainArray(op_t Name) {
	if (o_reg == Name.type) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		Name.reg = MDCanonicalizeSubReg(Name.reg);
	}
	this->SSAName = Name;
	return;
}

void SMPDUChainArray::SetName(op_t Name) {
	if (o_reg == Name.type) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		Name.reg = MDCanonicalizeSubReg(Name.reg);
	}
	this->SSAName = Name;
	return;
}

// DEBUG dump.
void SMPDUChainArray::Dump(void) {
	size_t index;
	for (index = 0; index < this->DUChains.size(); ++index) {
		this->DUChains.at(index).Dump((int) index);
	}
	return;
}

// *****************************************************************
// Class SMPCompleteDUChains
// *****************************************************************

// DEBUG dump.
void SMPCompleteDUChains::Dump(void) {
	size_t index;
	for (index = 0; index < this->ChainsByName.size(); ++index) {
		this->ChainsByName.at(index).Dump();
	}
	return;
} // end of SMPCompleteDUChains::Dump()

// Initialize the DFACategory[] array to define instruction classes
//   for the purposes of data flow analysis.
void InitDFACategory(void) {
	// Default category is 0, not the start or end of a basic block.
	(void) memset(DFACategory, 0, sizeof(DFACategory));

DFACategory[NN_call] = CALL;                // Call Procedure
DFACategory[NN_callfi] = INDIR_CALL;              // Indirect Call Far Procedure
DFACategory[NN_callni] = INDIR_CALL;              // Indirect Call Near Procedure

DFACategory[NN_hlt] = HALT;                 // Halt

DFACategory[NN_int] = INDIR_CALL;                 // Call to Interrupt Procedure
DFACategory[NN_into] = INDIR_CALL;                // Call to Interrupt Procedure if Overflow Flag = 1
DFACategory[NN_int3] = INDIR_CALL;                // Trap to Debugger
DFACategory[NN_iretw] = RETURN;               // Interrupt Return
DFACategory[NN_iret] = RETURN;                // Interrupt Return
DFACategory[NN_iretd] = RETURN;               // Interrupt Return (use32)
DFACategory[NN_iretq] = RETURN;               // Interrupt Return (use64)
DFACategory[NN_ja] = COND_BRANCH;                  // Jump if Above (CF=0 & ZF=0)
DFACategory[NN_jae] = COND_BRANCH;                 // Jump if Above or Equal (CF=0)
DFACategory[NN_jb] = COND_BRANCH;                  // Jump if Below (CF=1)
DFACategory[NN_jbe] = COND_BRANCH;                 // Jump if Below or Equal (CF=1 | ZF=1)
DFACategory[NN_jc] = COND_BRANCH;                  // Jump if Carry (CF=1)
DFACategory[NN_jcxz] = COND_BRANCH;                // Jump if CX is 0
DFACategory[NN_jecxz] = COND_BRANCH;               // Jump if ECX is 0
DFACategory[NN_jrcxz] = COND_BRANCH;               // Jump if RCX is 0
DFACategory[NN_je] = COND_BRANCH;                  // Jump if Equal (ZF=1)
DFACategory[NN_jg] = COND_BRANCH;                  // Jump if Greater (ZF=0 & SF=OF)
DFACategory[NN_jge] = COND_BRANCH;                 // Jump if Greater or Equal (SF=OF)
DFACategory[NN_jl] = COND_BRANCH;                  // Jump if Less (SF!=OF)
DFACategory[NN_jle] = COND_BRANCH;                 // Jump if Less or Equal (ZF=1 | SF!=OF)
DFACategory[NN_jna] = COND_BRANCH;                 // Jump if Not Above (CF=1 | ZF=1)
DFACategory[NN_jnae] = COND_BRANCH;                // Jump if Not Above or Equal (CF=1)
DFACategory[NN_jnb] = COND_BRANCH;                 // Jump if Not Below (CF=0)
DFACategory[NN_jnbe] = COND_BRANCH;                // Jump if Not Below or Equal (CF=0 & ZF=0)
DFACategory[NN_jnc] = COND_BRANCH;                 // Jump if Not Carry (CF=0)
DFACategory[NN_jne] = COND_BRANCH;                 // Jump if Not Equal (ZF=0)
DFACategory[NN_jng] = COND_BRANCH;                 // Jump if Not Greater (ZF=1 | SF!=OF)
DFACategory[NN_jnge] = COND_BRANCH;                // Jump if Not Greater or Equal (ZF=1)
DFACategory[NN_jnl] = COND_BRANCH;                 // Jump if Not Less (SF=OF)
DFACategory[NN_jnle] = COND_BRANCH;                // Jump if Not Less or Equal (ZF=0 & SF=OF)
DFACategory[NN_jno] = COND_BRANCH;                 // Jump if Not Overflow (OF=0)
DFACategory[NN_jnp] = COND_BRANCH;                 // Jump if Not Parity (PF=0)
DFACategory[NN_jns] = COND_BRANCH;                 // Jump if Not Sign (SF=0)
DFACategory[NN_jnz] = COND_BRANCH;                 // Jump if Not Zero (ZF=0)
DFACategory[NN_jo] = COND_BRANCH;                  // Jump if Overflow (OF=1)
DFACategory[NN_jp] = COND_BRANCH;                  // Jump if Parity (PF=1)
DFACategory[NN_jpe] = COND_BRANCH;                 // Jump if Parity Even (PF=1)
DFACategory[NN_jpo] = COND_BRANCH;                 // Jump if Parity Odd  (PF=0)
DFACategory[NN_js] = COND_BRANCH;                  // Jump if Sign (SF=1)
DFACategory[NN_jz] = COND_BRANCH;                  // Jump if Zero (ZF=1)
DFACategory[NN_jmp] = JUMP;                 // Jump
DFACategory[NN_jmpfi] = INDIR_JUMP;               // Indirect Far Jump
DFACategory[NN_jmpni] = INDIR_JUMP;               // Indirect Near Jump
DFACategory[NN_jmpshort] = JUMP;            // Jump Short (only in 64-bit mode)

DFACategory[NN_loopw] = COND_BRANCH;               // Loop while ECX != 0
DFACategory[NN_loop] = COND_BRANCH;                // Loop while CX != 0
DFACategory[NN_loopd] = COND_BRANCH;               // Loop while ECX != 0
DFACategory[NN_loopq] = COND_BRANCH;               // Loop while RCX != 0
DFACategory[NN_loopwe] = COND_BRANCH;              // Loop while CX != 0 and ZF=1
DFACategory[NN_loope] = COND_BRANCH;               // Loop while rCX != 0 and ZF=1
DFACategory[NN_loopde] = COND_BRANCH;              // Loop while ECX != 0 and ZF=1
DFACategory[NN_loopqe] = COND_BRANCH;              // Loop while RCX != 0 and ZF=1
DFACategory[NN_loopwne] = COND_BRANCH;             // Loop while CX != 0 and ZF=0
DFACategory[NN_loopne] = COND_BRANCH;              // Loop while rCX != 0 and ZF=0
DFACategory[NN_loopdne] = COND_BRANCH;             // Loop while ECX != 0 and ZF=0
DFACategory[NN_loopqne] = COND_BRANCH;             // Loop while RCX != 0 and ZF=0

DFACategory[NN_retn] = RETURN;                // Return Near from Procedure
DFACategory[NN_retf] = RETURN;                // Return Far from Procedure

//
//      Pentium instructions
//

DFACategory[NN_rsm] = HALT;                 // Resume from System Management Mode

//      Pentium II instructions

DFACategory[NN_sysenter] = CALL;            // Fast Transition to System Call Entry Point
DFACategory[NN_sysexit] = CALL;             // Fast Transition from System Call Entry Point

// AMD syscall/sysret instructions  NOTE: not AMD, found in Intel manual

DFACategory[NN_syscall] = CALL;             // Low latency system call
DFACategory[NN_sysret] = CALL;              // Return from system call

// VMX instructions

DFACategory[NN_vmcall] = INDIR_CALL;              // Call to VM Monitor

  return;

} // end InitDFACategory()

// Initialize the SMPDefsFlags[] array to define how we emit
//   optimizing annotations.
void InitSMPDefsFlags(void) {
	// Default value is true. Many instructions set the flags.
	(void) memset(SMPDefsFlags, true, sizeof(SMPDefsFlags));

SMPDefsFlags[NN_null] = false;            // Unknown Operation
SMPDefsFlags[NN_bound] = false;               // Check Array Index Against Bounds
SMPDefsFlags[NN_call] = false;                // Call Procedure
SMPDefsFlags[NN_callfi] = false;              // Indirect Call Far Procedure
SMPDefsFlags[NN_callni] = false;              // Indirect Call Near Procedure
SMPDefsFlags[NN_cbw] = false;                 // AL -> AX (with sign)           
SMPDefsFlags[NN_cwde] = false;                // AX -> EAX (with sign)            
SMPDefsFlags[NN_cdqe] = false;                // EAX -> RAX (with sign)           
SMPDefsFlags[NN_clts] = false;                // Clear Task-Switched Flag in CR0
SMPDefsFlags[NN_cwd] = false;                 // AX -> DX:AX (with sign)
SMPDefsFlags[NN_cdq] = false;                 // EAX -> EDX:EAX (with sign)
SMPDefsFlags[NN_cqo] = false;                 // RAX -> RDX:RAX (with sign)
SMPDefsFlags[NN_enterw] = false;              // Make Stack Frame for Procedure Parameters   
SMPDefsFlags[NN_enter] = false;               // Make Stack Frame for Procedure Parameters   
SMPDefsFlags[NN_enterd] = false;              // Make Stack Frame for Procedure Parameters   
SMPDefsFlags[NN_enterq] = false;              // Make Stack Frame for Procedure Parameters   
SMPDefsFlags[NN_hlt] = false;                 // Halt
SMPDefsFlags[NN_in] = false;                  // Input from Port                          
SMPDefsFlags[NN_ins] = false;                 // Input Byte(s) from Port to String        
SMPDefsFlags[NN_iretw] = false;               // Interrupt Return
SMPDefsFlags[NN_iret] = false;                // Interrupt Return
SMPDefsFlags[NN_iretd] = false;               // Interrupt Return (use32)
SMPDefsFlags[NN_iretq] = false;               // Interrupt Return (use64)
SMPDefsFlags[NN_ja] = false;                  // Jump if Above (CF=0 & ZF=0)
SMPDefsFlags[NN_jae] = false;                 // Jump if Above or Equal (CF=0)
SMPDefsFlags[NN_jb] = false;                  // Jump if Below (CF=1)
SMPDefsFlags[NN_jbe] = false;                 // Jump if Below or Equal (CF=1 | ZF=1)
SMPDefsFlags[NN_jc] = false;                  // Jump if Carry (CF=1)
SMPDefsFlags[NN_jcxz] = false;                // Jump if CX is 0
SMPDefsFlags[NN_jecxz] = false;               // Jump if ECX is 0
SMPDefsFlags[NN_jrcxz] = false;               // Jump if RCX is 0
SMPDefsFlags[NN_je] = false;                  // Jump if Equal (ZF=1)
SMPDefsFlags[NN_jg] = false;                  // Jump if Greater (ZF=0 & SF=OF)
SMPDefsFlags[NN_jge] = false;                 // Jump if Greater or Equal (SF=OF)
SMPDefsFlags[NN_jl] = false;                  // Jump if Less (SF!=OF)
SMPDefsFlags[NN_jle] = false;                 // Jump if Less or Equal (ZF=1 | SF!=OF)
SMPDefsFlags[NN_jna] = false;                 // Jump if Not Above (CF=1 | ZF=1)
SMPDefsFlags[NN_jnae] = false;                // Jump if Not Above or Equal (CF=1)
SMPDefsFlags[NN_jnb] = false;                 // Jump if Not Below (CF=0)
SMPDefsFlags[NN_jnbe] = false;                // Jump if Not Below or Equal (CF=0 & ZF=0)
SMPDefsFlags[NN_jnc] = false;                 // Jump if Not Carry (CF=0)
SMPDefsFlags[NN_jne] = false;                 // Jump if Not Equal (ZF=0)
SMPDefsFlags[NN_jng] = false;                 // Jump if Not Greater (ZF=1 | SF!=OF)
SMPDefsFlags[NN_jnge] = false;                // Jump if Not Greater or Equal (ZF=1)
SMPDefsFlags[NN_jnl] = false;                 // Jump if Not Less (SF=OF)
SMPDefsFlags[NN_jnle] = false;                // Jump if Not Less or Equal (ZF=0 & SF=OF)
SMPDefsFlags[NN_jno] = false;                 // Jump if Not Overflow (OF=0)
SMPDefsFlags[NN_jnp] = false;                 // Jump if Not Parity (PF=0)
SMPDefsFlags[NN_jns] = false;                 // Jump if Not Sign (SF=0)
SMPDefsFlags[NN_jnz] = false;                 // Jump if Not Zero (ZF=0)
SMPDefsFlags[NN_jo] = false;                  // Jump if Overflow (OF=1)
SMPDefsFlags[NN_jp] = false;                  // Jump if Parity (PF=1)
SMPDefsFlags[NN_jpe] = false;                 // Jump if Parity Even (PF=1)
SMPDefsFlags[NN_jpo] = false;                 // Jump if Parity Odd  (PF=0)
SMPDefsFlags[NN_js] = false;                  // Jump if Sign (SF=1)
SMPDefsFlags[NN_jz] = false;                  // Jump if Zero (ZF=1)
SMPDefsFlags[NN_jmp] = false;                 // Jump
SMPDefsFlags[NN_jmpfi] = false;               // Indirect Far Jump
SMPDefsFlags[NN_jmpni] = false;               // Indirect Near Jump
SMPDefsFlags[NN_jmpshort] = false;            // Jump Short (not used)
SMPDefsFlags[NN_lahf] = false;                // Load Flags into AH Register
SMPDefsFlags[NN_lea] = false;                 // Load Effective Address            
SMPDefsFlags[NN_leavew] = false;              // High Level Procedure Exit         
SMPDefsFlags[NN_leave] = false;               // High Level Procedure Exit         
SMPDefsFlags[NN_leaved] = false;              // High Level Procedure Exit         
SMPDefsFlags[NN_leaveq] = false;              // High Level Procedure Exit         
SMPDefsFlags[NN_lgdt] = false;                // Load Global Descriptor Table Register
SMPDefsFlags[NN_lidt] = false;                // Load Interrupt Descriptor Table Register
SMPDefsFlags[NN_lgs] = false;                 // Load Full Pointer to GS:xx
SMPDefsFlags[NN_lss] = false;                 // Load Full Pointer to SS:xx
SMPDefsFlags[NN_lds] = false;                 // Load Full Pointer to DS:xx
SMPDefsFlags[NN_les] = false;                 // Load Full Pointer to ES:xx
SMPDefsFlags[NN_lfs] = false;                 // Load Full Pointer to FS:xx
SMPDefsFlags[NN_loopwe] = false;              // Loop while CX != 0 and ZF=1
SMPDefsFlags[NN_loope] = false;               // Loop while rCX != 0 and ZF=1
SMPDefsFlags[NN_loopde] = false;              // Loop while ECX != 0 and ZF=1
SMPDefsFlags[NN_loopqe] = false;              // Loop while RCX != 0 and ZF=1
SMPDefsFlags[NN_loopwne] = false;             // Loop while CX != 0 and ZF=0
SMPDefsFlags[NN_loopne] = false;              // Loop while rCX != 0 and ZF=0
SMPDefsFlags[NN_loopdne] = false;             // Loop while ECX != 0 and ZF=0
SMPDefsFlags[NN_loopqne] = false;             // Loop while RCX != 0 and ZF=0
SMPDefsFlags[NN_ltr] = false;                 // Load Task Register
SMPDefsFlags[NN_mov] = false;                 // Move Data
SMPDefsFlags[NN_movsp] = false;               // Move to/from Special Registers
SMPDefsFlags[NN_movs] = false;                // Move Byte(s) from String to String
SMPDefsFlags[NN_movsx] = false;               // Move with Sign-Extend
SMPDefsFlags[NN_movzx] = false;               // Move with Zero-Extend
SMPDefsFlags[NN_nop] = false;                 // No Operation
SMPDefsFlags[NN_out] = false;                 // Output to Port
SMPDefsFlags[NN_outs] = false;                // Output Byte(s) to Port
SMPDefsFlags[NN_pop] = false;                 // Pop a word from the Stack
SMPDefsFlags[NN_popaw] = false;               // Pop all General Registers
SMPDefsFlags[NN_popa] = false;                // Pop all General Registers
SMPDefsFlags[NN_popad] = false;               // Pop all General Registers (use32)
SMPDefsFlags[NN_popaq] = false;               // Pop all General Registers (use64)
SMPDefsFlags[NN_push] = false;                // Push Operand onto the Stack
SMPDefsFlags[NN_pushaw] = false;              // Push all General Registers
SMPDefsFlags[NN_pusha] = false;               // Push all General Registers
SMPDefsFlags[NN_pushad] = false;              // Push all General Registers (use32)
SMPDefsFlags[NN_pushaq] = false;              // Push all General Registers (use64)
SMPDefsFlags[NN_pushfw] = false;              // Push Flags Register onto the Stack
SMPDefsFlags[NN_pushf] = false;               // Push Flags Register onto the Stack
SMPDefsFlags[NN_pushfd] = false;              // Push Flags Register onto the Stack (use32)
SMPDefsFlags[NN_pushfq] = false;              // Push Flags Register onto the Stack (use64)
SMPDefsFlags[NN_rep] = false;                 // Repeat String Operation
SMPDefsFlags[NN_repe] = false;                // Repeat String Operation while ZF=1
SMPDefsFlags[NN_repne] = false;               // Repeat String Operation while ZF=0
SMPDefsFlags[NN_retn] = false;                // Return Near from Procedure
SMPDefsFlags[NN_retf] = false;                // Return Far from Procedure
SMPDefsFlags[NN_shl] = false;                 // Shift Logical Left
SMPDefsFlags[NN_shr] = false;                 // Shift Logical Right
SMPDefsFlags[NN_seta] = false;                // Set Byte if Above (CF=0 & ZF=0)
SMPDefsFlags[NN_setae] = false;               // Set Byte if Above or Equal (CF=0)
SMPDefsFlags[NN_setb] = false;                // Set Byte if Below (CF=1)
SMPDefsFlags[NN_setbe] = false;               // Set Byte if Below or Equal (CF=1 | ZF=1)
SMPDefsFlags[NN_setc] = false;                // Set Byte if Carry (CF=1)
SMPDefsFlags[NN_sete] = false;                // Set Byte if Equal (ZF=1)
SMPDefsFlags[NN_setg] = false;                // Set Byte if Greater (ZF=0 & SF=OF)
SMPDefsFlags[NN_setge] = false;               // Set Byte if Greater or Equal (SF=OF)
SMPDefsFlags[NN_setl] = false;                // Set Byte if Less (SF!=OF)
SMPDefsFlags[NN_setle] = false;               // Set Byte if Less or Equal (ZF=1 | SF!=OF)
SMPDefsFlags[NN_setna] = false;               // Set Byte if Not Above (CF=1 | ZF=1)
SMPDefsFlags[NN_setnae] = false;              // Set Byte if Not Above or Equal (CF=1)
SMPDefsFlags[NN_setnb] = false;               // Set Byte if Not Below (CF=0)
SMPDefsFlags[NN_setnbe] = false;              // Set Byte if Not Below or Equal (CF=0 & ZF=0)
SMPDefsFlags[NN_setnc] = false;               // Set Byte if Not Carry (CF=0)
SMPDefsFlags[NN_setne] = false;               // Set Byte if Not Equal (ZF=0)
SMPDefsFlags[NN_setng] = false;               // Set Byte if Not Greater (ZF=1 | SF!=OF)
SMPDefsFlags[NN_setnge] = false;              // Set Byte if Not Greater or Equal (ZF=1)
SMPDefsFlags[NN_setnl] = false;               // Set Byte if Not Less (SF=OF)
SMPDefsFlags[NN_setnle] = false;              // Set Byte if Not Less or Equal (ZF=0 & SF=OF)
SMPDefsFlags[NN_setno] = false;               // Set Byte if Not Overflow (OF=0)
SMPDefsFlags[NN_setnp] = false;               // Set Byte if Not Parity (PF=0)
SMPDefsFlags[NN_setns] = false;               // Set Byte if Not Sign (SF=0)
SMPDefsFlags[NN_setnz] = false;               // Set Byte if Not Zero (ZF=0)
SMPDefsFlags[NN_seto] = false;                // Set Byte if Overflow (OF=1)
SMPDefsFlags[NN_setp] = false;                // Set Byte if Parity (PF=1)
SMPDefsFlags[NN_setpe] = false;               // Set Byte if Parity Even (PF=1)
SMPDefsFlags[NN_setpo] = false;               // Set Byte if Parity Odd  (PF=0)
SMPDefsFlags[NN_sets] = false;                // Set Byte if Sign (SF=1)
SMPDefsFlags[NN_setz] = false;                // Set Byte if Zero (ZF=1)
SMPDefsFlags[NN_sgdt] = false;                // Store Global Descriptor Table Register
SMPDefsFlags[NN_sidt] = false;                // Store Interrupt Descriptor Table Register
SMPDefsFlags[NN_sldt] = false;                // Store Local Descriptor Table Register
SMPDefsFlags[NN_str] = false;                 // Store Task Register
SMPDefsFlags[NN_wait] = false;                // Wait until BUSY# Pin is Inactive (HIGH)
SMPDefsFlags[NN_xchg] = false;                // Exchange Register/Memory with Register

//
//      486 instructions
//

SMPDefsFlags[NN_bswap] = false;               // Swap bytes in register
SMPDefsFlags[NN_invd] = false;                // Invalidate Data Cache
SMPDefsFlags[NN_wbinvd] = false;              // Invalidate Data Cache (write changes)
SMPDefsFlags[NN_invlpg] = false;              // Invalidate TLB entry

//
//      Pentium instructions
//

SMPDefsFlags[NN_rdmsr] = false;               // Read Machine Status Register
SMPDefsFlags[NN_wrmsr] = false;               // Write Machine Status Register
SMPDefsFlags[NN_cpuid] = false;               // Get CPU ID
SMPDefsFlags[NN_rdtsc] = false;               // Read Time Stamp Counter

//
//      Pentium Pro instructions
//

SMPDefsFlags[NN_cmova] = false;               // Move if Above (CF=0 & ZF=0)
SMPDefsFlags[NN_cmovb] = false;               // Move if Below (CF=1)
SMPDefsFlags[NN_cmovbe] = false;              // Move if Below or Equal (CF=1 | ZF=1)
SMPDefsFlags[NN_cmovg] = false;               // Move if Greater (ZF=0 & SF=OF)
SMPDefsFlags[NN_cmovge] = false;              // Move if Greater or Equal (SF=OF)
SMPDefsFlags[NN_cmovl] = false;               // Move if Less (SF!=OF)
SMPDefsFlags[NN_cmovle] = false;              // Move if Less or Equal (ZF=1 | SF!=OF)
SMPDefsFlags[NN_cmovnb] = false;              // Move if Not Below (CF=0)
SMPDefsFlags[NN_cmovno] = false;              // Move if Not Overflow (OF=0)
SMPDefsFlags[NN_cmovnp] = false;              // Move if Not Parity (PF=0)
SMPDefsFlags[NN_cmovns] = false;              // Move if Not Sign (SF=0)
SMPDefsFlags[NN_cmovnz] = false;              // Move if Not Zero (ZF=0)
SMPDefsFlags[NN_cmovo] = false;               // Move if Overflow (OF=1)
SMPDefsFlags[NN_cmovp] = false;               // Move if Parity (PF=1)
SMPDefsFlags[NN_cmovs] = false;               // Move if Sign (SF=1)
SMPDefsFlags[NN_cmovz] = false;               // Move if Zero (ZF=1)
SMPDefsFlags[NN_fcmovb] = false;              // Floating Move if Below          
SMPDefsFlags[NN_fcmove] = false;              // Floating Move if Equal          
SMPDefsFlags[NN_fcmovbe] = false;             // Floating Move if Below or Equal 
SMPDefsFlags[NN_fcmovu] = false;              // Floating Move if Unordered      
SMPDefsFlags[NN_fcmovnb] = false;             // Floating Move if Not Below      
SMPDefsFlags[NN_fcmovne] = false;             // Floating Move if Not Equal      
SMPDefsFlags[NN_fcmovnbe] = false;            // Floating Move if Not Below or Equal
SMPDefsFlags[NN_fcmovnu] = false;             // Floating Move if Not Unordered     
SMPDefsFlags[NN_rdpmc] = false;               // Read Performance Monitor Counter

//
//      FPP instructuions
//

SMPDefsFlags[NN_fld] = false;                 // Load Real              
SMPDefsFlags[NN_fst] = false;                 // Store Real            
SMPDefsFlags[NN_fstp] = false;                // Store Real and Pop   
SMPDefsFlags[NN_fxch] = false;                // Exchange Registers
SMPDefsFlags[NN_fild] = false;                // Load Integer           
SMPDefsFlags[NN_fist] = false;                // Store Integer
SMPDefsFlags[NN_fistp] = false;               // Store Integer and Pop
SMPDefsFlags[NN_fbld] = false;                // Load BCD
SMPDefsFlags[NN_fbstp] = false;               // Store BCD and Pop
SMPDefsFlags[NN_fadd] = false;                // Add Real
SMPDefsFlags[NN_faddp] = false;               // Add Real and Pop
SMPDefsFlags[NN_fiadd] = false;               // Add Integer
SMPDefsFlags[NN_fsub] = false;                // Subtract Real
SMPDefsFlags[NN_fsubp] = false;               // Subtract Real and Pop
SMPDefsFlags[NN_fisub] = false;               // Subtract Integer
SMPDefsFlags[NN_fsubr] = false;               // Subtract Real Reversed
SMPDefsFlags[NN_fsubrp] = false;              // Subtract Real Reversed and Pop
SMPDefsFlags[NN_fisubr] = false;              // Subtract Integer Reversed
SMPDefsFlags[NN_fmul] = false;                // Multiply Real
SMPDefsFlags[NN_fmulp] = false;               // Multiply Real and Pop
SMPDefsFlags[NN_fimul] = false;               // Multiply Integer
SMPDefsFlags[NN_fdiv] = false;                // Divide Real
SMPDefsFlags[NN_fdivp] = false;               // Divide Real and Pop
SMPDefsFlags[NN_fidiv] = false;               // Divide Integer
SMPDefsFlags[NN_fdivr] = false;               // Divide Real Reversed
SMPDefsFlags[NN_fdivrp] = false;              // Divide Real Reversed and Pop
SMPDefsFlags[NN_fidivr] = false;              // Divide Integer Reversed
SMPDefsFlags[NN_fsqrt] = false;               // Square Root
SMPDefsFlags[NN_fscale] = false;              // Scale:  st(0) <- st(0) * 2^st(1)
SMPDefsFlags[NN_fprem] = false;               // Partial Remainder
SMPDefsFlags[NN_frndint] = false;             // Round to Integer
SMPDefsFlags[NN_fxtract] = false;             // Extract exponent and significand
SMPDefsFlags[NN_fabs] = false;                // Absolute value
SMPDefsFlags[NN_fchs] = false;                // Change Sign
SMPDefsFlags[NN_ficom] = false;               // Compare Integer
SMPDefsFlags[NN_ficomp] = false;              // Compare Integer and Pop
SMPDefsFlags[NN_ftst] = false;                // Test
SMPDefsFlags[NN_fxam] = false;                // Examine
SMPDefsFlags[NN_fptan] = false;               // Partial tangent
SMPDefsFlags[NN_fpatan] = false;              // Partial arctangent
SMPDefsFlags[NN_f2xm1] = false;               // 2^x - 1
SMPDefsFlags[NN_fyl2x] = false;               // Y * lg2(X)
SMPDefsFlags[NN_fyl2xp1] = false;             // Y * lg2(X+1)
SMPDefsFlags[NN_fldz] = false;                // Load +0.0
SMPDefsFlags[NN_fld1] = false;                // Load +1.0
SMPDefsFlags[NN_fldpi] = false;               // Load PI=3.14...
SMPDefsFlags[NN_fldl2t] = false;              // Load lg2(10)
SMPDefsFlags[NN_fldl2e] = false;              // Load lg2(e)
SMPDefsFlags[NN_fldlg2] = false;              // Load lg10(2)
SMPDefsFlags[NN_fldln2] = false;              // Load ln(2)
SMPDefsFlags[NN_finit] = false;               // Initialize Processor
SMPDefsFlags[NN_fninit] = false;              // Initialize Processor (no wait)
SMPDefsFlags[NN_fsetpm] = false;              // Set Protected Mode
SMPDefsFlags[NN_fldcw] = false;               // Load Control Word
SMPDefsFlags[NN_fstcw] = false;               // Store Control Word
SMPDefsFlags[NN_fnstcw] = false;              // Store Control Word (no wait)
SMPDefsFlags[NN_fstsw] = false;               // Store Status Word to memory or AX
SMPDefsFlags[NN_fnstsw] = false;              // Store Status Word (no wait) to memory or AX
SMPDefsFlags[NN_fclex] = false;               // Clear Exceptions
SMPDefsFlags[NN_fnclex] = false;              // Clear Exceptions (no wait)
SMPDefsFlags[NN_fstenv] = false;              // Store Environment
SMPDefsFlags[NN_fnstenv] = false;             // Store Environment (no wait)
SMPDefsFlags[NN_fldenv] = false;              // Load Environment
SMPDefsFlags[NN_fsave] = false;               // Save State
SMPDefsFlags[NN_fnsave] = false;              // Save State (no wait)
SMPDefsFlags[NN_frstor] = false;              // Restore State      
SMPDefsFlags[NN_fincstp] = false;             // Increment Stack Pointer
SMPDefsFlags[NN_fdecstp] = false;             // Decrement Stack Pointer
SMPDefsFlags[NN_ffree] = false;               // Free Register
SMPDefsFlags[NN_fnop] = false;                // No Operation
SMPDefsFlags[NN_feni] = false;                // (8087 only)
SMPDefsFlags[NN_fneni] = false;               // (no wait) (8087 only)
SMPDefsFlags[NN_fdisi] = false;               // (8087 only)
SMPDefsFlags[NN_fndisi] = false;              // (no wait) (8087 only)

//
//      80387 instructions
//

SMPDefsFlags[NN_fprem1] = false;              // Partial Remainder ( < half )
SMPDefsFlags[NN_fsincos] = false;             // t<-cos(st); st<-sin(st); push t
SMPDefsFlags[NN_fsin] = false;                // Sine
SMPDefsFlags[NN_fcos] = false;                // Cosine
SMPDefsFlags[NN_fucom] = false;               // Compare Unordered Real
SMPDefsFlags[NN_fucomp] = false;              // Compare Unordered Real and Pop
SMPDefsFlags[NN_fucompp] = false;             // Compare Unordered Real and Pop Twice

//
//      Instructions added 28.02.96
//

SMPDefsFlags[NN_svdc] = false;                // Save Register and Descriptor
SMPDefsFlags[NN_rsdc] = false;                // Restore Register and Descriptor
SMPDefsFlags[NN_svldt] = false;               // Save LDTR and Descriptor
SMPDefsFlags[NN_rsldt] = false;               // Restore LDTR and Descriptor
SMPDefsFlags[NN_svts] = false;                // Save TR and Descriptor
SMPDefsFlags[NN_rsts] = false;                // Restore TR and Descriptor
SMPDefsFlags[NN_icebp] = false;               // ICE Break Point

//
//      MMX instructions
//

SMPDefsFlags[NN_emms] = false;                // Empty MMX state
SMPDefsFlags[NN_movd] = false;                // Move 32 bits
SMPDefsFlags[NN_movq] = false;                // Move 64 bits
SMPDefsFlags[NN_packsswb] = false;            // Pack with Signed Saturation (Word->Byte)
SMPDefsFlags[NN_packssdw] = false;            // Pack with Signed Saturation (Dword->Word)
SMPDefsFlags[NN_packuswb] = false;            // Pack with Unsigned Saturation (Word->Byte)
SMPDefsFlags[NN_paddb] = false;               // Packed Add Byte
SMPDefsFlags[NN_paddw] = false;               // Packed Add Word
SMPDefsFlags[NN_paddd] = false;               // Packed Add Dword
SMPDefsFlags[NN_paddsb] = false;              // Packed Add with Saturation (Byte)
SMPDefsFlags[NN_paddsw] = false;              // Packed Add with Saturation (Word)
SMPDefsFlags[NN_paddusb] = false;             // Packed Add Unsigned with Saturation (Byte)
SMPDefsFlags[NN_paddusw] = false;             // Packed Add Unsigned with Saturation (Word)
SMPDefsFlags[NN_pand] = false;                // Bitwise Logical And
SMPDefsFlags[NN_pandn] = false;               // Bitwise Logical And Not
SMPDefsFlags[NN_pcmpeqb] = false;             // Packed Compare for Equal (Byte)
SMPDefsFlags[NN_pcmpeqw] = false;             // Packed Compare for Equal (Word)
SMPDefsFlags[NN_pcmpeqd] = false;             // Packed Compare for Equal (Dword)
SMPDefsFlags[NN_pcmpgtb] = false;             // Packed Compare for Greater Than (Byte)
SMPDefsFlags[NN_pcmpgtw] = false;             // Packed Compare for Greater Than (Word)
SMPDefsFlags[NN_pcmpgtd] = false;             // Packed Compare for Greater Than (Dword)
SMPDefsFlags[NN_pmaddwd] = false;             // Packed Multiply and Add
SMPDefsFlags[NN_pmulhw] = false;              // Packed Multiply High
SMPDefsFlags[NN_pmullw] = false;              // Packed Multiply Low
SMPDefsFlags[NN_por] = false;                 // Bitwise Logical Or
SMPDefsFlags[NN_psllw] = false;               // Packed Shift Left Logical (Word)
SMPDefsFlags[NN_pslld] = false;               // Packed Shift Left Logical (Dword)
SMPDefsFlags[NN_psllq] = false;               // Packed Shift Left Logical (Qword)
SMPDefsFlags[NN_psraw] = false;               // Packed Shift Right Arithmetic (Word)
SMPDefsFlags[NN_psrad] = false;               // Packed Shift Right Arithmetic (Dword)
SMPDefsFlags[NN_psrlw] = false;               // Packed Shift Right Logical (Word)
SMPDefsFlags[NN_psrld] = false;               // Packed Shift Right Logical (Dword)
SMPDefsFlags[NN_psrlq] = false;               // Packed Shift Right Logical (Qword)
SMPDefsFlags[NN_psubb] = false;               // Packed Subtract Byte
SMPDefsFlags[NN_psubw] = false;               // Packed Subtract Word
SMPDefsFlags[NN_psubd] = false;               // Packed Subtract Dword
SMPDefsFlags[NN_psubsb] = false;              // Packed Subtract with Saturation (Byte)
SMPDefsFlags[NN_psubsw] = false;              // Packed Subtract with Saturation (Word)
SMPDefsFlags[NN_psubusb] = false;             // Packed Subtract Unsigned with Saturation (Byte)
SMPDefsFlags[NN_psubusw] = false;             // Packed Subtract Unsigned with Saturation (Word)
SMPDefsFlags[NN_punpckhbw] = false;           // Unpack High Packed Data (Byte->Word)
SMPDefsFlags[NN_punpckhwd] = false;           // Unpack High Packed Data (Word->Dword)
SMPDefsFlags[NN_punpckhdq] = false;           // Unpack High Packed Data (Dword->Qword)
SMPDefsFlags[NN_punpcklbw] = false;           // Unpack Low Packed Data (Byte->Word)
SMPDefsFlags[NN_punpcklwd] = false;           // Unpack Low Packed Data (Word->Dword)
SMPDefsFlags[NN_punpckldq] = false;           // Unpack Low Packed Data (Dword->Qword)
SMPDefsFlags[NN_pxor] = false;                // Bitwise Logical Exclusive Or

//
//      Undocumented Deschutes processor instructions
//

SMPDefsFlags[NN_fxsave] = false;              // Fast save FP context        
SMPDefsFlags[NN_fxrstor] = false;             // Fast restore FP context     

//      Pentium II instructions

SMPDefsFlags[NN_sysexit] = false;             // Fast Transition from System Call Entry Point

//      3DNow! instructions

SMPDefsFlags[NN_pavgusb] = false;             // Packed 8-bit Unsigned Integer Averaging
SMPDefsFlags[NN_pfadd] = false;               // Packed Floating-Point Addition
SMPDefsFlags[NN_pfsub] = false;               // Packed Floating-Point Subtraction
SMPDefsFlags[NN_pfsubr] = false;              // Packed Floating-Point Reverse Subtraction
SMPDefsFlags[NN_pfacc] = false;               // Packed Floating-Point Accumulate
SMPDefsFlags[NN_pfcmpge] = false;             // Packed Floating-Point Comparison, Greater or Equal
SMPDefsFlags[NN_pfcmpgt] = false;             // Packed Floating-Point Comparison, Greater
SMPDefsFlags[NN_pfcmpeq] = false;             // Packed Floating-Point Comparison, Equal
SMPDefsFlags[NN_pfmin] = false;               // Packed Floating-Point Minimum
SMPDefsFlags[NN_pfmax] = false;               // Packed Floating-Point Maximum
SMPDefsFlags[NN_pi2fd] = false;               // Packed 32-bit Integer to Floating-Point
SMPDefsFlags[NN_pf2id] = false;               // Packed Floating-Point to 32-bit Integer
SMPDefsFlags[NN_pfrcp] = false;               // Packed Floating-Point Reciprocal Approximation
SMPDefsFlags[NN_pfrsqrt] = false;             // Packed Floating-Point Reciprocal Square Root Approximation
SMPDefsFlags[NN_pfmul] = false;               // Packed Floating-Point Multiplication
SMPDefsFlags[NN_pfrcpit1] = false;            // Packed Floating-Point Reciprocal First Iteration Step
SMPDefsFlags[NN_pfrsqit1] = false;            // Packed Floating-Point Reciprocal Square Root First Iteration Step
SMPDefsFlags[NN_pfrcpit2] = false;            // Packed Floating-Point Reciprocal Second Iteration Step
SMPDefsFlags[NN_pmulhrw] = false;             // Packed Floating-Point 16-bit Integer Multiply with rounding
SMPDefsFlags[NN_femms] = false;               // Faster entry/exit of the MMX or floating-point state
SMPDefsFlags[NN_prefetch] = false;            // Prefetch at least a 32-byte line into L1 data cache
SMPDefsFlags[NN_prefetchw] = false;           // Prefetch processor cache line into L1 data cache (mark as modified)


//      Pentium III instructions

SMPDefsFlags[NN_addps] = false;               // Packed Single-FP Add
SMPDefsFlags[NN_addss] = false;               // Scalar Single-FP Add
SMPDefsFlags[NN_andnps] = false;              // Bitwise Logical And Not for Single-FP
SMPDefsFlags[NN_andps] = false;               // Bitwise Logical And for Single-FP
SMPDefsFlags[NN_cmpps] = false;               // Packed Single-FP Compare
SMPDefsFlags[NN_cmpss] = false;               // Scalar Single-FP Compare
SMPDefsFlags[NN_cvtpi2ps] = false;            // Packed signed INT32 to Packed Single-FP conversion
SMPDefsFlags[NN_cvtps2pi] = false;            // Packed Single-FP to Packed INT32 conversion
SMPDefsFlags[NN_cvtsi2ss] = false;            // Scalar signed INT32 to Single-FP conversion
SMPDefsFlags[NN_cvtss2si] = false;            // Scalar Single-FP to signed INT32 conversion
SMPDefsFlags[NN_cvttps2pi] = false;           // Packed Single-FP to Packed INT32 conversion (truncate)
SMPDefsFlags[NN_cvttss2si] = false;           // Scalar Single-FP to signed INT32 conversion (truncate)
SMPDefsFlags[NN_divps] = false;               // Packed Single-FP Divide
SMPDefsFlags[NN_divss] = false;               // Scalar Single-FP Divide
SMPDefsFlags[NN_ldmxcsr] = false;             // Load Streaming SIMD Extensions Technology Control/Status Register
SMPDefsFlags[NN_maxps] = false;               // Packed Single-FP Maximum
SMPDefsFlags[NN_maxss] = false;               // Scalar Single-FP Maximum
SMPDefsFlags[NN_minps] = false;               // Packed Single-FP Minimum
SMPDefsFlags[NN_minss] = false;               // Scalar Single-FP Minimum
SMPDefsFlags[NN_movaps] = false;              // Move Aligned Four Packed Single-FP  
SMPDefsFlags[NN_movhlps] = false;             // Move High to Low Packed Single-FP
SMPDefsFlags[NN_movhps] = false;              // Move High Packed Single-FP
SMPDefsFlags[NN_movlhps] = false;             // Move Low to High Packed Single-FP
SMPDefsFlags[NN_movlps] = false;              // Move Low Packed Single-FP
SMPDefsFlags[NN_movmskps] = false;            // Move Mask to Register
SMPDefsFlags[NN_movss] = false;               // Move Scalar Single-FP
SMPDefsFlags[NN_movups] = false;              // Move Unaligned Four Packed Single-FP
SMPDefsFlags[NN_mulps] = false;               // Packed Single-FP Multiply
SMPDefsFlags[NN_mulss] = false;               // Scalar Single-FP Multiply
SMPDefsFlags[NN_orps] = false;                // Bitwise Logical OR for Single-FP Data
SMPDefsFlags[NN_rcpps] = false;               // Packed Single-FP Reciprocal
SMPDefsFlags[NN_rcpss] = false;               // Scalar Single-FP Reciprocal
SMPDefsFlags[NN_rsqrtps] = false;             // Packed Single-FP Square Root Reciprocal
SMPDefsFlags[NN_rsqrtss] = false;             // Scalar Single-FP Square Root Reciprocal
SMPDefsFlags[NN_shufps] = false;              // Shuffle Single-FP
SMPDefsFlags[NN_sqrtps] = false;              // Packed Single-FP Square Root
SMPDefsFlags[NN_sqrtss] = false;              // Scalar Single-FP Square Root
SMPDefsFlags[NN_stmxcsr] = false;             // Store Streaming SIMD Extensions Technology Control/Status Register 
SMPDefsFlags[NN_subps] = false;               // Packed Single-FP Subtract
SMPDefsFlags[NN_subss] = false;               // Scalar Single-FP Subtract
SMPDefsFlags[NN_unpckhps] = false;            // Unpack High Packed Single-FP Data
SMPDefsFlags[NN_unpcklps] = false;            // Unpack Low Packed Single-FP Data
SMPDefsFlags[NN_xorps] = false;               // Bitwise Logical XOR for Single-FP Data
SMPDefsFlags[NN_pavgb] = false;               // Packed Average (Byte)
SMPDefsFlags[NN_pavgw] = false;               // Packed Average (Word)
SMPDefsFlags[NN_pextrw] = false;              // Extract Word
SMPDefsFlags[NN_pinsrw] = false;              // Insert Word
SMPDefsFlags[NN_pmaxsw] = false;              // Packed Signed Integer Word Maximum
SMPDefsFlags[NN_pmaxub] = false;              // Packed Unsigned Integer Byte Maximum
SMPDefsFlags[NN_pminsw] = false;              // Packed Signed Integer Word Minimum
SMPDefsFlags[NN_pminub] = false;              // Packed Unsigned Integer Byte Minimum
SMPDefsFlags[NN_pmovmskb] = false;            // Move Byte Mask to Integer
SMPDefsFlags[NN_pmulhuw] = false;             // Packed Multiply High Unsigned
SMPDefsFlags[NN_psadbw] = false;              // Packed Sum of Absolute Differences
SMPDefsFlags[NN_pshufw] = false;              // Packed Shuffle Word
SMPDefsFlags[NN_maskmovq] = false;            // Byte Mask write  
SMPDefsFlags[NN_movntps] = false;             // Move Aligned Four Packed Single-FP Non Temporal
SMPDefsFlags[NN_movntq] = false;              // Move 64 Bits Non Temporal   
SMPDefsFlags[NN_prefetcht0] = false;          // Prefetch to all cache levels
SMPDefsFlags[NN_prefetcht1] = false;          // Prefetch to all cache levels
SMPDefsFlags[NN_prefetcht2] = false;          // Prefetch to L2 cache
SMPDefsFlags[NN_prefetchnta] = false;         // Prefetch to L1 cache
SMPDefsFlags[NN_sfence] = false;              // Store Fence

// Pentium III Pseudo instructions

SMPDefsFlags[NN_cmpeqps] = false;             // Packed Single-FP Compare EQ
SMPDefsFlags[NN_cmpltps] = false;             // Packed Single-FP Compare LT
SMPDefsFlags[NN_cmpleps] = false;             // Packed Single-FP Compare LE
SMPDefsFlags[NN_cmpunordps] = false;          // Packed Single-FP Compare UNORD
SMPDefsFlags[NN_cmpneqps] = false;            // Packed Single-FP Compare NOT EQ
SMPDefsFlags[NN_cmpnltps] = false;            // Packed Single-FP Compare NOT LT
SMPDefsFlags[NN_cmpnleps] = false;            // Packed Single-FP Compare NOT LE
SMPDefsFlags[NN_cmpordps] = false;            // Packed Single-FP Compare ORDERED
SMPDefsFlags[NN_cmpeqss] = false;             // Scalar Single-FP Compare EQ
SMPDefsFlags[NN_cmpltss] = false;             // Scalar Single-FP Compare LT
SMPDefsFlags[NN_cmpless] = false;             // Scalar Single-FP Compare LE
SMPDefsFlags[NN_cmpunordss] = false;          // Scalar Single-FP Compare UNORD
SMPDefsFlags[NN_cmpneqss] = false;            // Scalar Single-FP Compare NOT EQ
SMPDefsFlags[NN_cmpnltss] = false;            // Scalar Single-FP Compare NOT LT
SMPDefsFlags[NN_cmpnless] = false;            // Scalar Single-FP Compare NOT LE
SMPDefsFlags[NN_cmpordss] = false;            // Scalar Single-FP Compare ORDERED

// AMD K7 instructions

// Revisit AMD if we port to it.
SMPDefsFlags[NN_pf2iw] = false;               // Packed Floating-Point to Integer with Sign Extend
SMPDefsFlags[NN_pfnacc] = false;              // Packed Floating-Point Negative Accumulate
SMPDefsFlags[NN_pfpnacc] = false;             // Packed Floating-Point Mixed Positive-Negative Accumulate
SMPDefsFlags[NN_pi2fw] = false;               // Packed 16-bit Integer to Floating-Point
SMPDefsFlags[NN_pswapd] = false;              // Packed Swap Double Word

// Undocumented FP instructions (thanks to norbert.juffa@adm.com)

SMPDefsFlags[NN_fstp1] = false;               // Alias of Store Real and Pop
SMPDefsFlags[NN_fxch4] = false;               // Alias of Exchange Registers
SMPDefsFlags[NN_ffreep] = false;              // Free Register and Pop
SMPDefsFlags[NN_fxch7] = false;               // Alias of Exchange Registers
SMPDefsFlags[NN_fstp8] = false;               // Alias of Store Real and Pop
SMPDefsFlags[NN_fstp9] = false;               // Alias of Store Real and Pop

// Pentium 4 instructions

SMPDefsFlags[NN_addpd] = false;               // Add Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_addsd] = false;               // Add Scalar Double-Precision Floating-Point Values
SMPDefsFlags[NN_andnpd] = false;              // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_andpd] = false;               // Bitwise Logical AND of Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_clflush] = false;             // Flush Cache Line
SMPDefsFlags[NN_cmppd] = false;               // Compare Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_cmpsd] = false;               // Compare Scalar Double-Precision Floating-Point Values
SMPDefsFlags[NN_cvtdq2pd] = false;            // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values
SMPDefsFlags[NN_cvtdq2ps] = false;            // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_cvtpd2dq] = false;            // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
SMPDefsFlags[NN_cvtpd2pi] = false;            // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
SMPDefsFlags[NN_cvtpd2ps] = false;            // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values
SMPDefsFlags[NN_cvtpi2pd] = false;            // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_cvtps2dq] = false;            // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
SMPDefsFlags[NN_cvtps2pd] = false;            // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_cvtsd2si] = false;            // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer
SMPDefsFlags[NN_cvtsd2ss] = false;            // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value
SMPDefsFlags[NN_cvtsi2sd] = false;            // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value
SMPDefsFlags[NN_cvtss2sd] = false;            // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value
SMPDefsFlags[NN_cvttpd2dq] = false;           // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
SMPDefsFlags[NN_cvttpd2pi] = false;           // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
SMPDefsFlags[NN_cvttps2dq] = false;           // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
SMPDefsFlags[NN_cvttsd2si] = false;           // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer
SMPDefsFlags[NN_divpd] = false;               // Divide Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_divsd] = false;               // Divide Scalar Double-Precision Floating-Point Values
SMPDefsFlags[NN_lfence] = false;              // Load Fence
SMPDefsFlags[NN_maskmovdqu] = false;          // Store Selected Bytes of Double Quadword 
SMPDefsFlags[NN_maxpd] = false;               // Return Maximum Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_maxsd] = false;               // Return Maximum Scalar Double-Precision Floating-Point Value
SMPDefsFlags[NN_mfence] = false;              // Memory Fence
SMPDefsFlags[NN_minpd] = false;               // Return Minimum Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_minsd] = false;               // Return Minimum Scalar Double-Precision Floating-Point Value
SMPDefsFlags[NN_movapd] = false;              // Move Aligned Packed Double-Precision Floating-Point Values 
SMPDefsFlags[NN_movdq2q] = false;             // Move Quadword from XMM to MMX Register
SMPDefsFlags[NN_movdqa] = false;              // Move Aligned Double Quadword  
SMPDefsFlags[NN_movdqu] = false;              // Move Unaligned Double Quadword  
SMPDefsFlags[NN_movhpd] = false;              // Move High Packed Double-Precision Floating-Point Values 
SMPDefsFlags[NN_movlpd] = false;              // Move Low Packed Double-Precision Floating-Point Values 
SMPDefsFlags[NN_movmskpd] = false;            // Extract Packed Double-Precision Floating-Point Sign Mask
SMPDefsFlags[NN_movntdq] = false;             // Store Double Quadword Using Non-Temporal Hint
SMPDefsFlags[NN_movnti] = false;              // Store Doubleword Using Non-Temporal Hint
SMPDefsFlags[NN_movntpd] = false;             // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint
SMPDefsFlags[NN_movq2dq] = false;             // Move Quadword from MMX to XMM Register
SMPDefsFlags[NN_movsd] = false;               // Move Scalar Double-Precision Floating-Point Values
SMPDefsFlags[NN_movupd] = false;              // Move Unaligned Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_mulpd] = false;               // Multiply Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_mulsd] = false;               // Multiply Scalar Double-Precision Floating-Point Values
SMPDefsFlags[NN_orpd] = false;                // Bitwise Logical OR of Double-Precision Floating-Point Values
SMPDefsFlags[NN_paddq] = false;               // Add Packed Quadword Integers
SMPDefsFlags[NN_pause] = false;               // Spin Loop Hint
SMPDefsFlags[NN_pmuludq] = false;             // Multiply Packed Unsigned Doubleword Integers
SMPDefsFlags[NN_pshufd] = false;              // Shuffle Packed Doublewords
SMPDefsFlags[NN_pshufhw] = false;             // Shuffle Packed High Words
SMPDefsFlags[NN_pshuflw] = false;             // Shuffle Packed Low Words
SMPDefsFlags[NN_pslldq] = false;              // Shift Double Quadword Left Logical
SMPDefsFlags[NN_psrldq] = false;              // Shift Double Quadword Right Logical
SMPDefsFlags[NN_psubq] = false;               // Subtract Packed Quadword Integers
SMPDefsFlags[NN_punpckhqdq] = false;          // Unpack High Data
SMPDefsFlags[NN_punpcklqdq] = false;          // Unpack Low Data
SMPDefsFlags[NN_shufpd] = false;              // Shuffle Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_sqrtpd] = false;              // Compute Square Roots of Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_sqrtsd] = false;              // Compute Square Rootof Scalar Double-Precision Floating-Point Value
SMPDefsFlags[NN_subpd] = false;               // Subtract Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_subsd] = false;               // Subtract Scalar Double-Precision Floating-Point Values
SMPDefsFlags[NN_unpckhpd] = false;            // Unpack and Interleave High Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_unpcklpd] = false;            // Unpack and Interleave Low Packed Double-Precision Floating-Point Values
SMPDefsFlags[NN_xorpd] = false;               // Bitwise Logical OR of Double-Precision Floating-Point Values


// AMD syscall/sysret instructions  NOTE: not AMD, found in Intel manual


// AMD64 instructions    NOTE: not AMD, found in Intel manual

SMPDefsFlags[NN_swapgs] = false;              // Exchange GS base with KernelGSBase MSR

// New Pentium instructions (SSE3)

SMPDefsFlags[NN_movddup] = false;             // Move One Double-FP and Duplicate
SMPDefsFlags[NN_movshdup] = false;            // Move Packed Single-FP High and Duplicate
SMPDefsFlags[NN_movsldup] = false;            // Move Packed Single-FP Low and Duplicate

// Missing AMD64 instructions  NOTE: also found in Intel manual

SMPDefsFlags[NN_movsxd] = false;              // Move with Sign-Extend Doubleword

// SSE3 instructions

SMPDefsFlags[NN_addsubpd] = false;            // Add /Sub packed DP FP numbers
SMPDefsFlags[NN_addsubps] = false;            // Add /Sub packed SP FP numbers
SMPDefsFlags[NN_haddpd] = false;              // Add horizontally packed DP FP numbers
SMPDefsFlags[NN_haddps] = false;              // Add horizontally packed SP FP numbers
SMPDefsFlags[NN_hsubpd] = false;              // Sub horizontally packed DP FP numbers
SMPDefsFlags[NN_hsubps] = false;              // Sub horizontally packed SP FP numbers
SMPDefsFlags[NN_monitor] = false;             // Set up a linear address range to be monitored by hardware
SMPDefsFlags[NN_mwait] = false;               // Wait until write-back store performed within the range specified by the MONITOR instruction
SMPDefsFlags[NN_fisttp] = false;              // Store ST in intXX (chop) and pop
SMPDefsFlags[NN_lddqu] = false;               // Load unaligned integer 128-bit

// SSSE3 instructions

SMPDefsFlags[NN_psignb] = false;              // Packed SIGN Byte
SMPDefsFlags[NN_psignw] = false;              // Packed SIGN Word
SMPDefsFlags[NN_psignd] = false;              // Packed SIGN Doubleword
SMPDefsFlags[NN_pshufb] = false;              // Packed Shuffle Bytes
SMPDefsFlags[NN_pmulhrsw] = false;            // Packed Multiply High with Round and Scale
SMPDefsFlags[NN_pmaddubsw] = false;           // Multiply and Add Packed Signed and Unsigned Bytes
SMPDefsFlags[NN_phsubsw] = false;             // Packed Horizontal Subtract and Saturate
SMPDefsFlags[NN_phaddsw] = false;             // Packed Horizontal Add and Saturate
SMPDefsFlags[NN_phaddw] = false;              // Packed Horizontal Add Word
SMPDefsFlags[NN_phaddd] = false;              // Packed Horizontal Add Doubleword
SMPDefsFlags[NN_phsubw] = false;              // Packed Horizontal Subtract Word
SMPDefsFlags[NN_phsubd] = false;              // Packed Horizontal Subtract Doubleword
SMPDefsFlags[NN_palignr] = false;             // Packed Align Right
SMPDefsFlags[NN_pabsb] = false;               // Packed Absolute Value Byte
SMPDefsFlags[NN_pabsw] = false;               // Packed Absolute Value Word
SMPDefsFlags[NN_pabsd] = false;               // Packed Absolute Value Doubleword

// VMX instructions

SMPDefsFlags[NN_last] = false;

  return;

} // end InitSMPDefsFlags()

// Initialize the SMPUsesFlags[] array to define how we emit
//   optimizing annotations.
void InitSMPUsesFlags(void) {
	// Default value is false. Few instructions use the flags.
	(void) memset(SMPUsesFlags, false, sizeof(SMPUsesFlags));

SMPUsesFlags[NN_null] = true;            // Unknown Operation
#if 1
SMPUsesFlags[NN_aaa] = true;                 // ASCII adjust after addition
SMPUsesFlags[NN_aas] = true;				 // ASCII adjust after subtraction
#endif
SMPUsesFlags[NN_adc] = true;                 // Add with Carry
SMPUsesFlags[NN_cmps] = true;                // Compare Strings (uses DF direction flag)
SMPUsesFlags[NN_into] = true;                // Call to Interrupt Procedure if Overflow Flag = 1
SMPUsesFlags[NN_ja] = true;                  // Jump if Above (CF=0 & ZF=0)
SMPUsesFlags[NN_jae] = true;                 // Jump if Above or Equal (CF=0)
SMPUsesFlags[NN_jb] = true;                  // Jump if Below (CF=1)
SMPUsesFlags[NN_jbe] = true;                 // Jump if Below or Equal (CF=1 | ZF=1)
SMPUsesFlags[NN_jc] = true;                  // Jump if Carry (CF=1)
SMPUsesFlags[NN_jcxz] = true;                // Jump if CX is 0
SMPUsesFlags[NN_jecxz] = true;               // Jump if ECX is 0
SMPUsesFlags[NN_jrcxz] = true;               // Jump if RCX is 0
SMPUsesFlags[NN_je] = true;                  // Jump if Equal (ZF=1)
SMPUsesFlags[NN_jg] = true;                  // Jump if Greater (ZF=0 & SF=OF)
SMPUsesFlags[NN_jge] = true;                 // Jump if Greater or Equal (SF=OF)
SMPUsesFlags[NN_jl] = true;                  // Jump if Less (SF!=OF)
SMPUsesFlags[NN_jle] = true;                 // Jump if Less or Equal (ZF=1 | SF!=OF)
SMPUsesFlags[NN_jna] = true;                 // Jump if Not Above (CF=1 | ZF=1)
SMPUsesFlags[NN_jnae] = true;                // Jump if Not Above or Equal (CF=1)
SMPUsesFlags[NN_jnb] = true;                 // Jump if Not Below (CF=0)
SMPUsesFlags[NN_jnbe] = true;                // Jump if Not Below or Equal (CF=0 & ZF=0)
SMPUsesFlags[NN_jnc] = true;                 // Jump if Not Carry (CF=0)
SMPUsesFlags[NN_jne] = true;                 // Jump if Not Equal (ZF=0)
SMPUsesFlags[NN_jng] = true;                 // Jump if Not Greater (ZF=1 | SF!=OF)
SMPUsesFlags[NN_jnge] = true;                // Jump if Not Greater or Equal (ZF=1)
SMPUsesFlags[NN_jnl] = true;                 // Jump if Not Less (SF=OF)
SMPUsesFlags[NN_jnle] = true;                // Jump if Not Less or Equal (ZF=0 & SF=OF)
SMPUsesFlags[NN_jno] = true;                 // Jump if Not Overflow (OF=0)
SMPUsesFlags[NN_jnp] = true;                 // Jump if Not Parity (PF=0)
SMPUsesFlags[NN_jns] = true;                 // Jump if Not Sign (SF=0)
SMPUsesFlags[NN_jnz] = true;                 // Jump if Not Zero (ZF=0)
SMPUsesFlags[NN_jo] = true;                  // Jump if Overflow (OF=1)
SMPUsesFlags[NN_jp] = true;                  // Jump if Parity (PF=1)
SMPUsesFlags[NN_jpe] = true;                 // Jump if Parity Even (PF=1)
SMPUsesFlags[NN_jpo] = true;                 // Jump if Parity Odd  (PF=0)
SMPUsesFlags[NN_js] = true;                  // Jump if Sign (SF=1)
SMPUsesFlags[NN_jz] = true;                  // Jump if Zero (ZF=1)
SMPUsesFlags[NN_lahf] = true;                // Load Flags into AH Register
SMPUsesFlags[NN_loopwe] = true;              // Loop while CX != 0 and ZF=1
SMPUsesFlags[NN_loope] = true;               // Loop while rCX != 0 and ZF=1
SMPUsesFlags[NN_loopde] = true;              // Loop while ECX != 0 and ZF=1
SMPUsesFlags[NN_loopqe] = true;              // Loop while RCX != 0 and ZF=1
SMPUsesFlags[NN_loopwne] = true;             // Loop while CX != 0 and ZF=0
SMPUsesFlags[NN_loopne] = true;              // Loop while rCX != 0 and ZF=0
SMPUsesFlags[NN_loopdne] = true;             // Loop while ECX != 0 and ZF=0
SMPUsesFlags[NN_loopqne] = true;             // Loop while RCX != 0 and ZF=0
SMPUsesFlags[NN_movs] = true;                // Move Byte(s) from String to String
SMPUsesFlags[NN_pushfw] = true;              // Push Flags Register onto the Stack
SMPUsesFlags[NN_pushf] = true;               // Push Flags Register onto the Stack
SMPUsesFlags[NN_pushfd] = true;              // Push Flags Register onto the Stack (use32)
SMPUsesFlags[NN_pushfq] = true;              // Push Flags Register onto the Stack (use64)
SMPUsesFlags[NN_repe] = true;                // Repeat String Operation while ZF=1
SMPUsesFlags[NN_repne] = true;               // Repeat String Operation while ZF=0
#if 0
SMPUsesFlags[NN_sahf] = true;                // Store AH into Flags Register
SMPUsesFlags[NN_shl] = true;                 // Shift Logical Left
SMPUsesFlags[NN_shr] = true;                 // Shift Logical Right
#endif
SMPUsesFlags[NN_sbb] = true;                 // Integer Subtraction with Borrow
SMPUsesFlags[NN_scas] = true;                // Compare String (uses DF direction flag)
SMPUsesFlags[NN_seta] = true;                // Set Byte if Above (CF=0 & ZF=0)
SMPUsesFlags[NN_setae] = true;               // Set Byte if Above or Equal (CF=0)
SMPUsesFlags[NN_setb] = true;                // Set Byte if Below (CF=1)
SMPUsesFlags[NN_setbe] = true;               // Set Byte if Below or Equal (CF=1 | ZF=1)
SMPUsesFlags[NN_setc] = true;                // Set Byte if Carry (CF=1)
SMPUsesFlags[NN_sete] = true;                // Set Byte if Equal (ZF=1)
SMPUsesFlags[NN_setg] = true;                // Set Byte if Greater (ZF=0 & SF=OF)
SMPUsesFlags[NN_setge] = true;               // Set Byte if Greater or Equal (SF=OF)
SMPUsesFlags[NN_setl] = true;                // Set Byte if Less (SF!=OF)
SMPUsesFlags[NN_setle] = true;               // Set Byte if Less or Equal (ZF=1 | SF!=OF)
SMPUsesFlags[NN_setna] = true;               // Set Byte if Not Above (CF=1 | ZF=1)
SMPUsesFlags[NN_setnae] = true;              // Set Byte if Not Above or Equal (CF=1)
SMPUsesFlags[NN_setnb] = true;               // Set Byte if Not Below (CF=0)
SMPUsesFlags[NN_setnbe] = true;              // Set Byte if Not Below or Equal (CF=0 & ZF=0)
SMPUsesFlags[NN_setnc] = true;               // Set Byte if Not Carry (CF=0)
SMPUsesFlags[NN_setne] = true;               // Set Byte if Not Equal (ZF=0)
SMPUsesFlags[NN_setng] = true;               // Set Byte if Not Greater (ZF=1 | SF!=OF)
SMPUsesFlags[NN_setnge] = true;              // Set Byte if Not Greater or Equal (ZF=1)
SMPUsesFlags[NN_setnl] = true;               // Set Byte if Not Less (SF=OF)
SMPUsesFlags[NN_setnle] = true;              // Set Byte if Not Less or Equal (ZF=0 & SF=OF)
SMPUsesFlags[NN_setno] = true;               // Set Byte if Not Overflow (OF=0)
SMPUsesFlags[NN_setnp] = true;               // Set Byte if Not Parity (PF=0)
SMPUsesFlags[NN_setns] = true;               // Set Byte if Not Sign (SF=0)
SMPUsesFlags[NN_setnz] = true;               // Set Byte if Not Zero (ZF=0)
SMPUsesFlags[NN_seto] = true;                // Set Byte if Overflow (OF=1)
SMPUsesFlags[NN_setp] = true;                // Set Byte if Parity (PF=1)
SMPUsesFlags[NN_setpe] = true;               // Set Byte if Parity Even (PF=1)
SMPUsesFlags[NN_setpo] = true;               // Set Byte if Parity Odd  (PF=0)
SMPUsesFlags[NN_sets] = true;                // Set Byte if Sign (SF=1)
SMPUsesFlags[NN_setz] = true;                // Set Byte if Zero (ZF=1)
SMPUsesFlags[NN_stos] = true;                // Store String

//
//      486 instructions
//

//
//      Pentium instructions
//

SMPUsesFlags[NN_cpuid] = true;               // Get CPU ID
#if 0
SMPUsesFlags[NN_cmpxchg8b] = true;           // Compare and Exchange Eight Bytes
#endif

//
//      Pentium Pro instructions
//

SMPUsesFlags[NN_cmova] = true;               // Move if Above (CF=0 & ZF=0)
SMPUsesFlags[NN_cmovb] = true;               // Move if Below (CF=1)
SMPUsesFlags[NN_cmovbe] = true;              // Move if Below or Equal (CF=1 | ZF=1)
SMPUsesFlags[NN_cmovg] = true;               // Move if Greater (ZF=0 & SF=OF)
SMPUsesFlags[NN_cmovge] = true;              // Move if Greater or Equal (SF=OF)
SMPUsesFlags[NN_cmovl] = true;               // Move if Less (SF!=OF)
SMPUsesFlags[NN_cmovle] = true;              // Move if Less or Equal (ZF=1 | SF!=OF)
SMPUsesFlags[NN_cmovnb] = true;              // Move if Not Below (CF=0)
SMPUsesFlags[NN_cmovno] = true;              // Move if Not Overflow (OF=0)
SMPUsesFlags[NN_cmovnp] = true;              // Move if Not Parity (PF=0)
SMPUsesFlags[NN_cmovns] = true;              // Move if Not Sign (SF=0)
SMPUsesFlags[NN_cmovnz] = true;              // Move if Not Zero (ZF=0)
SMPUsesFlags[NN_cmovo] = true;               // Move if Overflow (OF=1)
SMPUsesFlags[NN_cmovp] = true;               // Move if Parity (PF=1)
SMPUsesFlags[NN_cmovs] = true;               // Move if Sign (SF=1)
SMPUsesFlags[NN_cmovz] = true;               // Move if Zero (ZF=1)
SMPUsesFlags[NN_fcmovb] = true;              // Floating Move if Below          
SMPUsesFlags[NN_fcmove] = true;              // Floating Move if Equal          
SMPUsesFlags[NN_fcmovbe] = true;             // Floating Move if Below or Equal 
SMPUsesFlags[NN_fcmovu] = true;              // Floating Move if Unordered      
SMPUsesFlags[NN_fcmovnb] = true;             // Floating Move if Not Below      
SMPUsesFlags[NN_fcmovne] = true;             // Floating Move if Not Equal      
SMPUsesFlags[NN_fcmovnbe] = true;            // Floating Move if Not Below or Equal
SMPUsesFlags[NN_fcmovnu] = true;             // Floating Move if Not Unordered     

//
//      FPP instructions
//


//
//      80387 instructions
//


//
//      Instructions added 28.02.96
//

SMPUsesFlags[NN_setalc] = true;              // Set AL to Carry Flag      

//
//      MMX instructions
//


//
//      Undocumented Deschutes processor instructions
//


//      Pentium II instructions


//      3DNow! instructions


//      Pentium III instructions


// Pentium III Pseudo instructions


// AMD K7 instructions

// Revisit AMD if we port to it.

// Undocumented FP instructions (thanks to norbert.juffa@adm.com)

// Pentium 4 instructions



// AMD syscall/sysret instructions  NOTE: not AMD, found in Intel manual

// AMD64 instructions    NOTE: not AMD, found in Intel manual


// New Pentium instructions (SSE3)


// Missing AMD64 instructions  NOTE: also found in Intel manual


// SSE3 instructions


// SSSE3 instructions


// VMX instructions


SMPUsesFlags[NN_last] = false;

  return;

} // end InitSMPUsesFlags()


// Initialize the SMPTypeCategory[] array to define how we infer
//   numeric or pointer operand types for optimizing annotations.
void InitTypeCategory(void) {
	// Default category is 0, no type inference without knowing context.
	(void) memset(SMPTypeCategory, 0, sizeof(SMPTypeCategory));
	// Category 1 instructions have no valid inferences about their operand
	//  types that can be drawn, but will need no mmStrata instrumentation
	//  and are irrelevant to our type system.
	// 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 operand of type 'n'.
	//  NOTE: MOV is the 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,
	//   even if the operand is a memory operand.
	//   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'.
	// 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 13) or a FP reg destination
    //  (treat as category 1, as FP regs are always 'n' and ignored in our system).
	// Category 10 instructions have 'n' results if the sources are all 'n'; they
	//  have 'p' results if the sources are all 'p'; and we cannot infer the type
	//  of the result if the sources are of mixed types. Bitwise OR and AND are
	//  examples.
	// Category 11 instructions need to have their types and locations on the stack
	//  frame tracked, e.g. push and pop instructions. No direct type inference.
	// Category 12 instructions are similar to category 10, except that we do not
	//  output 'n' annotations when all sources are 'n'; rather, the instruction can
	//  be simply ignored (not instrumented by mmStrata) in that case. Conditional
	//  exchange instructions are examples; we do or do not
	//  move a numeric value into a register that already has numeric metadata.
	// Category 13 instructions imply that their memory destination is 'n'.
	// Category 14 instructions imply that their reg or memory source operand is 'n';
	//  if source is not memory, they are category 1 (inferences, but no instrumentation).
	//  There should never be a memory destination (usual destination is fpreg or flags).
	// Category 15 instructions always have 'n' source AND destination operands;
	//  if addressed using indirect or indexed addressing, they are a subset of category 0
	//  (must be instrumented by mmStrata to keep index in bounds). Memory destinations
	//  are common in this category.

	// 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, '/'.

SMPTypeCategory[NN_null] = 0;            // Unknown Operation
SMPTypeCategory[NN_aaa] = 2;                 // ASCII Adjust after Addition
SMPTypeCategory[NN_aad] = 2;                 // ASCII Adjust AX before Division
SMPTypeCategory[NN_aam] = 2;                 // ASCII Adjust AX after Multiply
SMPTypeCategory[NN_aas] = 2;                 // ASCII Adjust AL after Subtraction
SMPTypeCategory[NN_adc] = 5;                 // Add with Carry
SMPTypeCategory[NN_add] = 5;                 // Add
SMPTypeCategory[NN_and] = 10;                 // Logical AND
SMPTypeCategory[NN_arpl] = 1;                // Adjust RPL Field of Selector
SMPTypeCategory[NN_bound] = 1;               // Check Array Index Against Bounds
SMPTypeCategory[NN_bsf] = 2;                 // Bit Scan Forward
SMPTypeCategory[NN_bsr] = 2;                 // Bit Scan Reverse
SMPTypeCategory[NN_bt] = 2;                  // Bit Test
SMPTypeCategory[NN_btc] = 2;                 // Bit Test and Complement
SMPTypeCategory[NN_btr] = 2;                 // Bit Test and Reset
SMPTypeCategory[NN_bts] = 2;                 // Bit Test and Set
SMPTypeCategory[NN_call] = 1;                // Call Procedure
SMPTypeCategory[NN_callfi] = 1;              // Indirect Call Far Procedure
SMPTypeCategory[NN_callni] = 1;              // Indirect Call Near Procedure
SMPTypeCategory[NN_cbw] = 2;                 // AL -> AX (with sign)            ** No ops?
SMPTypeCategory[NN_cwde] = 2;                // AX -> EAX (with sign)           **
SMPTypeCategory[NN_cdqe] = 2;                // EAX -> RAX (with sign)          **
SMPTypeCategory[NN_clc] = 1;                 // Clear Carry Flag
SMPTypeCategory[NN_cld] = 1;                 // Clear Direction Flag
SMPTypeCategory[NN_cli] = 1;                 // Clear Interrupt Flag
SMPTypeCategory[NN_clts] = 1;                // Clear Task-Switched Flag in CR0
SMPTypeCategory[NN_cmc] = 1;                 // Complement Carry Flag
SMPTypeCategory[NN_cmp] = 1;                 // Compare Two Operands
SMPTypeCategory[NN_cmps] = 14;                // Compare Strings
SMPTypeCategory[NN_cwd] = 2;                 // AX -> DX:AX (with sign)
SMPTypeCategory[NN_cdq] = 2;                 // EAX -> EDX:EAX (with sign)
SMPTypeCategory[NN_cqo] = 2;                 // RAX -> RDX:RAX (with sign)
SMPTypeCategory[NN_daa] = 2;                 // Decimal Adjust AL after Addition
SMPTypeCategory[NN_das] = 2;                 // Decimal Adjust AL after Subtraction
SMPTypeCategory[NN_dec] = 4;                 // Decrement by 1
SMPTypeCategory[NN_div] = 7;                 // Unsigned Divide
SMPTypeCategory[NN_enterw] = 0;              // Make Stack Frame for Procedure Parameters  **
SMPTypeCategory[NN_enter] = 0;               // Make Stack Frame for Procedure Parameters  **
SMPTypeCategory[NN_enterd] = 0;              // Make Stack Frame for Procedure Parameters  **
SMPTypeCategory[NN_enterq] = 0;              // Make Stack Frame for Procedure Parameters  **
SMPTypeCategory[NN_hlt] = 0;                 // Halt
SMPTypeCategory[NN_idiv] = 7;                // Signed Divide
SMPTypeCategory[NN_imul] = 7;                // Signed Multiply
SMPTypeCategory[NN_in] = 0;                  // Input from Port                         **
SMPTypeCategory[NN_inc] = 4;                 // Increment by 1
SMPTypeCategory[NN_ins] = 2;                 // Input Byte(s) from Port to String       **
SMPTypeCategory[NN_int] = 1;                 // Call to Interrupt Procedure
SMPTypeCategory[NN_into] = 1;                // Call to Interrupt Procedure if Overflow Flag = 1
SMPTypeCategory[NN_int3] = 1;                // Trap to Debugger
SMPTypeCategory[NN_iretw] = 1;               // Interrupt Return
SMPTypeCategory[NN_iret] = 1;                // Interrupt Return
SMPTypeCategory[NN_iretd] = 1;               // Interrupt Return (use32)
SMPTypeCategory[NN_iretq] = 1;               // Interrupt Return (use64)
SMPTypeCategory[NN_ja] = 1;                  // Jump if Above (CF=0 & ZF=0)
SMPTypeCategory[NN_jae] = 1;                 // Jump if Above or Equal (CF=0)
SMPTypeCategory[NN_jb] = 1;                  // Jump if Below (CF=1)
SMPTypeCategory[NN_jbe] = 1;                 // Jump if Below or Equal (CF=1 | ZF=1)
SMPTypeCategory[NN_jc] = 1;                  // Jump if Carry (CF=1)
SMPTypeCategory[NN_jcxz] = 1;                // Jump if CX is 0
SMPTypeCategory[NN_jecxz] = 1;               // Jump if ECX is 0
SMPTypeCategory[NN_jrcxz] = 1;               // Jump if RCX is 0
SMPTypeCategory[NN_je] = 1;                  // Jump if Equal (ZF=1)
SMPTypeCategory[NN_jg] = 1;                  // Jump if Greater (ZF=0 & SF=OF)
SMPTypeCategory[NN_jge] = 1;                 // Jump if Greater or Equal (SF=OF)
SMPTypeCategory[NN_jl] = 1;                  // Jump if Less (SF!=OF)
SMPTypeCategory[NN_jle] = 1;                 // Jump if Less or Equal (ZF=1 | SF!=OF)
SMPTypeCategory[NN_jna] = 1;                 // Jump if Not Above (CF=1 | ZF=1)
SMPTypeCategory[NN_jnae] = 1;                // Jump if Not Above or Equal (CF=1)
SMPTypeCategory[NN_jnb] = 1;                 // Jump if Not Below (CF=0)
SMPTypeCategory[NN_jnbe] = 1;                // Jump if Not Below or Equal (CF=0 & ZF=0)
SMPTypeCategory[NN_jnc] = 1;                 // Jump if Not Carry (CF=0)
SMPTypeCategory[NN_jne] = 1;                 // Jump if Not Equal (ZF=0)
SMPTypeCategory[NN_jng] = 1;                 // Jump if Not Greater (ZF=1 | SF!=OF)
SMPTypeCategory[NN_jnge] = 1;                // Jump if Not Greater or Equal (ZF=1)
SMPTypeCategory[NN_jnl] = 1;                 // Jump if Not Less (SF=OF)
SMPTypeCategory[NN_jnle] = 1;                // Jump if Not Less or Equal (ZF=0 & SF=OF)
SMPTypeCategory[NN_jno] = 1;                 // Jump if Not Overflow (OF=0)
SMPTypeCategory[NN_jnp] = 1;                 // Jump if Not Parity (PF=0)
SMPTypeCategory[NN_jns] = 1;                 // Jump if Not Sign (SF=0)
SMPTypeCategory[NN_jnz] = 1;                 // Jump if Not Zero (ZF=0)
SMPTypeCategory[NN_jo] = 1;                  // Jump if Overflow (OF=1)
SMPTypeCategory[NN_jp] = 1;                  // Jump if Parity (PF=1)
SMPTypeCategory[NN_jpe] = 1;                 // Jump if Parity Even (PF=1)
SMPTypeCategory[NN_jpo] = 1;                 // Jump if Parity Odd  (PF=0)
SMPTypeCategory[NN_js] = 1;                  // Jump if Sign (SF=1)
SMPTypeCategory[NN_jz] = 1;                  // Jump if Zero (ZF=1)
SMPTypeCategory[NN_jmp] = 1;                 // Jump
SMPTypeCategory[NN_jmpfi] = 1;               // Indirect Far Jump
SMPTypeCategory[NN_jmpni] = 1;               // Indirect Near Jump
SMPTypeCategory[NN_jmpshort] = 1;            // Jump Short (not used)
SMPTypeCategory[NN_lahf] = 2;                // Load Flags into AH Register
SMPTypeCategory[NN_lar] = 2;                 // Load Access Rights Byte
SMPTypeCategory[NN_lea] = 0;                 // Load Effective Address           **
SMPTypeCategory[NN_leavew] = 0;              // High Level Procedure Exit        **
SMPTypeCategory[NN_leave] = 0;               // High Level Procedure Exit        **
SMPTypeCategory[NN_leaved] = 0;              // High Level Procedure Exit        **
SMPTypeCategory[NN_leaveq] = 0;              // High Level Procedure Exit        **
SMPTypeCategory[NN_lgdt] = 0;                // Load Global Descriptor Table Register
SMPTypeCategory[NN_lidt] = 0;                // Load Interrupt Descriptor Table Register
SMPTypeCategory[NN_lgs] = 6;                 // Load Full Pointer to GS:xx
SMPTypeCategory[NN_lss] = 6;                 // Load Full Pointer to SS:xx
SMPTypeCategory[NN_lds] = 6;                 // Load Full Pointer to DS:xx
SMPTypeCategory[NN_les] = 6;                 // Load Full Pointer to ES:xx
SMPTypeCategory[NN_lfs] = 6;                 // Load Full Pointer to FS:xx
SMPTypeCategory[NN_lldt] = 0;                // Load Local Descriptor Table Register
SMPTypeCategory[NN_lmsw] = 1;                // Load Machine Status Word
SMPTypeCategory[NN_lock] = 1;                // Assert LOCK# Signal Prefix
SMPTypeCategory[NN_lods] = 0;                // Load String
SMPTypeCategory[NN_loopw] = 1;               // Loop while ECX != 0
SMPTypeCategory[NN_loop] = 1;                // Loop while CX != 0
SMPTypeCategory[NN_loopd] = 1;               // Loop while ECX != 0
SMPTypeCategory[NN_loopq] = 1;               // Loop while RCX != 0
SMPTypeCategory[NN_loopwe] = 1;              // Loop while CX != 0 and ZF=1
SMPTypeCategory[NN_loope] = 1;               // Loop while rCX != 0 and ZF=1
SMPTypeCategory[NN_loopde] = 1;              // Loop while ECX != 0 and ZF=1
SMPTypeCategory[NN_loopqe] = 1;              // Loop while RCX != 0 and ZF=1
SMPTypeCategory[NN_loopwne] = 1;             // Loop while CX != 0 and ZF=0
SMPTypeCategory[NN_loopne] = 1;              // Loop while rCX != 0 and ZF=0
SMPTypeCategory[NN_loopdne] = 1;             // Loop while ECX != 0 and ZF=0
SMPTypeCategory[NN_loopqne] = 1;             // Loop while RCX != 0 and ZF=0
SMPTypeCategory[NN_lsl] = 6;                 // Load Segment Limit
SMPTypeCategory[NN_ltr] = 1;                 // Load Task Register
SMPTypeCategory[NN_mov] = 3;                 // Move Data
SMPTypeCategory[NN_movsp] = 3;               // Move to/from Special Registers
SMPTypeCategory[NN_movs] = 0;                // Move Byte(s) from String to String
SMPTypeCategory[NN_movsx] = 3;               // Move with Sign-Extend
SMPTypeCategory[NN_movzx] = 3;               // Move with Zero-Extend
SMPTypeCategory[NN_mul] = 7;                 // Unsigned Multiplication of AL or AX
SMPTypeCategory[NN_neg] = 2;                 // Two's Complement Negation
SMPTypeCategory[NN_nop] = 1;                 // No Operation
SMPTypeCategory[NN_not] = 2;                 // One's Complement Negation
SMPTypeCategory[NN_or] = 10;                  // Logical Inclusive OR
SMPTypeCategory[NN_out] = 0;                 // Output to Port
SMPTypeCategory[NN_outs] = 0;                // Output Byte(s) to Port
SMPTypeCategory[NN_pop] = 11;                 // Pop a word from the Stack
SMPTypeCategory[NN_popaw] = 11;               // Pop all General Registers
SMPTypeCategory[NN_popa] = 11;                // Pop all General Registers
SMPTypeCategory[NN_popad] = 11;               // Pop all General Registers (use32)
SMPTypeCategory[NN_popaq] = 11;               // Pop all General Registers (use64)
SMPTypeCategory[NN_popfw] = 11;               // Pop Stack into Flags Register         **
SMPTypeCategory[NN_popf] = 11;                // Pop Stack into Flags Register         **
SMPTypeCategory[NN_popfd] = 11;               // Pop Stack into Eflags Register        **
SMPTypeCategory[NN_popfq] = 11;               // Pop Stack into Rflags Register        **
SMPTypeCategory[NN_push] = 11;                // Push Operand onto the Stack
SMPTypeCategory[NN_pushaw] = 11;              // Push all General Registers
SMPTypeCategory[NN_pusha] = 11;               // Push all General Registers
SMPTypeCategory[NN_pushad] = 11;              // Push all General Registers (use32)
SMPTypeCategory[NN_pushaq] = 11;              // Push all General Registers (use64)
SMPTypeCategory[NN_pushfw] = 11;              // Push Flags Register onto the Stack
SMPTypeCategory[NN_pushf] = 11;               // Push Flags Register onto the Stack
SMPTypeCategory[NN_pushfd] = 11;              // Push Flags Register onto the Stack (use32)
SMPTypeCategory[NN_pushfq] = 11;              // Push Flags Register onto the Stack (use64)
SMPTypeCategory[NN_rcl] = 2;                 // Rotate Through Carry Left
SMPTypeCategory[NN_rcr] = 2;                 // Rotate Through Carry Right
SMPTypeCategory[NN_rol] = 2;                 // Rotate Left
SMPTypeCategory[NN_ror] = 2;                 // Rotate Right
SMPTypeCategory[NN_rep] = 0;                 // Repeat String Operation
SMPTypeCategory[NN_repe] = 0;                // Repeat String Operation while ZF=1
SMPTypeCategory[NN_repne] = 0;               // Repeat String Operation while ZF=0
SMPTypeCategory[NN_retn] = 0;                // Return Near from Procedure
SMPTypeCategory[NN_retf] = 0;                // Return Far from Procedure
SMPTypeCategory[NN_sahf] = 14;                // Store AH into Flags Register
SMPTypeCategory[NN_sal] = 2;                 // Shift Arithmetic Left
SMPTypeCategory[NN_sar] = 2;                 // Shift Arithmetic Right
SMPTypeCategory[NN_shl] = 2;                 // Shift Logical Left
SMPTypeCategory[NN_shr] = 2;                 // Shift Logical Right
SMPTypeCategory[NN_sbb] = 5;                 // Integer Subtraction with Borrow
SMPTypeCategory[NN_scas] = 14;                // Compare String
SMPTypeCategory[NN_seta] = 2;                // Set Byte if Above (CF=0 & ZF=0)
SMPTypeCategory[NN_setae] = 2;               // Set Byte if Above or Equal (CF=0)
SMPTypeCategory[NN_setb] = 2;                // Set Byte if Below (CF=1)
SMPTypeCategory[NN_setbe] = 2;               // Set Byte if Below or Equal (CF=1 | ZF=1)
SMPTypeCategory[NN_setc] = 2;                // Set Byte if Carry (CF=1)
SMPTypeCategory[NN_sete] = 2;                // Set Byte if Equal (ZF=1)
SMPTypeCategory[NN_setg] = 2;                // Set Byte if Greater (ZF=0 & SF=OF)
SMPTypeCategory[NN_setge] = 2;               // Set Byte if Greater or Equal (SF=OF)
SMPTypeCategory[NN_setl] = 2;                // Set Byte if Less (SF!=OF)
SMPTypeCategory[NN_setle] = 2;               // Set Byte if Less or Equal (ZF=1 | SF!=OF)
SMPTypeCategory[NN_setna] = 2;               // Set Byte if Not Above (CF=1 | ZF=1)
SMPTypeCategory[NN_setnae] = 2;              // Set Byte if Not Above or Equal (CF=1)
SMPTypeCategory[NN_setnb] = 2;               // Set Byte if Not Below (CF=0)
SMPTypeCategory[NN_setnbe] = 2;              // Set Byte if Not Below or Equal (CF=0 & ZF=0)
SMPTypeCategory[NN_setnc] = 2;               // Set Byte if Not Carry (CF=0)
SMPTypeCategory[NN_setne] = 2;               // Set Byte if Not Equal (ZF=0)
SMPTypeCategory[NN_setng] = 2;               // Set Byte if Not Greater (ZF=1 | SF!=OF)
SMPTypeCategory[NN_setnge] = 2;              // Set Byte if Not Greater or Equal (ZF=1)
SMPTypeCategory[NN_setnl] = 2;               // Set Byte if Not Less (SF=OF)
SMPTypeCategory[NN_setnle] = 2;              // Set Byte if Not Less or Equal (ZF=0 & SF=OF)
SMPTypeCategory[NN_setno] = 2;               // Set Byte if Not Overflow (OF=0)
SMPTypeCategory[NN_setnp] = 2;               // Set Byte if Not Parity (PF=0)
SMPTypeCategory[NN_setns] = 2;               // Set Byte if Not Sign (SF=0)
SMPTypeCategory[NN_setnz] = 2;               // Set Byte if Not Zero (ZF=0)
SMPTypeCategory[NN_seto] = 2;                // Set Byte if Overflow (OF=1)
SMPTypeCategory[NN_setp] = 2;                // Set Byte if Parity (PF=1)
SMPTypeCategory[NN_setpe] = 2;               // Set Byte if Parity Even (PF=1)
SMPTypeCategory[NN_setpo] = 2;               // Set Byte if Parity Odd  (PF=0)
SMPTypeCategory[NN_sets] = 2;                // Set Byte if Sign (SF=1)
SMPTypeCategory[NN_setz] = 2;                // Set Byte if Zero (ZF=1)
SMPTypeCategory[NN_sgdt] = 0;                // Store Global Descriptor Table Register
SMPTypeCategory[NN_sidt] = 0;                // Store Interrupt Descriptor Table Register
SMPTypeCategory[NN_shld] = 2;                // Double Precision Shift Left
SMPTypeCategory[NN_shrd] = 2;                // Double Precision Shift Right
SMPTypeCategory[NN_sldt] = 6;                // Store Local Descriptor Table Register
SMPTypeCategory[NN_smsw] = 2;                // Store Machine Status Word
SMPTypeCategory[NN_stc] = 1;                 // Set Carry Flag
SMPTypeCategory[NN_std] = 1;                 // Set Direction Flag
SMPTypeCategory[NN_sti] = 1;                 // Set Interrupt Flag
SMPTypeCategory[NN_stos] = 0;                // Store String
SMPTypeCategory[NN_str] = 6;                 // Store Task Register
SMPTypeCategory[NN_sub] = 5;                 // Integer Subtraction
SMPTypeCategory[NN_test] = 1;                // Logical Compare
SMPTypeCategory[NN_verr] = 1;                // Verify a Segment for Reading
SMPTypeCategory[NN_verw] = 1;                // Verify a Segment for Writing
SMPTypeCategory[NN_wait] = 1;                // Wait until BUSY# Pin is Inactive (HIGH)
SMPTypeCategory[NN_xchg] = 12;                // Exchange Register/Memory with Register
SMPTypeCategory[NN_xlat] = 0;                // Table Lookup Translation
SMPTypeCategory[NN_xor] = 2;                 // Logical Exclusive OR

//
//      486 instructions
//

SMPTypeCategory[NN_cmpxchg] = 12;             // Compare and Exchange
SMPTypeCategory[NN_bswap] = 1;               // Swap bytes in register
SMPTypeCategory[NN_xadd] = 12;                // t<-dest; dest<-src+dest; src<-t
SMPTypeCategory[NN_invd] = 1;                // Invalidate Data Cache
SMPTypeCategory[NN_wbinvd] = 1;              // Invalidate Data Cache (write changes)
SMPTypeCategory[NN_invlpg] = 1;              // Invalidate TLB entry

//
//      Pentium instructions
//

SMPTypeCategory[NN_rdmsr] = 8;               // Read Machine Status Register
SMPTypeCategory[NN_wrmsr] = 1;               // Write Machine Status Register
SMPTypeCategory[NN_cpuid] = 8;               // Get CPU ID
SMPTypeCategory[NN_cmpxchg8b] = 12;           // Compare and Exchange Eight Bytes
SMPTypeCategory[NN_rdtsc] = 8;               // Read Time Stamp Counter
SMPTypeCategory[NN_rsm] = 1;                 // Resume from System Management Mode

//
//      Pentium Pro instructions
//

SMPTypeCategory[NN_cmova] = 0;               // Move if Above (CF=0 & ZF=0)
SMPTypeCategory[NN_cmovb] = 0;               // Move if Below (CF=1)
SMPTypeCategory[NN_cmovbe] = 0;              // Move if Below or Equal (CF=1 | ZF=1)
SMPTypeCategory[NN_cmovg] = 0;               // Move if Greater (ZF=0 & SF=OF)
SMPTypeCategory[NN_cmovge] = 0;              // Move if Greater or Equal (SF=OF)
SMPTypeCategory[NN_cmovl] = 0;               // Move if Less (SF!=OF)
SMPTypeCategory[NN_cmovle] = 0;              // Move if Less or Equal (ZF=1 | SF!=OF)
SMPTypeCategory[NN_cmovnb] = 0;              // Move if Not Below (CF=0)
SMPTypeCategory[NN_cmovno] = 0;              // Move if Not Overflow (OF=0)
SMPTypeCategory[NN_cmovnp] = 0;              // Move if Not Parity (PF=0)
SMPTypeCategory[NN_cmovns] = 0;              // Move if Not Sign (SF=0)
SMPTypeCategory[NN_cmovnz] = 0;              // Move if Not Zero (ZF=0)
SMPTypeCategory[NN_cmovo] = 0;               // Move if Overflow (OF=1)
SMPTypeCategory[NN_cmovp] = 0;               // Move if Parity (PF=1)
SMPTypeCategory[NN_cmovs] = 0;               // Move if Sign (SF=1)
SMPTypeCategory[NN_cmovz] = 0;               // Move if Zero (ZF=1)
SMPTypeCategory[NN_fcmovb] = 1;              // Floating Move if Below          
SMPTypeCategory[NN_fcmove] = 1;              // Floating Move if Equal          
SMPTypeCategory[NN_fcmovbe] = 1;             // Floating Move if Below or Equal 
SMPTypeCategory[NN_fcmovu] = 1;              // Floating Move if Unordered      
SMPTypeCategory[NN_fcmovnb] = 1;             // Floating Move if Not Below      
SMPTypeCategory[NN_fcmovne] = 1;             // Floating Move if Not Equal      
SMPTypeCategory[NN_fcmovnbe] = 1;            // Floating Move if Not Below or Equal
SMPTypeCategory[NN_fcmovnu] = 1;             // Floating Move if Not Unordered     
SMPTypeCategory[NN_fcomi] = 1;               // FP Compare, result in EFLAGS
SMPTypeCategory[NN_fucomi] = 1;              // FP Unordered Compare, result in EFLAGS
SMPTypeCategory[NN_fcomip] = 1;              // FP Compare, result in EFLAGS, pop stack
SMPTypeCategory[NN_fucomip] = 1;             // FP Unordered Compare, result in EFLAGS, pop stack
SMPTypeCategory[NN_rdpmc] = 8;               // Read Performance Monitor Counter

//
//      FPP instructions
//

SMPTypeCategory[NN_fld] = 14;                 // Load Real             ** Infer src is 'n'
SMPTypeCategory[NN_fst] = 9;                 // Store Real            
SMPTypeCategory[NN_fstp] = 9;                // Store Real and Pop   
SMPTypeCategory[NN_fxch] = 1;                // Exchange Registers
SMPTypeCategory[NN_fild] = 14;                // Load Integer          ** Infer src is 'n'
SMPTypeCategory[NN_fist] = 13;                // Store Integer
SMPTypeCategory[NN_fistp] = 13;               // Store Integer and Pop
SMPTypeCategory[NN_fbld] = 1;                // Load BCD
SMPTypeCategory[NN_fbstp] = 13;               // Store BCD and Pop
SMPTypeCategory[NN_fadd] = 14;                // Add Real
SMPTypeCategory[NN_faddp] = 14;               // Add Real and Pop
SMPTypeCategory[NN_fiadd] = 14;               // Add Integer
SMPTypeCategory[NN_fsub] = 14;                // Subtract Real
SMPTypeCategory[NN_fsubp] = 14;               // Subtract Real and Pop
SMPTypeCategory[NN_fisub] = 14;               // Subtract Integer
SMPTypeCategory[NN_fsubr] = 14;               // Subtract Real Reversed
SMPTypeCategory[NN_fsubrp] = 14;              // Subtract Real Reversed and Pop
SMPTypeCategory[NN_fisubr] = 14;              // Subtract Integer Reversed
SMPTypeCategory[NN_fmul] = 14;                // Multiply Real
SMPTypeCategory[NN_fmulp] = 14;               // Multiply Real and Pop
SMPTypeCategory[NN_fimul] = 14;               // Multiply Integer
SMPTypeCategory[NN_fdiv] = 14;                // Divide Real
SMPTypeCategory[NN_fdivp] = 14;               // Divide Real and Pop
SMPTypeCategory[NN_fidiv] = 14;               // Divide Integer
SMPTypeCategory[NN_fdivr] = 14;               // Divide Real Reversed
SMPTypeCategory[NN_fdivrp] = 14;              // Divide Real Reversed and Pop
SMPTypeCategory[NN_fidivr] = 14;              // Divide Integer Reversed
SMPTypeCategory[NN_fsqrt] = 1;               // Square Root
SMPTypeCategory[NN_fscale] = 1;              // Scale:  st(0) <- st(0) * 2^st(1)
SMPTypeCategory[NN_fprem] = 1;               // Partial Remainder
SMPTypeCategory[NN_frndint] = 1;             // Round to Integer
SMPTypeCategory[NN_fxtract] = 1;             // Extract exponent and significand
SMPTypeCategory[NN_fabs] = 1;                // Absolute value
SMPTypeCategory[NN_fchs] = 1;                // Change Sign
SMPTypeCategory[NN_fcom] = 1;                // Compare Real
SMPTypeCategory[NN_fcomp] = 1;               // Compare Real and Pop
SMPTypeCategory[NN_fcompp] = 1;              // Compare Real and Pop Twice
SMPTypeCategory[NN_ficom] = 1;               // Compare Integer
SMPTypeCategory[NN_ficomp] = 1;              // Compare Integer and Pop
SMPTypeCategory[NN_ftst] = 1;                // Test
SMPTypeCategory[NN_fxam] = 1;                // Examine
SMPTypeCategory[NN_fptan] = 1;               // Partial tangent
SMPTypeCategory[NN_fpatan] = 1;              // Partial arctangent
SMPTypeCategory[NN_f2xm1] = 1;               // 2^x - 1
SMPTypeCategory[NN_fyl2x] = 1;               // Y * lg2(X)
SMPTypeCategory[NN_fyl2xp1] = 1;             // Y * lg2(X+1)
SMPTypeCategory[NN_fldz] = 1;                // Load +0.0
SMPTypeCategory[NN_fld1] = 1;                // Load +1.0
SMPTypeCategory[NN_fldpi] = 1;               // Load PI=3.14...
SMPTypeCategory[NN_fldl2t] = 1;              // Load lg2(10)
SMPTypeCategory[NN_fldl2e] = 1;              // Load lg2(e)
SMPTypeCategory[NN_fldlg2] = 1;              // Load lg10(2)
SMPTypeCategory[NN_fldln2] = 1;              // Load ln(2)
SMPTypeCategory[NN_finit] = 1;               // Initialize Processor
SMPTypeCategory[NN_fninit] = 1;              // Initialize Processor (no wait)
SMPTypeCategory[NN_fsetpm] = 1;              // Set Protected Mode
SMPTypeCategory[NN_fldcw] = 14;               // Load Control Word
SMPTypeCategory[NN_fstcw] = 13;               // Store Control Word
SMPTypeCategory[NN_fnstcw] = 13;              // Store Control Word (no wait)
SMPTypeCategory[NN_fstsw] = 2;               // Store Status Word to memory or AX
SMPTypeCategory[NN_fnstsw] = 2;              // Store Status Word (no wait) to memory or AX
SMPTypeCategory[NN_fclex] = 1;               // Clear Exceptions
SMPTypeCategory[NN_fnclex] = 1;              // Clear Exceptions (no wait)
SMPTypeCategory[NN_fstenv] = 13;              // Store Environment
SMPTypeCategory[NN_fnstenv] = 13;             // Store Environment (no wait)
SMPTypeCategory[NN_fldenv] = 14;              // Load Environment
SMPTypeCategory[NN_fsave] = 13;               // Save State
SMPTypeCategory[NN_fnsave] = 13;              // Save State (no wait)
SMPTypeCategory[NN_frstor] = 14;              // Restore State    **  infer src is 'n'
SMPTypeCategory[NN_fincstp] = 1;             // Increment Stack Pointer
SMPTypeCategory[NN_fdecstp] = 1;             // Decrement Stack Pointer
SMPTypeCategory[NN_ffree] = 1;               // Free Register
SMPTypeCategory[NN_fnop] = 1;                // No Operation
SMPTypeCategory[NN_feni] = 1;                // (8087 only)
SMPTypeCategory[NN_fneni] = 1;               // (no wait) (8087 only)
SMPTypeCategory[NN_fdisi] = 1;               // (8087 only)
SMPTypeCategory[NN_fndisi] = 1;              // (no wait) (8087 only)

//
//      80387 instructions
//

SMPTypeCategory[NN_fprem1] = 1;              // Partial Remainder ( < half )
SMPTypeCategory[NN_fsincos] = 1;             // t<-cos(st); st<-sin(st); push t
SMPTypeCategory[NN_fsin] = 1;                // Sine
SMPTypeCategory[NN_fcos] = 1;                // Cosine
SMPTypeCategory[NN_fucom] = 1;               // Compare Unordered Real
SMPTypeCategory[NN_fucomp] = 1;              // Compare Unordered Real and Pop
SMPTypeCategory[NN_fucompp] = 1;             // Compare Unordered Real and Pop Twice

//
//      Instructions added 28.02.96
//

SMPTypeCategory[NN_setalc] = 2;              // Set AL to Carry Flag     **
SMPTypeCategory[NN_svdc] = 0;                // Save Register and Descriptor
SMPTypeCategory[NN_rsdc] = 0;                // Restore Register and Descriptor
SMPTypeCategory[NN_svldt] = 0;               // Save LDTR and Descriptor
SMPTypeCategory[NN_rsldt] = 0;               // Restore LDTR and Descriptor
SMPTypeCategory[NN_svts] = 1;                // Save TR and Descriptor
SMPTypeCategory[NN_rsts] = 1;                // Restore TR and Descriptor
SMPTypeCategory[NN_icebp] = 1;               // ICE Break Point
SMPTypeCategory[NN_loadall] = 0;             // Load the entire CPU state from ES:EDI ???

//
//      MMX instructions
//

SMPTypeCategory[NN_emms] = 1;                // Empty MMX state
SMPTypeCategory[NN_movd] = 15;                // Move 32 bits
SMPTypeCategory[NN_movq] = 15;                // Move 64 bits
SMPTypeCategory[NN_packsswb] = 14;            // Pack with Signed Saturation (Word->Byte)
SMPTypeCategory[NN_packssdw] = 14;            // Pack with Signed Saturation (Dword->Word)
SMPTypeCategory[NN_packuswb] = 14;            // Pack with Unsigned Saturation (Word->Byte)
SMPTypeCategory[NN_paddb] = 14;               // Packed Add Byte
SMPTypeCategory[NN_paddw] = 14;               // Packed Add Word
SMPTypeCategory[NN_paddd] = 14;               // Packed Add Dword
SMPTypeCategory[NN_paddsb] = 14;              // Packed Add with Saturation (Byte)
SMPTypeCategory[NN_paddsw] = 14;              // Packed Add with Saturation (Word)
SMPTypeCategory[NN_paddusb] = 14;             // Packed Add Unsigned with Saturation (Byte)
SMPTypeCategory[NN_paddusw] = 14;             // Packed Add Unsigned with Saturation (Word)
SMPTypeCategory[NN_pand] = 14;                // Bitwise Logical And
SMPTypeCategory[NN_pandn] = 14;               // Bitwise Logical And Not
SMPTypeCategory[NN_pcmpeqb] = 14;             // Packed Compare for Equal (Byte)
SMPTypeCategory[NN_pcmpeqw] = 14;             // Packed Compare for Equal (Word)
SMPTypeCategory[NN_pcmpeqd] = 14;             // Packed Compare for Equal (Dword)
SMPTypeCategory[NN_pcmpgtb] = 14;             // Packed Compare for Greater Than (Byte)
SMPTypeCategory[NN_pcmpgtw] = 14;             // Packed Compare for Greater Than (Word)
SMPTypeCategory[NN_pcmpgtd] = 14;             // Packed Compare for Greater Than (Dword)
SMPTypeCategory[NN_pmaddwd] = 14;             // Packed Multiply and Add
SMPTypeCategory[NN_pmulhw] = 14;              // Packed Multiply High
SMPTypeCategory[NN_pmullw] = 14;              // Packed Multiply Low
SMPTypeCategory[NN_por] = 14;                 // Bitwise Logical Or
SMPTypeCategory[NN_psllw] = 14;               // Packed Shift Left Logical (Word)
SMPTypeCategory[NN_pslld] = 14;               // Packed Shift Left Logical (Dword)
SMPTypeCategory[NN_psllq] = 14;               // Packed Shift Left Logical (Qword)
SMPTypeCategory[NN_psraw] = 14;               // Packed Shift Right Arithmetic (Word)
SMPTypeCategory[NN_psrad] = 14;               // Packed Shift Right Arithmetic (Dword)
SMPTypeCategory[NN_psrlw] = 14;               // Packed Shift Right Logical (Word)
SMPTypeCategory[NN_psrld] = 14;               // Packed Shift Right Logical (Dword)
SMPTypeCategory[NN_psrlq] = 14;               // Packed Shift Right Logical (Qword)
SMPTypeCategory[NN_psubb] = 14;               // Packed Subtract Byte
SMPTypeCategory[NN_psubw] = 14;               // Packed Subtract Word
SMPTypeCategory[NN_psubd] = 14;               // Packed Subtract Dword
SMPTypeCategory[NN_psubsb] = 14;              // Packed Subtract with Saturation (Byte)
SMPTypeCategory[NN_psubsw] = 14;              // Packed Subtract with Saturation (Word)
SMPTypeCategory[NN_psubusb] = 14;             // Packed Subtract Unsigned with Saturation (Byte)
SMPTypeCategory[NN_psubusw] = 14;             // Packed Subtract Unsigned with Saturation (Word)
SMPTypeCategory[NN_punpckhbw] = 14;           // Unpack High Packed Data (Byte->Word)
SMPTypeCategory[NN_punpckhwd] = 14;           // Unpack High Packed Data (Word->Dword)
SMPTypeCategory[NN_punpckhdq] = 14;           // Unpack High Packed Data (Dword->Qword)
SMPTypeCategory[NN_punpcklbw] = 14;           // Unpack Low Packed Data (Byte->Word)
SMPTypeCategory[NN_punpcklwd] = 14;           // Unpack Low Packed Data (Word->Dword)
SMPTypeCategory[NN_punpckldq] = 14;           // Unpack Low Packed Data (Dword->Qword)
SMPTypeCategory[NN_pxor] = 14;                // Bitwise Logical Exclusive Or

//
//      Undocumented Deschutes processor instructions
//

SMPTypeCategory[NN_fxsave] = 1;              // Fast save FP context            ** to where?
SMPTypeCategory[NN_fxrstor] = 1;             // Fast restore FP context         ** from where?

//      Pentium II instructions

SMPTypeCategory[NN_sysenter] = 1;            // Fast Transition to System Call Entry Point
SMPTypeCategory[NN_sysexit] = 1;             // Fast Transition from System Call Entry Point

//      3DNow! instructions

SMPTypeCategory[NN_pavgusb] = 14;             // Packed 8-bit Unsigned Integer Averaging
SMPTypeCategory[NN_pfadd] = 14;               // Packed Floating-Point Addition
SMPTypeCategory[NN_pfsub] = 14;               // Packed Floating-Point Subtraction
SMPTypeCategory[NN_pfsubr] = 14;              // Packed Floating-Point Reverse Subtraction
SMPTypeCategory[NN_pfacc] = 14;               // Packed Floating-Point Accumulate
SMPTypeCategory[NN_pfcmpge] = 14;             // Packed Floating-Point Comparison, Greater or Equal
SMPTypeCategory[NN_pfcmpgt] = 14;             // Packed Floating-Point Comparison, Greater
SMPTypeCategory[NN_pfcmpeq] = 14;             // Packed Floating-Point Comparison, Equal
SMPTypeCategory[NN_pfmin] = 14;               // Packed Floating-Point Minimum
SMPTypeCategory[NN_pfmax] = 14;               // Packed Floating-Point Maximum
SMPTypeCategory[NN_pi2fd] = 14;               // Packed 32-bit Integer to Floating-Point
SMPTypeCategory[NN_pf2id] = 14;               // Packed Floating-Point to 32-bit Integer
SMPTypeCategory[NN_pfrcp] = 14;               // Packed Floating-Point Reciprocal Approximation
SMPTypeCategory[NN_pfrsqrt] = 14;             // Packed Floating-Point Reciprocal Square Root Approximation
SMPTypeCategory[NN_pfmul] = 14;               // Packed Floating-Point Multiplication
SMPTypeCategory[NN_pfrcpit1] = 14;            // Packed Floating-Point Reciprocal First Iteration Step
SMPTypeCategory[NN_pfrsqit1] = 14;            // Packed Floating-Point Reciprocal Square Root First Iteration Step
SMPTypeCategory[NN_pfrcpit2] = 14;            // Packed Floating-Point Reciprocal Second Iteration Step
SMPTypeCategory[NN_pmulhrw] = 14;             // Packed Floating-Point 16-bit Integer Multiply with rounding
SMPTypeCategory[NN_femms] = 1;               // Faster entry/exit of the MMX or floating-point state
SMPTypeCategory[NN_prefetch] = 1;            // Prefetch at least a 32-byte line into L1 data cache
SMPTypeCategory[NN_prefetchw] = 1;           // Prefetch processor cache line into L1 data cache (mark as modified)


//      Pentium III instructions

SMPTypeCategory[NN_addps] = 14;               // Packed Single-FP Add
SMPTypeCategory[NN_addss] = 14;               // Scalar Single-FP Add
SMPTypeCategory[NN_andnps] = 14;              // Bitwise Logical And Not for Single-FP
SMPTypeCategory[NN_andps] = 14;               // Bitwise Logical And for Single-FP
SMPTypeCategory[NN_cmpps] = 14;               // Packed Single-FP Compare
SMPTypeCategory[NN_cmpss] = 14;               // Scalar Single-FP Compare
SMPTypeCategory[NN_comiss] = 14;              // Scalar Ordered Single-FP Compare and Set EFLAGS
SMPTypeCategory[NN_cvtpi2ps] = 14;            // Packed signed INT32 to Packed Single-FP conversion
SMPTypeCategory[NN_cvtps2pi] = 14;            // Packed Single-FP to Packed INT32 conversion
SMPTypeCategory[NN_cvtsi2ss] = 14;            // Scalar signed INT32 to Single-FP conversion
SMPTypeCategory[NN_cvtss2si] = 14;            // Scalar Single-FP to signed INT32 conversion
SMPTypeCategory[NN_cvttps2pi] = 14;           // Packed Single-FP to Packed INT32 conversion (truncate)
SMPTypeCategory[NN_cvttss2si] = 14;           // Scalar Single-FP to signed INT32 conversion (truncate)
SMPTypeCategory[NN_divps] = 14;               // Packed Single-FP Divide
SMPTypeCategory[NN_divss] = 14;               // Scalar Single-FP Divide
SMPTypeCategory[NN_ldmxcsr] = 14;             // Load Streaming SIMD Extensions Technology Control/Status Register
SMPTypeCategory[NN_maxps] = 14;               // Packed Single-FP Maximum
SMPTypeCategory[NN_maxss] = 14;               // Scalar Single-FP Maximum
SMPTypeCategory[NN_minps] = 14;               // Packed Single-FP Minimum
SMPTypeCategory[NN_minss] = 14;               // Scalar Single-FP Minimum
SMPTypeCategory[NN_movaps] = 15;              // Move Aligned Four Packed Single-FP  ** infer memsrc 'n'?
SMPTypeCategory[NN_movhlps] = 15;             // Move High to Low Packed Single-FP
SMPTypeCategory[NN_movhps] = 15;              // Move High Packed Single-FP
SMPTypeCategory[NN_movlhps] = 15;             // Move Low to High Packed Single-FP
SMPTypeCategory[NN_movlps] = 15;              // Move Low Packed Single-FP
SMPTypeCategory[NN_movmskps] = 15;            // Move Mask to Register
SMPTypeCategory[NN_movss] = 15;               // Move Scalar Single-FP
SMPTypeCategory[NN_movups] = 15;              // Move Unaligned Four Packed Single-FP
SMPTypeCategory[NN_mulps] = 14;               // Packed Single-FP Multiply
SMPTypeCategory[NN_mulss] = 14;               // Scalar Single-FP Multiply
SMPTypeCategory[NN_orps] = 14;                // Bitwise Logical OR for Single-FP Data
SMPTypeCategory[NN_rcpps] = 14;               // Packed Single-FP Reciprocal
SMPTypeCategory[NN_rcpss] = 14;               // Scalar Single-FP Reciprocal
SMPTypeCategory[NN_rsqrtps] = 14;             // Packed Single-FP Square Root Reciprocal
SMPTypeCategory[NN_rsqrtss] = 14;             // Scalar Single-FP Square Root Reciprocal
SMPTypeCategory[NN_shufps] = 14;              // Shuffle Single-FP
SMPTypeCategory[NN_sqrtps] = 14;              // Packed Single-FP Square Root
SMPTypeCategory[NN_sqrtss] = 14;              // Scalar Single-FP Square Root
SMPTypeCategory[NN_stmxcsr] = 15;             // Store Streaming SIMD Extensions Technology Control/Status Register    ** Infer dest is 'n'
SMPTypeCategory[NN_subps] = 14;               // Packed Single-FP Subtract
SMPTypeCategory[NN_subss] = 14;               // Scalar Single-FP Subtract
SMPTypeCategory[NN_ucomiss] = 14;             // Scalar Unordered Single-FP Compare and Set EFLAGS
SMPTypeCategory[NN_unpckhps] = 14;            // Unpack High Packed Single-FP Data
SMPTypeCategory[NN_unpcklps] = 14;            // Unpack Low Packed Single-FP Data
SMPTypeCategory[NN_xorps] = 14;               // Bitwise Logical XOR for Single-FP Data
SMPTypeCategory[NN_pavgb] = 14;               // Packed Average (Byte)
SMPTypeCategory[NN_pavgw] = 14;               // Packed Average (Word)
SMPTypeCategory[NN_pextrw] = 2;               // Extract Word
SMPTypeCategory[NN_pinsrw] = 14;              // Insert Word
SMPTypeCategory[NN_pmaxsw] = 14;              // Packed Signed Integer Word Maximum
SMPTypeCategory[NN_pmaxub] = 14;              // Packed Unsigned Integer Byte Maximum
SMPTypeCategory[NN_pminsw] = 14;              // Packed Signed Integer Word Minimum
SMPTypeCategory[NN_pminub] = 14;              // Packed Unsigned Integer Byte Minimum
SMPTypeCategory[NN_pmovmskb] = 2;             // Move Byte Mask to Integer
SMPTypeCategory[NN_pmulhuw] = 14;             // Packed Multiply High Unsigned
SMPTypeCategory[NN_psadbw] = 14;              // Packed Sum of Absolute Differences
SMPTypeCategory[NN_pshufw] = 14;              // Packed Shuffle Word
SMPTypeCategory[NN_maskmovq] = 15;            // Byte Mask write   ** Infer dest is 'n'
SMPTypeCategory[NN_movntps] = 13;             // Move Aligned Four Packed Single-FP Non Temporal  * infer dest is 'n'
SMPTypeCategory[NN_movntq] = 13;              // Move 64 Bits Non Temporal    ** Infer dest is 'n'
SMPTypeCategory[NN_prefetcht0] = 1;          // Prefetch to all cache levels
SMPTypeCategory[NN_prefetcht1] = 1;          // Prefetch to all cache levels
SMPTypeCategory[NN_prefetcht2] = 1;          // Prefetch to L2 cache
SMPTypeCategory[NN_prefetchnta] = 1;         // Prefetch to L1 cache
SMPTypeCategory[NN_sfence] = 1;              // Store Fence

// Pentium III Pseudo instructions

SMPTypeCategory[NN_cmpeqps] = 14;             // Packed Single-FP Compare EQ
SMPTypeCategory[NN_cmpltps] = 14;             // Packed Single-FP Compare LT
SMPTypeCategory[NN_cmpleps] = 14;             // Packed Single-FP Compare LE
SMPTypeCategory[NN_cmpunordps] = 14;          // Packed Single-FP Compare UNORD
SMPTypeCategory[NN_cmpneqps] = 14;            // Packed Single-FP Compare NOT EQ
SMPTypeCategory[NN_cmpnltps] = 14;            // Packed Single-FP Compare NOT LT
SMPTypeCategory[NN_cmpnleps] = 14;            // Packed Single-FP Compare NOT LE
SMPTypeCategory[NN_cmpordps] = 14;            // Packed Single-FP Compare ORDERED
SMPTypeCategory[NN_cmpeqss] = 14;             // Scalar Single-FP Compare EQ
SMPTypeCategory[NN_cmpltss] = 14;             // Scalar Single-FP Compare LT
SMPTypeCategory[NN_cmpless] = 14;             // Scalar Single-FP Compare LE
SMPTypeCategory[NN_cmpunordss] = 14;          // Scalar Single-FP Compare UNORD
SMPTypeCategory[NN_cmpneqss] = 14;            // Scalar Single-FP Compare NOT EQ
SMPTypeCategory[NN_cmpnltss] = 14;            // Scalar Single-FP Compare NOT LT
SMPTypeCategory[NN_cmpnless] = 14;            // Scalar Single-FP Compare NOT LE
SMPTypeCategory[NN_cmpordss] = 14;            // Scalar Single-FP Compare ORDERED

// AMD K7 instructions

// Revisit AMD if we port to it.
SMPTypeCategory[NN_pf2iw] = 15;               // Packed Floating-Point to Integer with Sign Extend
SMPTypeCategory[NN_pfnacc] = 15;              // Packed Floating-Point Negative Accumulate
SMPTypeCategory[NN_pfpnacc] = 15;             // Packed Floating-Point Mixed Positive-Negative Accumulate
SMPTypeCategory[NN_pi2fw] = 15;               // Packed 16-bit Integer to Floating-Point
SMPTypeCategory[NN_pswapd] = 15;              // Packed Swap Double Word

// Undocumented FP instructions (thanks to norbert.juffa@adm.com)

SMPTypeCategory[NN_fstp1] = 9;               // Alias of Store Real and Pop
SMPTypeCategory[NN_fcom2] = 1;               // Alias of Compare Real
SMPTypeCategory[NN_fcomp3] = 1;              // Alias of Compare Real and Pop
SMPTypeCategory[NN_fxch4] = 1;               // Alias of Exchange Registers
SMPTypeCategory[NN_fcomp5] = 1;              // Alias of Compare Real and Pop
SMPTypeCategory[NN_ffreep] = 1;              // Free Register and Pop
SMPTypeCategory[NN_fxch7] = 1;               // Alias of Exchange Registers
SMPTypeCategory[NN_fstp8] = 9;               // Alias of Store Real and Pop
SMPTypeCategory[NN_fstp9] = 9;               // Alias of Store Real and Pop

// Pentium 4 instructions

SMPTypeCategory[NN_addpd] = 14;               // Add Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_addsd] = 14;               // Add Scalar Double-Precision Floating-Point Values
SMPTypeCategory[NN_andnpd] = 14;              // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_andpd] = 14;               // Bitwise Logical AND of Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_clflush] = 1;             // Flush Cache Line
SMPTypeCategory[NN_cmppd] = 14;               // Compare Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_cmpsd] = 14;               // Compare Scalar Double-Precision Floating-Point Values
SMPTypeCategory[NN_comisd] = 14;              // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS
SMPTypeCategory[NN_cvtdq2pd] = 14;            // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values
SMPTypeCategory[NN_cvtdq2ps] = 14;            // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_cvtpd2dq] = 14;            // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
SMPTypeCategory[NN_cvtpd2pi] = 14;            // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
SMPTypeCategory[NN_cvtpd2ps] = 14;            // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values
SMPTypeCategory[NN_cvtpi2pd] = 14;            // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_cvtps2dq] = 14;            // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
SMPTypeCategory[NN_cvtps2pd] = 14;            // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_cvtsd2si] = 14;            // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer
SMPTypeCategory[NN_cvtsd2ss] = 14;            // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value
SMPTypeCategory[NN_cvtsi2sd] = 14;            // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value
SMPTypeCategory[NN_cvtss2sd] = 14;            // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value
SMPTypeCategory[NN_cvttpd2dq] = 14;           // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
SMPTypeCategory[NN_cvttpd2pi] = 14;           // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
SMPTypeCategory[NN_cvttps2dq] = 14;           // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
SMPTypeCategory[NN_cvttsd2si] = 14;           // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer
SMPTypeCategory[NN_divpd] = 14;               // Divide Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_divsd] = 14;               // Divide Scalar Double-Precision Floating-Point Values
SMPTypeCategory[NN_lfence] = 1;              // Load Fence
SMPTypeCategory[NN_maskmovdqu] = 13;          // Store Selected Bytes of Double Quadword  ** Infer dest is 'n'
SMPTypeCategory[NN_maxpd] = 14;               // Return Maximum Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_maxsd] = 14;               // Return Maximum Scalar Double-Precision Floating-Point Value
SMPTypeCategory[NN_mfence] = 1;              // Memory Fence
SMPTypeCategory[NN_minpd] = 14;               // Return Minimum Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_minsd] = 14;               // Return Minimum Scalar Double-Precision Floating-Point Value
SMPTypeCategory[NN_movapd] = 15;              // Move Aligned Packed Double-Precision Floating-Point Values  ** Infer dest is 'n'
SMPTypeCategory[NN_movdq2q] = 15;             // Move Quadword from XMM to MMX Register
SMPTypeCategory[NN_movdqa] = 15;              // Move Aligned Double Quadword  ** Infer dest is 'n'
SMPTypeCategory[NN_movdqu] = 15;              // Move Unaligned Double Quadword  ** Infer dest is 'n'
SMPTypeCategory[NN_movhpd] = 15;              // Move High Packed Double-Precision Floating-Point Values  ** Infer dest is 'n'
SMPTypeCategory[NN_movlpd] = 15;              // Move Low Packed Double-Precision Floating-Point Values  ** Infer dest is 'n'
SMPTypeCategory[NN_movmskpd] = 15;            // Extract Packed Double-Precision Floating-Point Sign Mask
SMPTypeCategory[NN_movntdq] = 13;             // Store Double Quadword Using Non-Temporal Hint
SMPTypeCategory[NN_movnti] = 13;              // Store Doubleword Using Non-Temporal Hint
SMPTypeCategory[NN_movntpd] = 13;             // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint
SMPTypeCategory[NN_movq2dq] = 1;             // Move Quadword from MMX to XMM Register
SMPTypeCategory[NN_movsd] = 15;               // Move Scalar Double-Precision Floating-Point Values
SMPTypeCategory[NN_movupd] = 15;              // Move Unaligned Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_mulpd] = 14;               // Multiply Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_mulsd] = 14;               // Multiply Scalar Double-Precision Floating-Point Values
SMPTypeCategory[NN_orpd] = 14;                // Bitwise Logical OR of Double-Precision Floating-Point Values
SMPTypeCategory[NN_paddq] = 14;               // Add Packed Quadword Integers
SMPTypeCategory[NN_pause] = 1;               // Spin Loop Hint
SMPTypeCategory[NN_pmuludq] = 14;             // Multiply Packed Unsigned Doubleword Integers
SMPTypeCategory[NN_pshufd] = 14;              // Shuffle Packed Doublewords
SMPTypeCategory[NN_pshufhw] = 14;             // Shuffle Packed High Words
SMPTypeCategory[NN_pshuflw] = 14;             // Shuffle Packed Low Words
SMPTypeCategory[NN_pslldq] = 14;              // Shift Double Quadword Left Logical
SMPTypeCategory[NN_psrldq] = 14;              // Shift Double Quadword Right Logical
SMPTypeCategory[NN_psubq] = 14;               // Subtract Packed Quadword Integers
SMPTypeCategory[NN_punpckhqdq] = 14;          // Unpack High Data
SMPTypeCategory[NN_punpcklqdq] = 14;          // Unpack Low Data
SMPTypeCategory[NN_shufpd] = 14;              // Shuffle Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_sqrtpd] = 1;              // Compute Square Roots of Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_sqrtsd] = 14;              // Compute Square Rootof Scalar Double-Precision Floating-Point Value
SMPTypeCategory[NN_subpd] = 14;               // Subtract Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_subsd] = 14;               // Subtract Scalar Double-Precision Floating-Point Values
SMPTypeCategory[NN_ucomisd] = 14;             // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS
SMPTypeCategory[NN_unpckhpd] = 14;            // Unpack and Interleave High Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_unpcklpd] = 14;            // Unpack and Interleave Low Packed Double-Precision Floating-Point Values
SMPTypeCategory[NN_xorpd] = 14;               // Bitwise Logical OR of Double-Precision Floating-Point Values


// AMD syscall/sysret instructions  NOTE: not AMD, found in Intel manual

SMPTypeCategory[NN_syscall] = 1;             // Low latency system call
SMPTypeCategory[NN_sysret] = 1;              // Return from system call

// AMD64 instructions    NOTE: not AMD, found in Intel manual

SMPTypeCategory[NN_swapgs] = 1;              // Exchange GS base with KernelGSBase MSR

// New Pentium instructions (SSE3)

SMPTypeCategory[NN_movddup] = 14;             // Move One Double-FP and Duplicate
SMPTypeCategory[NN_movshdup] = 14;            // Move Packed Single-FP High and Duplicate
SMPTypeCategory[NN_movsldup] = 14;            // Move Packed Single-FP Low and Duplicate

// Missing AMD64 instructions  NOTE: also found in Intel manual

SMPTypeCategory[NN_movsxd] = 2;              // Move with Sign-Extend Doubleword
SMPTypeCategory[NN_cmpxchg16b] = 0;          // Compare and Exchange 16 Bytes

// SSE3 instructions

SMPTypeCategory[NN_addsubpd] = 14;            // Add /Sub packed DP FP numbers
SMPTypeCategory[NN_addsubps] = 14;            // Add /Sub packed SP FP numbers
SMPTypeCategory[NN_haddpd] = 14;              // Add horizontally packed DP FP numbers
SMPTypeCategory[NN_haddps] = 14;              // Add horizontally packed SP FP numbers
SMPTypeCategory[NN_hsubpd] = 14;              // Sub horizontally packed DP FP numbers
SMPTypeCategory[NN_hsubps] = 14;              // Sub horizontally packed SP FP numbers
SMPTypeCategory[NN_monitor] = 1;             // Set up a linear address range to be monitored by hardware
SMPTypeCategory[NN_mwait] = 1;               // Wait until write-back store performed within the range specified by the MONITOR instruction
SMPTypeCategory[NN_fisttp] = 13;              // Store ST in intXX (chop) and pop
SMPTypeCategory[NN_lddqu] = 14;               // Load unaligned integer 128-bit

// SSSE3 instructions

SMPTypeCategory[NN_psignb] = 14;              // Packed SIGN Byte
SMPTypeCategory[NN_psignw] = 14;              // Packed SIGN Word
SMPTypeCategory[NN_psignd] = 14;              // Packed SIGN Doubleword
SMPTypeCategory[NN_pshufb] = 14;              // Packed Shuffle Bytes
SMPTypeCategory[NN_pmulhrsw] = 14;            // Packed Multiply High with Round and Scale
SMPTypeCategory[NN_pmaddubsw] = 14;           // Multiply and Add Packed Signed and Unsigned Bytes
SMPTypeCategory[NN_phsubsw] = 14;             // Packed Horizontal Subtract and Saturate
SMPTypeCategory[NN_phaddsw] = 14;             // Packed Horizontal Add and Saturate
SMPTypeCategory[NN_phaddw] = 14;              // Packed Horizontal Add Word
SMPTypeCategory[NN_phaddd] = 14;              // Packed Horizontal Add Doubleword
SMPTypeCategory[NN_phsubw] = 14;              // Packed Horizontal Subtract Word
SMPTypeCategory[NN_phsubd] = 14;              // Packed Horizontal Subtract Doubleword
SMPTypeCategory[NN_palignr] = 14;             // Packed Align Right
SMPTypeCategory[NN_pabsb] = 14;               // Packed Absolute Value Byte
SMPTypeCategory[NN_pabsw] = 14;               // Packed Absolute Value Word
SMPTypeCategory[NN_pabsd] = 14;               // Packed Absolute Value Doubleword

// VMX instructions

SMPTypeCategory[NN_vmcall] = 1;              // Call to VM Monitor
SMPTypeCategory[NN_vmclear] = 0;             // Clear Virtual Machine Control Structure
SMPTypeCategory[NN_vmlaunch] = 1;            // Launch Virtual Machine
SMPTypeCategory[NN_vmresume] = 1;            // Resume Virtual Machine
SMPTypeCategory[NN_vmptrld] = 6;             // Load Pointer to Virtual Machine Control Structure
SMPTypeCategory[NN_vmptrst] = 0;             // Store Pointer to Virtual Machine Control Structure
SMPTypeCategory[NN_vmread] = 0;              // Read Field from Virtual Machine Control Structure
SMPTypeCategory[NN_vmwrite] = 0;             // Write Field from Virtual Machine Control Structure
SMPTypeCategory[NN_vmxoff] = 1;              // Leave VMX Operation
SMPTypeCategory[NN_vmxon] = 1;               // Enter VMX Operation

SMPTypeCategory[NN_last] = 1;

  return;

} // end InitTypeCategory()