/*
 * SMPDataFlowAnalysis.cpp - <see below>.
 *
 * Copyright (c) 2000, 2001, 2010 - University of Virginia 
 *
 * This file is part of the Memory Error Detection System (MEDS) infrastructure.
 * This file may be used and modified for non-commercial purposes as long as 
 * all copyright, permission, and nonwarranty notices are preserved.  
 * Redistribution is prohibited without prior written consent from the University 
 * of Virginia.
 *
 * Please contact the authors for restrictions applying to commercial use.
 *
 * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Author: University of Virginia
 * e-mail: jwd@virginia.com
 * URL   : http://www.cs.virginia.edu/
 *
 * Additional copyrights 2010, 2011, 2012, 2013, 2014, 2015 by Zephyr Software LLC
 * e-mail: {clc,jwd}@zephyr-software.com
 * URL   : http://www.zephyr-software.com/
 *
 */

//
// 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 <string>

#include <cstdlib>
#include <cstring>
#include <cassert>

#include "interfaces/SMPDBInterface.h"
#include "base/SMPDataFlowAnalysis.h"
#include "base/SMPInstr.h"
#include "base/SMPBasicBlock.h"
#include "base/SMPFunction.h"

using namespace std;

// Set these to 1 for debugging output
#define SMP_DEBUG_CONTROLFLOW 0  // tells what processing stage is entered
#define SMP_DEBUG_CHUNKS 1  // tracking down tail chunks for functions
#define SMP_DEBUG_FRAMEFIXUP 0  // Fixing up stack frame info the way we want the offsets
#define SMP_DEBUG_OPERAND_TYPES 1  // leave on; warnings that should never happen
#define STARS_DEBUG_DUMP_IDENTIFY_HIDDEN_OPERANDS 0 // print HIDDEN if operand.showed() is false

#define MAX_IDA_REG STARS_x86_R_last

// return true if Item is in IntList
bool IsIntInList(const std::list<int> &IntList, int Item) {
	bool Found = false;
	for (list<int>::const_iterator ListIter = IntList.cbegin(); ListIter != IntList.cend(); ++ListIter) {
		if ((*ListIter) == Item) {
			Found = true;
			break;
		}
	}
	return Found;
}

// Bit masks for extracting bits from a STARSBitSet unsigned char.
const uint8_t STARSBitMasks[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };

const char *RegNames[MAX_IDA_REG + 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", "PF",
	  "AF", "TF", "IF", "DF", "EFLAGS", "FPU_ST0", "FPU_ST1", "FPU_ST2",
	  "FPU_ST3", "FPU_ST4", "FPU_ST5", "FPU_ST6", "FPU_ST7", "FPU_CTRL", "FPU_STAT", "FPU_TAGS",
	  "MMX0", "MMX1", "MMX2", "MMX3", "MMX4", "MMX5", "MMX6", "MMX7",
	  "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7",
	  "XMM8", "XMM9", "XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15",
	  "MXCSR",
	  "YMM0", "YMM1", "YMM2", "YMM3", "YMM4", "YMM5", "YMM6", "YMM7",
	  "YMM8", "YMM9", "YMM10", "YMM11", "YMM12", "YMM13", "YMM14", "YMM15",
	  "BND0", "BND1", "BND2", "BND3",
	  "XMM16", "XMM17", "XMM18", "XMM19", "XMM20", "XMM21", "XMM22", "XMM23",
	  "XMM24", "XMM25", "XMM26", "XMM27", "XMM28", "XMM29", "XMM30", "XMM31",
	  "YMM16", "YMM17", "YMM18", "YMM19", "YMM20", "YMM21", "YMM22", "YMM23",
	  "YMM24", "YMM25", "YMM26", "YMM27", "YMM28", "YMM29", "YMM30", "YMM31",
	  "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7",
	  "XMM8", "XMM9", "XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15",
	  "ZMM16", "ZMM17", "ZMM18", "ZMM19", "ZMM20", "ZMM21", "ZMM22", "ZMM23",
	  "ZMM24", "ZMM25", "ZMM26", "ZMM27", "ZMM28", "ZMM29", "ZMM30", "ZMM31",
	  "K0", "K1", "K2", "K3", "K4", "K5", "K6", "K7",
	  "REG_ERROR"
	};

// NOTE: Review these sizes. Alter when annotation diffs can be isolated to the change.
//   !!!!****!!!! FP reg stack should be 10-byte registers, right?
const unsigned char RegSizes[MAX_IDA_REG + 1] =
	{ 4, 4, 4, 4, 4, 4, 4, 4,
	  8, 8, 8, 8, 8, 8, 8, 8,
	  1, 1, 1, 1, 1, 1, 1, 1,
	  1, 1, 1, 1, 4, 2, 2, 2,
	  2, 2, 2, 4, 4, 4, 4, 4,
	  4, 4, 4, 4, 4, 10, 10, 10,
	  10, 10, 10, 10, 10, 4, 4, 4,
	  16, 16, 16, 16, 16, 16, 16, 16,
	  16, 16, 16, 16, 16, 16, 16, 16,
	  16, 16, 16, 16, 16, 16, 16, 16,
	  4,
	  32, 32, 32, 32, 32, 32, 32, 32,
	  32, 32, 32, 32, 32, 32, 32, 32,
	  4
	};

unsigned char GetRegSize(STARS_regnum_t RegNum) {
	assert(RegNum != ((STARS_regnum_t) STARS_x86_R_none));
	return RegSizes[RegNum];
}

const char RegDtyps[MAX_IDA_REG + 1] =
{ STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword,
STARS_dt_qword, STARS_dt_qword, STARS_dt_qword, STARS_dt_qword, STARS_dt_qword, STARS_dt_qword, STARS_dt_qword, STARS_dt_qword,
STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte,
STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_byte, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword,
STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword,
STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_dword, STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_tbyte,
STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_tbyte, STARS_dt_word, STARS_dt_word, STARS_dt_word,
STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16,
STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16,
STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16, STARS_dt_byte16,
STARS_dt_word,
STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32,
STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32, STARS_dt_byte32,
STARS_dt_word 
};

const char *ErrorStrings[1] = { "ERROR_REG" };

const char *WordRegStrings[8] = { "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI" };

const char *QWordRegStrings[8] = { "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI" };

const char *QDWordRegStrings[8] = { "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D" };

const char *QWWordRegStrings[8] = { "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W" };

const char *QByteRegStrings[8] = { "R8L", "R9L", "R10L", "R11L", "R12L", "R13L", "R14L", "R15L" };

const char *SignednessStrings[4] = { "UNKNOWNSIGN", "SIGNED", "UNSIGNED", "UNKNOWNSIGN" };

const char *LeaSignednessStrings[4] = { "NOFLAGUNKNOWNSIGN", "NOFLAGSIGNED", "NOFLAGUNSIGNED", "NOFLAGUNKNOWNSIGN" };

const char *SPARKFloatingPointStackRegNames[8] = { "FloatingPointStackDummy", "FloatingPointStackDummy1", "FloatingPointStackDummy1", "FloatingPointStackDummy1",
"FloatingPointStackDummy1", "FloatingPointStackDummy1", "FloatingPointStackDummy1", "FloatingPointStackDummy1" };

const char *CFTTypeStrings[20] = { "FALL_THROUGH", "BRANCH_IF_THEN", "BRANCH_IF_THEN_ELSE", "JUMP_BEFORE_ELSE",
"LOOP_BACK", "LOOP_EXIT", "LOOP_CONTINUE", "JUMP_INTO_LOOP_TEST", "JUMP_TO_DEFAULT_CASE", "CASE_BREAK_TO_FOLLOW_NODE",
"JUMP_TO_SWITCH_INDIR_JUMP", "SHORT_CIRCUIT_BRANCH", "SHORT_CIRCUIT_LOOP_EXIT", "INVERTED_LOOP_EXIT", 
"INVERTED_LOOP_BACK", "SHORT_CIRCUIT_INVERTED_LOOP_EXIT", "", "", "", ""
};

// Distinguishes subword regs from their parent regs
const char *MDGetRegNumName(STARS_regnum_t RegNum, uint16_t ByteWidth) {
	if ((STARS_x86_R_none == RegNum) || (MAX_IDA_REG < RegNum))
		return ErrorStrings[0];
	else if ((ByteWidth == 2) && (RegNum >= STARS_x86_R_ax) && (RegNum <= STARS_x86_R_di)) {
		// 16-bit registers
		return WordRegStrings[RegNum];
	}
	else if ((ByteWidth == 8) && (RegNum >= STARS_x86_R_ax) && (RegNum <= STARS_x86_R_di)) {
		// 64-bit registers
		return QWordRegStrings[RegNum];
	}
	else if ((ByteWidth < 8) && (RegNum >= STARS_x86_R_r8) && (RegNum <= STARS_x86_R_r15)) {
		if (ByteWidth == 4)
			return QDWordRegStrings[RegNum - STARS_x86_R_r8];
		else if (ByteWidth == 2)
			return QWWordRegStrings[RegNum - STARS_x86_R_r8];
		else if (ByteWidth == 1)
			return QByteRegStrings[RegNum - STARS_x86_R_r8];
		else
			return ErrorStrings[0];
	}
	else {
		return RegNames[RegNum];
	}
} // end of MDGetRegNumName()

// Distinguishes subword regs from their parent regs, uses SPARK dummy names for FP stack.
const char *MDGetSPARKRegNumName(STARS_regnum_t RegNum, uint16_t ByteWidth) {
	if ((RegNum >= STARS_x86_R_st0) && (RegNum <= STARS_x86_R_st7))
		return SPARKFloatingPointStackRegNames[RegNum - STARS_x86_R_st0];
	else
		return MDGetRegNumName(RegNum, ByteWidth);
}

// Distinguishes subword regs from their parent regs
const char *MDGetRegName(const STARSOpndTypePtr &RegOp) {
	if (!(RegOp->IsRegOp() || RegOp->IsFloatingPointRegOp()))
		return ErrorStrings[0];

	STARS_regnum_t RegNum = RegOp->GetReg();
	uint16_t ByteWidth = RegOp->GetByteWidth();
	return MDGetRegNumName(RegNum, ByteWidth);
}

// Define instruction categories for data flow analysis.
vector<SMPitype> DFACategory;
// Define instruction categories for data type analysis.
int SMPTypeCategory[STARS_NN_last+1];

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

// print to log file using SMP_msg()
void DumpDataFlowType(const SMPitype FlowType) {
	switch (FlowType) {
	case DEFAULT:
		SMP_msg("DEFAULT\n");
		break;
	case LABEL:
		SMP_msg("LABEL\n");
		break;
	case CASE:
		SMP_msg("CASE\n");
		break;
	case JUMP:
		SMP_msg("JUMP\n");
		break;
	case COND_BRANCH:
		SMP_msg("COND_BRANCH\n");
		break;
	case INDIR_JUMP:
		SMP_msg("INDIR_JUMP\n");
		break;
	case CALL:
		SMP_msg("CALL\n");
		break;
	case INDIR_CALL:
		SMP_msg("INDIR_CALL\n");
		break;
	case RETURN:
		SMP_msg("RETURN\n");
		break;
	case HALT:
		SMP_msg("HALT\n");
		break;
	default:
		SMP_msg("ERROR\n");
		break;
	}
	return;
} // end of DumpDataFlowType()

// Hash a global name and SSA number into an int, for use in SMPFunction.GlobalDefAddrBySSA map
int HashGlobalNameAndSSA(const STARSOpndTypePtr &DefOp, int SSANum) { 
	int HashValue = 0;
	if (DefOp->IsRegOp()) {
		HashValue = ((SSANum << 16) | ((int)(DefOp->GetReg())));
	}
	return HashValue;
}

// Hash a global name and SSA number into an int, for use in SMPFunction.GlobalDefAddrBySSA map
int64_t HashGlobalStackNameAndSSA(const STARSOpndTypePtr &DefOp, int SSANum, bool UseFP) {
	int64_t HashValue = 0;
	assert(MDIsDirectStackAccessOpnd(DefOp, UseFP));
	HashValue = ((((int64_t) SSANum) << 32) | (((uint64_t)(DefOp->GetAddr())) & 0xffffffff));
	return HashValue;
}

// Get the size in bytes of the data type of an operand.
size_t GetOpDataSize(const STARSOpndTypePtr &DataOp) {
	size_t DataSize;
	char OpDtyp = DataOp->GetOpDtyp();
	if (DataOp->IsRegOp()) {
		DataSize = RegSizes[DataOp->GetReg()];
		if (OpDtyp == STARS_dt_word) {
			DataSize = 2;
#if 0
			SMP_msg("Found 16-bit register using dtyp field.\n");
#endif
		}
		else if (OpDtyp == STARS_dt_qword) {
			DataSize = 8;
#if 0
			SMP_msg("Found 64-bit register using dtyp field.\n");
#endif
		}
		return DataSize;
	}
	switch (OpDtyp) {
		case STARS_dt_byte:
			DataSize = 1;
			break;
		case STARS_dt_word:
			DataSize = 2;
			break;
		case STARS_dt_dword:
		case STARS_dt_float:
		case STARS_dt_code:
		case STARS_dt_unicode:
		case STARS_dt_string:
			DataSize = 4;
			break;
		case STARS_dt_double:
		case STARS_dt_qword:
			DataSize = 8;
			break;
		case STARS_dt_tbyte:
			DataSize = 10;
			break;
		case STARS_dt_packreal:
			DataSize = 12;
			break;
		case STARS_dt_byte16:
		case STARS_dt_ldbl:
			DataSize = 16;
			break;
		case STARS_dt_fword:
			DataSize = 6;
			break;
#if (IDA_SDK_VERSION < 700)
		case STARS_dt_3byte:
			DataSize = 3;
			break;
#endif
		case STARS_dt_byte32:
			DataSize = 32;
			break;
		case STARS_dt_byte64:
			DataSize = 64;
			break;
#if (IDA_SDK_VERSION >= 700)
		case STARS_dt_half:      // 2-byte floating point
			DataSize = 16;
			break;
#endif
		default:
			SMP_msg("ERROR: unexpected data type %d in GetOpDataSize() :", OpDtyp);
			PrintOperand(DataOp);
			SMP_msg("\n");
			DataSize = global_STARS_program->GetSTARS_ISA_dtyp();
			break;
	}
	return DataSize;
} // end of GetOpDataSize()

// Get the IDA Pro register size (dtyp) field
char GetRegDtyp(STARS_regnum_t RegNum, bool Has64BitOpnds) {
	assert(RegNum != ((STARS_regnum_t) STARS_x86_R_none));
	assert(RegNum < MAX_IDA_REG);
	char RegDtyp = RegDtyps[RegNum];
	if ((global_STARS_program->GetSTARS_ISA_Bytewidth() == 8) && Has64BitOpnds && (RegDtyp == STARS_dt_dword) && (RegNum <= STARS_x86_R_ip)) {
		// 32-bit IDA general regs are 64-bit for x86-64
		RegDtyp = STARS_dt_qword;
	}

	return RegDtyp;
}

// Return one of the bit width masks for the current operand.
//  Pass in DataSize in bytes if known, else pass in DataSize = 0.
unsigned short ComputeOperandBitWidthMask(const STARSOpndTypePtr &CurrOp, size_t DataSize) {
	unsigned short BitWidthMask = 32;
	if (0 == DataSize)
		DataSize = CurrOp->GetByteWidth();
	if (4 == DataSize)
		BitWidthMask = FG_MASK_BITWIDTH_32;
	else if (8 == DataSize)
		BitWidthMask = FG_MASK_BITWIDTH_64;
	else if (1 == DataSize)
		BitWidthMask = FG_MASK_BITWIDTH_8;
	else if (2 == DataSize)
		BitWidthMask = FG_MASK_BITWIDTH_16;
	else if (16 == DataSize)
		BitWidthMask = FG_MASK_BITWIDTH_128;
	else if (3 == DataSize)
		BitWidthMask = FG_MASK_BITWIDTH_24;
	else if (6 == DataSize)
		BitWidthMask = FG_MASK_BITWIDTH_48;
	else if (10 == DataSize)
		BitWidthMask = FG_MASK_BITWIDTH_80;
	else if (12 == DataSize)
		BitWidthMask = FG_MASK_BITWIDTH_96;
	else if (32 == DataSize)
		BitWidthMask = FG_MASK_BITWIDTH_256;
	else {
		SMP_msg("ERROR: Unknown DataSize: %zu bytes ", DataSize);
		PrintOperand(CurrOp);
		SMP_msg("\n");
	}
	return BitWidthMask;
} // end of ComputeOperandBitWidthMask()

// Compute largest bit width from a SignMiscInfo bit mask.
size_t LargestBitWidthFromMask(unsigned short WidthTypeInfo) {
	unsigned short BitWidthMask = WidthTypeInfo & FG_MASK_BITWIDTH_FIELDS;
	size_t LargestWidth = 0;

	// Go from highest bit width to lowest.
	if (BitWidthMask & FG_MASK_BITWIDTH_256)
		LargestWidth = 256;
	else if (BitWidthMask & FG_MASK_BITWIDTH_128)
		LargestWidth = 128;
	else if (BitWidthMask & FG_MASK_BITWIDTH_96)
		LargestWidth = 96;
	else if (BitWidthMask & FG_MASK_BITWIDTH_64)
		LargestWidth = 64;
	else if (BitWidthMask & FG_MASK_BITWIDTH_48)
		LargestWidth = 48;
	else if (BitWidthMask & FG_MASK_BITWIDTH_32)
		LargestWidth = 32;
	else if (BitWidthMask & FG_MASK_BITWIDTH_24)
		LargestWidth = 24;
	else if (BitWidthMask & FG_MASK_BITWIDTH_16)
		LargestWidth = 16;
	else if (BitWidthMask & FG_MASK_BITWIDTH_8)
		LargestWidth = 8;

	return LargestWidth;
} // end of LargestBitWidthFromMask()

// Is CurrOp a general purpose register? (not flags, instruction pointer, non-integer reg, etc.)
bool MDIsGeneralPurposeReg(const STARSOpndTypePtr &CurrOp) {
	bool success = (nullptr != CurrOp);
	if (success) {
		// intel.hpp defines two ranges that are general purpose regs in enum RegNo.
		STARS_regnum_t CurrReg = CurrOp->GetReg();
		success = (CurrOp->IsRegOp() && ((CurrReg >= STARS_x86_R_ax) && (CurrReg <= STARS_x86_R_dil)));
	}
	return success;
}

// Are operands equal?
bool IsEqOp(const STARSOpndTypePtr &Opnd1, const STARSOpndTypePtr &Opnd2) 
{
	if ((nullptr == Opnd1) && (nullptr == Opnd2))
		return true;
	if ((nullptr == Opnd1) || (nullptr == Opnd2))
		return false;

	// this expression is logically equiv. to "equal"
	//
	// truth table:
	//  
	//   O1 O2  O1<O2 !(O1<O2) O2<O1 !(O2<O1)  !(O1<O2)&&!(O2<O1) ==
		//    0  0      0        1     0        1                   1  1
		//    0  1      1        0     0        0                   0  0
		//    1  0      0        1     1        0                   0  0
		//    1  1      0        1     0        0                   1  1
	return !(*Opnd1 < *Opnd2) && !(*Opnd2 < *Opnd1);

} // end of function IsEqOp()

// Are operands equal, ignoring bitwidth differences for register operands?
bool IsEqOpIgnoreBitwidth(const STARSOpndTypePtr &Opnd1, const STARSOpndTypePtr &Opnd2) {
		if (Opnd1->GetOpType() != Opnd2->GetOpType())
			return false;

		if (Opnd1->IsRegOp())
			return (MDCanonicalizeSubReg(Opnd1->GetReg()) == MDCanonicalizeSubReg(Opnd2->GetReg())); // no concern for subword regs; AX == EAX == RAX
		else
			return IsEqOp(Opnd1, Opnd2);

} // end of function IsEqOpIgnoreBitwidth()

// Are operands equal, ignoring value differences for immediate operands?
bool IsEqOpIgnoreImmedValues(const STARSOpndTypePtr &Opnd1, const STARSOpndTypePtr &Opnd2) {
	if (nullptr == Opnd1)
		return (nullptr == Opnd2);

	if (nullptr == Opnd2)
		return (nullptr == Opnd1);

	if (Opnd1->GetOpType() != Opnd2->GetOpType())
		return false;

	if (Opnd1->IsImmedOp())
		return true;
	else
		return IsEqOp(Opnd1, Opnd2);

} // end of function IsEqOpIgnoreImmedValues()


// 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.
bool MDLessReg(const STARS_regnum_t Reg1, const STARS_regnum_t Reg2) {
	STARS_regnum_t SReg1 = MDCanonicalizeSubReg(Reg1);
	STARS_regnum_t SReg2 = MDCanonicalizeSubReg(Reg2);
	return (SReg1 < SReg2);
} // end of MDLessReg()

bool MDEqReg(const STARS_regnum_t Reg1, const STARS_regnum_t Reg2) {
	STARS_regnum_t SReg1 = MDCanonicalizeSubReg(Reg1);
	STARS_regnum_t SReg2 = MDCanonicalizeSubReg(Reg2);
	return (SReg1 == SReg2);
} // end of MDEqReg()

bool MDLessRegOpnd(const STARSOpndTypePtr &RegOp1, const STARSOpndTypePtr &RegOp2) {
	STARS_regnum_t SReg1 = MDCanonicalizeSubReg(RegOp1->GetReg());
	STARS_regnum_t SReg2 = MDCanonicalizeSubReg(RegOp2->GetReg());
	return ((SReg1 < SReg2) || ((SReg1 == SReg2) && (RegOp1->GetByteWidth() < RegOp2->GetByteWidth())));
} // end of MDLessRegOpnd()

STARS_regnum_t MDCanonicalizeSubReg(const STARS_regnum_t Reg1) {
	bool Subword = ((Reg1 >= FIRST_X86_SUBWORD_REG) && (Reg1 <= LAST_X86_SUBWORD_REG));
	STARS_regnum_t SReg1 = Reg1;

	if (Subword) {
		// See enumeration RegNo in intel.hpp.
		switch (SReg1) {
			case STARS_x86_R_al:
			case STARS_x86_R_ah:
				SReg1 = STARS_x86_R_ax;
				break;
			case STARS_x86_R_cl:
			case STARS_x86_R_ch:
				SReg1 = STARS_x86_R_cx;
				break;
			case STARS_x86_R_dl:
			case STARS_x86_R_dh:
				SReg1 = STARS_x86_R_dx;
				break;
			case STARS_x86_R_bl:
			case STARS_x86_R_bh:
				SReg1 = STARS_x86_R_bx;
				break;
			case STARS_x86_R_spl:
				SReg1 = STARS_x86_R_sp;
				break;
			case STARS_x86_R_bpl:
				SReg1 = STARS_x86_R_bp;
				break;
			case STARS_x86_R_sil:
				SReg1 = STARS_x86_R_si;
				break;
			case STARS_x86_R_dil:
				SReg1 = STARS_x86_R_di;
				break;
			default:
				assert(false);
		} // end switch (SReg1)
	}
	return SReg1;
} // end of MDCanonicalizeSubReg()


#if 0
// If TempOp is a register, call MDCanonicalizeSubReg() on it.
void CanonicalizeOpnd(STARSOpndTypePtr &TempOp) {
	if (TempOp->IsRegOp()) {
		STARS_regnum_t NewReg = MDCanonicalizeSubReg(TempOp->GetReg());
		if (TempOp->GetReg() != NewReg) {
			TempOp->SetReg(NewReg);
		}
	}
}

#else
// If TempOp is a register, call MDCanonicalizeSubReg() on it.
void CanonicalizeOpnd(STARSOpndTypePtr &TempOp) {
	if ((nullptr != TempOp) && TempOp->IsRegOp()) {
#if 0
		if (4 > TempOp->GetByteWidth()) {
			TempOp->SetReg(MDCanonicalizeSubReg(TempOp->GetReg()));
		}
#else
		STARS_regnum_t Reg1 = TempOp->GetReg();
		bool Subword = ((Reg1 >= FIRST_X86_SUBWORD_REG) && (Reg1 <= LAST_X86_SUBWORD_REG));
		if (Subword) {
			TempOp->SetReg(MDCanonicalizeSubReg(TempOp->GetReg()));
		}
#endif
		// Convert 32-bit regs to 64-bit on 64-bit binaries.
		uint16_t CanonicalByteWidth = global_STARS_program->GetSTARS_ISA_Bytewidth();
		if (TempOp->GetByteWidth() < CanonicalByteWidth) {
			TempOp->SetByteWidth(CanonicalByteWidth);
		}
	}
}
#endif

bool MDIsStackOrFramePointerReg(const STARSOpndTypePtr &RegOp, bool UseFP) {
	bool PtrReg = false;
	if ((nullptr != RegOp) && RegOp->IsRegOp()) {
		PtrReg = RegOp->MatchesReg(MD_STACK_POINTER_REG) || (UseFP && RegOp->MatchesReg(MD_FRAME_POINTER_REG));
	}
	return PtrReg;
}

// 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(const STARSOpndTypePtr &GlobalOp) {
	return GlobalOp->GetOpGlobalIndex();
}

void SetGlobalIndex(STARSOpndTypePtr TempOp, size_t index) {
	TempOp->SetOpGlobalIndex(index);
	return;
}

int MD_STARS_sib_base(const STARSOpndTypePtr &x) {                    // get extended sib base
	return x->MDGetSIBBaseReg();
}

short MD_STARS_sib_index(const STARSOpndTypePtr &x) {                  // get extended sib index
	return x->MDGetSIBIndexReg();
}

// Return true if CurrOp could be an indirect memory reference.
bool MDIsIndirectMemoryOpnd(const STARSOpndTypePtr &CurrOp, bool UseFP) {
	bool indirect = false;
	if ((nullptr == CurrOp) || (! CurrOp->IsMemOp()))
		return false;

	if (CurrOp->HasSIBByte()) {
		STARS_RegNo BaseReg = (STARS_RegNo) MD_STARS_sib_base(CurrOp);
		STARS_RegNo IndexReg = (STARS_RegNo) MD_STARS_sib_index(CurrOp);
		if ((STARS_x86_R_none != IndexReg) && (MD_STACK_POINTER_REG != IndexReg)) { 
			if ((MD_FRAME_POINTER_REG == IndexReg) && UseFP && (!CurrOp->IsStaticMemOp()))
				;
			else
				indirect = true;
		}
		if (0 != CurrOp->GetSIBScaleFactor())
			indirect = true;
		if (!indirect && (STARS_x86_R_none != BaseReg)) {
			if ((BaseReg == MD_FRAME_POINTER_REG) && CurrOp->IsStaticMemOp()) {
				; // EBP ==> no base register for o_mem type
			}
			else if ((BaseReg == MD_FRAME_POINTER_REG) && UseFP) 
				;  // EBP used as frame pointer for direct access
			else if (BaseReg == MD_STACK_POINTER_REG)
				;  // ESP used as stack pointer for direct access
			else
				indirect = true; // conservative; some register used for addressing
								// other than a stack or frame pointer
		}
	} // end if hasSIB
	else { // no SIB; can have base register only
		STARS_RegNo BaseReg = (STARS_RegNo) CurrOp->GetReg();
		if (CurrOp->IsStaticMemOp()) { // no base register for o_mem
#if 1
			if (!((0 == BaseReg) || (MD_FRAME_POINTER_REG == BaseReg))) {
				SMP_msg("ERROR: o_mem base reg %d ignored \n", BaseReg);
			}
#endif
		}
		else if ((BaseReg == MD_FRAME_POINTER_REG) && UseFP) 
			;  // EBP used as frame pointer for direct access
		else if (BaseReg == MD_STACK_POINTER_REG)
			;  // ESP used as stack pointer for direct access
		else {
			indirect = true;
		}
	}

	return indirect;
} // end MDIsIndirectMemoryOpnd()

// Extract the base and index registers and scale factor and displacement from the
//  memory operand.
void MDExtractAddressFields(const STARSOpndTypePtr &MemOp, int &BaseReg, int &IndexReg, uint16_t &Scale, STARS_ea_t &Offset) {
	assert(MemOp->IsMemOp());

	Scale = 0;
	BaseReg = STARS_x86_R_none;
	IndexReg = STARS_x86_R_none;
	Offset = MemOp->GetAddr();

	if (MemOp->HasSIBByte()) {
		BaseReg = MD_STARS_sib_base(MemOp);
		IndexReg = (int) MD_STARS_sib_index(MemOp);
		if (MD_STACK_POINTER_REG == IndexReg) // signifies no index register
			IndexReg = STARS_x86_R_none;
		if (STARS_x86_R_none != IndexReg) {
			Scale = (uint16_t) MemOp->GetSIBScaleFactor();
		}
		if (STARS_x86_R_none != BaseReg) {
			if (MemOp->IsStaticMemOp()) {
				BaseReg = STARS_x86_R_none;
				// Only IndexReg is allowed for o_mem with SIB byte
			}
		}
	}
	else { // no SIB byte; can have base reg but no index reg or scale factor
		BaseReg = (int) MemOp->GetReg();  // cannot be STARS_x86_R_none for no SIB case
		if (MemOp->IsStaticMemOp()) {
			BaseReg = STARS_x86_R_none; // no Base register for o_mem operands
		}
	}

	return;
} // end of MDExtractAddressFields()

// MACHINE DEPENDENT: Does MemOp have both a base reg and an index reg, or a scaled index reg?
bool MDIsIndexedMemoryAccess(const STARSOpndTypePtr &MemOp) {
	bool EIPRelativeAccess = (MemOp->HasSegReg() && (STARS_x86_R_cs == MemOp->GetSegReg()));
	if (!EIPRelativeAccess) {
		EIPRelativeAccess = (MemOp->GetReg() == STARS_x86_R_ip);
	}
	if (EIPRelativeAccess)
		return true;

	int BaseReg, IndexReg;
	uint16_t Scale;
	STARS_ea_t Offset;
	MDExtractAddressFields(MemOp, BaseReg, IndexReg, Scale, Offset);
	return ((Scale != 0) || ((BaseReg != STARS_x86_R_none) && (IndexReg != STARS_x86_R_none)));
}


// Is CurrOp a memory operand?
bool IsMemOperand(const STARSOpndTypePtr &CurrOp) {
	return ((nullptr != CurrOp) && CurrOp->IsMemOp());
}

// MACHINE DEPENDENT: Is CurrOp the flags register?
bool MDIsFlagsReg(const STARSOpndTypePtr &CurrOp) {
	return ((nullptr != CurrOp) && CurrOp->MatchesReg(X86_FLAGS_REG));
}

// MACHINE DEPENDENT: Is register a stack pointer or frame pointer?
bool MDIsStackPtrReg(int RegNumber, bool UseFP) {
	return ((RegNumber == MD_STACK_POINTER_REG) || (UseFP && (RegNumber == MD_FRAME_POINTER_REG)));
}

// MACHINE DEPENDENT: Is operand a stack memory access?
bool MDIsStackAccessOpnd(const STARSOpndTypePtr &CurrOp, bool UseFP) {
	int BaseReg;
	int IndexReg;
	uint16_t ScaleFactor;
	STARS_ea_t offset;

	if ((nullptr == CurrOp) || ((!CurrOp->IsMemDisplacementOp()) && (!CurrOp->IsMemNoDisplacementOp()))) {
		return false;
	}

	MDExtractAddressFields(CurrOp, BaseReg, IndexReg, ScaleFactor, offset);
	return MDIsStackPtrReg(BaseReg, UseFP);
} // end of MDIsStackAccessOpnd()

// MACHINE DEPENDENT: Is operand a direct stack memory access?
bool MDIsDirectStackAccessOpnd(const STARSOpndTypePtr &CurrOp, bool UseFP) {
	int BaseReg;
	int IndexReg;
	uint16_t ScaleFactor;
	STARS_ea_t offset;

	if ((nullptr == CurrOp) || ((! CurrOp->IsMemDisplacementOp()) && (! CurrOp->IsMemNoDisplacementOp()))) {
		return false;
	}

	MDExtractAddressFields(CurrOp, BaseReg, IndexReg, ScaleFactor, offset);
	// When the IndexReg is R_none, access is direct.
	return (MDIsStackPtrReg(BaseReg, UseFP) && (IndexReg == STARS_x86_R_none));
} // end of MDIsDirectStackAccessOpnd()

// MACHINE DEPENDENT: Is operand trackable in data flow analyses (i.e. a direct stack memory access or a register?)
bool MDIsDataFlowOpnd(const STARSOpndTypePtr &CurrOp, bool UseFP) {
	return ((nullptr != CurrOp) 
		&& ((CurrOp->IsRegOp() && ((STARS_x86_R_ip > CurrOp->GetReg()) || (STARS_x86_R_gs < CurrOp->GetReg()))) || MDIsDirectStackAccessOpnd(CurrOp, UseFP)));
}

// MACHINE DEPENDENT: Is operand a caller-saved register?
bool MDIsCallerSavedReg(const STARSOpndTypePtr &CurrOp) {
	if (! CurrOp->IsRegOp())
		return false;
	STARS_regnum_t CurrReg = MDCanonicalizeSubReg(CurrOp->GetReg());
	return ((STARS_x86_R_ax == CurrReg) || (STARS_x86_R_cx == CurrReg) || (STARS_x86_R_dx == CurrReg));
} // end of MDIsCallerSavedReg()

// If CurrOp would change when reg is canonicalized, then return CurrOp->clone(), else return CurrOp;
STARSOpndTypePtr CloneIfSubwordReg(const STARSOpndTypePtr &CurrOp) {
	if ((nullptr != CurrOp) && CurrOp->IsRegOp()) {
		if (global_STARS_program->GetSTARS_ISA_Bytewidth() > CurrOp->GetByteWidth()) {
			return CurrOp->clone();
		}
		else {
			return CurrOp;
		}
	}
	else {
		return CurrOp;
	}
} // end of CloneIfSubwordReg()

// If CurrOp would change when Canonicalized or stack-normalized, then return CurrOp->clone(), else return CurrOp;
STARSOpndTypePtr CloneIfNecessary(const STARSOpndTypePtr &CurrOp, bool UseFP) {
	if (MDIsStackAccessOpnd(CurrOp, UseFP)) {
		return CurrOp->clone();
	}
	else {
		return CloneIfSubwordReg(CurrOp);
	}
} // end of CloneIfNecessary()

// DEBUG Print DEF and/or USE for an operand.
void PrintDefUse(unsigned long 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 & STARS_CF_CHG1)
				SMP_msg(" DEF");
			if (feature & STARS_CF_USE1)
				SMP_msg(" USE");
			break;
		case 1:
			if (feature & STARS_CF_CHG2)
				SMP_msg(" DEF");
			if (feature & STARS_CF_USE2)
				SMP_msg(" USE");
			break;
		case 2:
			if (feature & STARS_CF_CHG3)
				SMP_msg(" DEF");
			if (feature & STARS_CF_USE3)
				SMP_msg(" USE");
			break;
		case 3:
			if (feature & STARS_CF_CHG4)
				SMP_msg(" DEF");
			if (feature & STARS_CF_USE4)
				SMP_msg(" USE");
			break;
		case 4:
			if (feature & STARS_CF_CHG5)
				SMP_msg(" DEF");
			if (feature & STARS_CF_USE5)
				SMP_msg(" USE");
			break;
		case 5:
			if (feature & STARS_CF_CHG6)
				SMP_msg(" DEF");
			if (feature & STARS_CF_USE6)
				SMP_msg(" USE");
			break;
	}
	return;
} // end PrintDefUse()

// DEBUG print SIB info for an operand.
void PrintSIB(const STARSOpndTypePtr &Opnd) {
	int BaseReg;
	int IndexReg;
	uint16_t ScaleFactor;
	STARS_ea_t offset;
#define NAME_LEN 5
	char BaseName[NAME_LEN] = {'N', 'o', 'n', 'e', '\0'};
	char IndexName[NAME_LEN] = {'N', 'o', 'n', 'e', '\0'};

	MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, offset);

	if (BaseReg != STARS_x86_R_none)
		SMP_strncpy(BaseName, RegNames[BaseReg], NAME_LEN - 1);

	if (IndexReg != STARS_x86_R_none) {
		SMP_strncpy(IndexName, RegNames[IndexReg], NAME_LEN -1);
	}
	SMP_msg(" Base %s Index %s Scale %d Flag4 %d", BaseName, IndexName, ScaleFactor, Opnd->GetSpecFlag4());
} // end PrintSIB()

// Annotations: concisely print SIB info for an operand.
void AnnotPrintSIB(const STARSOpndTypePtr &Opnd, bool HasOffset, FILE *OutFile, char OutString[STARS_MAXSTR], bool Has64BitAddressing) {
	int BaseReg;
	int IndexReg;
	uint16_t ScaleFactor;
	uint16_t ByteWidth = Opnd->GetByteWidth();
	STARS_ea_t offset;
	char ScaleString[4];

	if (Has64BitAddressing)
		ByteWidth = 8;

	SMP_strncat(OutString, "[", STARS_MAXSTR - 1);

	MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, offset);

	if (ScaleFactor > 0) {
		ScaleFactor = 1 << ScaleFactor;
		(void) SMP_snprintf(ScaleString, 4, "%d", ScaleFactor);
	}

	if (BaseReg != STARS_x86_R_none) {
		(void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) BaseReg, ByteWidth), STARS_MAXSTR - 1);
		if (IndexReg != STARS_x86_R_none) {
			(void) SMP_strncat(OutString, "+", STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1);
			if (ScaleFactor > 0) {
				(void) SMP_strncat(OutString, "*", STARS_MAXSTR - 1);
				(void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR - 1);
			}
		}
	}
	else if (IndexReg != STARS_x86_R_none) {
		(void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1);
		if (ScaleFactor > 0) {
			(void) SMP_strncat(OutString, "*", STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR - 1);
		}
	}
	else {
		SMP_msg("ERROR: No BaseReg, no IndexReg in SIB\n");
	}
	if (!HasOffset) // can close the brackets around regs
		(void) SMP_strncat(OutString, "]", STARS_MAXSTR - 1);
	SMP_fprintf(OutFile, " %s", OutString);
} // end AnnotPrintSIB()
		
// Annotations: concisely print SIB info for an operand to OutString.
void StringPrintSIB(const STARSOpndTypePtr &Opnd, bool HasOffset, char *OutString, bool Has64BitAddressing) {
	int BaseReg;
	int IndexReg;
	uint16_t ScaleFactor;
	uint16_t ByteWidth = Opnd->GetByteWidth();
	STARS_ea_t offset;
	char ScaleString[4];

	if (Has64BitAddressing)
		ByteWidth = 8;

	SMP_strncat(OutString, "[", STARS_MAXSTR - 1);

	MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, offset);

	if (ScaleFactor > 0) {
		ScaleFactor = 1 << ScaleFactor;
		(void) SMP_snprintf(ScaleString, 4, "%d", ScaleFactor);
	}

	if (BaseReg != STARS_x86_R_none) {
		(void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) BaseReg, ByteWidth), STARS_MAXSTR - 1);
		if (IndexReg != STARS_x86_R_none) {
			(void) SMP_strncat(OutString, "+", STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1);
			if (ScaleFactor > 0) {
				(void) SMP_strncat(OutString, "*", STARS_MAXSTR - 1);
				(void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR - 1);
			}
		}
	}
	else if (IndexReg != STARS_x86_R_none) {
		(void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1);
		if (ScaleFactor > 0) {
			(void) SMP_strncat(OutString, "*", STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR - 1);
		}
	}
	else {
		SMP_msg("ERROR: No BaseReg, no IndexReg in SIB\n");
	}
	if (!HasOffset) // can close the brackets around regs
		(void) SMP_strncat(OutString, "]", STARS_MAXSTR - 1);
	return;
} // end StringPrintSIB()

// Annotations: concisely print SIB info for an operand.
void SPARKAnnotPrintSIB(const STARSOpndTypePtr &Opnd, bool HasOffset, FILE *OutFile, STARS_regnum_t SegReg, bool UseFP, bool Has64BitAddressing, bool UseSavedStackPtr) {
#if 1
	std::string OutString;
	SPARKAnnotSIBToString(Opnd, HasOffset, OutString, SegReg, UseFP, Has64BitAddressing, UseSavedStackPtr);
	SMP_fprintf(OutFile, " %s", OutString.c_str());
#else
	int BaseReg;
	int IndexReg;
	uint16_t ScaleFactor;
	uint16_t ByteWidth = Opnd->GetByteWidth();
	STARS_ea_t offset;
	char OutString[STARS_MAXSTR] = {'(', '\0'};
	char ScaleString[4];

	if (Has64BitAddressing)
		ByteWidth = 8;

	MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, offset);

	bool SegRegPrefix = STARS_x86_is_segreg((int) SegReg);
	if (SegRegPrefix) {
		// Emit segment register string unless it is just the stack segment plus a stack operand,
		//  where the stack segment is implied anyway.
		if ((SegReg == STARS_x86_R_ss) && MDIsStackAccessOpnd(Opnd, UseFP)) {
			SegRegPrefix = false;
		}
#if STARS_SPARK_EMIT_SEGMENT_REGS
		else {
			(void) SMP_strncat(OutString, "X86.", STARS_MAXSTR-1);
			(void) SMP_strncat(OutString, MDGetRegNumName(SegReg, RegSizes[SegReg]), STARS_MAXSTR-1);
		}
#endif
	}

	if (ScaleFactor > 0) {
		ScaleFactor = 1 << (ScaleFactor - 1);
		(void) SMP_snprintf(ScaleString, 4, "%d", ScaleFactor);
	}

	if (BaseReg != STARS_x86_R_none) {
#if STARS_SPARK_EMIT_SEGMENT_REGS
		if (SegRegPrefix) {
			(void) SMP_strncat(OutString, " + ", STARS_MAXSTR-1);
		}
#endif
		if (!(UseSavedStackPtr && (BaseReg == MD_STACK_POINTER_REG))) {
			(void) SMP_strncat(OutString, "X86.", STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t)BaseReg, ByteWidth), STARS_MAXSTR - 1);
		}
		else {
			(void) SMP_strncat(OutString, "SaveStackPtr", STARS_MAXSTR - 1);
		}
		if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) {
			++SubwordAddressRegCount;
		}
		if (IndexReg != STARS_x86_R_none) {
			(void) SMP_strncat(OutString, " + ", STARS_MAXSTR - 1);
			if (!(UseSavedStackPtr && (IndexReg == MD_STACK_POINTER_REG))) {
				(void) SMP_strncat(OutString, "X86.", STARS_MAXSTR - 1);
				(void) SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1);
			}
			else {
				(void) SMP_strncat(OutString, "SaveStackPtr", STARS_MAXSTR - 1);
			}
			if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) {
				++SubwordAddressRegCount;
			}
			if (ScaleFactor > 0) {
				(void) SMP_strncat(OutString, "*", STARS_MAXSTR-1);
				(void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR-1);
			}
		}
	}
	else if (IndexReg != STARS_x86_R_none) {
#if STARS_SPARK_EMIT_SEGMENT_REGS
		if (SegRegPrefix) {
			(void) SMP_strncat(OutString, " + ", STARS_MAXSTR-1);
		}
#endif
		if (!(UseSavedStackPtr && (IndexReg == MD_STACK_POINTER_REG))) {
			(void)SMP_strncat(OutString, "X86.", STARS_MAXSTR - 1);
			(void)SMP_strncat(OutString, MDGetRegNumName((STARS_regnum_t)IndexReg, ByteWidth), STARS_MAXSTR - 1);
		}
		else {
			(void)SMP_strncat(OutString, "SaveStackPtr", STARS_MAXSTR - 1);
		}
		if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) {
			++SubwordAddressRegCount;
		}
		if (ScaleFactor > 0) {
			(void) SMP_strncat(OutString, "*", STARS_MAXSTR-1);
			(void) SMP_strncat(OutString, ScaleString, STARS_MAXSTR-1);
		}
	}
	else if (!SegRegPrefix) {
		SMP_msg("ERROR: No BaseReg, no IndexReg in SIB\n");
	}
	if (!HasOffset) // can close the parens around regs
		(void) SMP_strncat(OutString, ")", STARS_MAXSTR-1);
	SMP_fprintf(OutFile, " %s", OutString);
#endif
	return;
} // end SPARKAnnotPrintSIB()

void SPARKAnnotSIBToString(const STARSOpndTypePtr &Opnd, bool HasOffset, std::string &OutString, STARS_regnum_t SegReg, bool UseFP, bool Has64BitAddressing, bool UseSavedStackPtr) {
	int BaseReg;
	int IndexReg;
	uint16_t ScaleFactor;
	uint16_t ByteWidth = Opnd->GetByteWidth();
	STARS_ea_t offset;
	char OutString2[STARS_MAXSTR] = { '(', '\0' };
	char ScaleString[4];

	if (Has64BitAddressing)
		ByteWidth = 8;

	MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, offset);

	bool SegRegPrefix = STARS_x86_is_segreg((int)SegReg);
	if (SegRegPrefix) {
		// Emit segment register string unless it is just the stack segment plus a stack operand,
		//  where the stack segment is implied anyway.
		if ((SegReg == STARS_x86_R_ss) && MDIsStackAccessOpnd(Opnd, UseFP)) {
			SegRegPrefix = false;
		}
#if STARS_SPARK_EMIT_SEGMENT_REGS
		else {
			(void)SMP_strncat(OutString2, "X86.", STARS_MAXSTR - 1);
			(void)SMP_strncat(OutString2, MDGetRegNumName(SegReg, RegSizes[SegReg]), STARS_MAXSTR - 1);
		}
#endif
	}

	if (ScaleFactor > 0) {
		ScaleFactor = 1 << ScaleFactor;
		(void) SMP_snprintf(ScaleString, 4, "%d", ScaleFactor);
	}

	if (BaseReg != STARS_x86_R_none) {
#if STARS_SPARK_EMIT_SEGMENT_REGS
		if (SegRegPrefix) {
			(void) SMP_strncat(OutString2, " + ", STARS_MAXSTR - 1);
		}
#endif
		if (!(UseSavedStackPtr && (BaseReg == MD_STACK_POINTER_REG))) {
			(void) SMP_strncat(OutString2, "X86.", STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString2, MDGetRegNumName((STARS_regnum_t)BaseReg, ByteWidth), STARS_MAXSTR - 1);
		}
		else {
			(void) SMP_strncat(OutString2, "SaveStackPtr", STARS_MAXSTR - 1);
		}
		if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) {
			++SubwordAddressRegCount;
		}
		if (IndexReg != STARS_x86_R_none) {
			if (!(UseSavedStackPtr && (IndexReg == MD_STACK_POINTER_REG))) {
				(void) SMP_strncat(OutString2, " + X86.", STARS_MAXSTR - 1);
				(void) SMP_strncat(OutString2, MDGetRegNumName((STARS_regnum_t)IndexReg, ByteWidth), STARS_MAXSTR - 1);
			}
			else {
				(void) SMP_strncat(OutString2, " + SaveStackPtr", STARS_MAXSTR - 1);
			}
			if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) {
				++SubwordAddressRegCount;
			}
			if (ScaleFactor > 0) {
				(void) SMP_strncat(OutString2, "*", STARS_MAXSTR - 1);
				(void) SMP_strncat(OutString2, ScaleString, STARS_MAXSTR - 1);
			}
		}
	}
	else if (IndexReg != STARS_x86_R_none) {
#if STARS_SPARK_EMIT_SEGMENT_REGS
		if (SegRegPrefix) {
			(void) SMP_strncat(OutString2, " + ", STARS_MAXSTR - 1);
		}
#endif
		if (!(UseSavedStackPtr && (IndexReg == MD_STACK_POINTER_REG))) {
			(void)SMP_strncat(OutString2, "X86.", STARS_MAXSTR - 1);
			(void)SMP_strncat(OutString2, MDGetRegNumName((STARS_regnum_t) IndexReg, ByteWidth), STARS_MAXSTR - 1);
		}
		else {
			(void)SMP_strncat(OutString2, "SaveStackPtr", STARS_MAXSTR - 1);
		}
		if (global_STARS_program->GetSTARS_ISA_Bytewidth() > ByteWidth) {
			++SubwordAddressRegCount;
		}
		if (ScaleFactor > 0) {
			(void) SMP_strncat(OutString2, "*", STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString2, ScaleString, STARS_MAXSTR - 1);
		}
	}
	else if (!SegRegPrefix) {
		SMP_msg("ERROR: No BaseReg, no IndexReg in SIB\n");
	}
	if (!HasOffset) // can close the parens around regs
		(void) SMP_strncat(OutString2, ")", STARS_MAXSTR - 1);
	OutString.assign(OutString2);
	return;
} // end of SPARKAnnotSIBToString()

// Debug: print one operand from an instruction or DEF or USE list.
void PrintOneOperand(const STARSOpndTypePtr &Opnd, uint32_t features, int OpNum) { 
	if ((nullptr != Opnd) && (!Opnd->IsVoidOp())) {
		PrintOperand(Opnd);
		PrintDefUse(features, OpNum);
	}
	return;
} // end of PrintOneOperand()

// Debug: print one operand.
void PrintOperand(const STARSOpndTypePtr &Opnd) { 
	if ((nullptr == Opnd) || (Opnd->IsVoidOp()))
		return;
	else if (Opnd->IsStaticMemOp()) {
		SMP_msg(" Operand: memory : addr: %lx", (unsigned long) Opnd->GetAddr());
		if (Opnd->HasSIBByte()) {
			PrintSIB(Opnd);
		}
	}
	else if (Opnd->IsMemNoDisplacementOp()) {
		SMP_msg(" Operand: memory phrase :");
		if (Opnd->HasSIBByte()) { // has SIB info
			PrintSIB(Opnd);
		}
		else { // no SIB info
			STARS_regnum_t BaseReg = Opnd->GetReg();
			SMP_msg(" reg %s", RegNames[BaseReg]);
		}
		if (Opnd->GetAddr() != 0) {
			SMP_msg(" \n ERROR: addr for o_phrase type: %lx\n", (unsigned long) Opnd->GetAddr());
		}
	}
	else if (Opnd->IsMemDisplacementOp()) {
		SMP_msg(" Operand: memory displ :");
		STARS_ea_t offset = Opnd->GetAddr();
		int SignedOffset = (int) offset;
		if (Opnd->HasSIBByte()) {
			PrintSIB(Opnd);
			SMP_msg(" displ %d", SignedOffset);
		}
		else {
			STARS_regnum_t BaseReg = Opnd->GetReg();
			SMP_msg(" reg %s displ %d", RegNames[BaseReg], SignedOffset);
		}
	}
	else if (Opnd->IsRegOp()) {
		SMP_msg(" Operand: register %s", MDGetRegName(Opnd));
	}
	else if (Opnd->IsImmedOp()) {
		SMP_msg(" Operand: immed %ld", (long) Opnd->GetImmedValue());
	}
	else if (Opnd->IsFarPointer()) {
		SMP_msg(" Operand: FarPtrImmed addr: %lx", (unsigned long) Opnd->GetAddr());
	}
	else if (Opnd->IsNearPointer()) {
		SMP_msg(" Operand: NearPtrImmed addr: %lx", (unsigned long) Opnd->GetAddr());
	}
	else if (Opnd->IsTestRegOp()) {
		SMP_msg(" Operand: TestReg reg: %d", Opnd->GetReg());
	}
	else if (Opnd->IsDebugRegOp()) {
		SMP_msg(" Operand: DebugReg reg: %d", Opnd->GetReg());
	}
	else if (Opnd->IsControlRegOp()) {
		SMP_msg(" Operand: ControlReg reg: %d", Opnd->GetReg());
	}
	else if (Opnd->IsFloatingPointRegOp()) {
		SMP_msg(" Operand: FloatReg reg: %d", Opnd->GetReg());
	}
	else if (Opnd->IsMMXRegOp()) {
		SMP_msg(" Operand: MMXReg reg: %d", Opnd->GetReg());
	}
	else if (Opnd->IsXMMRegOp()) {
		SMP_msg(" Operand: XMMReg reg: %d", Opnd->GetReg());
	}
	else if (Opnd->IsYMMRegOp()) {
		SMP_msg(" Operand: YMMReg reg: %d", Opnd->GetReg());
	}
	else {
		SMP_msg(" Operand: unknown");
	}
#if STARS_DEBUG_DUMP_IDENTIFY_HIDDEN_OPERANDS
	if (!(Opnd->IsVisible()))
		SMP_msg(" HIDDEN ");
#endif
	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(const STARSOpndTypePtr &Opnd, int SSANum) {
	if ((nullptr != Opnd) && (!Opnd->IsVoidOp())) {
		PrintOperand(Opnd);
		if (!Opnd->IsImmedOp()) {
			SMP_msg(" SSANum: %d ", SSANum);
		}
		else {
			SMP_msg(" ");
		}
	}
	return;
} // end of PrintListOperand()

// Annotations: concisely print one operand to OutFile.
void AnnotPrintOperand(const STARSOpndTypePtr &Opnd, FILE *OutFile, bool UseFP, bool Has64BitAddressing) {
	char OutString[STARS_MAXSTR] = { '\0', '\0' };
	uint16_t ByteWidth = Opnd->GetByteWidth();
	if (Has64BitAddressing)
		ByteWidth = 8;

	STARS_regnum_t SegReg = Opnd->GetSegReg();
	bool SegRegPrefix = STARS_x86_is_segreg((int) SegReg);
	if (SegRegPrefix) {
		// Emit segment register string unless it is just the stack segment plus a stack operand,
		//  where the stack segment is implied anyway.
		if ((SegReg == STARS_x86_R_ss) && MDIsStackAccessOpnd(Opnd, UseFP)) {
			SegRegPrefix = false;
		}
		else if (SegReg != STARS_x86_R_ds) { // not default data segment 
			(void) SMP_strncat(OutString, MDGetRegNumName(SegReg, RegSizes[SegReg]), STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, ":", STARS_MAXSTR - 1);
		}
	}

	if (Opnd->IsStaticMemOp()) {
		SMP_snprintf(OutString, STARS_MAXSTR - 1, " %llx", (unsigned long long) Opnd->GetAddr());
		if (Opnd->HasSIBByte()) {
			AnnotPrintSIB(Opnd, false, OutFile, OutString, Has64BitAddressing);
		}
		else {
			SMP_fprintf(OutFile, " %s", OutString);
		}
	}
	else if (Opnd->IsMemNoDisplacementOp()) {
		if (Opnd->HasSIBByte()) { // has SIB info
			AnnotPrintSIB(Opnd, false, OutFile, OutString, Has64BitAddressing);
		}
		else { // no SIB info
			STARS_regnum_t BaseReg = Opnd->GetReg();
			SMP_fprintf(OutFile, " [%s]", MDGetRegNumName(BaseReg, ByteWidth));
		}
		if (Opnd->GetAddr() != 0) {
			SMP_msg(" \n ERROR: addr for o_phrase type: %llx\n", (unsigned long long) Opnd->GetAddr());
		}
	}
	else if (Opnd->IsMemDisplacementOp()) {
		STARS_ea_t offset = Opnd->GetAddr();
		int SignedOffset = (int) offset;
		if (Opnd->HasSIBByte()) {
			AnnotPrintSIB(Opnd, (SignedOffset != 0), OutFile, OutString, Has64BitAddressing);
			if (SignedOffset > 0) // print plus sign
				SMP_fprintf(OutFile, "+%d]", SignedOffset);
			else if (SignedOffset < 0) // minus sign will print automatically
				SMP_fprintf(OutFile, "%d]", SignedOffset);

		}
		else {
			STARS_regnum_t BaseReg = Opnd->GetReg();
			if (SignedOffset >= 0) // print plus sign
				SMP_fprintf(OutFile, " [%s+%d]", MDGetRegNumName(BaseReg, ByteWidth), SignedOffset);
			else // minus sign will print automatically
				SMP_fprintf(OutFile, " [%s%d]", MDGetRegNumName(BaseReg, ByteWidth), SignedOffset);
		}
	}
	else if (Opnd->IsRegOp()) {
		SMP_fprintf(OutFile, " %s", MDGetRegName(Opnd));
	}
	else if (Opnd->IsImmedOp()) {
		SMP_fprintf(OutFile, " %ld", (long) Opnd->GetImmedValue());
	}
	else if ((Opnd->IsFarPointer()) || (Opnd->IsNearPointer())) {
		SMP_fprintf(OutFile, " %llx", (unsigned long long) Opnd->GetAddr());
	}
	else {
		SMP_fprintf(OutFile, " ERROROP");
	}
	return;
} // end of AnnotPrintOperand()

// Annotations: concisely print one operand to a string.
void StringPrintOperand(const STARSOpndTypePtr &Opnd, string &OutStream, bool UseFP, bool Has64BitAddressing) {
	char OutString[STARS_MAXSTR] = { '\0', '\0' };
	char DummyBuf[STARS_MAXSTR] = { '\0', '\0' };
	uint16_t ByteWidth = Opnd->GetByteWidth();
	if (Has64BitAddressing)
		ByteWidth = 8;

	STARS_regnum_t SegReg = Opnd->GetSegReg();
	bool SegRegPrefix = STARS_x86_is_segreg((int)SegReg);
	if (SegRegPrefix) {
		// Emit segment register string unless it is just the stack segment plus a stack operand,
		//  where the stack segment is implied anyway.
		if ((SegReg == STARS_x86_R_ss) && MDIsStackAccessOpnd(Opnd, UseFP)) {
			SegRegPrefix = false;
		}
		else if (SegReg != STARS_x86_R_ds) { // not default data segment 
			(void) SMP_strncat(OutString, MDGetRegNumName(SegReg, RegSizes[SegReg]), STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, ":", STARS_MAXSTR - 1);
		}
	}

	if (Opnd->IsStaticMemOp()) {
		SMP_snprintf(OutString, STARS_MAXSTR - 1, " %llx", (unsigned long long) Opnd->GetAddr());
		if (Opnd->HasSIBByte()) {
			StringPrintSIB(Opnd, false, OutString, Has64BitAddressing);
		}
	}
	else if (Opnd->IsMemNoDisplacementOp()) {
		if (Opnd->HasSIBByte()) { // has SIB info
			StringPrintSIB(Opnd, false, OutString, Has64BitAddressing);
		}
		else { // no SIB info
			STARS_regnum_t BaseReg = Opnd->GetReg();
			(void) SMP_strncat(OutString, " [", STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, MDGetRegNumName(BaseReg, ByteWidth), STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, "] ", STARS_MAXSTR - 1);
		}
		if (Opnd->GetAddr() != 0) {
			SMP_msg(" \n ERROR: addr for o_phrase type: %llx\n", (unsigned long long) Opnd->GetAddr());
		}
	}
	else if (Opnd->IsMemDisplacementOp()) {
		STARS_ea_t offset = Opnd->GetAddr();
		int SignedOffset = (int) offset;
		if (Opnd->HasSIBByte()) {
			StringPrintSIB(Opnd, (SignedOffset != 0), OutString, Has64BitAddressing);
			if (SignedOffset > 0) { // print plus sign
				(void) SMP_strncat(OutString, "+", STARS_MAXSTR - 1);
			}
#if 0
			(void) SMP_snprintf(DummyBuf, STARS_MAXSTR - 1, "%lld", (int64_t) Opnd->GetImmedValue());
#else
			(void)SMP_snprintf(DummyBuf, STARS_MAXSTR - 1, "%lld", (int64_t)SignedOffset);
			SMP_msg("INFO: StringPrintOperand case reached: MemDisplacement with SIB byte.\n");
#endif
			(void) SMP_strncat(OutString, DummyBuf, STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, "]", STARS_MAXSTR - 1);
		}
		else {
			STARS_regnum_t BaseReg = Opnd->GetReg();
			(void) SMP_strncat(OutString, " [", STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, MDGetRegNumName(BaseReg, ByteWidth), STARS_MAXSTR - 1);
			if (SignedOffset >= 0) { // print plus sign
				(void) SMP_strncat(OutString, "+", STARS_MAXSTR - 1);
			}
			(void) SMP_snprintf(DummyBuf, STARS_MAXSTR - 1, "%lld", (int64_t)SignedOffset);
			(void) SMP_strncat(OutString, DummyBuf, STARS_MAXSTR - 1);
			(void) SMP_strncat(OutString, "] ", STARS_MAXSTR - 1);
		}
	}
	else if (Opnd->IsRegOp()) {
		SMP_strncat(OutString, MDGetRegName(Opnd), STARS_MAXSTR - 1);
	}
	else if (Opnd->IsImmedOp()) {
		SMP_snprintf(DummyBuf, STARS_MAXSTR - 1, "%lld", (int64_t) Opnd->GetImmedValue());
		SMP_strncat(OutString, DummyBuf, STARS_MAXSTR - 1);
	}
	else if ((Opnd->IsFarPointer()) || (Opnd->IsNearPointer())) {
		SMP_snprintf(DummyBuf, STARS_MAXSTR - 1, " %llx", (uint64_t) Opnd->GetAddr());
		SMP_strncat(OutString, DummyBuf, STARS_MAXSTR - 1);
	}
	else {
		SMP_strncat(OutString, " ERROROP", STARS_MAXSTR - 1);
	}
	OutStream += OutString;
	return;
} // end of StringPrintOperand()

// Print opcode string.
void PrintOpcode(uint16_t opcode, FILE *OutFile) {
	switch (opcode) {
		case STARS_NN_null:                // Unknown Operation
		case STARS_NN_aaa:                 // ASCII Adjust after Addition
		case STARS_NN_aad:                 // ASCII Adjust AX before Division
		case STARS_NN_aam:                 // ASCII Adjust AX after Multiply
		case STARS_NN_aas:                 // ASCII Adjust AL after Subtraction
		case STARS_NN_adc:                 // Add with Carry
			SMP_fprintf(OutFile, "ERROR");
			break;

		case STARS_NN_add:                 // Add
			SMP_fprintf(OutFile, "add");
			break;

		case STARS_NN_and:                 // Logical AND
			SMP_fprintf(OutFile, "and");
			break;

		case STARS_NN_arpl:                // Adjust RPL Field of Selector
		case STARS_NN_bound:               // Check Array Index Against Bounds
		case STARS_NN_bsf:                 // Bit Scan Forward
		case STARS_NN_bsr:                 // Bit Scan Reverse
		case STARS_NN_bt:                  // Bit Test
		case STARS_NN_btc:                 // Bit Test and Complement
		case STARS_NN_btr:                 // Bit Test and Reset
		case STARS_NN_bts:                 // Bit Test and Set
			SMP_fprintf(OutFile, "ERROR");
			break;

		case STARS_NN_call:                // Call Procedure
		case STARS_NN_callfi:              // Indirect Call Far Procedure
		case STARS_NN_callni:              // Indirect Call Near Procedure
			SMP_fprintf(OutFile, "");
			break;

		case STARS_NN_cbw:                 // AL -> AX (with sign)
		case STARS_NN_cwde:                // AX -> EAX (with sign)
		case STARS_NN_cdqe:                // EAX -> RAX (with sign)
		case STARS_NN_clc:                 // Clear Carry Flag
		case STARS_NN_cld:                 // Clear Direction Flag
		case STARS_NN_cli:                 // Clear Interrupt Flag
		case STARS_NN_clts:                // Clear Task-Switched Flag in CR0
		case STARS_NN_cmc:                 // Complement Carry Flag
		case STARS_NN_cmp:                 // Compare Two Operands
		case STARS_NN_cmps:                // Compare Strings
		case STARS_NN_cwd:                 // AX -> DX:AX (with sign)
		case STARS_NN_cdq:                 // EAX -> EDX:EAX (with sign)
		case STARS_NN_cqo:                 // RAX -> RDX:RAX (with sign)
		case STARS_NN_daa:                 // Decimal Adjust AL after Addition
		case STARS_NN_das:                 // Decimal Adjust AL after Subtraction
			SMP_fprintf(OutFile, "ERROR");
			break;

		case STARS_NN_dec:                 // Decrement by 1
			SMP_fprintf(OutFile, "sub");
			break;
		case STARS_NN_div:                 // Unsigned Divide
			SMP_fprintf(OutFile, "div");
			break;
		case STARS_NN_enterw:              // Make Stack Frame for Procedure Parameters
		case STARS_NN_enter:               // Make Stack Frame for Procedure Parameters
		case STARS_NN_enterd:              // Make Stack Frame for Procedure Parameters
		case STARS_NN_enterq:              // Make Stack Frame for Procedure Parameters
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_hlt:                 // Halt
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_idiv:                // Signed Divide
			SMP_fprintf(OutFile, "div");
			break;
		case STARS_NN_imul:                // Signed Multiply
			SMP_fprintf(OutFile, "mul");
			break;
		case STARS_NN_in:                  // Input from Port
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_inc:                 // Increment by 1
			SMP_fprintf(OutFile, "add");
			break;
		case STARS_NN_ins:                 // Input Byte(s) from Port to String
		case STARS_NN_int:                 // Call to Interrupt Procedure
		case STARS_NN_into:                // Call to Interrupt Procedure if Overflow Flag = 1
		case STARS_NN_int3:                // Trap to Debugger
		case STARS_NN_iretw:               // Interrupt Return
		case STARS_NN_iret:                // Interrupt Return
		case STARS_NN_iretd:               // Interrupt Return (use32)
		case STARS_NN_iretq:               // Interrupt Return (use64)
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_ja:                  // Jump if Above (CF=0 & ZF=0)
		case STARS_NN_jae:                 // Jump if Above or Equal (CF=0)
		case STARS_NN_jb:                  // Jump if Below (CF=1)
		case STARS_NN_jbe:                 // Jump if Below or Equal (CF=1 | ZF=1)
		case STARS_NN_jc:                  // Jump if Carry (CF=1)
		case STARS_NN_jcxz:                // Jump if CX is 0
		case STARS_NN_jecxz:               // Jump if ECX is 0
		case STARS_NN_jrcxz:               // Jump if RCX is 0
		case STARS_NN_je:                  // Jump if Equal (ZF=1)
		case STARS_NN_jg:                  // Jump if Greater (ZF=0 & SF=OF)
		case STARS_NN_jge:                 // Jump if Greater or Equal (SF=OF)
		case STARS_NN_jl:                  // Jump if Less (SF!=OF)
		case STARS_NN_jle:                 // Jump if Less or Equal (ZF=1 | SF!=OF)
		case STARS_NN_jna:                 // Jump if Not Above (CF=1 | ZF=1)
		case STARS_NN_jnae:                // Jump if Not Above or Equal (CF=1)
		case STARS_NN_jnb:                 // Jump if Not Below (CF=0)
		case STARS_NN_jnbe:                // Jump if Not Below or Equal (CF=0 & ZF=0)
		case STARS_NN_jnc:                 // Jump if Not Carry (CF=0)
		case STARS_NN_jne:                 // Jump if Not Equal (ZF=0)
		case STARS_NN_jng:                 // Jump if Not Greater (ZF=1 | SF!=OF)
		case STARS_NN_jnge:                // Jump if Not Greater or Equal (ZF=1)
		case STARS_NN_jnl:                 // Jump if Not Less (SF=OF)
		case STARS_NN_jnle:                // Jump if Not Less or Equal (ZF=0 & SF=OF)
		case STARS_NN_jno:                 // Jump if Not Overflow (OF=0)
		case STARS_NN_jnp:                 // Jump if Not Parity (PF=0)
		case STARS_NN_jns:                 // Jump if Not Sign (SF=0)
		case STARS_NN_jnz:                 // Jump if Not Zero (ZF=0)
		case STARS_NN_jo:                  // Jump if Overflow (OF=1)
		case STARS_NN_jp:                  // Jump if Parity (PF=1)
		case STARS_NN_jpe:                 // Jump if Parity Even (PF=1)
		case STARS_NN_jpo:                 // Jump if Parity Odd  (PF=0)
		case STARS_NN_js:                  // Jump if Sign (SF=1)
		case STARS_NN_jz:                  // Jump if Zero (ZF=1)
		case STARS_NN_jmp:                 // Jump
		case STARS_NN_jmpfi:               // Indirect Far Jump
		case STARS_NN_jmpni:               // Indirect Near Jump
		case STARS_NN_jmpshort:            // Jump Short (not used)
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_lahf:                // Load Flags into AH Register
		case STARS_NN_lar:                 // Load Access Right Byte
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_lea:                 // Load Effective Address
				SMP_fprintf(OutFile, "lea");
			break;
		case STARS_NN_leavew:              // High Level Procedure Exit
		case STARS_NN_leave:               // High Level Procedure Exit
		case STARS_NN_leaved:              // High Level Procedure Exit
		case STARS_NN_leaveq:              // High Level Procedure Exit
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_lgdt:                // Load Global Descriptor Table Register
		case STARS_NN_lidt:                // Load Interrupt Descriptor Table Register
		case STARS_NN_lgs:                 // Load Full Pointer to GS:xx
		case STARS_NN_lss:                 // Load Full Pointer to SS:xx
		case STARS_NN_lds:                 // Load Full Pointer to DS:xx
		case STARS_NN_les:                 // Load Full Pointer to ES:xx
		case STARS_NN_lfs:                 // Load Full Pointer to FS:xx
		case STARS_NN_lldt:                // Load Local Descriptor Table Register
		case STARS_NN_lmsw:                // Load Machine Status Word
		case STARS_NN_lock:                // Assert LOCK# Signal Prefix
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_lods:                // Load String
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_loopw:               // Loop while ECX != 0
		case STARS_NN_loop:                // Loop while CX != 0
		case STARS_NN_loopd:               // Loop while ECX != 0
		case STARS_NN_loopq:               // Loop while RCX != 0
		case STARS_NN_loopwe:              // Loop while CX != 0 and ZF=1
		case STARS_NN_loope:               // Loop while rCX != 0 and ZF=1
		case STARS_NN_loopde:              // Loop while ECX != 0 and ZF=1
		case STARS_NN_loopqe:              // Loop while RCX != 0 and ZF=1
		case STARS_NN_loopwne:             // Loop while CX != 0 and ZF=0
		case STARS_NN_loopne:              // Loop while rCX != 0 and ZF=0
		case STARS_NN_loopdne:             // Loop while ECX != 0 and ZF=0
		case STARS_NN_loopqne:             // Loop while RCX != 0 and ZF=0
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_lsl:                 // Load Segment Limit
		case STARS_NN_ltr:                 // Load Task Register
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_mov:                 // Move Data
			SMP_fprintf(OutFile, "mov");
			break;
		case STARS_NN_movsp:               // Move to/from Special Registers
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_movs:                // Move Byte(s) from String to String
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_movsx:               // Move with Sign-Extend
			SMP_fprintf(OutFile, "movsx");
			break;
		case STARS_NN_movzx:               // Move with Zero-Extend
			SMP_fprintf(OutFile, "movzx");
			break;
		case STARS_NN_mul:                 // Unsigned Multiplication of AL or AX
			SMP_fprintf(OutFile, "mul");
			break;
		case STARS_NN_neg:                 // Two's Complement Negation
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_nop:                 // No Operation
			SMP_fprintf(OutFile, "");
			break;
		case STARS_NN_not:                 // One's Complement Negation
			SMP_fprintf(OutFile, "not");
			break;
		case STARS_NN_or:                  // Logical Inclusive OR
			SMP_fprintf(OutFile, "or");
			break;
		case STARS_NN_out:                 // Output to Port
		case STARS_NN_outs:                // Output Byte(s) to Port
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_pop:                 // Pop a word from the Stack
			SMP_fprintf(OutFile, "pop");
			break;
		case STARS_NN_popaw:               // Pop all General Registers
		case STARS_NN_popa:                // Pop all General Registers
		case STARS_NN_popad:               // Pop all General Registers (use32)
		case STARS_NN_popaq:               // Pop all General Registers (use64)
		case STARS_NN_popfw:               // Pop Stack into Flags Register
		case STARS_NN_popf:                // Pop Stack into Flags Register
		case STARS_NN_popfd:               // Pop Stack into Eflags Register
		case STARS_NN_popfq:               // Pop Stack into Rflags Register
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_push:                // Push Operand onto the Stack
			SMP_fprintf(OutFile, "push");
			break;
		case STARS_NN_pushaw:              // Push all General Registers
		case STARS_NN_pusha:               // Push all General Registers
		case STARS_NN_pushad:              // Push all General Registers (use32)
		case STARS_NN_pushaq:              // Push all General Registers (use64)
		case STARS_NN_pushfw:              // Push Flags Register onto the Stack
		case STARS_NN_pushf:               // Push Flags Register onto the Stack
		case STARS_NN_pushfd:              // Push Flags Register onto the Stack (use32)
		case STARS_NN_pushfq:              // Push Flags Register onto the Stack (use64)
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_rcl:                 // Rotate Through Carry Left
		case STARS_NN_rcr:                 // Rotate Through Carry Right
		case STARS_NN_rol:                 // Rotate Left
		case STARS_NN_ror:                 // Rotate Right
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_rep:                 // Repeat String Operation
		case STARS_NN_repe:                // Repeat String Operation while ZF=1
		case STARS_NN_repne:               // Repeat String Operation while ZF=0
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_retn:                // Return Near from Procedure
		case STARS_NN_retf:                // Return Far from Procedure
			SMP_fprintf(OutFile, "return");
			break;
		case STARS_NN_sahf:                // Store AH into Flags Register
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_sal:                 // Shift Arithmetic Left
			SMP_fprintf(OutFile, "sal");
			break;
		case STARS_NN_sar:                 // Shift Arithmetic Right
			SMP_fprintf(OutFile, "sar");
			break;
		case STARS_NN_shl:                 // Shift Logical Left
			SMP_fprintf(OutFile, "shl");
			break;
		case STARS_NN_shr:                 // Shift Logical Right
			SMP_fprintf(OutFile, "shr");
			break;
		case STARS_NN_sbb:                 // Integer Subtraction with Borrow
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_scas:                // Compare String
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_seta:                // Set Byte if Above (CF=0 & ZF=0)
		case STARS_NN_setae:               // Set Byte if Above or Equal (CF=0)
		case STARS_NN_setb:                // Set Byte if Below (CF=1)
		case STARS_NN_setbe:               // Set Byte if Below or Equal (CF=1 | ZF=1)
		case STARS_NN_setc:                // Set Byte if Carry (CF=1)
		case STARS_NN_sete:                // Set Byte if Equal (ZF=1)
		case STARS_NN_setg:                // Set Byte if Greater (ZF=0 & SF=OF)
		case STARS_NN_setge:               // Set Byte if Greater or Equal (SF=OF)
		case STARS_NN_setl:                // Set Byte if Less (SF!=OF)
		case STARS_NN_setle:               // Set Byte if Less or Equal (ZF=1 | SF!=OF)
		case STARS_NN_setna:               // Set Byte if Not Above (CF=1 | ZF=1)
		case STARS_NN_setnae:              // Set Byte if Not Above or Equal (CF=1)
		case STARS_NN_setnb:               // Set Byte if Not Below (CF=0)
		case STARS_NN_setnbe:              // Set Byte if Not Below or Equal (CF=0 & ZF=0)
		case STARS_NN_setnc:               // Set Byte if Not Carry (CF=0)
		case STARS_NN_setne:               // Set Byte if Not Equal (ZF=0)
		case STARS_NN_setng:               // Set Byte if Not Greater (ZF=1 | SF!=OF)
		case STARS_NN_setnge:              // Set Byte if Not Greater or Equal (ZF=1)
		case STARS_NN_setnl:               // Set Byte if Not Less (SF=OF)
		case STARS_NN_setnle:              // Set Byte if Not Less or Equal (ZF=0 & SF=OF)
		case STARS_NN_setno:               // Set Byte if Not Overflow (OF=0)
		case STARS_NN_setnp:               // Set Byte if Not Parity (PF=0)
		case STARS_NN_setns:               // Set Byte if Not Sign (SF=0)
		case STARS_NN_setnz:               // Set Byte if Not Zero (ZF=0)
		case STARS_NN_seto:                // Set Byte if Overflow (OF=1)
		case STARS_NN_setp:                // Set Byte if Parity (PF=1)
		case STARS_NN_setpe:               // Set Byte if Parity Even (PF=1)
		case STARS_NN_setpo:               // Set Byte if Parity Odd  (PF=0)
		case STARS_NN_sets:                // Set Byte if Sign (SF=1)
		case STARS_NN_setz:                // Set Byte if Zero (ZF=1)
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_sgdt:                // Store Global Descriptor Table Register
		case STARS_NN_sidt:                // Store Interrupt Descriptor Table Register
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_shld:                // Double Precision Shift Left
		case STARS_NN_shrd:                // Double Precision Shift Right
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_sldt:                // Store Local Descriptor Table Register
		case STARS_NN_smsw:                // Store Machine Status Word
		case STARS_NN_stc:                 // Set Carry Flag
		case STARS_NN_std:                 // Set Direction Flag
		case STARS_NN_sti:                 // Set Interrupt Flag
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_stos:                // Store String
		case STARS_NN_str:                 // Store Task Register
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_sub:                 // Integer Subtraction
			SMP_fprintf(OutFile, "sub");
			break;
		case STARS_NN_test:                // Logical Compare
			SMP_fprintf(OutFile, "test");
			break;
		case STARS_NN_verr:                // Verify a Segment for Reading
		case STARS_NN_verw:                // Verify a Segment for Writing
		case STARS_NN_wait:                // Wait until BUSY# Pin is Inactive (HIGH)
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_xchg:                // Exchange Register/Memory with Register
		case STARS_NN_xlat:                // Table Lookup Translation
			SMP_fprintf(OutFile, "ERROR");
			break;
		case STARS_NN_xor:                 // Logical Exclusive OR
			SMP_fprintf(OutFile, "xor");
			break;

//
//      486 instructions
//

		case STARS_NN_cmpxchg:             // Compare and Exchange
		case STARS_NN_bswap:               // Swap bits in EAX
		case STARS_NN_xadd:                // t<-dest; dest<-src+dest; src<-t
		case STARS_NN_invd:                // Invalidate Data Cache
		case STARS_NN_wbinvd:              // Invalidate Data Cache (write changes)
		case STARS_NN_invlpg:              // Invalidate TLB entry
			SMP_fprintf(OutFile, "ERROR");
			break;

//
//      Pentium instructions
//

		case STARS_NN_rdmsr:               // Read Machine Status Register
		case STARS_NN_wrmsr:               // Write Machine Status Register
		case STARS_NN_cpuid:               // Get CPU ID
		case STARS_NN_cmpxchg8b:           // Compare and Exchange Eight Bytes
		case STARS_NN_rdtsc:               // Read Time Stamp Counter
		case STARS_NN_rsm:                 // Resume from System Management Mode
			SMP_fprintf(OutFile, "ERROR");
			break;

//
//      Pentium Pro instructions
//

		case STARS_NN_cmova:               // Move if Above (CF=0 & ZF=0)
		case STARS_NN_cmovb:               // Move if Below (CF=1)
		case STARS_NN_cmovbe:              // Move if Below or Equal (CF=1 | ZF=1)
		case STARS_NN_cmovg:               // Move if Greater (ZF=0 & SF=OF)
		case STARS_NN_cmovge:              // Move if Greater or Equal (SF=OF)
		case STARS_NN_cmovl:               // Move if Less (SF!=OF)
		case STARS_NN_cmovle:              // Move if Less or Equal (ZF=1 | SF!=OF)
		case STARS_NN_cmovnb:              // Move if Not Below (CF=0)
		case STARS_NN_cmovno:              // Move if Not Overflow (OF=0)
		case STARS_NN_cmovnp:              // Move if Not Parity (PF=0)
		case STARS_NN_cmovns:              // Move if Not Sign (SF=0)
		case STARS_NN_cmovnz:              // Move if Not Zero (ZF=0)
		case STARS_NN_cmovo:               // Move if Overflow (OF=1)
		case STARS_NN_cmovp:               // Move if Parity (PF=1)
		case STARS_NN_cmovs:               // Move if Sign (SF=1)
		case STARS_NN_cmovz:               // Move if Zero (ZF=1)
		case STARS_NN_fcmovb:              // Floating Move if Below
		case STARS_NN_fcmove:              // Floating Move if Equal
		case STARS_NN_fcmovbe:             // Floating Move if Below or Equal
		case STARS_NN_fcmovu:              // Floating Move if Unordered
		case STARS_NN_fcmovnb:             // Floating Move if Not Below
		case STARS_NN_fcmovne:             // Floating Move if Not Equal
		case STARS_NN_fcmovnbe:            // Floating Move if Not Below or Equal
		case STARS_NN_fcmovnu:             // Floating Move if Not Unordered
		case STARS_NN_fcomi:               // FP Compare, result in EFLAGS
		case STARS_NN_fucomi:              // FP Unordered Compare, result in EFLAGS
		case STARS_NN_fcomip:              // FP Compare, result in EFLAGS, pop stack
		case STARS_NN_fucomip:             // FP Unordered Compare, result in EFLAGS, pop stack
		case STARS_NN_rdpmc:               // Read Performance Monitor Counter
			SMP_fprintf(OutFile, "ERROR");
			break;

//
//      FPP instructions
//

		case STARS_NN_fld:                 // Load Real
		case STARS_NN_fst:                 // Store Real
		case STARS_NN_fstp:                // Store Real and Pop
		case STARS_NN_fxch:                // Exchange Registers
		case STARS_NN_fild:                // Load Integer
		case STARS_NN_fist:                // Store Integer
		case STARS_NN_fistp:               // Store Integer and Pop
		case STARS_NN_fbld:                // Load BCD
		case STARS_NN_fbstp:               // Store BCD and Pop
		case STARS_NN_fadd:                // Add Real
		case STARS_NN_faddp:               // Add Real and Pop
		case STARS_NN_fiadd:               // Add Integer
		case STARS_NN_fsub:                // Subtract Real
		case STARS_NN_fsubp:               // Subtract Real and Pop
		case STARS_NN_fisub:               // Subtract Integer
		case STARS_NN_fsubr:               // Subtract Real Reversed
		case STARS_NN_fsubrp:              // Subtract Real Reversed and Pop
		case STARS_NN_fisubr:              // Subtract Integer Reversed
		case STARS_NN_fmul:                // Multiply Real
		case STARS_NN_fmulp:               // Multiply Real and Pop
		case STARS_NN_fimul:               // Multiply Integer
		case STARS_NN_fdiv:                // Divide Real
		case STARS_NN_fdivp:               // Divide Real and Pop
		case STARS_NN_fidiv:               // Divide Integer
		case STARS_NN_fdivr:               // Divide Real Reversed
		case STARS_NN_fdivrp:              // Divide Real Reversed and Pop
		case STARS_NN_fidivr:              // Divide Integer Reversed
		case STARS_NN_fsqrt:               // Square Root
		case STARS_NN_fscale:              // Scale:  st(0) <- st(0) * 2^st(1)
		case STARS_NN_fprem:               // Partial Remainder
		case STARS_NN_frndint:             // Round to Integer
		case STARS_NN_fxtract:             // Extract exponent and significand
		case STARS_NN_fabs:                // Absolute value
		case STARS_NN_fchs:                // Change Sign
		case STARS_NN_fcom:                // Compare Real
		case STARS_NN_fcomp:               // Compare Real and Pop
		case STARS_NN_fcompp:              // Compare Real and Pop Twice
		case STARS_NN_ficom:               // Compare Integer
		case STARS_NN_ficomp:              // Compare Integer and Pop
		case STARS_NN_ftst:                // Test
		case STARS_NN_fxam:                // Examine
		case STARS_NN_fptan:               // Partial tangent
		case STARS_NN_fpatan:              // Partial arctangent
		case STARS_NN_f2xm1:               // 2^x - 1
		case STARS_NN_fyl2x:               // Y * lg2(X)
		case STARS_NN_fyl2xp1:             // Y * lg2(X+1)
		case STARS_NN_fldz:                // Load +0.0
		case STARS_NN_fld1:                // Load +1.0
		case STARS_NN_fldpi:               // Load PI=3.14...
		case STARS_NN_fldl2t:              // Load lg2(10)
		case STARS_NN_fldl2e:              // Load lg2(e)
		case STARS_NN_fldlg2:              // Load lg10(2)
		case STARS_NN_fldln2:              // Load ln(2)
		case STARS_NN_finit:               // Initialize Processor
		case STARS_NN_fninit:              // Initialize Processor (no wait)
		case STARS_NN_fsetpm:              // Set Protected Mode
		case STARS_NN_fldcw:               // Load Control Word
		case STARS_NN_fstcw:               // Store Control Word
		case STARS_NN_fnstcw:              // Store Control Word (no wait)
		case STARS_NN_fstsw:               // Store Status Word
		case STARS_NN_fnstsw:              // Store Status Word (no wait)
		case STARS_NN_fclex:               // Clear Exceptions
		case STARS_NN_fnclex:              // Clear Exceptions (no wait)
		case STARS_NN_fstenv:              // Store Environment
		case STARS_NN_fnstenv:             // Store Environment (no wait)
		case STARS_NN_fldenv:              // Load Environment
		case STARS_NN_fsave:               // Save State
		case STARS_NN_fnsave:              // Save State (no wait)
		case STARS_NN_frstor:              // Restore State
		case STARS_NN_fincstp:             // Increment Stack Pointer
		case STARS_NN_fdecstp:             // Decrement Stack Pointer
		case STARS_NN_ffree:               // Free Register
		case STARS_NN_fnop:                // No Operation
		case STARS_NN_feni:                // (8087 only)
		case STARS_NN_fneni:               // (no wait) (8087 only)
		case STARS_NN_fdisi:               // (8087 only)
		case STARS_NN_fndisi:              // (no wait) (8087 only)
			SMP_fprintf(OutFile, "ERROR");
			break;

//
//      80387 instructions
//

		case STARS_NN_fprem1:              // Partial Remainder ( < half )
		case STARS_NN_fsincos:             // t<-cos(st); st<-sin(st); push t
		case STARS_NN_fsin:                // Sine
		case STARS_NN_fcos:                // Cosine
		case STARS_NN_fucom:               // Compare Unordered Real
		case STARS_NN_fucomp:              // Compare Unordered Real and Pop
		case STARS_NN_fucompp:             // Compare Unordered Real and Pop Twice
			SMP_fprintf(OutFile, "ERROR");
			break;

//
//      Instructions added 28.02.96
//

		case STARS_NN_setalc:              // Set AL to Carry Flag
		case STARS_NN_svdc:                // Save Register and Descriptor
		case STARS_NN_rsdc:                // Restore Register and Descriptor
		case STARS_NN_svldt:               // Save LDTR and Descriptor
		case STARS_NN_rsldt:               // Restore LDTR and Descriptor
		case STARS_NN_svts:                // Save TR and Descriptor
		case STARS_NN_rsts:                // Restore TR and Descriptor
		case STARS_NN_icebp:               // ICE Break Point
		case STARS_NN_loadall:             // Load the entire CPU state from ES:EDI
			SMP_fprintf(OutFile, "ERROR");
			break;

//
//      MMX instructions
//

		case STARS_NN_emms:                // Empty MMX state
		case STARS_NN_movd:                // Move 32 bits
		case STARS_NN_movq:                // Move 64 bits
		case STARS_NN_packsswb:            // Pack with Signed Saturation (Word->Byte)
		case STARS_NN_packssdw:            // Pack with Signed Saturation (Dword->Word)
		case STARS_NN_packuswb:            // Pack with Unsigned Saturation (Word->Byte)
		case STARS_NN_paddb:               // Packed Add Byte
		case STARS_NN_paddw:               // Packed Add Word
		case STARS_NN_paddd:               // Packed Add Dword
		case STARS_NN_paddsb:              // Packed Add with Saturation (Byte)
		case STARS_NN_paddsw:              // Packed Add with Saturation (Word)
		case STARS_NN_paddusb:             // Packed Add Unsigned with Saturation (Byte)
		case STARS_NN_paddusw:             // Packed Add Unsigned with Saturation (Word)
		case STARS_NN_pand:                // Bitwise Logical And
		case STARS_NN_pandn:               // Bitwise Logical And Not
		case STARS_NN_pcmpeqb:             // Packed Compare for Equal (Byte)
		case STARS_NN_pcmpeqw:             // Packed Compare for Equal (Word)
		case STARS_NN_pcmpeqd:             // Packed Compare for Equal (Dword)
		case STARS_NN_pcmpgtb:             // Packed Compare for Greater Than (Byte)
		case STARS_NN_pcmpgtw:             // Packed Compare for Greater Than (Word)
		case STARS_NN_pcmpgtd:             // Packed Compare for Greater Than (Dword)
		case STARS_NN_pmaddwd:             // Packed Multiply and Add
		case STARS_NN_pmulhw:              // Packed Multiply High
		case STARS_NN_pmullw:              // Packed Multiply Low
		case STARS_NN_por:                 // Bitwise Logical Or
		case STARS_NN_psllw:               // Packed Shift Left Logical (Word)
		case STARS_NN_pslld:               // Packed Shift Left Logical (Dword)
		case STARS_NN_psllq:               // Packed Shift Left Logical (Qword)
		case STARS_NN_psraw:               // Packed Shift Right Arithmetic (Word)
		case STARS_NN_psrad:               // Packed Shift Right Arithmetic (Dword)
		case STARS_NN_psrlw:               // Packed Shift Right Logical (Word)
		case STARS_NN_psrld:               // Packed Shift Right Logical (Dword)
		case STARS_NN_psrlq:               // Packed Shift Right Logical (Qword)
		case STARS_NN_psubb:               // Packed Subtract Byte
		case STARS_NN_psubw:               // Packed Subtract Word
		case STARS_NN_psubd:               // Packed Subtract Dword
		case STARS_NN_psubsb:              // Packed Subtract with Saturation (Byte)
		case STARS_NN_psubsw:              // Packed Subtract with Saturation (Word)
		case STARS_NN_psubusb:             // Packed Subtract Unsigned with Saturation (Byte)
		case STARS_NN_psubusw:             // Packed Subtract Unsigned with Saturation (Word)
		case STARS_NN_punpckhbw:           // Unpack High Packed Data (Byte->Word)
		case STARS_NN_punpckhwd:           // Unpack High Packed Data (Word->Dword)
		case STARS_NN_punpckhdq:           // Unpack High Packed Data (Dword->Qword)
		case STARS_NN_punpcklbw:           // Unpack Low Packed Data (Byte->Word)
		case STARS_NN_punpcklwd:           // Unpack Low Packed Data (Word->Dword)
		case STARS_NN_punpckldq:           // Unpack Low Packed Data (Dword->Qword)
		case STARS_NN_pxor:                // Bitwise Logical Exclusive Or
			SMP_fprintf(OutFile, "ERROR");
			break;

//
//      Undocumented Deschutes processor instructions
//

		case STARS_NN_fxsave:              // Fast save FP context
		case STARS_NN_fxrstor:             // Fast restore FP context
			SMP_fprintf(OutFile, "ERROR");
			break;

//      Pentium II instructions

		case STARS_NN_sysenter:            // Fast Transition to System Call Entry Point
		case STARS_NN_sysexit:             // Fast Transition from System Call Entry Point
			SMP_fprintf(OutFile, "ERROR");
			break;

//      3DNow! instructions

		case STARS_NN_pavgusb:             // Packed 8-bit Unsigned Integer Averaging
		case STARS_NN_pfadd:               // Packed Floating-Point Addition
		case STARS_NN_pfsub:               // Packed Floating-Point Subtraction
		case STARS_NN_pfsubr:              // Packed Floating-Point Reverse Subtraction
		case STARS_NN_pfacc:               // Packed Floating-Point Accumulate
		case STARS_NN_pfcmpge:             // Packed Floating-Point Comparison, Greater or Equal
		case STARS_NN_pfcmpgt:             // Packed Floating-Point Comparison, Greater
		case STARS_NN_pfcmpeq:             // Packed Floating-Point Comparison, Equal
		case STARS_NN_pfmin:               // Packed Floating-Point Minimum
		case STARS_NN_pfmax:               // Packed Floating-Point Maximum
		case STARS_NN_pi2fd:               // Packed 32-bit Integer to Floating-Point
		case STARS_NN_pf2id:               // Packed Floating-Point to 32-bit Integer
		case STARS_NN_pfrcp:               // Packed Floating-Point Reciprocal Approximation
		case STARS_NN_pfrsqrt:             // Packed Floating-Point Reciprocal Square Root Approximation
		case STARS_NN_pfmul:               // Packed Floating-Point Multiplication
		case STARS_NN_pfrcpit1:            // Packed Floating-Point Reciprocal First Iteration Step
		case STARS_NN_pfrsqit1:            // Packed Floating-Point Reciprocal Square Root First Iteration Step
		case STARS_NN_pfrcpit2:            // Packed Floating-Point Reciprocal Second Iteration Step
		case STARS_NN_pmulhrw:             // Packed Floating-Point 16-bit Integer Multiply with rounding
		case STARS_NN_femms:               // Faster entry/exit of the MMX or floating-point state
		case STARS_NN_prefetch:            // Prefetch at least a 32-byte line into L1 data cache
		case STARS_NN_prefetchw:           // Prefetch processor cache line into L1 data cache (mark as modified)
			SMP_fprintf(OutFile, "ERROR");
			break;


//      Pentium III instructions

		case STARS_NN_addps:               // Packed Single-FP Add
		case STARS_NN_addss:               // Scalar Single-FP Add
		case STARS_NN_andnps:              // Bitwise Logical And Not for Single-FP
		case STARS_NN_andps:               // Bitwise Logical And for Single-FP
		case STARS_NN_cmpps:               // Packed Single-FP Compare
		case STARS_NN_cmpss:               // Scalar Single-FP Compare
		case STARS_NN_comiss:              // Scalar Ordered Single-FP Compare and Set EFLAGS
		case STARS_NN_cvtpi2ps:            // Packed signed INT32 to Packed Single-FP conversion
		case STARS_NN_cvtps2pi:            // Packed Single-FP to Packed INT32 conversion
		case STARS_NN_cvtsi2ss:            // Scalar signed INT32 to Single-FP conversion
		case STARS_NN_cvtss2si:            // Scalar Single-FP to signed INT32 conversion
		case STARS_NN_cvttps2pi:           // Packed Single-FP to Packed INT32 conversion (truncate)
		case STARS_NN_cvttss2si:           // Scalar Single-FP to signed INT32 conversion (truncate)
		case STARS_NN_divps:               // Packed Single-FP Divide
		case STARS_NN_divss:               // Scalar Single-FP Divide
		case STARS_NN_ldmxcsr:             // Load Streaming SIMD Extensions Technology Control/Status Register
		case STARS_NN_maxps:               // Packed Single-FP Maximum
		case STARS_NN_maxss:               // Scalar Single-FP Maximum
		case STARS_NN_minps:               // Packed Single-FP Minimum
		case STARS_NN_minss:               // Scalar Single-FP Minimum
		case STARS_NN_movaps:              // Move Aligned Four Packed Single-FP
		case STARS_NN_movhlps:             // Move High to Low Packed Single-FP
		case STARS_NN_movhps:              // Move High Packed Single-FP
		case STARS_NN_movlhps:             // Move Low to High Packed Single-FP
		case STARS_NN_movlps:              // Move Low Packed Single-FP
		case STARS_NN_movmskps:            // Move Mask to Register
		case STARS_NN_movss:               // Move Scalar Single-FP
		case STARS_NN_movups:              // Move Unaligned Four Packed Single-FP
		case STARS_NN_mulps:               // Packed Single-FP Multiply
		case STARS_NN_mulss:               // Scalar Single-FP Multiply
		case STARS_NN_orps:                // Bitwise Logical OR for Single-FP Data
		case STARS_NN_rcpps:               // Packed Single-FP Reciprocal
		case STARS_NN_rcpss:               // Scalar Single-FP Reciprocal
		case STARS_NN_rsqrtps:             // Packed Single-FP Square Root Reciprocal
		case STARS_NN_rsqrtss:             // Scalar Single-FP Square Root Reciprocal
		case STARS_NN_shufps:              // Shuffle Single-FP
		case STARS_NN_sqrtps:              // Packed Single-FP Square Root
		case STARS_NN_sqrtss:              // Scalar Single-FP Square Root
		case STARS_NN_stmxcsr:             // Store Streaming SIMD Extensions Technology Control/Status Register
		case STARS_NN_subps:               // Packed Single-FP Subtract
		case STARS_NN_subss:               // Scalar Single-FP Subtract
		case STARS_NN_ucomiss:             // Scalar Unordered Single-FP Compare and Set EFLAGS
		case STARS_NN_unpckhps:            // Unpack High Packed Single-FP Data
		case STARS_NN_unpcklps:            // Unpack Low Packed Single-FP Data
		case STARS_NN_xorps:               // Bitwise Logical XOR for Single-FP Data
		case STARS_NN_pavgb:               // Packed Average (Byte)
		case STARS_NN_pavgw:               // Packed Average (Word)
		case STARS_NN_pextrw:              // Extract Word
		case STARS_NN_pinsrw:              // Insert Word
		case STARS_NN_pmaxsw:              // Packed Signed Integer Word Maximum
		case STARS_NN_pmaxub:              // Packed Unsigned Integer Byte Maximum
		case STARS_NN_pminsw:              // Packed Signed Integer Word Minimum
		case STARS_NN_pminub:              // Packed Unsigned Integer Byte Minimum
		case STARS_NN_pmovmskb:            // Move Byte Mask to Integer
		case STARS_NN_pmulhuw:             // Packed Multiply High Unsigned
		case STARS_NN_psadbw:              // Packed Sum of Absolute Differences
		case STARS_NN_pshufw:              // Packed Shuffle Word
		case STARS_NN_maskmovq:            // Byte Mask write
		case STARS_NN_movntps:             // Move Aligned Four Packed Single-FP Non Temporal
		case STARS_NN_movntq:              // Move 64 Bits Non Temporal
		case STARS_NN_prefetcht0:          // Prefetch to all cache levels
		case STARS_NN_prefetcht1:          // Prefetch to all cache levels
		case STARS_NN_prefetcht2:          // Prefetch to L2 cache
		case STARS_NN_prefetchnta:         // Prefetch to L1 cache
		case STARS_NN_sfence:              // Store Fence
			SMP_fprintf(OutFile, "ERROR");
			break;

// Pentium III Pseudo instructions

		case STARS_NN_cmpeqps:             // Packed Single-FP Compare EQ
		case STARS_NN_cmpltps:             // Packed Single-FP Compare LT
		case STARS_NN_cmpleps:             // Packed Single-FP Compare LE
		case STARS_NN_cmpunordps:          // Packed Single-FP Compare UNORD
		case STARS_NN_cmpneqps:            // Packed Single-FP Compare NOT EQ
		case STARS_NN_cmpnltps:            // Packed Single-FP Compare NOT LT
		case STARS_NN_cmpnleps:            // Packed Single-FP Compare NOT LE
		case STARS_NN_cmpordps:            // Packed Single-FP Compare ORDERED
		case STARS_NN_cmpeqss:             // Scalar Single-FP Compare EQ
		case STARS_NN_cmpltss:             // Scalar Single-FP Compare LT
		case STARS_NN_cmpless:             // Scalar Single-FP Compare LE
		case STARS_NN_cmpunordss:          // Scalar Single-FP Compare UNORD
		case STARS_NN_cmpneqss:            // Scalar Single-FP Compare NOT EQ
		case STARS_NN_cmpnltss:            // Scalar Single-FP Compare NOT LT
		case STARS_NN_cmpnless:            // Scalar Single-FP Compare NOT LE
		case STARS_NN_cmpordss:            // Scalar Single-FP Compare ORDERED
			SMP_fprintf(OutFile, "ERROR");
			break;

// AMD K7 instructions

		case STARS_NN_pf2iw:               // Packed Floating-Point to Integer with Sign Extend
		case STARS_NN_pfnacc:              // Packed Floating-Point Negative Accumulate
		case STARS_NN_pfpnacc:             // Packed Floating-Point Mixed Positive-Negative Accumulate
		case STARS_NN_pi2fw:               // Packed 16-bit Integer to Floating-Point
		case STARS_NN_pswapd:              // Packed Swap Double Word
			SMP_fprintf(OutFile, "ERROR");
			break;

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

		case STARS_NN_fstp1:               // Alias of Store Real and Pop
		case STARS_NN_fcom2:               // Alias of Compare Real
		case STARS_NN_fcomp3:              // Alias of Compare Real and Pop
		case STARS_NN_fxch4:               // Alias of Exchange Registers
		case STARS_NN_fcomp5:              // Alias of Compare Real and Pop
		case STARS_NN_ffreep:              // Free Register and Pop
		case STARS_NN_fxch7:               // Alias of Exchange Registers
		case STARS_NN_fstp8:               // Alias of Store Real and Pop
		case STARS_NN_fstp9:               // Alias of Store Real and Pop
			SMP_fprintf(OutFile, "ERROR");
			break;

// Pentium 4 instructions

		case STARS_NN_addpd:               // Add Packed Double-Precision Floating-Point Values
		case STARS_NN_addsd:               // Add Scalar Double-Precision Floating-Point Values
		case STARS_NN_andnpd:              // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values
		case STARS_NN_andpd:               // Bitwise Logical AND of Packed Double-Precision Floating-Point Values
		case STARS_NN_clflush:             // Flush Cache Line
		case STARS_NN_cmppd:               // Compare Packed Double-Precision Floating-Point Values
		case STARS_NN_cmpsd:               // Compare Scalar Double-Precision Floating-Point Values
		case STARS_NN_comisd:              // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS
		case STARS_NN_cvtdq2pd:            // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values
		case STARS_NN_cvtdq2ps:            // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values
		case STARS_NN_cvtpd2dq:            // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case STARS_NN_cvtpd2pi:            // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case STARS_NN_cvtpd2ps:            // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values
		case STARS_NN_cvtpi2pd:            // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values
		case STARS_NN_cvtps2dq:            // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
		case STARS_NN_cvtps2pd:            // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values
		case STARS_NN_cvtsd2si:            // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer
		case STARS_NN_cvtsd2ss:            // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value
		case STARS_NN_cvtsi2sd:            // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value
		case STARS_NN_cvtss2sd:            // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value
		case STARS_NN_cvttpd2dq:           // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case STARS_NN_cvttpd2pi:           // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case STARS_NN_cvttps2dq:           // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
		case STARS_NN_cvttsd2si:           // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer
		case STARS_NN_divpd:               // Divide Packed Double-Precision Floating-Point Values
		case STARS_NN_divsd:               // Divide Scalar Double-Precision Floating-Point Values
		case STARS_NN_lfence:              // Load Fence
		case STARS_NN_maskmovdqu:          // Store Selected Bytes of Double Quadword
		case STARS_NN_maxpd:               // Return Maximum Packed Double-Precision Floating-Point Values
		case STARS_NN_maxsd:               // Return Maximum Scalar Double-Precision Floating-Point Value
		case STARS_NN_mfence:              // Memory Fence
		case STARS_NN_minpd:               // Return Minimum Packed Double-Precision Floating-Point Values
		case STARS_NN_minsd:               // Return Minimum Scalar Double-Precision Floating-Point Value
		case STARS_NN_movapd:              // Move Aligned Packed Double-Precision Floating-Point Values
		case STARS_NN_movdq2q:             // Move Quadword from XMM to MMX Register
		case STARS_NN_movdqa:              // Move Aligned Double Quadword
		case STARS_NN_movdqu:              // Move Unaligned Double Quadword
		case STARS_NN_movhpd:              // Move High Packed Double-Precision Floating-Point Values
		case STARS_NN_movlpd:              // Move Low Packed Double-Precision Floating-Point Values
		case STARS_NN_movmskpd:            // Extract Packed Double-Precision Floating-Point Sign Mask
		case STARS_NN_movntdq:             // Store Double Quadword Using Non-Temporal Hint
		case STARS_NN_movnti:              // Store Doubleword Using Non-Temporal Hint
		case STARS_NN_movntpd:             // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint
		case STARS_NN_movq2dq:             // Move Quadword from MMX to XMM Register
		case STARS_NN_movsd:               // Move Scalar Double-Precision Floating-Point Values
		case STARS_NN_movupd:              // Move Unaligned Packed Double-Precision Floating-Point Values
		case STARS_NN_mulpd:               // Multiply Packed Double-Precision Floating-Point Values
		case STARS_NN_mulsd:               // Multiply Scalar Double-Precision Floating-Point Values
		case STARS_NN_orpd:                // Bitwise Logical OR of Double-Precision Floating-Point Values
		case STARS_NN_paddq:               // Add Packed Quadword Integers
		case STARS_NN_pause:               // Spin Loop Hint
		case STARS_NN_pmuludq:             // Multiply Packed Unsigned Doubleword Integers
		case STARS_NN_pshufd:              // Shuffle Packed Doublewords
		case STARS_NN_pshufhw:             // Shuffle Packed High Words
		case STARS_NN_pshuflw:             // Shuffle Packed Low Words
		case STARS_NN_pslldq:              // Shift Double Quadword Left Logical
		case STARS_NN_psrldq:              // Shift Double Quadword Right Logical
		case STARS_NN_psubq:               // Subtract Packed Quadword Integers
		case STARS_NN_punpckhqdq:          // Unpack High Data
		case STARS_NN_punpcklqdq:          // Unpack Low Data
		case STARS_NN_shufpd:              // Shuffle Packed Double-Precision Floating-Point Values
		case STARS_NN_sqrtpd:              // Compute Square Roots of Packed Double-Precision Floating-Point Values
		case STARS_NN_sqrtsd:              // Compute Square Rootof Scalar Double-Precision Floating-Point Value
		case STARS_NN_subpd:               // Subtract Packed Double-Precision Floating-Point Values
		case STARS_NN_subsd:               // Subtract Scalar Double-Precision Floating-Point Values
		case STARS_NN_ucomisd:             // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS
		case STARS_NN_unpckhpd:            // Unpack and Interleave High Packed Double-Precision Floating-Point Values
		case STARS_NN_unpcklpd:            // Unpack and Interleave Low Packed Double-Precision Floating-Point Values
		case STARS_NN_xorpd:               // Bitwise Logical OR of Double-Precision Floating-Point Values
			SMP_fprintf(OutFile, "ERROR");
			break;

// AMD syscall/sysret instructions

		case STARS_NN_syscall:             // Low latency system call
		case STARS_NN_sysret:              // Return from system call
			SMP_fprintf(OutFile, "ERROR");
			break;

// AMD64 instructions

		case STARS_NN_swapgs:              // Exchange GS base with KernelGSBase MSR
			SMP_fprintf(OutFile, "ERROR");
			break;

// New Pentium instructions (SSE3)

		case STARS_NN_movddup:             // Move One Double-FP and Duplicate
		case STARS_NN_movshdup:            // Move Packed Single-FP High and Duplicate
		case STARS_NN_movsldup:            // Move Packed Single-FP Low and Duplicate
			SMP_fprintf(OutFile, "ERROR");
			break;

// Missing AMD64 instructions

		case STARS_NN_movsxd:              // Move with Sign-Extend Doubleword
		case STARS_NN_cmpxchg16b:          // Compare and Exchange 16 Bytes
			SMP_fprintf(OutFile, "ERROR");
			break;

// SSE3 instructions

		case STARS_NN_addsubpd:            // Add /Sub packed DP FP numbers
		case STARS_NN_addsubps:            // Add /Sub packed SP FP numbers
		case STARS_NN_haddpd:              // Add horizontally packed DP FP numbers
		case STARS_NN_haddps:              // Add horizontally packed SP FP numbers
		case STARS_NN_hsubpd:              // Sub horizontally packed DP FP numbers
		case STARS_NN_hsubps:              // Sub horizontally packed SP FP numbers
		case STARS_NN_monitor:             // Set up a linear address range to be monitored by hardware
		case STARS_NN_mwait:               // Wait until write-back store performed within the range specified by the MONITOR instruction
		case STARS_NN_fisttp:              // Store ST in intXX (chop) and pop
		case STARS_NN_lddqu:               // Load unaligned integer 128-bit
			SMP_fprintf(OutFile, "ERROR");
			break;

// SSSE3 instructions

		case STARS_NN_psignb:              // Packed SIGN Byte
		case STARS_NN_psignw:              // Packed SIGN Word
		case STARS_NN_psignd:              // Packed SIGN Doubleword
		case STARS_NN_pshufb:              // Packed Shuffle Bytes
		case STARS_NN_pmulhrsw:            // Packed Multiply High with Round and Scale
		case STARS_NN_pmaddubsw:           // Multiply and Add Packed Signed and Unsigned Bytes
		case STARS_NN_phsubsw:             // Packed Horizontal Subtract and Saturate
		case STARS_NN_phaddsw:             // Packed Horizontal Add and Saturate
		case STARS_NN_phaddw:              // Packed Horizontal Add Word
		case STARS_NN_phaddd:              // Packed Horizontal Add Doubleword
		case STARS_NN_phsubw:              // Packed Horizontal Subtract Word
		case STARS_NN_phsubd:              // Packed Horizontal Subtract Doubleword
		case STARS_NN_palignr:             // Packed Align Right
		case STARS_NN_pabsb:               // Packed Absolute Value Byte
		case STARS_NN_pabsw:               // Packed Absolute Value Word
		case STARS_NN_pabsd:               // Packed Absolute Value Doubleword
			SMP_fprintf(OutFile, "ERROR");
			break;

// VMX instructions

		case STARS_NN_vmcall:              // Call to VM Monitor
		case STARS_NN_vmclear:             // Clear Virtual Machine Control Structure
		case STARS_NN_vmlaunch:            // Launch Virtual Machine
		case STARS_NN_vmresume:            // Resume Virtual Machine
		case STARS_NN_vmptrld:             // Load Pointer to Virtual Machine Control Structure
		case STARS_NN_vmptrst:             // Store Pointer to Virtual Machine Control Structure
		case STARS_NN_vmread:              // Read Field from Virtual Machine Control Structure
		case STARS_NN_vmwrite:             // Write Field from Virtual Machine Control Structure
		case STARS_NN_vmxoff:              // Leave VMX Operation
		case STARS_NN_vmxon:               // Enter VMX Operation
			SMP_fprintf(OutFile, "ERROR");
			break;

// Undefined Instruction

		case STARS_NN_ud2:                 // Undefined Instruction
			SMP_fprintf(OutFile, "ERROR");
			break;

// Added with x86-64

		case STARS_NN_rdtscp:              // Read Time-Stamp Counter and Processor ID
			SMP_fprintf(OutFile, "ERROR");
			break;

// Geode LX 3DNow! extensions

		case STARS_NN_pfrcpv:              // Reciprocal Approximation for a Pair of 32-bit Floats
		case STARS_NN_pfrsqrtv:            // Reciprocal Square Root Approximation for a Pair of 32-bit Floats
			SMP_fprintf(OutFile, "ERROR");
			break;

// SSE2 pseudoinstructions

		case STARS_NN_cmpeqpd:             // Packed Double-FP Compare EQ
		case STARS_NN_cmpltpd:             // Packed Double-FP Compare LT
		case STARS_NN_cmplepd:             // Packed Double-FP Compare LE
		case STARS_NN_cmpunordpd:          // Packed Double-FP Compare UNORD
		case STARS_NN_cmpneqpd:            // Packed Double-FP Compare NOT EQ
		case STARS_NN_cmpnltpd:            // Packed Double-FP Compare NOT LT
		case STARS_NN_cmpnlepd:            // Packed Double-FP Compare NOT LE
		case STARS_NN_cmpordpd:            // Packed Double-FP Compare ORDERED
		case STARS_NN_cmpeqsd:             // Scalar Double-FP Compare EQ
		case STARS_NN_cmpltsd:             // Scalar Double-FP Compare LT
		case STARS_NN_cmplesd:             // Scalar Double-FP Compare LE
		case STARS_NN_cmpunordsd:          // Scalar Double-FP Compare UNORD
		case STARS_NN_cmpneqsd:            // Scalar Double-FP Compare NOT EQ
		case STARS_NN_cmpnltsd:            // Scalar Double-FP Compare NOT LT
		case STARS_NN_cmpnlesd:            // Scalar Double-FP Compare NOT LE
		case STARS_NN_cmpordsd:            // Scalar Double-FP Compare ORDERED
			SMP_fprintf(OutFile, "ERROR");
			break;

// SSSE4.1 instructions

		case STARS_NN_blendpd:              // Blend Packed Double Precision Floating-Point Values
		case STARS_NN_blendps:              // Blend Packed Single Precision Floating-Point Values
		case STARS_NN_blendvpd:             // Variable Blend Packed Double Precision Floating-Point Values
		case STARS_NN_blendvps:             // Variable Blend Packed Single Precision Floating-Point Values
		case STARS_NN_dppd:                 // Dot Product of Packed Double Precision Floating-Point Values
		case STARS_NN_dpps:                 // Dot Product of Packed Single Precision Floating-Point Values
		case STARS_NN_extractps:            // Extract Packed Single Precision Floating-Point Value
		case STARS_NN_insertps:             // Insert Packed Single Precision Floating-Point Value
		case STARS_NN_movntdqa:             // Load Double Quadword Non-Temporal Aligned Hint
		case STARS_NN_mpsadbw:              // Compute Multiple Packed Sums of Absolute Difference
		case STARS_NN_packusdw:             // Pack with Unsigned Saturation
		case STARS_NN_pblendvb:             // Variable Blend Packed Bytes
		case STARS_NN_pblendw:              // Blend Packed Words
		case STARS_NN_pcmpeqq:              // Compare Packed Qword Data for Equal
		case STARS_NN_pextrb:               // Extract Byte
		case STARS_NN_pextrd:               // Extract Dword
		case STARS_NN_pextrq:               // Extract Qword
		case STARS_NN_phminposuw:           // Packed Horizontal Word Minimum
		case STARS_NN_pinsrb:               // Insert Byte
		case STARS_NN_pinsrd:               // Insert Dword
		case STARS_NN_pinsrq:               // Insert Qword
		case STARS_NN_pmaxsb:               // Maximum of Packed Signed Byte Integers
		case STARS_NN_pmaxsd:               // Maximum of Packed Signed Dword Integers
		case STARS_NN_pmaxud:               // Maximum of Packed Unsigned Dword Integers
		case STARS_NN_pmaxuw:               // Maximum of Packed Word Integers
		case STARS_NN_pminsb:               // Minimum of Packed Signed Byte Integers
		case STARS_NN_pminsd:               // Minimum of Packed Signed Dword Integers
		case STARS_NN_pminud:               // Minimum of Packed Unsigned Dword Integers
		case STARS_NN_pminuw:               // Minimum of Packed Word Integers
		case STARS_NN_pmovsxbw:             // Packed Move with Sign Extend
		case STARS_NN_pmovsxbd:             // Packed Move with Sign Extend
		case STARS_NN_pmovsxbq:             // Packed Move with Sign Extend
		case STARS_NN_pmovsxwd:             // Packed Move with Sign Extend
		case STARS_NN_pmovsxwq:             // Packed Move with Sign Extend
		case STARS_NN_pmovsxdq:             // Packed Move with Sign Extend
		case STARS_NN_pmovzxbw:             // Packed Move with Zero Extend
		case STARS_NN_pmovzxbd:             // Packed Move with Zero Extend
		case STARS_NN_pmovzxbq:             // Packed Move with Zero Extend
		case STARS_NN_pmovzxwd:             // Packed Move with Zero Extend
		case STARS_NN_pmovzxwq:             // Packed Move with Zero Extend
		case STARS_NN_pmovzxdq:             // Packed Move with Zero Extend
		case STARS_NN_pmuldq:               // Multiply Packed Signed Dword Integers
		case STARS_NN_pmulld:               // Multiply Packed Signed Dword Integers and Store Low Result
		case STARS_NN_ptest:                // Logical Compare
		case STARS_NN_roundpd:              // Round Packed Double Precision Floating-Point Values
		case STARS_NN_roundps:              // Round Packed Single Precision Floating-Point Values
		case STARS_NN_roundsd:              // Round Scalar Double Precision Floating-Point Values
		case STARS_NN_roundss:              // Round Scalar Single Precision Floating-Point Values
			SMP_fprintf(OutFile, "ERROR");
			break;

// SSSE4.2 instructions

		case STARS_NN_crc32:                // Accumulate CRC32 Value
		case STARS_NN_pcmpestri:            // Packed Compare Explicit Length Strings: Return Index
		case STARS_NN_pcmpestrm:            // Packed Compare Explicit Length Strings: Return Mask
		case STARS_NN_pcmpistri:            // Packed Compare Implicit Length Strings: Return Index
		case STARS_NN_pcmpistrm:            // Packed Compare Implicit Length Strings: Return Mask
		case STARS_NN_pcmpgtq:              // Compare Packed Data for Greater Than
		case STARS_NN_popcnt:               // Return the Count of Number of Bits Set to 1
			SMP_fprintf(OutFile, "ERROR");
			break;

// AMD SSE4a instructions

		case STARS_NN_extrq:                // Extract Field From Register
		case STARS_NN_insertq:              // Insert Field
		case STARS_NN_movntsd:              // Move Non-Temporal Scalar Double-Precision Floating-Point
		case STARS_NN_movntss:              // Move Non-Temporal Scalar Single-Precision Floating-Point
		case STARS_NN_lzcnt:                // Leading Zero Count
			SMP_fprintf(OutFile, "ERROR");
			break;

// xsave/xrstor instructions

		case STARS_NN_xgetbv:               // Get Value of Extended Control Register
		case STARS_NN_xrstor:               // Restore Processor Extended States
		case STARS_NN_xsave:                // Save Processor Extended States
		case STARS_NN_xsetbv:               // Set Value of Extended Control Register
			SMP_fprintf(OutFile, "ERROR");
			break;

// Intel Safer Mode Extensions (SMX)

		case STARS_NN_getsec:               // Safer Mode Extensions (SMX) Instruction
			SMP_fprintf(OutFile, "ERROR");
			break;

// AMD-V Virtualization ISA Extension

		case STARS_NN_clgi:                 // Clear Global Interrupt Flag
		case STARS_NN_invlpga:              // Invalidate TLB Entry in a Specified ASID
		case STARS_NN_skinit:               // Secure Init and Jump with Attestation
		case STARS_NN_stgi:                 // Set Global Interrupt Flag
		case STARS_NN_vmexit:               // Stop Executing Guest: Begin Executing Host
		case STARS_NN_vmload:               // Load State from VMCB
		case STARS_NN_vmmcall:              // Call VMM
		case STARS_NN_vmrun:                // Run Virtual Machine
		case STARS_NN_vmsave:               // Save State to VMCB
			SMP_fprintf(OutFile, "ERROR");
			break;

// VMX+ instructions

		case STARS_NN_invept:               // Invalidate Translations Derived from EPT
		case STARS_NN_invvpid:              // Invalidate Translations Based on VPID
			SMP_fprintf(OutFile, "ERROR");
			break;

// Intel Atom instructions

		case STARS_NN_movbe:                // Move Data After Swapping Bytes
			SMP_fprintf(OutFile, "ERROR");
			break;

// Intel AES instructions

		case STARS_NN_aesenc:                // Perform One Round of an AES Encryption Flow
		case STARS_NN_aesenclast:            // Perform the Last Round of an AES Encryption Flow
		case STARS_NN_aesdec:                // Perform One Round of an AES Decryption Flow
		case STARS_NN_aesdeclast:            // Perform the Last Round of an AES Decryption Flow
		case STARS_NN_aesimc:                // Perform the AES InvMixColumn Transformation
		case STARS_NN_aeskeygenassist:       // AES Round Key Generation Assist
			SMP_fprintf(OutFile, "ERROR");
			break;

// Carryless multiplication

		case STARS_NN_pclmulqdq:            // Carry-Less Multiplication Quadword
			SMP_fprintf(OutFile, "ERROR");
			break;

// Returns modifies by operand size prefixes

		case STARS_NN_retnw:               // Return Near from Procedure (use16)
		case STARS_NN_retnd:               // Return Near from Procedure (use32)
		case STARS_NN_retnq:               // Return Near from Procedure (use64)
		case STARS_NN_retfw:               // Return Far from Procedure (use16)
		case STARS_NN_retfd:               // Return Far from Procedure (use32)
		case STARS_NN_retfq:               // Return Far from Procedure (use64)
			SMP_fprintf(OutFile, "return");
			break;

// RDRAND support

		case STARS_NN_rdrand:              // Read Random Number
			SMP_fprintf(OutFile, "ERROR");
			break;

// new GPR instructions

		case STARS_NN_adcx:                 // Unsigned Integer Addition of Two Operands with Carry Flag
		case STARS_NN_adox:                 // Unsigned Integer Addition of Two Operands with Overflow Flag
		case STARS_NN_andn:                 // Logical AND NOT
		case STARS_NN_bextr:                // Bit Field Extract
		case STARS_NN_blsi:                 // Extract Lowest Set Isolated Bit
		case STARS_NN_blsmsk:               // Get Mask Up to Lowest Set Bit
		case STARS_NN_blsr:                 // Reset Lowest Set Bit
		case STARS_NN_bzhi:                 // Zero High Bits Starting with Specified Bit Position
		case STARS_NN_clac:                 // Clear AC Flag in EFLAGS Register
		case STARS_NN_mulx:                 // Unsigned Multiply Without Affecting Flags
		case STARS_NN_pdep:                 // Parallel Bits Deposit
		case STARS_NN_pext:                 // Parallel Bits Extract
		case STARS_NN_rorx:                 // Rotate Right Logical Without Affecting Flags
		case STARS_NN_sarx:                 // Shift Arithmetically Right Without Affecting Flags
		case STARS_NN_shlx:                 // Shift Logically Left Without Affecting Flags
		case STARS_NN_shrx:                 // Shift Logically Right Without Affecting Flags
		case STARS_NN_stac:                 // Set AC Flag in EFLAGS Register
		case STARS_NN_tzcnt:                // Count the Number of Trailing Zero Bits
		case STARS_NN_xsaveopt:             // Save Processor Extended States Optimized
		case STARS_NN_invpcid:              // Invalidate Processor Context ID
		case STARS_NN_rdseed:               // Read Random Seed
		case STARS_NN_rdfsbase:             // Read FS Segment Base
		case STARS_NN_rdgsbase:             // Read GS Segment Base
		case STARS_NN_wrfsbase:             // Write FS Segment Base
		case STARS_NN_wrgsbase:             // Write GS Segment Base
			SMP_fprintf(OutFile, "ERROR");
			break;

// new AVX instructions
		case STARS_NN_vaddpd:               // Add Packed Double-Precision Floating-Point Values
		case STARS_NN_vaddps:               // Packed Single-FP Add
		case STARS_NN_vaddsd:               // Add Scalar Double-Precision Floating-Point Values
		case STARS_NN_vaddss:               // Scalar Single-FP Add
		case STARS_NN_vaddsubpd:            // Add /Sub packed DP FP numbers
		case STARS_NN_vaddsubps:            // Add /Sub packed SP FP numbers
		case STARS_NN_vaesdec:              // Perform One Round of an AES Decryption Flow
		case STARS_NN_vaesdeclast:          // Perform the Last Round of an AES Decryption Flow
		case STARS_NN_vaesenc:              // Perform One Round of an AES Encryption Flow
		case STARS_NN_vaesenclast:          // Perform the Last Round of an AES Encryption Flow
		case STARS_NN_vaesimc:              // Perform the AES InvMixColumn Transformation
		case STARS_NN_vaeskeygenassist:     // AES Round Key Generation Assist
		case STARS_NN_vandnpd:              // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values
		case STARS_NN_vandnps:              // Bitwise Logical And Not for Single-FP
		case STARS_NN_vandpd:               // Bitwise Logical AND of Packed Double-Precision Floating-Point Values
		case STARS_NN_vandps:               // Bitwise Logical And for Single-FP
		case STARS_NN_vblendpd:             // Blend Packed Double Precision Floating-Point Values
		case STARS_NN_vblendps:             // Blend Packed Single Precision Floating-Point Values
		case STARS_NN_vblendvpd:            // Variable Blend Packed Double Precision Floating-Point Values
		case STARS_NN_vblendvps:            // Variable Blend Packed Single Precision Floating-Point Values
		case STARS_NN_vbroadcastf128:       // Broadcast 128 Bits of Floating-Point Data
		case STARS_NN_vbroadcasti128:       // Broadcast 128 Bits of Integer Data
		case STARS_NN_vbroadcastsd:         // Broadcast Double-Precision Floating-Point Element
		case STARS_NN_vbroadcastss:         // Broadcast Single-Precision Floating-Point Element
		case STARS_NN_vcmppd:               // Compare Packed Double-Precision Floating-Point Values
		case STARS_NN_vcmpps:               // Packed Single-FP Compare
		case STARS_NN_vcmpsd:               // Compare Scalar Double-Precision Floating-Point Values
		case STARS_NN_vcmpss:               // Scalar Single-FP Compare
		case STARS_NN_vcomisd:              // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS
		case STARS_NN_vcomiss:              // Scalar Ordered Single-FP Compare and Set EFLAGS
		case STARS_NN_vcvtdq2pd:            // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values
		case STARS_NN_vcvtdq2ps:            // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values
		case STARS_NN_vcvtpd2dq:            // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case STARS_NN_vcvtpd2ps:            // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values
		case STARS_NN_vcvtph2ps:            // Convert 16-bit FP Values to Single-Precision FP Values
		case STARS_NN_vcvtps2dq:            // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
		case STARS_NN_vcvtps2pd:            // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values
		case STARS_NN_vcvtps2ph:            // Convert Single-Precision FP value to 16-bit FP value
		case STARS_NN_vcvtsd2si:            // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer
		case STARS_NN_vcvtsd2ss:            // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value
		case STARS_NN_vcvtsi2sd:            // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value
		case STARS_NN_vcvtsi2ss:            // Scalar signed INT32 to Single-FP conversion
		case STARS_NN_vcvtss2sd:            // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value
		case STARS_NN_vcvtss2si:            // Scalar Single-FP to signed INT32 conversion
		case STARS_NN_vcvttpd2dq:           // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case STARS_NN_vcvttps2dq:           // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
		case STARS_NN_vcvttsd2si:           // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer
		case STARS_NN_vcvttss2si:           // Scalar Single-FP to signed INT32 conversion (truncate)
		case STARS_NN_vdivpd:               // Divide Packed Double-Precision Floating-Point Values
		case STARS_NN_vdivps:               // Packed Single-FP Divide
		case STARS_NN_vdivsd:               // Divide Scalar Double-Precision Floating-Point Values
		case STARS_NN_vdivss:               // Scalar Single-FP Divide
		case STARS_NN_vdppd:                // Dot Product of Packed Double Precision Floating-Point Values
		case STARS_NN_vdpps:                // Dot Product of Packed Single Precision Floating-Point Values
		case STARS_NN_vextractf128:         // Extract Packed Floating-Point Values
		case STARS_NN_vextracti128:         // Extract Packed Integer Values
		case STARS_NN_vextractps:           // Extract Packed Floating-Point Values
		case STARS_NN_vfmadd132pd:          // Fused Multiply-Add of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmadd132ps:          // Fused Multiply-Add of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfmadd132sd:          // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfmadd132ss:          // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vfmadd213pd:          // Fused Multiply-Add of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmadd213ps:          // Fused Multiply-Add of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfmadd213sd:          // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfmadd213ss:          // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vfmadd231pd:          // Fused Multiply-Add of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmadd231ps:          // Fused Multiply-Add of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfmadd231sd:          // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfmadd231ss:          // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vfmaddsub132pd:       // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmaddsub132ps:       // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfmaddsub213pd:       // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmaddsub213ps:       // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfmaddsub231pd:       // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmaddsub231ps:       // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfmsub132pd:          // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmsub132ps:          // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfmsub132sd:          // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfmsub132ss:          // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vfmsub213pd:          // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmsub213ps:          // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfmsub213sd:          // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfmsub213ss:          // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vfmsub231pd:          // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmsub231ps:          // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfmsub231sd:          // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfmsub231ss:          // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vfmsubadd132pd:       // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmsubadd132ps:       // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfmsubadd213pd:       // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmsubadd213ps:       // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfmsubadd231pd:       // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfmsubadd231ps:       // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfnmadd132pd:         // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfnmadd132ps:         // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfnmadd132sd:         // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfnmadd132ss:         // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vfnmadd213pd:         // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfnmadd213ps:         // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfnmadd213sd:         // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfnmadd213ss:         // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vfnmadd231pd:         // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfnmadd231ps:         // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfnmadd231sd:         // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfnmadd231ss:         // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vfnmsub132pd:         // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfnmsub132ps:         // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfnmsub132sd:         // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfnmsub132ss:         // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vfnmsub213pd:         // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfnmsub213ps:         // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfnmsub213sd:         // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfnmsub213ss:         // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vfnmsub231pd:         // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case STARS_NN_vfnmsub231ps:         // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case STARS_NN_vfnmsub231sd:         // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case STARS_NN_vfnmsub231ss:         // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values
		case STARS_NN_vgatherdps:           // Gather Packed SP FP Values Using Signed Dword Indices
		case STARS_NN_vgatherdpd:           // Gather Packed DP FP Values Using Signed Dword Indices
		case STARS_NN_vgatherqps:           // Gather Packed SP FP Values Using Signed Qword Indices
		case STARS_NN_vgatherqpd:           // Gather Packed DP FP Values Using Signed Qword Indices
		case STARS_NN_vhaddpd:              // Add horizontally packed DP FP numbers
		case STARS_NN_vhaddps:              // Add horizontally packed SP FP numbers
		case STARS_NN_vhsubpd:              // Sub horizontally packed DP FP numbers
		case STARS_NN_vhsubps:              // Sub horizontally packed SP FP numbers
		case STARS_NN_vinsertf128:          // Insert Packed Floating-Point Values
		case STARS_NN_vinserti128:          // Insert Packed Integer Values
		case STARS_NN_vinsertps:            // Insert Packed Single Precision Floating-Point Value
		case STARS_NN_vlddqu:               // Load Unaligned Packed Integer Values
		case STARS_NN_vldmxcsr:             // Load Streaming SIMD Extensions Technology Control/Status Register
		case STARS_NN_vmaskmovdqu:          // Store Selected Bytes of Double Quadword with NT Hint
		case STARS_NN_vmaskmovpd:           // Conditionally Load Packed Double-Precision Floating-Point Values
		case STARS_NN_vmaskmovps:           // Conditionally Load Packed Single-Precision Floating-Point Values
		case STARS_NN_vmaxpd:               // Return Maximum Packed Double-Precision Floating-Point Values
		case STARS_NN_vmaxps:               // Packed Single-FP Maximum
		case STARS_NN_vmaxsd:               // Return Maximum Scalar Double-Precision Floating-Point Value
		case STARS_NN_vmaxss:               // Scalar Single-FP Maximum
		case STARS_NN_vminpd:               // Return Minimum Packed Double-Precision Floating-Point Values
		case STARS_NN_vminps:               // Packed Single-FP Minimum
		case STARS_NN_vminsd:               // Return Minimum Scalar Double-Precision Floating-Point Value
		case STARS_NN_vminss:               // Scalar Single-FP Minimum
		case STARS_NN_vmovapd:              // Move Aligned Packed Double-Precision Floating-Point Values
		case STARS_NN_vmovaps:              // Move Aligned Four Packed Single-FP
		case STARS_NN_vmovd:                // Move 32 bits
		case STARS_NN_vmovddup:             // Move One Double-FP and Duplicate
		case STARS_NN_vmovdqa:              // Move Aligned Double Quadword
		case STARS_NN_vmovdqu:              // Move Unaligned Double Quadword
		case STARS_NN_vmovhlps:             // Move High to Low Packed Single-FP
		case STARS_NN_vmovhpd:              // Move High Packed Double-Precision Floating-Point Values
		case STARS_NN_vmovhps:              // Move High Packed Single-FP
		case STARS_NN_vmovlhps:             // Move Low to High Packed Single-FP
		case STARS_NN_vmovlpd:              // Move Low Packed Double-Precision Floating-Point Values
		case STARS_NN_vmovlps:              // Move Low Packed Single-FP
		case STARS_NN_vmovmskpd:            // Extract Packed Double-Precision Floating-Point Sign Mask
		case STARS_NN_vmovmskps:            // Move Mask to Register
		case STARS_NN_vmovntdq:             // Store Double Quadword Using Non-Temporal Hint
		case STARS_NN_vmovntdqa:            // Load Double Quadword Non-Temporal Aligned Hint
		case STARS_NN_vmovntpd:             // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint
		case STARS_NN_vmovntps:             // Move Aligned Four Packed Single-FP Non Temporal
#if (IDA_SDK_VERSION < 700)      // Incredibly, these opcodes were removed in IDA Pro 7.0
		case STARS_NN_vmovntsd:             // Move Non-Temporal Scalar Double-Precision Floating-Point
		case STARS_NN_vmovntss:             // Move Non-Temporal Scalar Single-Precision Floating-Point
#endif
		case STARS_NN_vmovq:                // Move 64 bits
		case STARS_NN_vmovsd:               // Move Scalar Double-Precision Floating-Point Values
		case STARS_NN_vmovshdup:            // Move Packed Single-FP High and Duplicate
		case STARS_NN_vmovsldup:            // Move Packed Single-FP Low and Duplicate
		case STARS_NN_vmovss:               // Move Scalar Single-FP
		case STARS_NN_vmovupd:              // Move Unaligned Packed Double-Precision Floating-Point Values
		case STARS_NN_vmovups:              // Move Unaligned Four Packed Single-FP
		case STARS_NN_vmpsadbw:             // Compute Multiple Packed Sums of Absolute Difference
		case STARS_NN_vmulpd:               // Multiply Packed Double-Precision Floating-Point Values
		case STARS_NN_vmulps:               // Packed Single-FP Multiply
		case STARS_NN_vmulsd:               // Multiply Scalar Double-Precision Floating-Point Values
		case STARS_NN_vmulss:               // Scalar Single-FP Multiply
		case STARS_NN_vorpd:                // Bitwise Logical OR of Double-Precision Floating-Point Values
		case STARS_NN_vorps:                // Bitwise Logical OR for Single-FP Data
		case STARS_NN_vpabsb:               // Packed Absolute Value Byte
		case STARS_NN_vpabsd:               // Packed Absolute Value Doubleword
		case STARS_NN_vpabsw:               // Packed Absolute Value Word
		case STARS_NN_vpackssdw:            // Pack with Signed Saturation (Dword->Word)
		case STARS_NN_vpacksswb:            // Pack with Signed Saturation (Word->Byte)
		case STARS_NN_vpackusdw:            // Pack with Unsigned Saturation
		case STARS_NN_vpackuswb:            // Pack with Unsigned Saturation (Word->Byte)
		case STARS_NN_vpaddb:               // Packed Add Byte
		case STARS_NN_vpaddd:               // Packed Add Dword
		case STARS_NN_vpaddq:               // Add Packed Quadword Integers
		case STARS_NN_vpaddsb:              // Packed Add with Saturation (Byte)
		case STARS_NN_vpaddsw:              // Packed Add with Saturation (Word)
		case STARS_NN_vpaddusb:             // Packed Add Unsigned with Saturation (Byte)
		case STARS_NN_vpaddusw:             // Packed Add Unsigned with Saturation (Word)
		case STARS_NN_vpaddw:               // Packed Add Word
		case STARS_NN_vpalignr:             // Packed Align Right
		case STARS_NN_vpand:                // Bitwise Logical And
		case STARS_NN_vpandn:               // Bitwise Logical And Not
		case STARS_NN_vpavgb:               // Packed Average (Byte)
		case STARS_NN_vpavgw:               // Packed Average (Word)
		case STARS_NN_vpblendd:             // Blend Packed Dwords
		case STARS_NN_vpblendvb:            // Variable Blend Packed Bytes
		case STARS_NN_vpblendw:             // Blend Packed Words
		case STARS_NN_vpbroadcastb:         // Broadcast a Byte Integer
		case STARS_NN_vpbroadcastd:         // Broadcast a Dword Integer
		case STARS_NN_vpbroadcastq:         // Broadcast a Qword Integer
		case STARS_NN_vpbroadcastw:         // Broadcast a Word Integer
		case STARS_NN_vpclmulqdq:           // Carry-Less Multiplication Quadword
		case STARS_NN_vpcmpeqb:             // Packed Compare for Equal (Byte)
		case STARS_NN_vpcmpeqd:             // Packed Compare for Equal (Dword)
		case STARS_NN_vpcmpeqq:             // Compare Packed Qword Data for Equal
		case STARS_NN_vpcmpeqw:             // Packed Compare for Equal (Word)
		case STARS_NN_vpcmpestri:           // Packed Compare Explicit Length Strings: Return Index
		case STARS_NN_vpcmpestrm:           // Packed Compare Explicit Length Strings: Return Mask
		case STARS_NN_vpcmpgtb:             // Packed Compare for Greater Than (Byte)
		case STARS_NN_vpcmpgtd:             // Packed Compare for Greater Than (Dword)
		case STARS_NN_vpcmpgtq:             // Compare Packed Data for Greater Than
		case STARS_NN_vpcmpgtw:             // Packed Compare for Greater Than (Word)
		case STARS_NN_vpcmpistri:           // Packed Compare Implicit Length Strings: Return Index
		case STARS_NN_vpcmpistrm:           // Packed Compare Implicit Length Strings: Return Mask
		case STARS_NN_vperm2f128:           // Permute Floating-Point Values
		case STARS_NN_vperm2i128:           // Permute Integer Values
		case STARS_NN_vpermd:               // Full Doublewords Element Permutation
		case STARS_NN_vpermilpd:            // Permute Double-Precision Floating-Point Values
		case STARS_NN_vpermilps:            // Permute Single-Precision Floating-Point Values
		case STARS_NN_vpermpd:              // Permute Double-Precision Floating-Point Elements
		case STARS_NN_vpermps:              // Permute Single-Precision Floating-Point Elements
		case STARS_NN_vpermq:               // Qwords Element Permutation
		case STARS_NN_vpextrb:              // Extract Byte
		case STARS_NN_vpextrd:              // Extract Dword
		case STARS_NN_vpextrq:              // Extract Qword
		case STARS_NN_vpextrw:              // Extract Word
		case STARS_NN_vpgatherdd:           // Gather Packed Dword Values Using Signed Dword Indices
		case STARS_NN_vpgatherdq:           // Gather Packed Qword Values Using Signed Dword Indices
		case STARS_NN_vpgatherqd:           // Gather Packed Dword Values Using Signed Qword Indices
		case STARS_NN_vpgatherqq:           // Gather Packed Qword Values Using Signed Qword Indices
		case STARS_NN_vphaddd:              // Packed Horizontal Add Doubleword
		case STARS_NN_vphaddsw:             // Packed Horizontal Add and Saturate
		case STARS_NN_vphaddw:              // Packed Horizontal Add Word
		case STARS_NN_vphminposuw:          // Packed Horizontal Word Minimum
		case STARS_NN_vphsubd:              // Packed Horizontal Subtract Doubleword
		case STARS_NN_vphsubsw:             // Packed Horizontal Subtract and Saturate
		case STARS_NN_vphsubw:              // Packed Horizontal Subtract Word
		case STARS_NN_vpinsrb:              // Insert Byte
		case STARS_NN_vpinsrd:              // Insert Dword
		case STARS_NN_vpinsrq:              // Insert Qword
		case STARS_NN_vpinsrw:              // Insert Word
		case STARS_NN_vpmaddubsw:           // Multiply and Add Packed Signed and Unsigned Bytes
		case STARS_NN_vpmaddwd:             // Packed Multiply and Add
		case STARS_NN_vpmaskmovd:           // Conditionally Store Dword Values Using Mask
		case STARS_NN_vpmaskmovq:           // Conditionally Store Qword Values Using Mask
		case STARS_NN_vpmaxsb:              // Maximum of Packed Signed Byte Integers
		case STARS_NN_vpmaxsd:              // Maximum of Packed Signed Dword Integers
		case STARS_NN_vpmaxsw:              // Packed Signed Integer Word Maximum
		case STARS_NN_vpmaxub:              // Packed Unsigned Integer Byte Maximum
		case STARS_NN_vpmaxud:              // Maximum of Packed Unsigned Dword Integers
		case STARS_NN_vpmaxuw:              // Maximum of Packed Word Integers
		case STARS_NN_vpminsb:              // Minimum of Packed Signed Byte Integers
		case STARS_NN_vpminsd:              // Minimum of Packed Signed Dword Integers
		case STARS_NN_vpminsw:              // Packed Signed Integer Word Minimum
		case STARS_NN_vpminub:              // Packed Unsigned Integer Byte Minimum
		case STARS_NN_vpminud:              // Minimum of Packed Unsigned Dword Integers
		case STARS_NN_vpminuw:              // Minimum of Packed Word Integers
		case STARS_NN_vpmovmskb:            // Move Byte Mask to Integer
		case STARS_NN_vpmovsxbd:            // Packed Move with Sign Extend
		case STARS_NN_vpmovsxbq:            // Packed Move with Sign Extend
		case STARS_NN_vpmovsxbw:            // Packed Move with Sign Extend
		case STARS_NN_vpmovsxdq:            // Packed Move with Sign Extend
		case STARS_NN_vpmovsxwd:            // Packed Move with Sign Extend
		case STARS_NN_vpmovsxwq:            // Packed Move with Sign Extend
		case STARS_NN_vpmovzxbd:            // Packed Move with Zero Extend
		case STARS_NN_vpmovzxbq:            // Packed Move with Zero Extend
		case STARS_NN_vpmovzxbw:            // Packed Move with Zero Extend
		case STARS_NN_vpmovzxdq:            // Packed Move with Zero Extend
		case STARS_NN_vpmovzxwd:            // Packed Move with Zero Extend
		case STARS_NN_vpmovzxwq:            // Packed Move with Zero Extend
		case STARS_NN_vpmuldq:              // Multiply Packed Signed Dword Integers
		case STARS_NN_vpmulhrsw:            // Packed Multiply High with Round and Scale
		case STARS_NN_vpmulhuw:             // Packed Multiply High Unsigned
		case STARS_NN_vpmulhw:              // Packed Multiply High
		case STARS_NN_vpmulld:              // Multiply Packed Signed Dword Integers and Store Low Result
		case STARS_NN_vpmullw:              // Packed Multiply Low
		case STARS_NN_vpmuludq:             // Multiply Packed Unsigned Doubleword Integers
		case STARS_NN_vpor:                 // Bitwise Logical Or
		case STARS_NN_vpsadbw:              // Packed Sum of Absolute Differences
		case STARS_NN_vpshufb:              // Packed Shuffle Bytes
		case STARS_NN_vpshufd:              // Shuffle Packed Doublewords
		case STARS_NN_vpshufhw:             // Shuffle Packed High Words
		case STARS_NN_vpshuflw:             // Shuffle Packed Low Words
		case STARS_NN_vpsignb:              // Packed SIGN Byte
		case STARS_NN_vpsignd:              // Packed SIGN Doubleword
		case STARS_NN_vpsignw:              // Packed SIGN Word
		case STARS_NN_vpslld:               // Packed Shift Left Logical (Dword)
		case STARS_NN_vpslldq:              // Shift Double Quadword Left Logical
		case STARS_NN_vpsllq:               // Packed Shift Left Logical (Qword)
		case STARS_NN_vpsllvd:              // Variable Bit Shift Left Logical (Dword)
		case STARS_NN_vpsllvq:              // Variable Bit Shift Left Logical (Qword)
		case STARS_NN_vpsllw:               // Packed Shift Left Logical (Word)
		case STARS_NN_vpsrad:               // Packed Shift Right Arithmetic (Dword)
		case STARS_NN_vpsravd:              // Variable Bit Shift Right Arithmetic
		case STARS_NN_vpsraw:               // Packed Shift Right Arithmetic (Word)
		case STARS_NN_vpsrld:               // Packed Shift Right Logical (Dword)
		case STARS_NN_vpsrldq:              // Shift Double Quadword Right Logical (Qword)
		case STARS_NN_vpsrlq:               // Packed Shift Right Logical (Qword)
		case STARS_NN_vpsrlvd:              // Variable Bit Shift Right Logical (Dword)
		case STARS_NN_vpsrlvq:              // Variable Bit Shift Right Logical (Qword)
		case STARS_NN_vpsrlw:               // Packed Shift Right Logical (Word)
		case STARS_NN_vpsubb:               // Packed Subtract Byte
		case STARS_NN_vpsubd:               // Packed Subtract Dword
		case STARS_NN_vpsubq:               // Subtract Packed Quadword Integers
		case STARS_NN_vpsubsb:              // Packed Subtract with Saturation (Byte)
		case STARS_NN_vpsubsw:              // Packed Subtract with Saturation (Word)
		case STARS_NN_vpsubusb:             // Packed Subtract Unsigned with Saturation (Byte)
		case STARS_NN_vpsubusw:             // Packed Subtract Unsigned with Saturation (Word)
		case STARS_NN_vpsubw:               // Packed Subtract Word
		case STARS_NN_vptest:               // Logical Compare
		case STARS_NN_vpunpckhbw:           // Unpack High Packed Data (Byte->Word)
		case STARS_NN_vpunpckhdq:           // Unpack High Packed Data (Dword->Qword)
		case STARS_NN_vpunpckhqdq:          // Unpack High Packed Data (Qword->Xmmword)
		case STARS_NN_vpunpckhwd:           // Unpack High Packed Data (Word->Dword)
		case STARS_NN_vpunpcklbw:           // Unpack Low Packed Data (Byte->Word)
		case STARS_NN_vpunpckldq:           // Unpack Low Packed Data (Dword->Qword)
		case STARS_NN_vpunpcklqdq:          // Unpack Low Packed Data (Qword->Xmmword)
		case STARS_NN_vpunpcklwd:           // Unpack Low Packed Data (Word->Dword)
		case STARS_NN_vpxor:                // Bitwise Logical Exclusive Or
		case STARS_NN_vrcpps:               // Packed Single-FP Reciprocal
		case STARS_NN_vrcpss:               // Scalar Single-FP Reciprocal
		case STARS_NN_vroundpd:             // Round Packed Double Precision Floating-Point Values
		case STARS_NN_vroundps:             // Round Packed Single Precision Floating-Point Values
		case STARS_NN_vroundsd:             // Round Scalar Double Precision Floating-Point Values
		case STARS_NN_vroundss:             // Round Scalar Single Precision Floating-Point Values
		case STARS_NN_vrsqrtps:             // Packed Single-FP Square Root Reciprocal
		case STARS_NN_vrsqrtss:             // Scalar Single-FP Square Root Reciprocal
		case STARS_NN_vshufpd:              // Shuffle Packed Double-Precision Floating-Point Values
		case STARS_NN_vshufps:              // Shuffle Single-FP
		case STARS_NN_vsqrtpd:              // Compute Square Roots of Packed Double-Precision Floating-Point Values
		case STARS_NN_vsqrtps:              // Packed Single-FP Square Root
		case STARS_NN_vsqrtsd:              // Compute Square Rootof Scalar Double-Precision Floating-Point Value
		case STARS_NN_vsqrtss:              // Scalar Single-FP Square Root
		case STARS_NN_vstmxcsr:             // Store Streaming SIMD Extensions Technology Control/Status Register
		case STARS_NN_vsubpd:               // Subtract Packed Double-Precision Floating-Point Values
		case STARS_NN_vsubps:               // Packed Single-FP Subtract
		case STARS_NN_vsubsd:               // Subtract Scalar Double-Precision Floating-Point Values
		case STARS_NN_vsubss:               // Scalar Single-FP Subtract
		case STARS_NN_vtestpd:              // Packed Double-Precision Floating-Point Bit Test
		case STARS_NN_vtestps:              // Packed Single-Precision Floating-Point Bit Test
		case STARS_NN_vucomisd:             // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS
		case STARS_NN_vucomiss:             // Scalar Unordered Single-FP Compare and Set EFLAGS
		case STARS_NN_vunpckhpd:            // Unpack and Interleave High Packed Double-Precision Floating-Point Values
		case STARS_NN_vunpckhps:            // Unpack High Packed Single-FP Data
		case STARS_NN_vunpcklpd:            // Unpack and Interleave Low Packed Double-Precision Floating-Point Values
		case STARS_NN_vunpcklps:            // Unpack Low Packed Single-FP Data
		case STARS_NN_vxorpd:               // Bitwise Logical OR of Double-Precision Floating-Point Values
		case STARS_NN_vxorps:               // Bitwise Logical XOR for Single-FP Data
		case STARS_NN_vzeroall:             // Zero All YMM Registers
		case STARS_NN_vzeroupper:           // Zero Upper Bits of YMM Registers
			SMP_fprintf(OutFile, "ERROR");
			break;

// Transactional Synchronization Extensions

		case STARS_NN_xabort:               // Transaction Abort
		case STARS_NN_xbegin:               // Transaction Begin
		case STARS_NN_xend:                 // Transaction End
		case STARS_NN_xtest:                // Test If In Transactional Execution
			SMP_fprintf(OutFile, "ERROR");
			break;

// Virtual PC synthetic instructions

		case STARS_NN_vmgetinfo:            // Virtual PC - Get VM Information
		case STARS_NN_vmsetinfo:            // Virtual PC - Set VM Information
		case STARS_NN_vmdxdsbl:             // Virtual PC - Disable Direct Execution
		case STARS_NN_vmdxenbl:             // Virtual PC - Enable Direct Execution
		case STARS_NN_vmcpuid:              // Virtual PC - Virtualized CPU Information
		case STARS_NN_vmhlt:                // Virtual PC - Halt
		case STARS_NN_vmsplaf:              // Virtual PC - Spin Lock Acquisition Failed
		case STARS_NN_vmpushfd:             // Virtual PC - Push virtualized flags register
		case STARS_NN_vmpopfd:              // Virtual PC - Pop virtualized flags register
		case STARS_NN_vmcli:                // Virtual PC - Clear Interrupt Flag
		case STARS_NN_vmsti:                // Virtual PC - Set Interrupt Flag
		case STARS_NN_vmiretd:              // Virtual PC - Return From Interrupt
		case STARS_NN_vmsgdt:               // Virtual PC - Store Global Descriptor Table
		case STARS_NN_vmsidt:               // Virtual PC - Store Interrupt Descriptor Table
		case STARS_NN_vmsldt:               // Virtual PC - Store Local Descriptor Table
		case STARS_NN_vmstr:                // Virtual PC - Store Task Register
		case STARS_NN_vmsdte:               // Virtual PC - Store to Descriptor Table Entry
		case STARS_NN_vpcext:               // Virtual PC - ISA extension
			SMP_fprintf(OutFile, "ERROR");
			break;

		case STARS_NN_last:	
			SMP_fprintf(OutFile, "ERROR");
			break;

		default:
			SMP_fprintf(OutFile, "ERROR");
			break;
	}

	return;
} // end of PrintOpcode()


// MACHINE DEPENDENT: Is operand type a known type that we want to analyze?
bool MDKnownOperandType(const STARSOpndTypePtr &TempOp) {
	bool GoodOpType = (nullptr != TempOp) && TempOp->MDIsKnownOpType();
#if SMP_DEBUG_OPERAND_TYPES
	if (!GoodOpType && (! TempOp->IsVoidOp())) {
		SMP_msg("WARNING: Operand type %d \n", TempOp->GetOpType());
	}
#endif 
	return GoodOpType;
}

// Meet function over any two types in the type lattice.
SMPOperandType SMPTypeMeet(SMPOperandType Type1, SMPOperandType Type2, bool &ErrorFlag) {
	SMPOperandType MeetType = UNKNOWN;
	ErrorFlag = false;
	bool ProfDerived = IsProfDerived(Type1) || IsProfDerived(Type2);
	if (IsEqType(UNINIT, Type1))
		MeetType = Type2;
	else if (IsEqType(UNINIT, Type2) || IsEqType(Type1, Type2)
		|| IsUnknown(Type1))
		MeetType = Type1;
	else if (IsNumeric(Type1)) {
		if (IsNumeric(Type2))  // one is NUMERIC, one is CODEPTR
			MeetType = CODEPTR;
		else if (IsDataPtr(Type2) || IsUnknown(Type2))
			MeetType = UNKNOWN;
		else {
			SMP_msg("ERROR #1 in SMPTypeMeet.\n");
			ErrorFlag = true;
		}
	}
	else if (IsDataPtr(Type1)) {
		if (IsDataPtr(Type2))  // two different POINTER subtypes
			MeetType = POINTER;
		else if (IsNumeric(Type2) || IsUnknown(Type2))
			MeetType = UNKNOWN;
		else {
			SMP_msg("ERROR #2 in SMPTypeMeet.\n");
			ErrorFlag = true;
		}
	}
	if (ProfDerived && IsNotEqType(UNINIT, MeetType))
		MeetType = MakeProfDerived(MeetType);
	return MeetType;
} // end of SMPTypeMeet()

// Meet function for SCCP constant propagation; updates NewConstStruct
void STARSConstantTypeMeet(struct STARS_SCCP_Const_Struct OldConstStruct, struct STARS_SCCP_Const_Struct &NewConstStruct) {
	if ((OldConstStruct.ConstType != STARS_CONST_BOTTOM) && (NewConstStruct.ConstType != STARS_CONST_TOP)) {
		// We have four possibilities. Three of them have NewConstStruct lower in the type lattice, which means the final
		//  result is simply the NewConstStruct (i.e. if Old == TOP, New == CONST or BOTTOM; or Old == CONST, New == BOTTOM).
		// The fourth possibility is that Old == CONST, New == CONST, and we have to check the const values for consistency,
		//  lowering NewConstStruct to BOTTOM if they are inconsistent.
		if ((OldConstStruct.ConstType == STARS_CONST_HAS_VALUE) && (NewConstStruct.ConstType == STARS_CONST_HAS_VALUE)) {
			if (OldConstStruct.ConstValue != NewConstStruct.ConstValue) { // inconsistent const values
				NewConstStruct.ConstType = STARS_CONST_BOTTOM;
			}
		}
	}
	else {
		NewConstStruct = OldConstStruct;
	}
	return;
} // end of STARSConstantTypeMeet()

// If one constant is greater width than another, trim it down.
void HandleConstStructWidths(size_t LeftByteWidth, size_t RightByteWidth, struct STARS_SCCP_Const_Struct &LeftValue, struct STARS_SCCP_Const_Struct &RightValue) {
	size_t LesserByteWidth = LeftByteWidth;
	if (LeftByteWidth > RightByteWidth) {
		LesserByteWidth = RightByteWidth;
		if (RightByteWidth == 4) {
			LeftValue.ConstValue &= 0xffffffff;
		}
		else if (RightByteWidth == 2) {
			LeftValue.ConstValue &= 0xffff;
		}
		else if (RightByteWidth == 1) {
			LeftValue.ConstValue &= 0xff;
		}
		else {
			SMP_msg("ERROR: Const struct width of %zu\n", RightByteWidth);
		}
	}
	else if (RightByteWidth > LeftByteWidth) {
		if (LeftByteWidth == 4) {
			RightValue.ConstValue &= 0xffffffff;
		}
		else if (LeftByteWidth == 2) {
			RightValue.ConstValue &= 0xffff;
		}
		else if (LeftByteWidth == 1) {
			RightValue.ConstValue &= 0xff;
		}
		else {
			SMP_msg("ERROR: Const struct width of %zu\n", LeftByteWidth);
		}
	}
	if (LesserByteWidth <= 4) {
		// Solve potential problem even if Left and Right widths are the same.
		STARS_uval_t LimitValue = 0xffffffff;
		if (LesserByteWidth == 2)
			LimitValue = 0xffff;
		else if (LesserByteWidth == 1)
			LimitValue = 0xff;
		if (LeftValue.ConstValue > LimitValue)
			LeftValue.ConstValue &= LimitValue;
		if (RightValue.ConstValue > LimitValue)
			RightValue.ConstValue &= LimitValue;
	}
	return;
} // end of HandleConstStructWidths()

// *****************************************************************
// Class DisAsmString
// *****************************************************************
DisAsmString::DisAsmString(void) {
	this->CurrAddr = STARS_BADADDR;
	this->StringLen = 0;
	this->CachedDisAsm[0] = '\0';
	return;
}

char *DisAsmString::GetDisAsm(STARS_ea_t InstAddr, bool MarkerInst) {
	if (InstAddr != this->CurrAddr) {
		this->CurrAddr = InstAddr;
		if (MarkerInst) {
			this->SetMarkerInstText(InstAddr);
		}
		else {
			bool IDAsuccess = SMP_generate_disasm_line(InstAddr, this->CachedDisAsm, sizeof(this->CachedDisAsm) - 1);
			if (IDAsuccess) {
				// Remove interactive color-coding tags.
				this->StringLen = SMP_tag_remove(this->CachedDisAsm, this->CachedDisAsm, sizeof(this->CachedDisAsm) - 1);
				if (-1 >= StringLen) {
					SMP_msg("ERROR: tag_remove failed at addr %lx \n", (unsigned long) InstAddr);
					this->CachedDisAsm[0] = '\0';
				}
			}
			else {
				SMP_msg("ERROR: generate_disasm_line failed at addr %lx \n", (unsigned long) InstAddr);
				this->CachedDisAsm[0] = '\0';
			}
		}
	}
	return (char *) this->CachedDisAsm;
} // end of DisAsmString::GetDisasm()

// Set the disasm text for the SSA marker instructions, which have no IDA Pro disasm because
//  they are pseudo-instructions that we add at the top of each function to hold LiveIn name info.
void DisAsmString::SetMarkerInstText(STARS_ea_t InstAddr) {
	if (InstAddr != this->CurrAddr) {
		this->CurrAddr = InstAddr;
		SMP_strncpy(this->CachedDisAsm, "\tfnop\t; Top of function SSA marker for SMP", 
			sizeof(this->CachedDisAsm) - 1);
		this->StringLen = (STARS_ssize_t) strlen(this->CachedDisAsm);
	}
	return;
} // end of DisAsmString::SetMarkerInstText()

DisAsmString DisAsmText;

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

// Default constructor to make the compilers happy.
DefOrUse::DefOrUse(void) {
	this->Operand = nullptr;
	this->SSANumber = -2;
	this->OpType = UNINIT;
	this->NonSpeculativeOpType = UNINIT;
	this->MetadataStatus = DEF_METADATA_UNANALYZED;
	this->booleans1 = 0;
	return;
}

// Constructor.
DefOrUse::DefOrUse(STARSOpndTypePtr Ref, SMPOperandType Type, int SSASub) {
	if (Ref->IsRegOp()) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		STARSOpndTypePtr Ref2 = CloneIfSubwordReg(Ref);
		CanonicalizeOpnd(Ref2);
		this->Operand = Ref2;
	}
	else {
		this->Operand = Ref;
	}
	this->SSANumber = SSASub;
	this->OpType = Type;

#if 0
	// Not true if we construct a reference for fptr shadowing late in our analyses.
	assert(!IsProfDerived(Type));
#endif
	this->NonSpeculativeOpType = Type;
	this->MetadataStatus = DEF_METADATA_UNANALYZED;
	this->booleans1 = 0;
	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->NonSpeculativeOpType = rhs.NonSpeculativeOpType;
	this->SSANumber = rhs.SSANumber;
	this->MetadataStatus = rhs.MetadataStatus;
	this->booleans1 = rhs.booleans1;
	return *this;
}

// Set the operand type for this DEF or USE - don't forget to take
//  into account the speculative (profiler) status.
void DefOrUse::SetType(SMPOperandType Type, const SMPInstr *Instr) {
	SMPOperandType OldType = this->OpType;

	SMPOperandType NewType = Type;
	if (Instr->GetBlock()->GetFunc()->GetIsSpeculative()) {
		NewType = (SMPOperandType)(((int)NewType) | PROF_BASE);
		if (!IsProfDerived(OldType))
			this->NonSpeculativeOpType = OldType;
	}

	this->OpType = NewType;
}

void DefOrUse::SetMetadataStatus(SMPMetadataType NewStatus) {
	// See if we are just updating explanation codes.
	bool OldUsed = ((this->MetadataStatus >= DEF_METADATA_USED) && (this->MetadataStatus < DEF_METADATA_REDUNDANT));
	if (OldUsed) {
		bool NewUsed = ((NewStatus >= DEF_METADATA_USED) && (NewStatus < DEF_METADATA_REDUNDANT));
		if (NewUsed) { 
			// Union the explanation codes.
			int TempInt = (int) this->GetMetadataStatus();
			TempInt |= (int) NewStatus; 
			this->MetadataStatus = (SMPMetadataType) TempInt; 
			return;
		}
	}
	this->MetadataStatus = NewStatus;
	return;
}

// Debug printing.
void DefOrUse::Dump(void) const {
	PrintListOperand(this->Operand, this->SSANumber);
	if (IsEqType(this->OpType , NUMERIC))
		SMP_msg("N ");
	else if (IsEqType(this->OpType , CODEPTR))
		SMP_msg("C ");
	else if (IsEqType(this->OpType , POINTER))
		SMP_msg("P ");
	else if (IsEqType(this->OpType , STACKPTR))
		SMP_msg("S ");
	else if (IsEqType(this->OpType , GLOBALPTR))
		SMP_msg("G ");
	else if (IsEqType(this->OpType , HEAPPTR))
		SMP_msg("H ");
	else if (IsEqType(this->OpType , PTROFFSET))
		SMP_msg("O ");
	else if (IsEqType(this->OpType , NEGATEDPTR))
		SMP_msg("NegP ");
	else if (IsEqType(this->OpType , UNKNOWN))
		SMP_msg("U ");

	/* emit the profile bit */
	if (IsProfDerived(this->OpType))
		SMP_msg("Pr ");

	// Don't write anything for UNINIT OpType

	// Emit the metadata status.
	if (DEF_METADATA_UNUSED == this->MetadataStatus)
		SMP_msg("Mn ");
	else if (DEF_METADATA_USED == this->MetadataStatus)
		SMP_msg("Mu ");
	else if (DEF_METADATA_REDUNDANT == this->MetadataStatus)
		SMP_msg("Mr ");
	// Is the DEF possibly aliased because of an indirect write in
	//  the DEF-USE chain?
	if (this->HasIndirectWrite())
		SMP_msg("Al* ");
	return;
} // end of DefOrUse::Dump()

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

// Default constructor.
DefOrUseSet::DefOrUseSet(void) {
	this->Refs.clear();
	return;
}

// Destructor.
DefOrUseSet::~DefOrUseSet() {
	this->Refs.clear();
	return;
}

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

std::set<DefOrUse, LessDefUse>::const_iterator DefOrUseSet::FindConstRef(const STARSOpndTypePtr &SearchOp) const {
	set<DefOrUse, LessDefUse>::const_iterator CurrRef;
	DefOrUse DummyRef(SearchOp);
	CurrRef = this->Refs.find(DummyRef);
	return CurrRef;

}

// Insert a new DEF or USE; must be new, insert must succeed else we assert.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::InsertRef(DefOrUse Ref) {
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	InsertResult = this->Refs.insert(Ref);
	assert(InsertResult.second);
	return InsertResult.first;
}

// Set a Def or Use into the list, along with its type.
void DefOrUseSet::SetRef(STARSOpndTypePtr Ref, SMPOperandType Type, int SSASub) {
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	DefOrUse CurrRef(Ref, Type, SSASub);
	InsertResult = this->Refs.insert(CurrRef);
	if ((!(InsertResult.second)) && (! Ref->IsRegOp())) {
		SMP_msg("WARNING: Inserted duplicate DEF or USE: ");
		CurrRef.Dump(); SMP_msg("\n");
	}
	return;
}

// Change the indirect write status for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetOp(set<DefOrUse, LessDefUse>::iterator CurrRef, STARSOpndTypePtr NewOp) {
	// 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.
	assert(CurrRef != this->Refs.end());
	DefOrUse NewCopy = (*CurrRef);
	NewCopy.SetOp(NewOp);
	this->Refs.erase(CurrRef);
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	InsertResult = this->Refs.insert(NewCopy);
	assert(InsertResult.second);
	return InsertResult.first;
} // end of DefOrUseSet::SetOp()

// Change the SSA subscript for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetSSANum(const STARSOpndTypePtr &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;
} // end of DefOrUseSet::SetSSANum()

// Change the operand type for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetType(const STARSOpndTypePtr &CurrOp, SMPOperandType Type, const SMPInstr* Instr) {
	// 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 (CurrOp->IsImmedOp()) {
		if (UNINIT != CurrRef->GetType() && Type != CurrRef->GetType()) {
			SMP_msg("ERROR: Changing type of immediate from %d to %d at %llx: ", CurrRef->GetType(), Type, (uint64_t) Instr->GetAddr());
			CurrRef->Dump();
			SMP_msg("\n");
			Instr->Dump();
		}
	}
#endif
	DefOrUse NewCopy = (*CurrRef);
	NewCopy.SetType(Type,Instr);
	this->Refs.erase(CurrRef);
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	InsertResult = this->Refs.insert(NewCopy);
	assert(InsertResult.second);
	CurrRef = InsertResult.first;
	return CurrRef;
} // end of DefOrUseSet::SetType()

// Change the Metadata type for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetMetadata(const STARSOpndTypePtr &CurrOp, SMPMetadataType Status) {
	// 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());
	DefOrUse NewCopy = (*CurrRef);
	NewCopy.SetMetadataStatus(Status);
	this->Refs.erase(CurrRef);
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	InsertResult = this->Refs.insert(NewCopy);
	assert(InsertResult.second);
	CurrRef = InsertResult.first;
	return CurrRef;
} // end of DefOrUseSet::SetMetadata()

// Change the indirect write status for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetIndWrite(const STARSOpndTypePtr &CurrOp, bool IndWriteFlag) {
	// 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());
	DefOrUse NewCopy = (*CurrRef);
	NewCopy.SetIndWrite(IndWriteFlag);
	this->Refs.erase(CurrRef);
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	InsertResult = this->Refs.insert(NewCopy);
	assert(InsertResult.second);
	CurrRef = InsertResult.first;
	return CurrRef;
} // end of DefOrUseSet::SetIndWrite()

// Change the ignore apparent truncation flag for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetNoTruncation(const STARSOpndTypePtr &CurrOp, bool NoTruncFlag) {
	// 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());
	DefOrUse NewCopy = (*CurrRef);
	NewCopy.SetNoTruncation(NoTruncFlag);
	this->Refs.erase(CurrRef);
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	InsertResult = this->Refs.insert(NewCopy);
	assert(InsertResult.second);
	CurrRef = InsertResult.first;
	return CurrRef;
} // end of DefOrUseSet::SetNoTruncation()

// Change the ignore apparent overflow flag for a reference.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetNoOverflow(const STARSOpndTypePtr &CurrOp, bool NoOverflowFlag) {
	// 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());
	DefOrUse NewCopy = (*CurrRef);
	NewCopy.SetNoOverflow(NoOverflowFlag);
	this->Refs.erase(CurrRef);
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	InsertResult = this->Refs.insert(NewCopy);
	assert(InsertResult.second);
	CurrRef = InsertResult.first;
	return CurrRef;
} // end of DefOrUseSet::SetNoOverflow()

// Set a DEF as being invariant for all loops in the func.
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetLoopInvariant(const STARSOpndTypePtr &CurrOp) {
	// 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());
	DefOrUse NewCopy = (*CurrRef);
	NewCopy.SetInvariantForAllLoops();
	this->Refs.erase(CurrRef);
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	InsertResult = this->Refs.insert(NewCopy);
	assert(InsertResult.second);
	CurrRef = InsertResult.first;
	return CurrRef;
} // end of DefOrUseSet::SetLoopInvariant()

// Set a DEF as being a safe memory write
set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetSafeMemWrite(const STARSOpndTypePtr &CurrOp) {
	// 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());
	DefOrUse NewCopy = (*CurrRef);
	NewCopy.SetSafeMemWriteDef();
	this->Refs.erase(CurrRef);
	pair<set<DefOrUse, LessDefUse>::iterator, bool> InsertResult;
	InsertResult = this->Refs.insert(NewCopy);
	assert(InsertResult.second);
	CurrRef = InsertResult.first;
	return CurrRef;
} // end of DefOrUseSet::SetSafeMemWrite()

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

// Do all types agree, ignoring any flags registers in the set? This is used
//  for conditional move instructions; if all types agree, it does not matter
//  whether the move happens or not.
bool DefOrUseSet::TypesAgreeNoFlags(void) {
	bool FoundFirstUse = false;
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	SMPOperandType UseType = UNINIT;
	for (CurrUse = this->Refs.begin(); CurrUse != this->Refs.end(); ++CurrUse) {
		if (!(CurrUse->GetOp()->MatchesReg(X86_FLAGS_REG))) { // ignore flags
			if (!FoundFirstUse) {
				FoundFirstUse = true;
				UseType = CurrUse->GetType();
			}
			else {
				if (IsNotEqType(CurrUse->GetType(), UseType)) {
					return false; // inconsistent types
				}
			}
		}
	}
	return true;
} // end of DefOrUseSet::TypesAgreeNoFlags()


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

// Default constructor.
DefOrUseList::DefOrUseList(void) {
	this->Refs.clear();
	return;
}

// Set a Def or Use into the list, along with its type.
void DefOrUseList::SetRef(STARSOpndTypePtr 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, const SMPInstr* Instr) {
	this->Refs[index].SetType(Type,Instr);
	return;
}

void DefOrUseList::SetMaybeAliased(std::size_t index) {
	this->Refs[index].SetIndWrite(true);
	return;
}

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

// Erase duplicate entries, in case SMPInstr::MDFixupDefUseLists() adds one.
void DefOrUseList::EraseDuplicates(void) {
	STARSOpndSet TempRefs; // Use STL set to find duplicates
	STARSOpndSet::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;
	this->SubscriptedOps.clear();
	return;
}

DefOrUse SMPPhiFunction::GetDefCopy(void) const {
	DefOrUse DefCopy(this->DefName);
	return DefCopy;
}

// 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, const SMPInstr* Instr) {
	this->DefName.SetType(Type, Instr);
	return;
}

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

// Record that the memory DEF might be aliased.
void SMPPhiFunction::SetDefMaybeAliased(void) {
	this->DefName.SetIndWrite(true);
	return;
}

// Record that the memory USE might be aliased.
void SMPPhiFunction::SetRefMaybeAliased(std::size_t index) {
	this->SubscriptedOps.SetMaybeAliased(index);
	return;
}

// Set the metadata status of the DEF variable.
void SMPPhiFunction::SetDefMetadata(SMPMetadataType Status) {
	this->DefName.SetMetadataStatus(Status);
	return;
} // end of SMPPhiFunction::SetDefMetadata()

// Does at least one USE have a type other than UNINIT?
bool SMPPhiFunction::HasTypedUses(void) {
	size_t index;
	for (index = 0; index < this->GetPhiListSize(); ++index) {
		if (UNINIT != this->GetUseType(index))
			return true;
	}
	return false;
} // end of SMPPhiFunction::HasTypedUses()

// Return the result of applying the conditional type propagation meet operator
//  over all the USE types.
SMPOperandType SMPPhiFunction::ConditionalMeetType(SMPBasicBlock *CurrBlock) const {
	SMPOperandType MeetType;
	SMPOperandType PtrType = UNINIT;
	SMPOperandType NumericType = UNINIT; // can end up NUMERIC or CODEPTR
	bool FoundUNINIT  = false; // any USE type UNINIT?
	bool FoundNUMERIC = false; // any USE type NUMERIC?
	bool FoundZero = false; // was DEF to zero? (could be POINTER or NUMERIC
	bool FoundPOINTER = false; // includes all POINTER subtypes
	bool FoundUNKNOWN = false; // any USE type UNKNOWN?
	bool FoundPTROFFSET = false; // any USE type PTROFFSET?
	bool FoundNEGATEDPTR = false; // any USE type NEGATEDPTR?
	bool ProfilerDerived = false; // was any USE type Profiler-derived?
	list<size_t> ZeroConstIndices;
	STARS_ea_t BlockStartAddr = CurrBlock->GetFirstAddr(); // for debugging
	STARSOpndTypePtr PhiOp = this->GetAnyOp();

	for (size_t index = 0; index < this->GetPhiListSize(); ++index) {
		SMPOperandType UseType = this->GetUseType(index);
		if (IsEqType(UseType, UNINIT))
			FoundUNINIT = true;
		else if (IsNumeric(UseType)) {
			// Check for possibility that we aggressively declared NUMERIC when register was set to zero.
			int UseSSANum = this->GetUseSSANum(index);
			bool CurrentUseZeroCase = false;
			if (MDIsDataFlowOpnd(PhiOp, false)) {
				STARS_ea_t DefAddr = CurrBlock->GetFunc()->GetGlobalDefAddr(PhiOp, UseSSANum);
				// Handle simple case: DEF is in an instruction.
				if ((STARS_BADADDR != DefAddr) && (DefAddr < STARS_PSEUDO_ID_MIN)) {
					SMPInstr *DefInst = CurrBlock->GetFunc()->GetInstFromAddr(DefAddr);
					CurrentUseZeroCase = DefInst->IsSetToZero();
				}
			}
			if (CurrentUseZeroCase) {
				FoundZero = true;
				ZeroConstIndices.push_back(index);
			}
			else {
				FoundNUMERIC = true;
				if (IsEqType(NumericType, CODEPTR)) {
					// Already refined. If current type agrees, leave it
					//  alone, else revert to generic type NUMERIC.
					if (IsNotEqType(UseType, NumericType))
						NumericType = NUMERIC;
				}
				else {
					// Have not yet refined NumericType; might still be UNINIT.
					if (IsEqType(UNINIT, NumericType))
						NumericType = UseType;
					else { // NumericType is NUMERIC; leave it as NUMERIC.
						assert(IsEqType(NUMERIC, NumericType));
					}
				}
			}
		}
		else if (IsDataPtr(UseType)) {
			FoundPOINTER = true;
			// Perform a meet over the pointer types.
			if (IsRefinedDataPtr(PtrType)) {
				// Already refined. If current type agrees, leave it
				//  alone, else revert to generic type POINTER.
				if (IsNotEqType(UseType, PtrType))
					PtrType = POINTER;
			}
			else {
				// Have not yet refined PtrType; might still be UNINIT.
				if (IsEqType(UNINIT, PtrType))
					PtrType = UseType;
				else { // PtrType is POINTER because we saw POINTER or
					// had a conflict between pointer refinements; leave
					// it as POINTER.
					assert(IsEqType(POINTER, PtrType));
				}
			}
		}
		else if (IsEqType(PTROFFSET, UseType)) 
			FoundPTROFFSET = true;
		else if (IsEqType(NEGATEDPTR, UseType)) 
			FoundNEGATEDPTR = true;
		else if (IsUnknown(UseType))
			FoundUNKNOWN = true;

		if (IsProfDerived(UseType))
			ProfilerDerived = true;
	}

	// Use the boolean flags to compute the meet function.
	if (FoundUNKNOWN || (FoundNUMERIC && FoundPOINTER) 
		|| ((FoundNUMERIC || FoundPOINTER || FoundNEGATEDPTR) && FoundPTROFFSET)
		|| ((FoundNUMERIC || FoundPOINTER || FoundPTROFFSET) && FoundNEGATEDPTR))
		MeetType = UNKNOWN;
	else if (FoundNUMERIC)
		MeetType = NumericType;
	else if (FoundPOINTER) {
		MeetType = PtrType;
		if (FoundZero) { // mixture of POINTER and const zero DEFs, i.e. ptr := NULL;
			// Undo the aggressive NUMERIC inference when registers are set to zero.
			//  NOTE: There cannot be any alterations to the reg between the zero DEF and
			//  the current block on at least one path, or it would not show up in the Phi function with the
			//  current SSA number.
			do {
				size_t ZeroConstIndex = ZeroConstIndices.front();
				int UseSSANum = this->GetUseSSANum(ZeroConstIndex);
				STARS_ea_t DefAddr = CurrBlock->GetFunc()->GetGlobalDefAddr(PhiOp, UseSSANum);
				// Handle simple case: DEF is in an instruction.
				if ((STARS_BADADDR != DefAddr) && (DefAddr < STARS_PSEUDO_ID_MIN)) {
					SMPInstr *DefInst = CurrBlock->GetFunc()->GetInstFromAddr(DefAddr);
					set<DefOrUse, LessDefUse>::iterator DefIter = DefInst->SetDefType(PhiOp, PtrType);
#if 0
					SMP_msg("INFO: Converting zeroed reg from NUMERIC to POINTER at %lx for Block at %lx\n",
						(unsigned long) DefAddr, (unsigned long) BlockStartAddr);
#endif
					CurrBlock->GetFunc()->ResetProcessedBlocks();
					SMPBasicBlock *DefBlock = CurrBlock->GetFunc()->GetBlockFromInstAddr(DefAddr);
#if 0 // Causes infinite loops, crashes; need to debug !!!!****!!!!
					DefBlock->PropagateGlobalDefType(PhiOp, PtrType, UseSSANum, false, true);
#else
					DefBlock->PropagateGlobalDefType(PhiOp, PtrType, UseSSANum, false, false);
#endif
				}
				ZeroConstIndices.pop_front();
			} while (!ZeroConstIndices.empty());
		}
	}
	else if (FoundPTROFFSET)
		MeetType = PTROFFSET;
	else if (FoundNEGATEDPTR)
		MeetType = NEGATEDPTR;
	else if (FoundZero && (!FoundUNINIT)) // nothing but zeroes
		MeetType = NUMERIC;
	else {
		assert(FoundUNINIT);
		MeetType = UNINIT;
	}
	if (ProfilerDerived)
		MeetType = MakeProfDerived(MeetType);
	return MeetType;
} // end of SMPPhiFunction::ConditionalMeetType()

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

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

// Constructors
SMPDefUseChain::SMPDefUseChain(void) {
	this->SSAName = nullptr;
	this->RefInstrs.clear();
	this->RefInstrs.push_back((unsigned short) STARS_BADADDR);
	this->IndWrite = false;
	return;
}

SMPDefUseChain::SMPDefUseChain(STARSOpndTypePtr Name, STARS_ea_t Def) {
	this->SetName(Name);
	this->RefInstrs.push_back(Def);
	this->IndWrite = false;
	return;
}

// Set the variable name.
void SMPDefUseChain::SetName(STARSOpndTypePtr Name) {
	STARSOpndTypePtr Name2 = nullptr;
	if (Name->IsRegOp()) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		Name2 = CloneIfSubwordReg(Name);
		CanonicalizeOpnd(Name2);
	}
	else {
		Name2 = Name;
	}
	this->SSAName = Name2;
	return;
}

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

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

// Set the indirect memory write flag.
void SMPDefUseChain::SetIndWrite(bool IndMemWrite) {
	this->IndWrite = IndMemWrite;
	return;
}

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

// *****************************************************************
// Class SMPDUChainArray
// *****************************************************************
SMPDUChainArray::SMPDUChainArray(void) {
	this->SSAName = nullptr;
	this->DUChains.clear();
	return;
}

SMPDUChainArray::SMPDUChainArray(STARSOpndTypePtr Name, STARS_ea_t FirstAddrMinusOne) {
	STARSOpndTypePtr Name2 = nullptr;
	if (Name->IsRegOp()) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		Name2 = CloneIfSubwordReg(Name);
		CanonicalizeOpnd(Name2);
	}
	else {
		Name2 = Name;
	}
	this->SSAName = Name2;
	this->BaseAddr = FirstAddrMinusOne;
	this->DUChains.clear();
	return;
}

STARS_ea_t SMPDUChainArray::GetLastUse(int SSANum) const {
	STARS_ea_t TempAddr = DUChains[(size_t)SSANum].GetLastUse();
	if (STARS_BADADDR != TempAddr) {
		// If STARS_BADADDR, leave it as STARS_BADADDR. Otherwise, add in BaseAddr.
		TempAddr += this->BaseAddr;
	}
	return TempAddr;
}

void SMPDUChainArray::SetName(STARSOpndTypePtr Name, STARS_ea_t FirstAddrMinusOne) {
	STARSOpndTypePtr Name2 = nullptr;
	if (Name->IsRegOp()) {
		// We want to map AH, AL, and AX to EAX, etc. throughout our data flow analysis
		//  and type inference systems.
		Name2 = CloneIfSubwordReg(Name);
		CanonicalizeOpnd(Name2);
	}
	else {
		Name2 = Name;
	}
	this->SSAName = Name2;
	this->BaseAddr = FirstAddrMinusOne;
	return;
}

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

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

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

// *****************************************************************
// Class STARSBitSet
// *****************************************************************

// Constructors.
STARSBitSet::STARSBitSet() {
	this->BitLimit = 0;
}

// Get methods
bool STARSBitSet::GetBit(size_t BitIndex) const {
	size_t ByteIndex = BitIndex / 8;
	size_t BitNumber = BitIndex % 8;
	assert(BitIndex <= this->BitLimit);
	return (0 != (this->STARSBits[ByteIndex] & STARSBitMasks[BitNumber]));
}

uint8_t STARSBitSet::GetByte(std::size_t ByteIndex) const {
	assert(ByteIndex < this->STARSBits.size());
	return this->STARSBits[ByteIndex];
}

// Set methods
void STARSBitSet::AllocateBits(size_t Size) {
	size_t Bytes = Size / 8;
	size_t ExtraBits = Size % 8;
	this->BitLimit = Size;
	if (0 != ExtraBits) {
		this->STARSBits.resize(1 + Bytes);
	}
	else {
		this->STARSBits.resize(Bytes);
	}
	for (Bytes = 0; Bytes < this->STARSBits.size(); ++Bytes) {
		this->STARSBits[Bytes] = 0;
	}
}

void STARSBitSet::SetBit(size_t BitIndex) {
	size_t ByteIndex = BitIndex / 8;
	size_t BitNumber = BitIndex % 8;
	assert(BitIndex <= this->BitLimit);
	this->STARSBits[ByteIndex] |= STARSBitMasks[BitNumber];
	return;
}

void STARSBitSet::ResetBit(size_t BitIndex) {
	size_t ByteIndex = BitIndex / 8;
	size_t BitNumber = BitIndex % 8;
	assert(BitIndex <= this->BitLimit);
	this->STARSBits[ByteIndex] &= (~STARSBitMasks[BitNumber]);
	return;
}

void STARSBitSet::ResetAllBits(void) {
	size_t NumBytes = this->STARSBits.size();
	for (size_t ByteIndex = 0; ByteIndex < NumBytes; ++ByteIndex) {
		this->STARSBits[ByteIndex] = 0;
	}
	return;
} // end of STARSBitSet::ResetAllBits()

// Query methods

// Returns false if all bits are zero, true otherwise.
bool STARSBitSet::IsAnyBitSet(void) const {
	bool FoundSetBit = false;
	size_t ByteIndex;
	for (ByteIndex = 0; ByteIndex < this->STARSBits.size(); ++ByteIndex) {
		if (0 != this->STARSBits[ByteIndex]) {
			FoundSetBit = true;
			break;
		}
	}

	return FoundSetBit;
}

// Return highest index set; -1 if no bits set.
int STARSBitSet::FindHighestBitSet(void) const {
	bool FoundSetBit = false;
	size_t ByteIndex, BitIndex, BitSetSize = this->STARSBits.size();
	assert(0 < BitSetSize);
	for (ByteIndex = BitSetSize; ByteIndex > 0; --ByteIndex) {
		if (0 != this->STARSBits[ByteIndex - 1]) {
			FoundSetBit = true;
			--ByteIndex;
			BitIndex = HighestBitSet(this->STARSBits[ByteIndex]);
			break;
		}
	}

	if (FoundSetBit) {
		return (int)(8 * ByteIndex + BitIndex);
	}
	else {
		return -1;
	}
} // end of STARSBitSet::FindHighestBitSet()

// Return lowest index set; -1 if no bits set.
int STARSBitSet::FindLowestBitSet(void) const {
	bool FoundSetBit = false;
	size_t ByteIndex, BitIndex, BitSetSize = this->STARSBits.size();
	assert(0 < BitSetSize);
	for (ByteIndex = 0; ByteIndex < BitSetSize; ++ByteIndex) {
		if (0 != this->STARSBits[ByteIndex]) {
			FoundSetBit = true;
			BitIndex = LowestBitSet(this->STARSBits[ByteIndex]);
			break;
		}
	}

	if (FoundSetBit) {
		return (int)(8 * ByteIndex + BitIndex);
	}
	else {
		return -1;
	}
} // end of STARSBitSet::FindLowestBitSet()

// return count of set bits
size_t STARSBitSet::CountSetBits(void) const {
	size_t ByteIndex, BitCount = 0, BitSetSize = this->STARSBits.size();
	assert(0 < BitSetSize);
	for (ByteIndex = 0; ByteIndex < BitSetSize; ++ByteIndex) {
		uint8_t CurrByte = this->STARSBits[ByteIndex];
		if (0 != CurrByte) {
			BitCount += CountBitsSet((unsigned int) CurrByte);
		}
	}
	return BitCount;
} // end of STARSBitSet::CountSetBits()

// Debugging output of bits set
void STARSBitSet::DumpBitsSet(void) const {
	size_t ByteIndex, BitCount = 0, BitSetSize = this->STARSBits.size();
	assert(0 < BitSetSize);
	for (ByteIndex = 0; ByteIndex < BitSetSize; ++ByteIndex) {
		uint8_t CurrByte = this->STARSBits[ByteIndex];
		if (0 != CurrByte) {
			size_t CurrBitLimit = 8 + (8 * ByteIndex);
			if (CurrBitLimit > this->GetNumBits())
				CurrBitLimit = this->GetNumBits();
			for (size_t BitIndex = 8 * ByteIndex; BitIndex < CurrBitLimit; ++BitIndex) {
				if (this->GetBit(BitIndex)) {
					SMP_msg("%zu ", BitIndex);
				}
			}
		}
	}
	return;
} // end of STARSBitSet::DumpBitsSet()

void STARSBitSet::SetByte(const std::size_t ByteIndex, const uint8_t ByteValue) {
	assert(ByteIndex < this->STARSBits.size());
	this->STARSBits[ByteIndex] = ByteValue;
	return;
}

void STARSBitSet::UnionSets(const STARSBitSet &BitSet2) {
	assert(this->GetNumBits() == BitSet2.GetNumBits());

	for (size_t ByteIndex = 0; ByteIndex < this->STARSBits.size(); ++ByteIndex) {
		this->STARSBits[ByteIndex] = (this->STARSBits[ByteIndex] | BitSet2.GetByte(ByteIndex));
	}

	return;
} // end of STARSBitSet::UnionSets()

STARSBitSet STARSBitSetIntersection(const STARSBitSet &BitSet1, const STARSBitSet &BitSet2) {
	size_t NumBits = BitSet1.GetNumBits();
	assert(NumBits == BitSet2.GetNumBits());
	STARSBitSet ReturnBitSet;
	ReturnBitSet.AllocateBits(NumBits);
	size_t NumBytes = (NumBits / 8);
	if (0 != (NumBits % 8))
		++NumBytes;

	for (size_t ByteIndex = 0; ByteIndex < NumBytes; ++ByteIndex) {
		ReturnBitSet.SetByte(ByteIndex, (BitSet1.GetByte(ByteIndex) & BitSet2.GetByte(ByteIndex)));
	}

	return ReturnBitSet;
} // end of STARSBitSetIntersection()

STARSBitSet STARSBitSetUnion(const STARSBitSet &BitSet1, const STARSBitSet &BitSet2) {
	size_t NumBits = BitSet1.GetNumBits();
	assert(NumBits == BitSet2.GetNumBits());
	STARSBitSet ReturnBitSet;
	ReturnBitSet.AllocateBits(NumBits);
	size_t NumBytes = (NumBits / 8);
	if (0 != (NumBits % 8))
		++NumBytes;

	for (size_t ByteIndex = 0; ByteIndex < NumBytes; ++ByteIndex) {
		ReturnBitSet.SetByte(ByteIndex, (BitSet1.GetByte(ByteIndex) | BitSet2.GetByte(ByteIndex)));
	}

	return ReturnBitSet;
} // end of STARSBitSetUnion()


// Map system or library call name to FG info about its return value.
map<string, struct FineGrainedInfo> ReturnRegisterTypeMap;

// Map system or library call name to the annotation substring that
//  guides saturating arithmetic or other continuation policies in 
//  the case of integer error detection of a value passed to that call.
// If we don't care about a certain call, we return an empty string.
static map<string, string> IntegerErrorCallSinkMap;

void InitIntegerErrorCallSinkMap(void) {

	// in case STARS was invoked before.
	IntegerErrorCallSinkMap.clear();

	pair<string, string> MapEntry;
	pair<map<string, string>::iterator, bool> InsertResult;

	MapEntry.first = string("malloc");
	MapEntry.second = string("SINKMALLOC");
	InsertResult = IntegerErrorCallSinkMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("calloc");
	MapEntry.second = string("SINKMALLOC");
	InsertResult = IntegerErrorCallSinkMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("realloc");
	MapEntry.second = string("SINKMALLOC");
	InsertResult = IntegerErrorCallSinkMap.insert(MapEntry);
	assert(InsertResult.second);

	return;
}

// Return sink string for call name from the sink map.
// If we don't care find the call name, we return an empty string.
void GetSinkStringForCallName(string CalleeName, string &SinkString) {
	map<string, string>::iterator MapIter;

	SinkString.clear(); // empty string, append map string if found later
	MapIter = IntegerErrorCallSinkMap.find(CalleeName);

	if (MapIter != IntegerErrorCallSinkMap.end()) { // found it
		SinkString.append(MapIter->second);
	}
	return;
}

// Map system or library call name to the argument number that
//  should have an unsigned value and should be guarded from the
//  signedness error that results from copying a signed value
//  into the outgoing argument. Argument numbers are zero-based.
//  We will return 0 when there is no argument to worry about
//  for a particular library or system call name.
static map<string, unsigned int> UnsignedArgPositionMap;

void InitUnsignedArgPositionMap(void) {
	// clear in case stars invoked multiple times.
	UnsignedArgPositionMap.clear();

	pair<string, unsigned int> MapEntry;
	pair<map<string, unsigned int>::iterator, bool> InsertResult;

	// <string.h>
	MapEntry.first = string("memchr");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcmp");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcpy");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memmove");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memset");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncat");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncmp");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncpy");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strxfrm");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <stdlib.h>
	MapEntry.first = string("malloc");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("calloc");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("realloc");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("bsearch");
	MapEntry.second = (STARS_ARG_POS_2 | STARS_ARG_POS_3);
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("qsort");
	MapEntry.second = (STARS_ARG_POS_1 | STARS_ARG_POS_2);
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mblen");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mbtowc");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mbstowcs");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("wcstombs");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <stdio.h>
	MapEntry.first = string("setvbuf");
	MapEntry.second = STARS_ARG_POS_3;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <time.h>
	MapEntry.first = string("strftime");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = UnsignedArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	return;
} // end of InitUnsignedArgPositionMap()

// Return unsigned arg position bitset for call name from the unsigned arg map.
// If we don't find the call name, we return 0 in ArgPosBits.
void GetUnsignedArgPositionsForCallName(string CalleeName, unsigned int &ArgPosBits) {
	map<string, unsigned int>::iterator MapIter;

	ArgPosBits = 0; // Change if found later
	MapIter = UnsignedArgPositionMap.find(CalleeName);

	if (MapIter != UnsignedArgPositionMap.end()) { // found it
		ArgPosBits = MapIter->second;
	}
	return;
}

// Map of function names to arguments that are dangerous to supply
//  with user-tainted input values.
static map<string, unsigned int> TaintWarningArgPositionMap;

void InitTaintWarningArgPositionMap(void) {
	// clear in case STARS re-init'd.
	TaintWarningArgPositionMap.clear();

	pair<string, unsigned int> MapEntry;
	pair<map<string, unsigned int>::iterator, bool> InsertResult;

	// <string.h>
	MapEntry.first = string("memchr");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcmp");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcpy");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memmove");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memset");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncat");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncmp");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncpy");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strxfrm");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <stdlib.h>
	MapEntry.first = string("malloc");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("calloc");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("realloc");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("bsearch");
	MapEntry.second = (STARS_ARG_POS_2 | STARS_ARG_POS_3);
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("qsort");
	MapEntry.second = (STARS_ARG_POS_1 | STARS_ARG_POS_2);
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mblen");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mbtowc");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mbstowcs");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("wcstombs");
	MapEntry.second = STARS_ARG_POS_2;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <stdio.h>
	MapEntry.first = string("setvbuf");
	MapEntry.second = STARS_ARG_POS_3;
	InsertResult = TaintWarningArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	return;
} // end of InitTaintWarningArgPositionMap()

// Return dangerous-to-taint arg position bitset for call name from the taint warning map.
// If we don't find the call name, we return 0 in ArgPosBits.
void GetTaintWarningArgPositionsForCallName(string CalleeName, unsigned int &ArgPosBits) {
	map<string, unsigned int>::iterator MapIter;

	ArgPosBits = 0; // Change if found later
	MapIter = TaintWarningArgPositionMap.find(CalleeName);

	if (MapIter != TaintWarningArgPositionMap.end()) { // found it
		ArgPosBits = MapIter->second;
	}
	return;
}

// Map of function names to POINTER argument positions.
static map<string, unsigned int> PointerArgPositionMap;

// Init map of system or library call name to the argument number that
//  should have a POINTER value.
void InitPointerArgPositionMap(void) {
	// clear in case re-initing.
	PointerArgPositionMap.clear();

	pair<string, unsigned int> MapEntry;
	pair<map<string, unsigned int>::iterator, bool> InsertResult;

	// <locale.h>
	MapEntry.first = string("setlocale");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <math.h>
	MapEntry.first = string("modf");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <string.h>
	MapEntry.first = string("memchr");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcmp");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memcpy");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memmove");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("memset");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strcat");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncat");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strcmp");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncmp");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strcpy");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strcpy_chk");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strncpy");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strcoll");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strxfrm");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strchr");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strcspn");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strpbrk");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strrchr");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strspn");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strstr");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strtok");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strlen");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <stdlib.h>
	MapEntry.first = string("atof");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("atoi");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("atol");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strtod");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strtol");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strtoul");
	MapEntry.second = STARS_ARG_POS_0 | STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("free");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("realloc");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("getenv");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("system");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("bsearch");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("qsort");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mblen");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mbtowc");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("wctomb");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("mbstowcs");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("wcstombs");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <stdio.h>
	MapEntry.first = string("remove");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("rename");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("tmpnam");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fclose");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fflush");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fopen");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("freopen");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1 | STARS_ARG_POS_2);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("setbuf");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("setvbuf");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fprintf");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fscanf");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("isoc99_fscanf");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("printf");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("scanf");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("isoc99_scanf");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("sprintf");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("sscanf");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("vfprintf");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("vprintf");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("vsprintf");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fgetc");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fgets");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_2);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fputc");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fputs");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("getc");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("gets");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("putc");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("puts");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("ungetc");
	MapEntry.second = STARS_ARG_POS_1;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fread");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_3);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fwrite");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_3);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fgetpos");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fseek");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("fsetpos");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_1);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("ftell");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("rewind");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("clearerr");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("feof");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("ferror");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("perror");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	// <time.h>
	MapEntry.first = string("mktime");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("time");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("asctime");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("ctime");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("gmtime");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("localtime");
	MapEntry.second = STARS_ARG_POS_0;
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = string("strftime");
	MapEntry.second = (STARS_ARG_POS_0 | STARS_ARG_POS_2 | STARS_ARG_POS_3);
	InsertResult = PointerArgPositionMap.insert(MapEntry);
	assert(InsertResult.second);

	return;
} // end of InitPointerArgPositionMap()

// Return POINTER arg position bitset for call name from the POINTER arg map.
// If we don't find the call name, we return 0 in ArgPosBits.
void GetPointerArgPositionsForCallName(string CalleeName, unsigned int &ArgPosBits) {
	map<string, unsigned int>::iterator MapIter;

	ArgPosBits = 0; // Change if found later
	MapIter = PointerArgPositionMap.find(CalleeName);

	if (MapIter != PointerArgPositionMap.end()) { // found it
		ArgPosBits = MapIter->second;
	}
	return;
}

static set<string> MathLibraryFuncNames;
static set<string> StdioLibraryFuncNames;
static set<string> StdlibLibraryFuncNames;
static set<string> BufferArgLibraryFuncNames;

void InitLibraryFuncNames(void) {
	// <math.h>
	MathLibraryFuncNames.insert("acos");
	MathLibraryFuncNames.insert("cos");
	MathLibraryFuncNames.insert("sin");
	MathLibraryFuncNames.insert("asin");
	MathLibraryFuncNames.insert("tan");
	MathLibraryFuncNames.insert("atan");
	MathLibraryFuncNames.insert("cosh");
	MathLibraryFuncNames.insert("sinh");
	MathLibraryFuncNames.insert("tanh");
	MathLibraryFuncNames.insert("atan2");
	MathLibraryFuncNames.insert("exp");
	MathLibraryFuncNames.insert("ldexp");
	MathLibraryFuncNames.insert("frexp");
	MathLibraryFuncNames.insert("log");
	MathLibraryFuncNames.insert("modf");
	MathLibraryFuncNames.insert("log10");
	MathLibraryFuncNames.insert("pow");
	MathLibraryFuncNames.insert("sqrt");
	MathLibraryFuncNames.insert("ceil");
	MathLibraryFuncNames.insert("fmod");
	MathLibraryFuncNames.insert("fabs");
	MathLibraryFuncNames.insert("floor");

	StdioLibraryFuncNames.insert("printf");
	StdioLibraryFuncNames.insert("scanf");
	StdioLibraryFuncNames.insert("isoc99_scanf");
	StdioLibraryFuncNames.insert("printf_chk");
	StdioLibraryFuncNames.insert("fprintf");
	StdioLibraryFuncNames.insert("fscanf");
	StdioLibraryFuncNames.insert("isoc99_fscanf");
	StdioLibraryFuncNames.insert("sprintf");
	StdioLibraryFuncNames.insert("sscanf");
	StdioLibraryFuncNames.insert("vfprintf");
	StdioLibraryFuncNames.insert("fgetc");
	StdioLibraryFuncNames.insert("vprintf");
	StdioLibraryFuncNames.insert("fgets");
	StdioLibraryFuncNames.insert("vsprintf");
	StdioLibraryFuncNames.insert("fputc");
	StdioLibraryFuncNames.insert("getc");
	StdioLibraryFuncNames.insert("fputs");
	StdioLibraryFuncNames.insert("getchar");
	StdioLibraryFuncNames.insert("putchar");
	StdioLibraryFuncNames.insert("gets");
	StdioLibraryFuncNames.insert("putc");
	StdioLibraryFuncNames.insert("ungetc");
	StdioLibraryFuncNames.insert("puts");
	StdioLibraryFuncNames.insert("fwrite");
	StdioLibraryFuncNames.insert("fread");
	StdioLibraryFuncNames.insert("fgetpos");
	StdioLibraryFuncNames.insert("printf");
	StdioLibraryFuncNames.insert("fseek");
	StdioLibraryFuncNames.insert("rewind");
	StdioLibraryFuncNames.insert("fsetpos");
	StdioLibraryFuncNames.insert("clearerr");
	StdioLibraryFuncNames.insert("ftell");
	StdioLibraryFuncNames.insert("perror");
	StdioLibraryFuncNames.insert("feof");
	StdioLibraryFuncNames.insert("remove");
	StdioLibraryFuncNames.insert("ferror");
	StdioLibraryFuncNames.insert("rename");
	StdioLibraryFuncNames.insert("fopen");
	StdioLibraryFuncNames.insert("tmpfile");
	StdioLibraryFuncNames.insert("freopen");
	StdioLibraryFuncNames.insert("tmpnam");
	StdioLibraryFuncNames.insert("fclose");
	StdioLibraryFuncNames.insert("setbuf");
	StdioLibraryFuncNames.insert("fflush");
	StdioLibraryFuncNames.insert("setvbuf");

	StdlibLibraryFuncNames.insert("atol");
	StdlibLibraryFuncNames.insert("atof");
	StdlibLibraryFuncNames.insert("atoi");
	StdlibLibraryFuncNames.insert("strtod");
	StdlibLibraryFuncNames.insert("strtol");
	StdlibLibraryFuncNames.insert("strtoul");
	StdlibLibraryFuncNames.insert("rand");
	StdlibLibraryFuncNames.insert("srand");
	StdlibLibraryFuncNames.insert("calloc");
	StdlibLibraryFuncNames.insert("free");
	StdlibLibraryFuncNames.insert("malloc");
	StdlibLibraryFuncNames.insert("realloc");
	StdlibLibraryFuncNames.insert("abort");
	StdlibLibraryFuncNames.insert("atexit");
	StdlibLibraryFuncNames.insert("exit");
	StdlibLibraryFuncNames.insert("getenv");
	StdlibLibraryFuncNames.insert("system");
	StdlibLibraryFuncNames.insert("bsearch");
	StdlibLibraryFuncNames.insert("qsort");
	StdlibLibraryFuncNames.insert("abs");
	StdlibLibraryFuncNames.insert("div");
	StdlibLibraryFuncNames.insert("labs");
	StdlibLibraryFuncNames.insert("ldiv");
	StdlibLibraryFuncNames.insert("mblen");
	StdlibLibraryFuncNames.insert("mbtowc");
	StdlibLibraryFuncNames.insert("wctomb");
	StdlibLibraryFuncNames.insert("mbstowcs");
	StdlibLibraryFuncNames.insert("wcstombs");

	// Add special functions often inserted by gcc.
	StdlibLibraryFuncNames.insert("stack_chk_fail");

	// Funcs with buffers as arguments; could analyze static size of buffers.
	BufferArgLibraryFuncNames.insert("strcpy");
	BufferArgLibraryFuncNames.insert("strcpy_chk"); // GNU safer version, but crashes on error
	BufferArgLibraryFuncNames.insert("memcpy");
	BufferArgLibraryFuncNames.insert("memmove");
	BufferArgLibraryFuncNames.insert("strcat");
	BufferArgLibraryFuncNames.insert("strcmp");

	return;
} // end of InitLibraryFuncNames()

bool IsMathLibraryFunc(string CalleeName) {
	set<string>::const_iterator FuncIter = MathLibraryFuncNames.find(CalleeName);
	return (FuncIter != MathLibraryFuncNames.cend());
}

bool IsStdioLibraryFunc(string CalleeName) {
	set<string>::const_iterator FuncIter = StdioLibraryFuncNames.find(CalleeName);
	return (FuncIter != StdioLibraryFuncNames.cend());
}

bool IsStdlibLibraryFunc(string CalleeName) {
	set<string>::const_iterator FuncIter = StdlibLibraryFuncNames.find(CalleeName);
	return (FuncIter != StdlibLibraryFuncNames.cend());
}

// Is FuncName a function that operates on buffers that might be of analyzeable buffer length?
bool IsBufferArgFuncName(const string CalleeName) {
	set<string>::const_iterator FuncIter = BufferArgLibraryFuncNames.find(CalleeName);
	return (FuncIter != BufferArgLibraryFuncNames.cend());
}

// Utility to count bits set in an unsigned int, e.g. ArgPosBits.
unsigned int CountBitsSet(unsigned int ArgPosBits) {
	unsigned int count; // count accumulates the total bits set in ArgPosBits
	for (count = 0; ArgPosBits; ++count) {
		ArgPosBits &= (ArgPosBits - 1); // clear the least significant bit set
	}
	// Brian Kernighan's method goes through as many iterations as there are set bits. 
	//  So if we have a 32-bit word with only the high bit set, then it will only go once through the loop.
	// Published in 1988, the C Programming Language 2nd Ed. (by Brian W. Kernighan and Dennis M. Ritchie) mentions this in exercise 2-9.
	//  On April 19, 2006 Don Knuth pointed out to me that this method "was first published by Peter Wegner in CACM 3 (1960), 322.
	//  (Also discovered independently by Derrick Lehmer and published in 1964 in a book edited by Beckenbach.)"
	return count;
}

// Utility to get highest bit set in a byte, numbered 0 (lowest) to 7 (highest).
unsigned int HighestBitSet(uint8_t Byte) {
	unsigned int RetVal = 0;
	if (Byte & 0xf0) { // check upper 4 bits
		RetVal |= 4;  // at least bit 4 or higher is set
		Byte >>= 4;   // shift upper nibble to lower nibble
	}
	if (Byte & 0xc) { // check upper two bits of lower nibble
		RetVal |= 2;  // At least bit 2 or higher is set
		Byte >>= 2;   // shift upper two bits of lower nibble into lowest two bits
	}
	if (Byte & 0x2) { // Check second least significant bit
		RetVal |= 1;
	}
	return RetVal;
} // end of HighestBitSet()

// Utility to get lowest bit set in a byte, numbered 0 (lowest) to 7 (highest).
unsigned int LowestBitSet(unsigned char Byte) {
	unsigned int RetVal = 0;
	if (Byte & 0x03) { // check lower 2 bits
		RetVal = (Byte & 1) ? 0 : 1;
	}
	else if (Byte & 0x0c) { // check upper two bits of lower nibble
		RetVal = (Byte & 4) ? 2 : 3;
	}
	else if (Byte & 0x30) { // Check lower two bits of upper nibble
		RetVal = (Byte & 16) ? 4 : 5;
	}
	else {
		assert(Byte & 0xc0);
		RetVal = (Byte & 64) ? 6 : 7;
	}
	return RetVal;
}

// Utility to get highest bit set in an uint32_t, numbered 0 (lowest) to 31 (highest).
// Assumes that UintVal is non-zero and has some bit set.
unsigned int HighestBitSetInUint(uint32_t UintVal) {
	unsigned int RetVal = 0;
	uint8_t Byte0 = UintVal & 0xff;
	uint8_t Byte1 = UintVal & 0xff00;
	uint8_t Byte2 = UintVal & 0xff0000;
	uint8_t Byte3 = UintVal & 0xff000000;
	if (Byte3 > 0) {
		RetVal = HighestBitSet(Byte3) + 24;
	}
	else if (Byte2 > 0) {
		RetVal = HighestBitSet(Byte2) + 16;
	}
	else if (Byte1 > 0) {
		RetVal = HighestBitSet(Byte1) + 8;
	}
	else if (Byte0 > 0) {
		RetVal = HighestBitSet(Byte0);
	}
	return RetVal;
} // end of HighestBitSetInUint()


// Initialize the FG info for the return register from any library function
//  whose name implies that we know certain return values (e.g. atoi() returns
//  a signed integer, while strtoul() returns an unsigned long).
void GetLibFuncFGInfo(string FuncName, struct FineGrainedInfo &InitFGInfo) {
	map<string, struct FineGrainedInfo>::iterator FindIter;

	FindIter = ReturnRegisterTypeMap.find(FuncName);
	if (FindIter == ReturnRegisterTypeMap.end()) { // not found
		InitFGInfo.SignMiscInfo = 0;
		InitFGInfo.SizeInfo = 0;
	}
	else { // found
		InitFGInfo = FindIter->second;
	}
	return;
} // end of GetLibFuncFGInfo()


// Is FuncName a standard library function name?
bool IsLibFuncName(std::string CalleeName) {
	// Return true if we find the name in any of our function type maps.

	map<string, struct FineGrainedInfo>::iterator RetTypeIter = ReturnRegisterTypeMap.find(CalleeName);
	if (RetTypeIter != ReturnRegisterTypeMap.end()) { // found
		return true;
	}

	map<string, unsigned int>::iterator PtrArgIter = PointerArgPositionMap.find(CalleeName);
	if (PtrArgIter != PointerArgPositionMap.end()) { // found it
		return true;
	}

	map<string, unsigned int>::iterator TaintIter = TaintWarningArgPositionMap.find(CalleeName);
	if (TaintIter != TaintWarningArgPositionMap.end()) { // found it
		return true;
	}

	map<string, unsigned int>::iterator UnsignedIter = UnsignedArgPositionMap.find(CalleeName);
	if (UnsignedIter != UnsignedArgPositionMap.end()) { // found it
		return true;
	}

	map<string, string>::iterator SinkIter = IntegerErrorCallSinkMap.find(CalleeName);
	if (SinkIter != IntegerErrorCallSinkMap.end()) { // found it
		return true;
	}

	// Put searches for additional library function names here.
	if (0 == CalleeName.compare("setuid")) {
		return true;
	}
	else if (IsStdioLibraryFunc(CalleeName)) {
		return true;
	}
	else if (IsMathLibraryFunc(CalleeName)) {
		return true;
	}
	else if (IsStdlibLibraryFunc(CalleeName)) {
		return true;
	}

	return false;
} // end of IsLibFuncName()

// Is FuncName a startup func called before main(), or a wrapup function called by the system?
bool IsStartupFuncName(const std::string FuncName) {
	bool NameMatched = false;
	char IDA_func_name[STARS_MAXSTR];
	std::size_t SkipCount;

	SkipCount = strspn(FuncName.c_str(), "._");
	std::string TempFuncName = FuncName.substr(SkipCount); // remove leading periods and underscores

	if (0 == TempFuncName.compare("init_proc")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("init")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("start")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("gmon_start")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("call_gmon_start")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("libc_start_main")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("call_gmon_start__")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("libc_start_main__")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("libc_csu_init")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("libc_csu_fini")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("do_global_dtors_aux")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("term_proc")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("fini")) {
		NameMatched = true;
	}
	else if (0 == TempFuncName.compare("frame_dummy")) {
		NameMatched = true;
	}


	return NameMatched;
}