Skip to content
Snippets Groups Projects
STARSProgram.cpp 597 KiB
Newer Older
	OptCategory[STARS_NN_vpcomleuw] = 1;            // Compare Vector Unsigned Words
	OptCategory[STARS_NN_vpcomgtuw] = 1;            // Compare Vector Unsigned Words
	OptCategory[STARS_NN_vpcomgeuw] = 1;            // Compare Vector Unsigned Words
	OptCategory[STARS_NN_vpcomequw] = 1;            // Compare Vector Unsigned Words
	OptCategory[STARS_NN_vpcomnequw] = 1;           // Compare Vector Unsigned Words
	OptCategory[STARS_NN_vpcomfalseuw] = 1;         // Compare Vector Unsigned Words
	OptCategory[STARS_NN_vpcomtrueuw] = 1;          // Compare Vector Unsigned Words

	OptCategory[STARS_NN_vpcomltud] = 1;            // Compare Vector Unsigned Doublewords
	OptCategory[STARS_NN_vpcomleud] = 1;            // Compare Vector Unsigned Doublewords
	OptCategory[STARS_NN_vpcomgtud] = 1;            // Compare Vector Unsigned Doublewords
	OptCategory[STARS_NN_vpcomgeud] = 1;            // Compare Vector Unsigned Doublewords
	OptCategory[STARS_NN_vpcomequd] = 1;            // Compare Vector Unsigned Doublewords
	OptCategory[STARS_NN_vpcomnequd] = 1;           // Compare Vector Unsigned Doublewords
	OptCategory[STARS_NN_vpcomfalseud] = 1;         // Compare Vector Unsigned Doublewords
	OptCategory[STARS_NN_vpcomtrueud] = 1;          // Compare Vector Unsigned Doublewords

	OptCategory[STARS_NN_vpcomltuq] = 1;            // Compare Vector Unsigned Quadwords
	OptCategory[STARS_NN_vpcomleuq] = 1;            // Compare Vector Unsigned Quadwords
	OptCategory[STARS_NN_vpcomgtuq] = 1;            // Compare Vector Unsigned Quadwords
	OptCategory[STARS_NN_vpcomgeuq] = 1;            // Compare Vector Unsigned Quadwords
	OptCategory[STARS_NN_vpcomequq] = 1;            // Compare Vector Unsigned Quadwords
	OptCategory[STARS_NN_vpcomnequq] = 1;           // Compare Vector Unsigned Quadwords
	OptCategory[STARS_NN_vpcomfalseuq] = 1;         // Compare Vector Unsigned Quadwords
	OptCategory[STARS_NN_vpcomtrueuq] = 1;          // Compare Vector Unsigned Quadwords

	// AMD Excavator

	OptCategory[STARS_NN_monitorx] = 1;             // Setup Monitor Address
	OptCategory[STARS_NN_mwaitx] = 1;               // Monitor Wait with Timeout

	// AMD Zen

	OptCategory[STARS_NN_clzero] = 1;               // Zero out 64 byte cache

	// Intel Processor Trace

	OptCategory[STARS_NN_ptwrite] = 1;              // Write Data to a Processor Trace Packet

	// new Intel AVX-512 instructions (December 2016)

	OptCategory[STARS_NN_v4fmaddps] = 1;            // Packed Single-Precision Floating-Point Fused Multiply-Add (4-iterations)
	OptCategory[STARS_NN_v4fnmaddps] = 1;           // Packed Single-Precision Floating-Point Fused Multiply-Add (4-iterations)
	OptCategory[STARS_NN_v4fmaddss] = 1;            // Scalar Single-Precision Floating-Point Fused Multiply-Add (4-iterations)
	OptCategory[STARS_NN_v4fnmaddss] = 1;           // Scalar Single-Precision Floating-Point Fused Multiply-Add (4-iterations)
	OptCategory[STARS_NN_vp4dpwssd] = 1;            // Dot Product of Signed Words with Dword Accumulation (4-iterations)
	OptCategory[STARS_NN_vp4dpwssds] = 1;           // Dot Product of Signed Words with Dword Accumulation and Saturation (4-iterations)
	OptCategory[STARS_NN_vpopcntd] = 1;             // Return the Count of Number of Bits Set to 1 in DWORD
	OptCategory[STARS_NN_vpopcntq] = 1;             // Return the Count of Number of Bits Set to 1 in QWORD

	// Read Processor ID

	OptCategory[STARS_NN_rdpid] = 2;                // Read Processor ID

	// Invoke VM function

	OptCategory[STARS_NN_vmfunc] = 1;               // Invoke VM function

	// Control-flow Enforcement

	OptCategory[STARS_NN_incsspd] = 1;              // Increment Shadow Stack Pointer (by 4)
	OptCategory[STARS_NN_incsspq] = 1;              // Increment Shadow Stack Pointer (by 8)
	OptCategory[STARS_NN_rdsspd] = 6;               // Read (low 32 bits of) Shadow Stack Pointer
	OptCategory[STARS_NN_rdsspq] = 6;               // Read Shadow Stack Pointer
	OptCategory[STARS_NN_saveprevssp] = 1;          // Save Previous Shadow Stack Pointer
	OptCategory[STARS_NN_rstorssp] = 1;             // Restore saved Shadow Stack Pointer
	OptCategory[STARS_NN_wrssd] = 1;                // Write (4 bytes) to shadow stack
	OptCategory[STARS_NN_wrssq] = 1;                // Write (8 bytes) to shadow stack
	OptCategory[STARS_NN_wrussd] = 1;               // Write (4 bytes) to User Shadow Stack
	OptCategory[STARS_NN_wrussq] = 1;               // Write (8 bytes) to User Shadow Stack
	OptCategory[STARS_NN_setssbsy] = 1;             // Mark Shadow Stack Busy
	OptCategory[STARS_NN_clrssbsy] = 1;             // Clear Shadow Stack Busy Flag
	OptCategory[STARS_NN_endbr64] = 1;              // Terminate an Indirect Branch in 64-bit Mode
	OptCategory[STARS_NN_endbr32] = 1;              // Terminate an Indirect Branch in 32-bit and Compatibility Mode

	// Undefined Instruction

	OptCategory[STARS_NN_ud0] = 1;                 // Undefined Instruction
	OptCategory[STARS_NN_ud1] = 1;                 // Undefined Instruction

	// Enqueue Stores

	OptCategory[STARS_NN_enqcmd] = 1;              // Enqueue Command
	OptCategory[STARS_NN_enqcmds] = 1;             // Enqueue Command Supervisor

	// AMD Zen2

	OptCategory[STARS_NN_mcommit] = 1;             // Commit Stores to Memory
	OptCategory[STARS_NN_rdpru] = 8;               // Read Processor Register

	// Intel Tremont instructions

	OptCategory[STARS_NN_cldemote] = 1;            // Cache Line Demote
	OptCategory[STARS_NN_enclv] = 1;               // Execute an Enclave VMM Function of Specified Leaf Number

	// Direct Stores

	OptCategory[STARS_NN_movdiri] = 1;             // Move Doubleword as Direct Store
	OptCategory[STARS_NN_movdir64b] = 1;           // Move 64 Bytes as Direct Store

	// Intel WAITPKG instructions

	OptCategory[STARS_NN_tpause] = 1;              // Timed PAUSE
	OptCategory[STARS_NN_umonitor] = 1;            // User Level Set Up Monitor Address
	OptCategory[STARS_NN_umwait] = 1;              // User Level Monitor Wait

	// Intel Sapphire Rapids instructions

	OptCategory[STARS_NN_serialize] = 1;           // Serialize Instruction Execution

	// Intel TSX

	OptCategory[STARS_NN_xresldtrk] = 1;           // Resume Tracking Load Addresses
	OptCategory[STARS_NN_xsusldtrk] = 1;           // Suspend Tracking Load Addresses

	// Intel Affine Transformation instructions

	OptCategory[STARS_NN_gf2p8mulb] = 1;           // Galois Field Multiply Bytes
	OptCategory[STARS_NN_gf2p8affineqb] = 1;       // Computes Affine Transformation
	OptCategory[STARS_NN_gf2p8affineinvqb] = 1;    // Computes Inverse Affine Transformation

	// VEX versions
	OptCategory[STARS_NN_vgf2p8mulb] = 1;          // Galois Field Multiply Bytes
	OptCategory[STARS_NN_vgf2p8affineqb] = 1;      // Computes Affine Transformation
	OptCategory[STARS_NN_vgf2p8affineinvqb] = 1;   // Computes Inverse Affine Transformation

	// Intrinsics for Saving and Restoring the Extended Processor States (64-bits)

	OptCategory[STARS_NN_fxsave64] = 1;            // Fast save FP context (64-bits)
	OptCategory[STARS_NN_fxrstor64] = 1;           // Fast restore FP context (64-bits)

	OptCategory[STARS_NN_last] = 1;

	return;

} // end of STARS_Program_t::InitOptCategory()

// Initialize the StackAlteration[] array to define how opcodes adjust the stack pointer.
void STARS_Program_t::InitStackAlteration(void) {
	// Default category is 0; most instructions do not alter the stack pointer.
	(void)memset(StackAlteration, 0, sizeof(StackAlteration));

	// Many arithmetic instructions could alter the stack pointer. We will have to
	//  examine each instruction that performs addition, subtraction, logical AND, etc.,
	//  to determine if the stack pointer was the DEF operand. We cannot use a purely
	//  table driven approach to compute stack pointer alteration. The table is used for
	//  the deterministic cases, e.g. push, pop, call, return. Because of variability on
	//  a few of these instructions, a value of 1 in the table below is a trigger to investigate RTLs
	//  that might or might not alter the stack pointer, e.g. add, subtract, etc., or that might
	//  have operand-dependent effects on the stack pointer.

	StackAlteration[STARS_NN_add] = 1;                  // Addition; check operands for stack pointer
	StackAlteration[STARS_NN_adc] = 1;                  // Addition; check operands for stack pointer ; RARE for stack pointer
	StackAlteration[STARS_NN_and] = 1;                  // Logical AND; check operands for stack pointer
	StackAlteration[STARS_NN_call] = -((STARS_sval_t) this->GetSTARS_ISA_Bytewidth());   // Call Procedure; -4, but return cancels it to zero
	StackAlteration[STARS_NN_callfi] = -2 * ((STARS_sval_t) this->GetSTARS_ISA_Bytewidth());              // Indirect Call Far Procedure; -8, but far return cancels it to zero
	StackAlteration[STARS_NN_callni] = -((STARS_sval_t) this->GetSTARS_ISA_Bytewidth());              // Indirect Call Near Procedure; -4, but return cancels it to zero
	StackAlteration[STARS_NN_enterw] = 1;              // Make Stack Frame for Procedure Parameters  **
	StackAlteration[STARS_NN_enter] = 1;               // Make Stack Frame for Procedure Parameters  **
	StackAlteration[STARS_NN_enterd] = 1;              // Make Stack Frame for Procedure Parameters  **
	StackAlteration[STARS_NN_enterq] = 1;              // Make Stack Frame for Procedure Parameters  **
	StackAlteration[STARS_NN_int] = 0;                 // Call to Interrupt Procedure
	StackAlteration[STARS_NN_into] = 0;                // Call to Interrupt Procedure if Overflow Flag = 1
	StackAlteration[STARS_NN_int3] = 0;                // Trap to Debugger
	StackAlteration[STARS_NN_iretw] = 6;               // Interrupt Return
	StackAlteration[STARS_NN_iret] = 12;                // Interrupt Return
	StackAlteration[STARS_NN_iretd] = 12;               // Interrupt Return (use32)
	StackAlteration[STARS_NN_iretq] = 40;               // Interrupt Return (use64)
	StackAlteration[STARS_NN_lea] = 1;                 // Load Effective Address (can be used for basic arithmetic assignments)
	StackAlteration[STARS_NN_leavew] = 1;              // High Level Procedure Exit        **
	StackAlteration[STARS_NN_leave] = 1;               // High Level Procedure Exit        **
	StackAlteration[STARS_NN_leaved] = 1;              // High Level Procedure Exit        **
	StackAlteration[STARS_NN_leaveq] = 1;              // High Level Procedure Exit        **
	StackAlteration[STARS_NN_mov] = 1;                 // Move Data ; could be esp := ebp (deallocate stack frame) or esp := ebx (unknown)
	StackAlteration[STARS_NN_pop] = 1;                 // Pop a word from the Stack  ; could be 16-bit or 32-bit operand, etc.
	StackAlteration[STARS_NN_popaw] = 14;               // Pop all General Registers
	StackAlteration[STARS_NN_popa] = 28;                // Pop all General Registers
	StackAlteration[STARS_NN_popad] = 28;               // Pop all General Registers (use32)
	StackAlteration[STARS_NN_popaq] = 56;               // Pop all General Registers (use64)
	StackAlteration[STARS_NN_popfw] = 2;               // Pop Stack into Flags Register         **
	StackAlteration[STARS_NN_popf] = 4;                // Pop Stack into Flags Register         **
	StackAlteration[STARS_NN_popfd] = 4;               // Pop Stack into Eflags Register        **
	StackAlteration[STARS_NN_popfq] = 8;               // Pop Stack into Rflags Register        **
	StackAlteration[STARS_NN_push] = 1;                // Push Operand onto the Stack  ; could be 16-bit or 32-bit operand, etc.
	StackAlteration[STARS_NN_pushaw] = -14;              // Push all General Registers
	StackAlteration[STARS_NN_pusha] = -28;               // Push all General Registers
	StackAlteration[STARS_NN_pushad] = -28;              // Push all General Registers (use32)
	StackAlteration[STARS_NN_pushaq] = -56;              // Push all General Registers (use64)
	StackAlteration[STARS_NN_pushfw] = -2;              // Push Flags Register onto the Stack
	StackAlteration[STARS_NN_pushf] = -4;               // Push Flags Register onto the Stack
	StackAlteration[STARS_NN_pushfd] = -4;              // Push Flags Register onto the Stack (use32)
	StackAlteration[STARS_NN_pushfq] = -8;              // Push Flags Register onto the Stack (use64)
	StackAlteration[STARS_NN_retn] = 1;                // Return Near from Procedure (usually 4 bytes)
	StackAlteration[STARS_NN_retf] = 1;                // Return Far from Procedure (usually 8 bytes)
	StackAlteration[STARS_NN_sub] = 1;                  // Subtraction; check operands for stack pointer
	StackAlteration[STARS_NN_sbb] = 1;                  // Subtraction; check operands for stack pointer ; RARE for stack pointer

	//
	//      486 instructions
	//


	//
	//      Pentium instructions
	//


	//
	//      Pentium Pro instructions
	//


	//
	//      FPP instructions
	//


	//
	//      80387 instructions
	//

	//
	//      Instructions added 28.02.96
	//

	StackAlteration[STARS_NN_loadall] = 0;             // Load the entire CPU state from ES:EDI ?? Cannot find in Intel manuals

	//
	//      MMX instructions
	//


	//
	//      Undocumented Deschutes processor instructions
	//

	//      Pentium II instructions

	StackAlteration[STARS_NN_sysenter] = 0;            // Fast Transition to System Call Entry Point
	StackAlteration[STARS_NN_sysexit] = 0;             // Fast Transition from System Call Entry Point

	//      3DNow! instructions


	//      Pentium III instructions


	// Pentium III Pseudo instructions

	// AMD K7 instructions

	// Revisit AMD if we port to it.

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

	// Pentium 4 instructions


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

	StackAlteration[STARS_NN_syscall] = 0;             // Low latency system call
	StackAlteration[STARS_NN_sysret] = 0;              // Return from system call

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

	// New Pentium instructions (SSE3)


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

	// SSE3 instructions

	// SSSE3 instructions


	// VMX instructions

	// Added with x86-64

	// Geode LX 3DNow! extensions

	// SSE2 pseudoinstructions


	// SSSE4.1 instructions


	// SSSE4.2 instructions

	// AMD SSE4a instructions

	// xsave/xrstor instructions

	// Intel Safer Mode Extensions (SMX)

	// AMD-V Virtualization ISA Extension

	// VMX+ instructions

	// Intel Atom instructions

	// Intel AES instructions

	// Carryless multiplication

	// Returns modified by operand size prefixes

	StackAlteration[STARS_NN_retnw] = 1;               // Return Near from Procedure (use16)
	StackAlteration[STARS_NN_retnd] = 1;               // Return Near from Procedure (use32)
	StackAlteration[STARS_NN_retnq] = 1;               // Return Near from Procedure (use64)
	StackAlteration[STARS_NN_retfw] = 1;               // Return Far from Procedure (use16)
	StackAlteration[STARS_NN_retfd] = 1;               // Return Far from Procedure (use32)
	StackAlteration[STARS_NN_retfq] = 1;               // Return Far from Procedure (use64)

	// RDRAND support

	// new GPR instructions

	// new AVX instructions

	// Transactional Synchronization Extensions

	// Virtual PC synthetic instructions

	// FMA4

	// Intel Memory Protection Extensions (MPX)

	// New xstate instructions

	// PREFETCHWT1 support

	// Memory instructions

	// Protection Key Rights for User Pages

	// AVX comparison pseudo-ops

	// AVX-512 instructions

	// AVX-512 comparison pseudo-ops

	// Opmask instructions

	// SHA Extensions

	// Intel Software Guard Extensions

	// AMD XOP

	// AMP XOP comparison pseudo-ops

	// AMD Excavator

	// AMD Zen

	// Intel Processor Trace

	// new Intel AVX-512 instructions (December 2016)

	// Read Processor ID

	// Invoke VM function

	// Control-flow Enforcement

	// Undefined Instruction

	// Enqueue Stores

	// AMD Zen2

	// Intel Tremont instructions

	// Direct Stores

	// Intel WAITPKG instructions

	// Intel Sapphire Rapids instructions

	// Intel TSX

	// Intel Affine Transformation instructions

	// VEX versions

	// Intrinsics for Saving and Restoring the Extended Processor States (64-bits)


	StackAlteration[STARS_NN_last] = 0;

	return;

} // end STARS_Program_t::InitStackAlteration()

// Initialize the lookup maps that are used to define the FG info that can
//  be inferred from a library function name.
void STARS_Program_t::InitLibFuncFGInfoMaps(void) {

	// empty it in case it was filled from a prevoius stars invocation.
	ReturnRegisterTypeMap.clear();

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

	// Add functions that return signed integers.
	FGEntry.SignMiscInfo = FG_MASK_SIGNED;
	FGEntry.SizeInfo = (FG_MASK_INTEGER | ComputeOperandBitWidthMask(nullptr, sizeof(int)));
	MapEntry.second = FGEntry;

	MapEntry.first = "atoi";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strcmp";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strcoll";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strncmp";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "memcmp";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "isalnum";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "isalpha";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "islower";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "isupper";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "isdigit";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "isxdigit";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "iscntrl";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "isgraph";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "isblank";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "isspace";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "isprint";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "ispunct";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	// Functions that return signed longs.
	if (sizeof(long int) != sizeof(int)) {
		FGEntry.SizeInfo = (FG_MASK_INTEGER | ComputeOperandBitWidthMask(nullptr, sizeof(long int)));
		MapEntry.second = FGEntry;
	}

	MapEntry.first = "atol";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strtol";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	// Functions that return signed long longs.
	if (sizeof(long long int) != sizeof(long int)) {
		FGEntry.SizeInfo = (FG_MASK_INTEGER | ComputeOperandBitWidthMask(nullptr, sizeof(long long int)));
		MapEntry.second = FGEntry;
	}

	MapEntry.first = "atoll";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strtoll";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	// Functions that return unsigned long longs.
	FGEntry.SignMiscInfo = FG_MASK_UNSIGNED;
	MapEntry.second = FGEntry;

	MapEntry.first = "strtoull";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	// Functions that return unsigned longs.
	if (sizeof(long long int) != sizeof(long int)) {
		FGEntry.SizeInfo = (FG_MASK_INTEGER | ComputeOperandBitWidthMask(nullptr, sizeof(long int)));
		MapEntry.second = FGEntry;
	}

	MapEntry.first = "strtoul";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	// Functions that return size_t.
	FGEntry.SizeInfo = (FG_MASK_INTEGER | ComputeOperandBitWidthMask(nullptr, sizeof(size_t)));
	FGEntry.SignMiscInfo = FG_MASK_UNSIGNED;
	MapEntry.second = FGEntry;

	MapEntry.first = "strlen";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strxfrm";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strspn";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strcspn";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strftime";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	// Functions that return (char *).
	FGEntry.SizeInfo = (FG_MASK_DATAPOINTER | ComputeOperandBitWidthMask(nullptr, sizeof(char *)));
	FGEntry.SignMiscInfo = FG_MASK_UNSIGNED;
	MapEntry.second = FGEntry;

	MapEntry.first = "strcpy";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strncpy";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strcat";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strncat";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strchr";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strrchr";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strpbrk";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strstr";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strtok";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "strerror";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "asctime";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "ctime";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	// Functions that return (void *) or a similar data pointer.
	FGEntry.SizeInfo = (FG_MASK_DATAPOINTER | ComputeOperandBitWidthMask(nullptr, sizeof(void *)));
	FGEntry.SignMiscInfo = FG_MASK_UNSIGNED;
	MapEntry.second = FGEntry;

	MapEntry.first = "setlocale";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "localeconv";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "malloc";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "calloc";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "realloc";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "memchr";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "memcpy";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "mempcpy";  // non-standard, found in glibc
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "memmove";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "memset";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "gmtime";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	MapEntry.first = "localtime";
	InsertResult = ReturnRegisterTypeMap.insert(MapEntry);
	assert(InsertResult.second);

	// Functions that return bool.
	FGEntry.SizeInfo = (FG_MASK_INTEGER | ComputeOperandBitWidthMask(nullptr, sizeof(bool)));
	FGEntry.SignMiscInfo = FG_MASK_UNSIGNED;
	MapEntry.second = FGEntry;


	// NOTE: Add <math.h> functions later.

	return;
} // end of STARS_Program_t::InitLibFuncFGInfoMaps()

// Initialize the DFACategory[] array to define instruction classes
//   for the purposes of data flow analysis. (Really, control flow analysis.)
void STARS_Program_t::InitDFACategory(void) 
{
	if(processor_type==ptARM64)
	{
		DFACategory.resize(STARS_ARM_last+1);
		DFACategory[STARS_ARM_bl]  = CALL;                    
		DFACategory[STARS_ARM_blr] = INDIR_CALL;              
		DFACategory[STARS_ARM_br]  = INDIR_JUMP;             
		DFACategory[STARS_ARM_ret] = RETURN;                
	}
	else
	{
		// Default category is 0, not the start or end of a basic block.
		DFACategory.resize(STARS_NN_last+1);

		DFACategory[STARS_NN_call] = CALL;                // Call Procedure
		DFACategory[STARS_NN_callfi] = INDIR_CALL;              // Indirect Call Far Procedure
		DFACategory[STARS_NN_callni] = INDIR_CALL;              // Indirect Call Near Procedure

		DFACategory[STARS_NN_hlt] = HALT;                 // Halt

		DFACategory[STARS_NN_int] = INDIR_CALL;                 // Call to Interrupt Procedure
		DFACategory[STARS_NN_into] = INDIR_CALL;                // Call to Interrupt Procedure if Overflow Flag = 1
		DFACategory[STARS_NN_int3] = INDIR_CALL;                // Trap to Debugger
		DFACategory[STARS_NN_iretw] = RETURN;               // Interrupt Return
		DFACategory[STARS_NN_iret] = RETURN;                // Interrupt Return
		DFACategory[STARS_NN_iretd] = RETURN;               // Interrupt Return (use32)
		DFACategory[STARS_NN_iretq] = RETURN;               // Interrupt Return (use64)
		DFACategory[STARS_NN_ja] = COND_BRANCH;                  // Jump if Above (CF=0 & ZF=0)
		DFACategory[STARS_NN_jae] = COND_BRANCH;                 // Jump if Above or Equal (CF=0)
		DFACategory[STARS_NN_jb] = COND_BRANCH;                  // Jump if Below (CF=1)
		DFACategory[STARS_NN_jbe] = COND_BRANCH;                 // Jump if Below or Equal (CF=1 | ZF=1)
		DFACategory[STARS_NN_jc] = COND_BRANCH;                  // Jump if Carry (CF=1)
		DFACategory[STARS_NN_jcxz] = COND_BRANCH;                // Jump if CX is 0
		DFACategory[STARS_NN_jecxz] = COND_BRANCH;               // Jump if ECX is 0
		DFACategory[STARS_NN_jrcxz] = COND_BRANCH;               // Jump if RCX is 0
		DFACategory[STARS_NN_je] = COND_BRANCH;                  // Jump if Equal (ZF=1)
		DFACategory[STARS_NN_jg] = COND_BRANCH;                  // Jump if Greater (ZF=0 & SF=OF)
		DFACategory[STARS_NN_jge] = COND_BRANCH;                 // Jump if Greater or Equal (SF=OF)
		DFACategory[STARS_NN_jl] = COND_BRANCH;                  // Jump if Less (SF!=OF)
		DFACategory[STARS_NN_jle] = COND_BRANCH;                 // Jump if Less or Equal (ZF=1 | SF!=OF)
		DFACategory[STARS_NN_jna] = COND_BRANCH;                 // Jump if Not Above (CF=1 | ZF=1)
		DFACategory[STARS_NN_jnae] = COND_BRANCH;                // Jump if Not Above or Equal (CF=1)
		DFACategory[STARS_NN_jnb] = COND_BRANCH;                 // Jump if Not Below (CF=0)
		DFACategory[STARS_NN_jnbe] = COND_BRANCH;                // Jump if Not Below or Equal (CF=0 & ZF=0)
		DFACategory[STARS_NN_jnc] = COND_BRANCH;                 // Jump if Not Carry (CF=0)
		DFACategory[STARS_NN_jne] = COND_BRANCH;                 // Jump if Not Equal (ZF=0)
		DFACategory[STARS_NN_jng] = COND_BRANCH;                 // Jump if Not Greater (ZF=1 | SF!=OF)
		DFACategory[STARS_NN_jnge] = COND_BRANCH;                // Jump if Not Greater or Equal (SF!=OF)
		DFACategory[STARS_NN_jnl] = COND_BRANCH;                 // Jump if Not Less (SF=OF)
		DFACategory[STARS_NN_jnle] = COND_BRANCH;                // Jump if Not Less or Equal (ZF=0 & SF=OF)
		DFACategory[STARS_NN_jno] = COND_BRANCH;                 // Jump if Not Overflow (OF=0)
		DFACategory[STARS_NN_jnp] = COND_BRANCH;                 // Jump if Not Parity (PF=0)
		DFACategory[STARS_NN_jns] = COND_BRANCH;                 // Jump if Not Sign (SF=0)
		DFACategory[STARS_NN_jnz] = COND_BRANCH;                 // Jump if Not Zero (ZF=0)
		DFACategory[STARS_NN_jo] = COND_BRANCH;                  // Jump if Overflow (OF=1)
		DFACategory[STARS_NN_jp] = COND_BRANCH;                  // Jump if Parity (PF=1)
		DFACategory[STARS_NN_jpe] = COND_BRANCH;                 // Jump if Parity Even (PF=1)
		DFACategory[STARS_NN_jpo] = COND_BRANCH;                 // Jump if Parity Odd  (PF=0)
		DFACategory[STARS_NN_js] = COND_BRANCH;                  // Jump if Sign (SF=1)
		DFACategory[STARS_NN_jz] = COND_BRANCH;                  // Jump if Zero (ZF=1)
		DFACategory[STARS_NN_jmp] = JUMP;                 // Jump
		DFACategory[STARS_NN_jmpfi] = INDIR_JUMP;               // Indirect Far Jump
		DFACategory[STARS_NN_jmpni] = INDIR_JUMP;               // Indirect Near Jump
		DFACategory[STARS_NN_jmpshort] = JUMP;            // Jump Short (only in 64-bit mode)
		DFACategory[STARS_NN_loopw] = COND_BRANCH;               // Loop while ECX != 0
		DFACategory[STARS_NN_loop] = COND_BRANCH;                // Loop while CX != 0
		DFACategory[STARS_NN_loopd] = COND_BRANCH;               // Loop while ECX != 0
		DFACategory[STARS_NN_loopq] = COND_BRANCH;               // Loop while RCX != 0
		DFACategory[STARS_NN_loopwe] = COND_BRANCH;              // Loop while CX != 0 and ZF=1
		DFACategory[STARS_NN_loope] = COND_BRANCH;               // Loop while rCX != 0 and ZF=1
		DFACategory[STARS_NN_loopde] = COND_BRANCH;              // Loop while ECX != 0 and ZF=1
		DFACategory[STARS_NN_loopqe] = COND_BRANCH;              // Loop while RCX != 0 and ZF=1
		DFACategory[STARS_NN_loopwne] = COND_BRANCH;             // Loop while CX != 0 and ZF=0
		DFACategory[STARS_NN_loopne] = COND_BRANCH;              // Loop while rCX != 0 and ZF=0
		DFACategory[STARS_NN_loopdne] = COND_BRANCH;             // Loop while ECX != 0 and ZF=0
		DFACategory[STARS_NN_loopqne] = COND_BRANCH;             // Loop while RCX != 0 and ZF=0
		DFACategory[STARS_NN_retn] = RETURN;                // Return Near from Procedure
		DFACategory[STARS_NN_retf] = RETURN;                // Return Far from Procedure
		DFACategory[STARS_NN_rsm] = HALT;                 // Resume from System Management Mode
		DFACategory[STARS_NN_sysenter] = INDIR_CALL;            // Fast Transition to System Call Entry Point
		DFACategory[STARS_NN_sysexit] = RETURN;             // Fast Transition from System Call Entry Point
		// AMD syscall/sysret instructions  NOTE: not AMD, found in Intel manual
		DFACategory[STARS_NN_syscall] = INDIR_CALL;             // Low latency system call
		DFACategory[STARS_NN_sysret] = RETURN;              // Return from system call
		DFACategory[STARS_NN_vmcall] = INDIR_CALL;              // Call to VM Monitor
		// AMD-V Virtualization ISA Extension
		// Returns modified by operand size prefixes
		DFACategory[STARS_NN_retnw] = RETURN;               // Return Near from Procedure (use16)
		DFACategory[STARS_NN_retnd] = RETURN;               // Return Near from Procedure (use32)
		DFACategory[STARS_NN_retnq] = RETURN;               // Return Near from Procedure (use64)
		DFACategory[STARS_NN_retfw] = RETURN;               // Return Far from Procedure (use16)
		DFACategory[STARS_NN_retfd] = RETURN;               // Return Far from Procedure (use32)
		DFACategory[STARS_NN_retfq] = RETURN;               // Return Far from Procedure (use64)
		// Transactional Synchronization Extensions

		// Virtual PC synthetic instructions

		// FMA4

		// Intel Memory Protection Extensions (MPX)

		// New xstate instructions

		// PREFETCHWT1 support

		// Memory instructions

		// Protection Key Rights for User Pages

		// AVX comparison pseudo-ops

		// AVX-512 instructions

		// AVX-512 comparison pseudo-ops

		// Opmask instructions

		// SHA Extensions

		// Intel Software Guard Extensions

		// AMD XOP

		// AMP XOP comparison pseudo-ops

		// AMD Excavator

		// AMD Zen

		// Intel Processor Trace

		// new Intel AVX-512 instructions (December 2016)

		// Read Processor ID

		// Invoke VM function

		// Control-flow Enforcement

		// Undefined Instruction

		// Enqueue Stores

		// AMD Zen2

		// Intel Tremont instructions

		// Direct Stores

		// Intel WAITPKG instructions

		// Intel Sapphire Rapids instructions

		// Intel TSX

		// Intel Affine Transformation instructions

		// VEX versions

		// Intrinsics for Saving and Restoring the Extended Processor States (64-bits)



} // end of STARS_Program_t::InitDFACategory()

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

	SMPDefsFlags[STARS_NN_null] = false;            // Unknown Operation
	SMPDefsFlags[STARS_NN_bound] = false;               // Check Array Index Against Bounds
	SMPDefsFlags[STARS_NN_call] = false;                // Call Procedure
	SMPDefsFlags[STARS_NN_callfi] = false;              // Indirect Call Far Procedure
	SMPDefsFlags[STARS_NN_callni] = false;              // Indirect Call Near Procedure
	SMPDefsFlags[STARS_NN_cbw] = false;                 // AL -> AX (with sign)           
	SMPDefsFlags[STARS_NN_cwde] = false;                // AX -> EAX (with sign)            
	SMPDefsFlags[STARS_NN_cdqe] = false;                // EAX -> RAX (with sign)           
	SMPDefsFlags[STARS_NN_clts] = false;                // Clear Task-Switched Flag in CR0
	SMPDefsFlags[STARS_NN_cwd] = false;                 // AX -> DX:AX (with sign)
	SMPDefsFlags[STARS_NN_cdq] = false;                 // EAX -> EDX:EAX (with sign)
	SMPDefsFlags[STARS_NN_cqo] = false;                 // RAX -> RDX:RAX (with sign)
	SMPDefsFlags[STARS_NN_enterw] = false;              // Make Stack Frame for Procedure Parameters   
	SMPDefsFlags[STARS_NN_enter] = false;               // Make Stack Frame for Procedure Parameters   
	SMPDefsFlags[STARS_NN_enterd] = false;              // Make Stack Frame for Procedure Parameters   
	SMPDefsFlags[STARS_NN_enterq] = false;              // Make Stack Frame for Procedure Parameters   
	SMPDefsFlags[STARS_NN_hlt] = false;                 // Halt
	SMPDefsFlags[STARS_NN_in] = false;                  // Input from Port                          
	SMPDefsFlags[STARS_NN_ins] = false;                 // Input Byte(s) from Port to String        
	SMPDefsFlags[STARS_NN_iretw] = false;               // Interrupt Return
	SMPDefsFlags[STARS_NN_iret] = false;                // Interrupt Return
	SMPDefsFlags[STARS_NN_iretd] = false;               // Interrupt Return (use32)
	SMPDefsFlags[STARS_NN_iretq] = false;               // Interrupt Return (use64)
	SMPDefsFlags[STARS_NN_ja] = false;                  // Jump if Above (CF=0 & ZF=0)
	SMPDefsFlags[STARS_NN_jae] = false;                 // Jump if Above or Equal (CF=0)
	SMPDefsFlags[STARS_NN_jb] = false;                  // Jump if Below (CF=1)
	SMPDefsFlags[STARS_NN_jbe] = false;                 // Jump if Below or Equal (CF=1 | ZF=1)
	SMPDefsFlags[STARS_NN_jc] = false;                  // Jump if Carry (CF=1)
	SMPDefsFlags[STARS_NN_jcxz] = false;                // Jump if CX is 0
	SMPDefsFlags[STARS_NN_jecxz] = false;               // Jump if ECX is 0
	SMPDefsFlags[STARS_NN_jrcxz] = false;               // Jump if RCX is 0
	SMPDefsFlags[STARS_NN_je] = false;                  // Jump if Equal (ZF=1)
	SMPDefsFlags[STARS_NN_jg] = false;                  // Jump if Greater (ZF=0 & SF=OF)
	SMPDefsFlags[STARS_NN_jge] = false;                 // Jump if Greater or Equal (SF=OF)
	SMPDefsFlags[STARS_NN_jl] = false;                  // Jump if Less (SF!=OF)
	SMPDefsFlags[STARS_NN_jle] = false;                 // Jump if Less or Equal (ZF=1 | SF!=OF)
	SMPDefsFlags[STARS_NN_jna] = false;                 // Jump if Not Above (CF=1 | ZF=1)
	SMPDefsFlags[STARS_NN_jnae] = false;                // Jump if Not Above or Equal (CF=1)
	SMPDefsFlags[STARS_NN_jnb] = false;                 // Jump if Not Below (CF=0)
	SMPDefsFlags[STARS_NN_jnbe] = false;                // Jump if Not Below or Equal (CF=0 & ZF=0)
	SMPDefsFlags[STARS_NN_jnc] = false;                 // Jump if Not Carry (CF=0)
	SMPDefsFlags[STARS_NN_jne] = false;                 // Jump if Not Equal (ZF=0)
	SMPDefsFlags[STARS_NN_jng] = false;                 // Jump if Not Greater (ZF=1 | SF!=OF)
	SMPDefsFlags[STARS_NN_jnge] = false;                // Jump if Not Greater or Equal (SF!=OF)
	SMPDefsFlags[STARS_NN_jnl] = false;                 // Jump if Not Less (SF=OF)
	SMPDefsFlags[STARS_NN_jnle] = false;                // Jump if Not Less or Equal (ZF=0 & SF=OF)
	SMPDefsFlags[STARS_NN_jno] = false;                 // Jump if Not Overflow (OF=0)
	SMPDefsFlags[STARS_NN_jnp] = false;                 // Jump if Not Parity (PF=0)
	SMPDefsFlags[STARS_NN_jns] = false;                 // Jump if Not Sign (SF=0)
	SMPDefsFlags[STARS_NN_jnz] = false;                 // Jump if Not Zero (ZF=0)
	SMPDefsFlags[STARS_NN_jo] = false;                  // Jump if Overflow (OF=1)
	SMPDefsFlags[STARS_NN_jp] = false;                  // Jump if Parity (PF=1)
	SMPDefsFlags[STARS_NN_jpe] = false;                 // Jump if Parity Even (PF=1)
	SMPDefsFlags[STARS_NN_jpo] = false;                 // Jump if Parity Odd  (PF=0)
	SMPDefsFlags[STARS_NN_js] = false;                  // Jump if Sign (SF=1)
	SMPDefsFlags[STARS_NN_jz] = false;                  // Jump if Zero (ZF=1)
	SMPDefsFlags[STARS_NN_jmp] = false;                 // Jump
	SMPDefsFlags[STARS_NN_jmpfi] = false;               // Indirect Far Jump
	SMPDefsFlags[STARS_NN_jmpni] = false;               // Indirect Near Jump
	SMPDefsFlags[STARS_NN_jmpshort] = false;            // Jump Short (not used)
	SMPDefsFlags[STARS_NN_lahf] = false;                // Load Flags into AH Register
	SMPDefsFlags[STARS_NN_lea] = false;                 // Load Effective Address            
	SMPDefsFlags[STARS_NN_leavew] = false;              // High Level Procedure Exit         
	SMPDefsFlags[STARS_NN_leave] = false;               // High Level Procedure Exit         
	SMPDefsFlags[STARS_NN_leaved] = false;              // High Level Procedure Exit         
	SMPDefsFlags[STARS_NN_leaveq] = false;              // High Level Procedure Exit         
	SMPDefsFlags[STARS_NN_lgdt] = false;                // Load Global Descriptor Table Register
	SMPDefsFlags[STARS_NN_lidt] = false;                // Load Interrupt Descriptor Table Register
	SMPDefsFlags[STARS_NN_lgs] = false;                 // Load Full Pointer to GS:xx
	SMPDefsFlags[STARS_NN_lss] = false;                 // Load Full Pointer to SS:xx
	SMPDefsFlags[STARS_NN_lds] = false;                 // Load Full Pointer to DS:xx
	SMPDefsFlags[STARS_NN_les] = false;                 // Load Full Pointer to ES:xx
	SMPDefsFlags[STARS_NN_lfs] = false;                 // Load Full Pointer to FS:xx
	SMPDefsFlags[STARS_NN_loopw] = false;               // Loop while ECX != 0
	SMPDefsFlags[STARS_NN_loop] = false;                // Loop while ECX != 0
	SMPDefsFlags[STARS_NN_loopwe] = false;              // Loop while CX != 0 and ZF=1
	SMPDefsFlags[STARS_NN_loope] = false;               // Loop while rCX != 0 and ZF=1
	SMPDefsFlags[STARS_NN_loopde] = false;              // Loop while ECX != 0 and ZF=1
	SMPDefsFlags[STARS_NN_loopqe] = false;              // Loop while RCX != 0 and ZF=1
	SMPDefsFlags[STARS_NN_loopwne] = false;             // Loop while CX != 0 and ZF=0
	SMPDefsFlags[STARS_NN_loopne] = false;              // Loop while rCX != 0 and ZF=0
	SMPDefsFlags[STARS_NN_loopdne] = false;             // Loop while ECX != 0 and ZF=0
	SMPDefsFlags[STARS_NN_loopqne] = false;             // Loop while RCX != 0 and ZF=0
	SMPDefsFlags[STARS_NN_ltr] = false;                 // Load Task Register
	SMPDefsFlags[STARS_NN_mov] = false;                 // Move Data
	SMPDefsFlags[STARS_NN_movsp] = true;                // Move to/from Special Registers
	SMPDefsFlags[STARS_NN_movs] = false;                // Move Byte(s) from String to String
	SMPDefsFlags[STARS_NN_movsx] = false;               // Move with Sign-Extend
	SMPDefsFlags[STARS_NN_movzx] = false;               // Move with Zero-Extend
	SMPDefsFlags[STARS_NN_nop] = false;                 // No Operation
	SMPDefsFlags[STARS_NN_not] = false;                 // One's Complement Negation
	SMPDefsFlags[STARS_NN_out] = false;                 // Output to Port
	SMPDefsFlags[STARS_NN_outs] = false;                // Output Byte(s) to Port
	SMPDefsFlags[STARS_NN_pop] = false;                 // Pop a word from the Stack
	SMPDefsFlags[STARS_NN_popaw] = false;               // Pop all General Registers
	SMPDefsFlags[STARS_NN_popa] = false;                // Pop all General Registers
	SMPDefsFlags[STARS_NN_popad] = false;               // Pop all General Registers (use32)
	SMPDefsFlags[STARS_NN_popaq] = false;               // Pop all General Registers (use64)
	SMPDefsFlags[STARS_NN_push] = false;                // Push Operand onto the Stack
	SMPDefsFlags[STARS_NN_pushaw] = false;              // Push all General Registers
	SMPDefsFlags[STARS_NN_pusha] = false;               // Push all General Registers
	SMPDefsFlags[STARS_NN_pushad] = false;              // Push all General Registers (use32)
	SMPDefsFlags[STARS_NN_pushaq] = false;              // Push all General Registers (use64)
	SMPDefsFlags[STARS_NN_pushfw] = false;              // Push Flags Register onto the Stack
	SMPDefsFlags[STARS_NN_pushf] = false;               // Push Flags Register onto the Stack
	SMPDefsFlags[STARS_NN_pushfd] = false;              // Push Flags Register onto the Stack (use32)
	SMPDefsFlags[STARS_NN_pushfq] = false;              // Push Flags Register onto the Stack (use64)
	SMPDefsFlags[STARS_NN_rep] = false;                 // Repeat String Operation