void Register_is_not_too_big() { const int maxValue = IcedConstants.RegisterEnumCount - 1 + Registers.ExtraRegisters; Static.Assert(maxValue < (1 << InstrOpInfo.TEST_RegisterBits) ? 0 : -1); Static.Assert(maxValue >= (1 << (InstrOpInfo.TEST_RegisterBits - 1)) ? 0 : -1); }
static (string hexBytes, Code code, DecoderOptions options, InstructionInfoTestCase testCase) ParseLine(string line, int bitness, Dictionary <string, Register> toRegister) { Static.Assert(MiscInstrInfoTestConstants.InstrInfoElemsPerLine == 5 ? 0 : -1); var elems = line.Split(commaSeparator, MiscInstrInfoTestConstants.InstrInfoElemsPerLine); if (elems.Length != MiscInstrInfoTestConstants.InstrInfoElemsPerLine) { throw new Exception($"Expected {MiscInstrInfoTestConstants.InstrInfoElemsPerLine - 1} commas"); } var testCase = new InstructionInfoTestCase(); testCase.IP = bitness switch { 16 => DecoderConstants.DEFAULT_IP16, 32 => DecoderConstants.DEFAULT_IP32, 64 => DecoderConstants.DEFAULT_IP64, _ => throw new InvalidOperationException(), }; var hexBytes = ToHexBytes(elems[0].Trim()); var codeStr = elems[1].Trim(); if (CodeUtils.IsIgnored(codeStr)) { return(default);
/// <summary> /// Negates the condition code, eg. <c>JE</c> -> <c>JNE</c>. Can be used if it's <c>Jcc</c>, <c>SETcc</c>, <c>CMOVcc</c>, <c>LOOPcc</c> /// and returns the original value if it's none of those instructions. /// </summary> /// <param name="code">Code value</param> /// <returns></returns> public static Code NegateConditionCode(this Code code) { uint t; if ((t = (uint)(code - Code.Jo_rel16)) <= (uint)(Code.Jg_rel32_64 - Code.Jo_rel16) || (t = (uint)(code - Code.Jo_rel8_16)) <= (uint)(Code.Jg_rel8_64 - Code.Jo_rel8_16) || (t = (uint)(code - Code.Cmovo_r16_rm16)) <= (uint)(Code.Cmovg_r64_rm64 - Code.Cmovo_r16_rm16)) { // They're ordered, eg. je_16, je_32, je_64, jne_16, jne_32, jne_64 // if low 3, add 3, else if high 3, subtract 3. //return (((int)((t / 3) << 31) >> 31) | 1) * 3 + code; if (((t / 3) & 1) != 0) { return(code - 3); } return(code + 3); } t = (uint)(code - Code.Seto_rm8); if (t <= (uint)(Code.Setg_rm8 - Code.Seto_rm8)) { return((int)(t ^ 1) + Code.Seto_rm8); } Static.Assert(Code.Loopne_rel8_16_CX + 7 == Code.Loope_rel8_16_CX ? 0 : -1); t = (uint)(code - Code.Loopne_rel8_16_CX); if (t <= (uint)(Code.Loope_rel8_64_RCX - Code.Loopne_rel8_16_CX)) { return(Code.Loopne_rel8_16_CX + (int)((t + 7) % 14)); } return(code); }
public override void Decode(Decoder decoder, ref Instruction instruction) { Debug.Assert(decoder.state.Encoding == EncodingKind.MVEX); if (decoder.invalidCheckMask != 0 && ((decoder.state.vvvv_invalidCheck & 0xF) != 0 || decoder.state.aaa == 0)) { decoder.SetInvalidInstruction(); } instruction.InternalSetCodeNoCheck(code); Static.Assert(OpKind.Register == 0 ? 0 : -1); //instruction.Op1Kind = OpKind.Register; instruction.Op1Register = (int)(decoder.state.reg + decoder.state.zs.extraRegisterBase + decoder.state.extraRegisterBaseEVEX) + Register.ZMM0; var mvex = new MvexInfo(code); var sss = decoder.state.Sss; if (decoder.state.mod == 3) { decoder.SetInvalidInstruction(); } else { instruction.Op0Kind = OpKind.Memory; if ((decoder.state.zs.flags & StateFlags.MvexEH) != 0) { instruction.InternalSetIsMvexEvictionHint(); } if ((mvex.InvalidConvFns & (1U << sss) & decoder.invalidCheckMask) != 0) { decoder.SetInvalidInstruction(); } instruction.InternalSetMvexRegMemConv(MvexRegMemConv.MemConvNone + sss); decoder.ReadOpMem_VSIB(ref instruction, Register.ZMM0, mvex.GetTupleType(sss)); } }
static MemorySizeInfoTestCase ParseLine(string line, int lineNo) { Static.Assert(MiscInstrInfoTestConstants.MemorySizeElemsPerLine == 6 ? 0 : -1); var elems = line.Split(commaSeparator, MiscInstrInfoTestConstants.MemorySizeElemsPerLine); if (elems.Length != MiscInstrInfoTestConstants.MemorySizeElemsPerLine) { throw new Exception($"Expected {MiscInstrInfoTestConstants.MemorySizeElemsPerLine - 1} commas"); } var tc = new MemorySizeInfoTestCase(); tc.LineNumber = lineNo; tc.MemorySize = ToEnumConverter.GetMemorySize(elems[0].Trim()); tc.Size = NumberConverter.ToInt32(elems[1].Trim()); tc.ElementSize = NumberConverter.ToInt32(elems[2].Trim()); tc.ElementType = ToEnumConverter.GetMemorySize(elems[3].Trim()); tc.ElementCount = NumberConverter.ToInt32(elems[4].Trim()); foreach (var value in elems[5].Split(spaceSeparator, StringSplitOptions.RemoveEmptyEntries)) { if (!InstructionInfoDicts.MemorySizeFlagsTable.TryGetValue(value, out var flags)) { throw new InvalidOperationException($"Invalid flags value: {value}"); } tc.Flags |= flags; } return(tc); }
public static bool IsNotrackPrefixBranch(Code code) { Static.Assert(Code.Jmp_rm16 + 1 == Code.Jmp_rm32 ? 0 : -1); Static.Assert(Code.Jmp_rm16 + 2 == Code.Jmp_rm64 ? 0 : -1); Static.Assert(Code.Call_rm16 + 1 == Code.Call_rm32 ? 0 : -1); Static.Assert(Code.Call_rm16 + 2 == Code.Call_rm64 ? 0 : -1); return (uint)code - (uint)Code.Jmp_rm16 <= 2 || (uint)code - (uint)Code.Call_rm16 <= 2; }
public override void Decode(Decoder decoder, ref Instruction instruction) { Debug.Assert(decoder.state.Encoding == EncodingKind.Legacy); Static.Assert(OpKind.Register == 0 ? 0 : -1); //instruction.Op0Kind = OpKind.Register; instruction.Op0Register = (int)decoder.state.reg + Register.MM0; if (decoder.state.mod == 3) { Static.Assert(OpKind.Register == 0 ? 0 : -1); //instruction.Op1Kind = OpKind.Register; instruction.Op1Register = (int)decoder.state.rm + Register.MM0; } else { instruction.Op1Kind = OpKind.Memory; decoder.ReadOpMem(ref instruction); } var code = codeValues[(int)decoder.ReadByte()]; switch (code) { case Code.D3NOW_Pfrcpv_mm_mmm64: case Code.D3NOW_Pfrsqrtv_mm_mmm64: if ((decoder.options & DecoderOptions.Cyrix) == 0 || decoder.Bitness == 64) { code = Code.INVALID; } break; } instruction.InternalSetCodeNoCheck(code); if (code == Code.INVALID) { decoder.SetInvalidInstruction(); } }
void INVALID_Code_value_is_zero() { // A 'default' Instruction should be an invalid instruction Static.Assert((int)Code.INVALID == 0 ? 0 : -1); Instruction instruction1 = default; Assert.Equal(Code.INVALID, instruction1.Code); var instruction2 = new Instruction(); Assert.Equal(Code.INVALID, instruction2.Code); Assert.True(Instruction.EqualsAllBits(instruction1, instruction2)); }
public OpCodeHandler_MandatoryPrefix2_NoModRM(OpCodeHandler handler, OpCodeHandler handler66, OpCodeHandler handlerF3, OpCodeHandler handlerF2) { Static.Assert((int)MandatoryPrefixByte.None == 0 ? 0 : -1); Static.Assert((int)MandatoryPrefixByte.P66 == 1 ? 0 : -1); Static.Assert((int)MandatoryPrefixByte.PF3 == 2 ? 0 : -1); Static.Assert((int)MandatoryPrefixByte.PF2 == 3 ? 0 : -1); handlers = new OpCodeHandler[4] { handler ?? throw new ArgumentNullException(nameof(handler)), handler66 ?? throw new ArgumentNullException(nameof(handler66)), handlerF3 ?? throw new ArgumentNullException(nameof(handlerF3)), handlerF2 ?? throw new ArgumentNullException(nameof(handlerF2)), }; Debug.Assert(handler.HasModRM == HasModRM); Debug.Assert(handler66.HasModRM == HasModRM); Debug.Assert(handlerF3.HasModRM == HasModRM); Debug.Assert(handlerF2.HasModRM == HasModRM); }
void Verify_ConditionCode_values_are_in_correct_order() { Static.Assert((int)ConditionCode.None == 0 ? 0 : -1); Static.Assert((int)ConditionCode.o == 1 ? 0 : -1); Static.Assert((int)ConditionCode.no == 2 ? 0 : -1); Static.Assert((int)ConditionCode.b == 3 ? 0 : -1); Static.Assert((int)ConditionCode.ae == 4 ? 0 : -1); Static.Assert((int)ConditionCode.e == 5 ? 0 : -1); Static.Assert((int)ConditionCode.ne == 6 ? 0 : -1); Static.Assert((int)ConditionCode.be == 7 ? 0 : -1); Static.Assert((int)ConditionCode.a == 8 ? 0 : -1); Static.Assert((int)ConditionCode.s == 9 ? 0 : -1); Static.Assert((int)ConditionCode.ns == 10 ? 0 : -1); Static.Assert((int)ConditionCode.p == 11 ? 0 : -1); Static.Assert((int)ConditionCode.np == 12 ? 0 : -1); Static.Assert((int)ConditionCode.l == 13 ? 0 : -1); Static.Assert((int)ConditionCode.ge == 14 ? 0 : -1); Static.Assert((int)ConditionCode.le == 15 ? 0 : -1); Static.Assert((int)ConditionCode.g == 16 ? 0 : -1); }
static Code[] CreateCodeValues() { var result = new Code[0x100]; Static.Assert(Code.INVALID == 0 ? 0 : -1); // GENERATOR-BEGIN: D3nowCodeValues // ⚠️This was generated by GENERATOR!🦹♂️ result[0xBF] = Code.D3NOW_Pavgusb_mm_mmm64; result[0xBB] = Code.D3NOW_Pswapd_mm_mmm64; result[0xB7] = Code.D3NOW_Pmulhrw_mm_mmm64; result[0xB6] = Code.D3NOW_Pfrcpit2_mm_mmm64; result[0xB4] = Code.D3NOW_Pfmul_mm_mmm64; result[0xB0] = Code.D3NOW_Pfcmpeq_mm_mmm64; result[0xAE] = Code.D3NOW_Pfacc_mm_mmm64; result[0xAA] = Code.D3NOW_Pfsubr_mm_mmm64; result[0xA7] = Code.D3NOW_Pfrsqit1_mm_mmm64; result[0xA6] = Code.D3NOW_Pfrcpit1_mm_mmm64; result[0xA4] = Code.D3NOW_Pfmax_mm_mmm64; result[0xA0] = Code.D3NOW_Pfcmpgt_mm_mmm64; result[0x9E] = Code.D3NOW_Pfadd_mm_mmm64; result[0x9A] = Code.D3NOW_Pfsub_mm_mmm64; result[0x97] = Code.D3NOW_Pfrsqrt_mm_mmm64; result[0x96] = Code.D3NOW_Pfrcp_mm_mmm64; result[0x94] = Code.D3NOW_Pfmin_mm_mmm64; result[0x90] = Code.D3NOW_Pfcmpge_mm_mmm64; result[0x8E] = Code.D3NOW_Pfpnacc_mm_mmm64; result[0x8A] = Code.D3NOW_Pfnacc_mm_mmm64; result[0x87] = Code.D3NOW_Pfrsqrtv_mm_mmm64; result[0x86] = Code.D3NOW_Pfrcpv_mm_mmm64; result[0x1D] = Code.D3NOW_Pf2id_mm_mmm64; result[0x1C] = Code.D3NOW_Pf2iw_mm_mmm64; result[0x0D] = Code.D3NOW_Pi2fd_mm_mmm64; result[0x0C] = Code.D3NOW_Pi2fw_mm_mmm64; // GENERATOR-END: D3nowCodeValues return(result); }
static (string hexBytes, Code code, DecoderOptions options, InstructionInfoTestCase testCase) ParseLine(string line, int bitness, Dictionary <string, Register> toRegister) { Static.Assert(MiscInstrInfoTestConstants.InstrInfoElemsPerLine == 5 ? 0 : -1); var elems = line.Split(commaSeparator, MiscInstrInfoTestConstants.InstrInfoElemsPerLine); if (elems.Length != MiscInstrInfoTestConstants.InstrInfoElemsPerLine) { throw new Exception($"Expected {MiscInstrInfoTestConstants.InstrInfoElemsPerLine - 1} commas"); } var testCase = new InstructionInfoTestCase(); var hexBytes = ToHexBytes(elems[0].Trim()); var code = ToEnumConverter.GetCode(elems[1].Trim()); testCase.Encoding = ToEnumConverter.GetEncodingKind(elems[2].Trim()); var cpuidFeatureStrings = elems[3].Trim().Split(new[] { ';' }); var cpuidFeatures = new CpuidFeature[cpuidFeatureStrings.Length]; testCase.CpuidFeatures = cpuidFeatures; for (int i = 0; i < cpuidFeatures.Length; i++) { cpuidFeatures[i] = ToEnumConverter.GetCpuidFeature(cpuidFeatureStrings[i]); } var options = DecoderOptions.None; foreach (var keyValue in elems[4].Split(spaceSeparator, StringSplitOptions.RemoveEmptyEntries)) { string key, value; int index = keyValue.IndexOf('='); if (index >= 0) { key = keyValue.Substring(0, index); value = keyValue.Substring(index + 1); } else { key = keyValue; value = string.Empty; } switch (key) { case InstructionInfoKeys.IsProtectedMode: if (value != string.Empty) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } testCase.IsProtectedMode = true; break; case InstructionInfoKeys.IsPrivileged: if (value != string.Empty) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } testCase.IsPrivileged = true; break; case InstructionInfoKeys.IsSaveRestoreInstruction: if (value != string.Empty) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } testCase.IsSaveRestoreInstruction = true; break; case InstructionInfoKeys.IsStackInstruction: if (!int.TryParse(value, out testCase.StackPointerIncrement)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } testCase.IsStackInstruction = true; break; case InstructionInfoKeys.IsSpecial: if (value != string.Empty) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } testCase.IsSpecial = true; break; case InstructionInfoKeys.RflagsRead: if (!ParseRflags(value, ref testCase.RflagsRead)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.RflagsUndefined: if (!ParseRflags(value, ref testCase.RflagsUndefined)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.RflagsWritten: if (!ParseRflags(value, ref testCase.RflagsWritten)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.RflagsCleared: if (!ParseRflags(value, ref testCase.RflagsCleared)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.RflagsSet: if (!ParseRflags(value, ref testCase.RflagsSet)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.FlowControl: if (!ToEnumConverter.TryFlowControl(value, out testCase.FlowControl)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.Op0Access: if (!InstructionInfoDicts.ToAccess.TryGetValue(value, out testCase.Op0Access)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.Op1Access: if (!InstructionInfoDicts.ToAccess.TryGetValue(value, out testCase.Op1Access)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.Op2Access: if (!InstructionInfoDicts.ToAccess.TryGetValue(value, out testCase.Op2Access)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.Op3Access: if (!InstructionInfoDicts.ToAccess.TryGetValue(value, out testCase.Op3Access)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.Op4Access: if (!InstructionInfoDicts.ToAccess.TryGetValue(value, out testCase.Op4Access)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.ReadRegister: if (!AddRegisters(toRegister, value, OpAccess.Read, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.CondReadRegister: if (!AddRegisters(toRegister, value, OpAccess.CondRead, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.WriteRegister: if (!AddRegisters(toRegister, value, OpAccess.Write, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.CondWriteRegister: if (!AddRegisters(toRegister, value, OpAccess.CondWrite, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.ReadWriteRegister: if (!AddRegisters(toRegister, value, OpAccess.ReadWrite, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.ReadCondWriteRegister: if (!AddRegisters(toRegister, value, OpAccess.ReadCondWrite, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.ReadMemory: if (!AddMemory(bitness, toRegister, value, OpAccess.Read, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.CondReadMemory: if (!AddMemory(bitness, toRegister, value, OpAccess.CondRead, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.ReadWriteMemory: if (!AddMemory(bitness, toRegister, value, OpAccess.ReadWrite, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.ReadCondWriteMemory: if (!AddMemory(bitness, toRegister, value, OpAccess.ReadCondWrite, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.WriteMemory: if (!AddMemory(bitness, toRegister, value, OpAccess.Write, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.CondWriteMemory: if (!AddMemory(bitness, toRegister, value, OpAccess.CondWrite, testCase)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; case InstructionInfoKeys.DecoderOptions: if (!TryParseDecoderOptions(value.Split(semicolonSeparator), ref options)) { throw new Exception($"Invalid key-value value, '{keyValue}'"); } break; default: throw new Exception($"Invalid key-value value, '{keyValue}'"); } } return(hexBytes, code, options, testCase); }
static OpCodeInfoTestCase ReadTestCase(string line, int lineNo) { var parts = line.Split(seps); if (parts.Length != 8) { throw new InvalidOperationException($"Invalid number of commas ({parts.Length - 1} commas)"); } var tc = new OpCodeInfoTestCase(); tc.LineNumber = lineNo; tc.IsInstruction = true; tc.GroupIndex = -1; var code = parts[0].Trim(); if (CodeUtils.IsIgnored(code)) { return(null); } tc.Code = ToCode(code); tc.Encoding = ToEncoding(parts[1].Trim()); tc.MandatoryPrefix = ToMandatoryPrefix(parts[2].Trim()); tc.Table = ToTable(parts[3].Trim()); tc.OpCode = ToOpCode(parts[4].Trim(), out tc.OpCodeLength); tc.OpCodeString = parts[5].Trim(); tc.InstructionString = parts[6].Trim().Replace('|', ','); bool gotVectorLength = false; bool gotW = false; foreach (var part in parts[7].Split(optsseps)) { var key = part.Trim(); if (key.Length == 0) { continue; } int index = key.IndexOf('='); if (index >= 0) { var value = key.Substring(index + 1); key = key.Substring(0, index); switch (key) { case OpCodeInfoKeys.GroupIndex: if (!uint.TryParse(value, out uint groupIndex) || groupIndex > 7) { throw new InvalidOperationException($"Invalid group index: {value}"); } tc.GroupIndex = (int)groupIndex; tc.IsGroup = true; break; case OpCodeInfoKeys.RmGroupIndex: if (!uint.TryParse(value, out uint rmGroupIndex) || rmGroupIndex > 7) { throw new InvalidOperationException($"Invalid group index: {value}"); } tc.RmGroupIndex = (int)rmGroupIndex; tc.IsRmGroup = true; break; case OpCodeInfoKeys.OpCodeOperandKind: var opParts = value.Split(opseps); tc.OpCount = opParts.Length; if (opParts.Length >= 1) { tc.Op0Kind = ToOpCodeOperandKind(opParts[0]); } if (opParts.Length >= 2) { tc.Op1Kind = ToOpCodeOperandKind(opParts[1]); } if (opParts.Length >= 3) { tc.Op2Kind = ToOpCodeOperandKind(opParts[2]); } if (opParts.Length >= 4) { tc.Op3Kind = ToOpCodeOperandKind(opParts[3]); } if (opParts.Length >= 5) { tc.Op4Kind = ToOpCodeOperandKind(opParts[4]); } Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1); if (opParts.Length >= 6) { throw new InvalidOperationException($"Invalid number of operands: '{value}'"); } break; case OpCodeInfoKeys.TupleType: tc.TupleType = ToTupleType(value.Trim()); break; case OpCodeInfoKeys.DecoderOption: tc.DecoderOption = ToDecoderOptions(value.Trim()); break; default: throw new InvalidOperationException($"Invalid key: '{key}'"); } } else { switch (key) { case OpCodeInfoFlags.NoInstruction: tc.IsInstruction = false; break; case OpCodeInfoFlags.Bit16: tc.Mode16 = true; break; case OpCodeInfoFlags.Bit32: tc.Mode32 = true; break; case OpCodeInfoFlags.Bit64: tc.Mode64 = true; break; case OpCodeInfoFlags.Fwait: tc.Fwait = true; break; case OpCodeInfoFlags.OperandSize16: tc.OperandSize = 16; break; case OpCodeInfoFlags.OperandSize32: tc.OperandSize = 32; break; case OpCodeInfoFlags.OperandSize64: tc.OperandSize = 64; break; case OpCodeInfoFlags.AddressSize16: tc.AddressSize = 16; break; case OpCodeInfoFlags.AddressSize32: tc.AddressSize = 32; break; case OpCodeInfoFlags.AddressSize64: tc.AddressSize = 64; break; case OpCodeInfoFlags.LIG: tc.IsLIG = true; gotVectorLength = true; break; case OpCodeInfoFlags.L0: tc.L = 0; gotVectorLength = true; break; case OpCodeInfoFlags.L1: tc.L = 1; gotVectorLength = true; break; case OpCodeInfoFlags.L128: tc.L = 0; gotVectorLength = true; break; case OpCodeInfoFlags.L256: tc.L = 1; gotVectorLength = true; break; case OpCodeInfoFlags.L512: tc.L = 2; gotVectorLength = true; break; case OpCodeInfoFlags.WIG: tc.IsWIG = true; gotW = true; break; case OpCodeInfoFlags.WIG32: tc.W = 0; tc.IsWIG32 = true; gotW = true; break; case OpCodeInfoFlags.W0: tc.W = 0; gotW = true; break; case OpCodeInfoFlags.W1: tc.W = 1; gotW = true; break; case OpCodeInfoFlags.Broadcast: tc.CanBroadcast = true; break; case OpCodeInfoFlags.RoundingControl: tc.CanUseRoundingControl = true; break; case OpCodeInfoFlags.SuppressAllExceptions: tc.CanSuppressAllExceptions = true; break; case OpCodeInfoFlags.OpMaskRegister: tc.CanUseOpMaskRegister = true; break; case OpCodeInfoFlags.RequireOpMaskRegister: tc.CanUseOpMaskRegister = true; tc.RequireOpMaskRegister = true; break; case OpCodeInfoFlags.ZeroingMasking: tc.CanUseZeroingMasking = true; break; case OpCodeInfoFlags.Lock: tc.CanUseLockPrefix = true; break; case OpCodeInfoFlags.Xacquire: tc.CanUseXacquirePrefix = true; break; case OpCodeInfoFlags.Xrelease: tc.CanUseXreleasePrefix = true; break; case OpCodeInfoFlags.Rep: case OpCodeInfoFlags.Repe: tc.CanUseRepPrefix = true; break; case OpCodeInfoFlags.Repne: tc.CanUseRepnePrefix = true; break; case OpCodeInfoFlags.Bnd: tc.CanUseBndPrefix = true; break; case OpCodeInfoFlags.HintTaken: tc.CanUseHintTakenPrefix = true; break; case OpCodeInfoFlags.Notrack: tc.CanUseNotrackPrefix = true; break; case OpCodeInfoFlags.IgnoresRoundingControl: tc.IgnoresRoundingControl = true; break; case OpCodeInfoFlags.AmdLockRegBit: tc.AmdLockRegBit = true; break; case OpCodeInfoFlags.DefaultOpSize64: tc.DefaultOpSize64 = true; break; case OpCodeInfoFlags.ForceOpSize64: tc.ForceOpSize64 = true; break; case OpCodeInfoFlags.IntelForceOpSize64: tc.IntelForceOpSize64 = true; break; case OpCodeInfoFlags.Cpl0: tc.Cpl0 = true; break; case OpCodeInfoFlags.Cpl1: tc.Cpl1 = true; break; case OpCodeInfoFlags.Cpl2: tc.Cpl2 = true; break; case OpCodeInfoFlags.Cpl3: tc.Cpl3 = true; break; case OpCodeInfoFlags.InputOutput: tc.IsInputOutput = true; break; case OpCodeInfoFlags.Nop: tc.IsNop = true; break; case OpCodeInfoFlags.ReservedNop: tc.IsReservedNop = true; break; case OpCodeInfoFlags.SerializingIntel: tc.IsSerializingIntel = true; break; case OpCodeInfoFlags.SerializingAmd: tc.IsSerializingAmd = true; break; case OpCodeInfoFlags.MayRequireCpl0: tc.MayRequireCpl0 = true; break; case OpCodeInfoFlags.CetTracked: tc.IsCetTracked = true; break; case OpCodeInfoFlags.NonTemporal: tc.IsNonTemporal = true; break; case OpCodeInfoFlags.FpuNoWait: tc.IsFpuNoWait = true; break; case OpCodeInfoFlags.IgnoresModBits: tc.IgnoresModBits = true; break; case OpCodeInfoFlags.No66: tc.No66 = true; break; case OpCodeInfoFlags.NFx: tc.NFx = true; break; case OpCodeInfoFlags.RequiresUniqueRegNums: tc.RequiresUniqueRegNums = true; break; case OpCodeInfoFlags.Privileged: tc.IsPrivileged = true; break; case OpCodeInfoFlags.SaveRestore: tc.IsSaveRestore = true; break; case OpCodeInfoFlags.StackInstruction: tc.IsStackInstruction = true; break; case OpCodeInfoFlags.IgnoresSegment: tc.IgnoresSegment = true; break; case OpCodeInfoFlags.OpMaskReadWrite: tc.IsOpMaskReadWrite = true; break; case OpCodeInfoFlags.RealMode: tc.RealMode = true; break; case OpCodeInfoFlags.ProtectedMode: tc.ProtectedMode = true; break; case OpCodeInfoFlags.Virtual8086Mode: tc.Virtual8086Mode = true; break; case OpCodeInfoFlags.CompatibilityMode: tc.CompatibilityMode = true; break; case OpCodeInfoFlags.LongMode: tc.LongMode = true; break; case OpCodeInfoFlags.UseOutsideSmm: tc.UseOutsideSmm = true; break; case OpCodeInfoFlags.UseInSmm: tc.UseInSmm = true; break; case OpCodeInfoFlags.UseOutsideEnclaveSgx: tc.UseOutsideEnclaveSgx = true; break; case OpCodeInfoFlags.UseInEnclaveSgx1: tc.UseInEnclaveSgx1 = true; break; case OpCodeInfoFlags.UseInEnclaveSgx2: tc.UseInEnclaveSgx2 = true; break; case OpCodeInfoFlags.UseOutsideVmxOp: tc.UseOutsideVmxOp = true; break; case OpCodeInfoFlags.UseInVmxRootOp: tc.UseInVmxRootOp = true; break; case OpCodeInfoFlags.UseInVmxNonRootOp: tc.UseInVmxNonRootOp = true; break; case OpCodeInfoFlags.UseOutsideSeam: tc.UseOutsideSeam = true; break; case OpCodeInfoFlags.UseInSeam: tc.UseInSeam = true; break; case OpCodeInfoFlags.TdxNonRootGenUd: tc.TdxNonRootGenUd = true; break; case OpCodeInfoFlags.TdxNonRootGenVe: tc.TdxNonRootGenVe = true; break; case OpCodeInfoFlags.TdxNonRootMayGenEx: tc.TdxNonRootMayGenEx = true; break; case OpCodeInfoFlags.IntelVmExit: tc.IntelVmExit = true; break; case OpCodeInfoFlags.IntelMayVmExit: tc.IntelMayVmExit = true; break; case OpCodeInfoFlags.IntelSmmVmExit: tc.IntelSmmVmExit = true; break; case OpCodeInfoFlags.AmdVmExit: tc.AmdVmExit = true; break; case OpCodeInfoFlags.AmdMayVmExit: tc.AmdMayVmExit = true; break; case OpCodeInfoFlags.TsxAbort: tc.TsxAbort = true; break; case OpCodeInfoFlags.TsxImplAbort: tc.TsxImplAbort = true; break; case OpCodeInfoFlags.TsxMayAbort: tc.TsxMayAbort = true; break; case OpCodeInfoFlags.IntelDecoder16: tc.IntelDecoder16 = true; break; case OpCodeInfoFlags.IntelDecoder32: tc.IntelDecoder32 = true; break; case OpCodeInfoFlags.IntelDecoder64: tc.IntelDecoder64 = true; break; case OpCodeInfoFlags.AmdDecoder16: tc.AmdDecoder16 = true; break; case OpCodeInfoFlags.AmdDecoder32: tc.AmdDecoder32 = true; break; case OpCodeInfoFlags.AmdDecoder64: tc.AmdDecoder64 = true; break; default: throw new InvalidOperationException($"Invalid key: '{key}'"); } } } switch (tc.Encoding) { case EncodingKind.Legacy: case EncodingKind.D3NOW: break; case EncodingKind.VEX: case EncodingKind.EVEX: case EncodingKind.XOP: if (!gotVectorLength) { throw new InvalidOperationException("Missing vector length: L0/L1/L128/L256/L512/LIG"); } if (!gotW) { throw new InvalidOperationException("Missing W bit: W0/W1/WIG/WIG32"); } break; default: throw new InvalidOperationException(); } return(tc); }
protected void TestInstructionInfo(int bitness, string hexBytes, Code code, DecoderOptions options, int lineNo, InstructionInfoTestCase testCase) { var codeBytes = HexUtils.ToByteArray(hexBytes); Instruction instruction; if (testCase.IsSpecial) { if (bitness == 16 && code == Code.Popw_CS && hexBytes == "0F") { instruction = default; instruction.Code = Code.Popw_CS; instruction.Op0Kind = OpKind.Register; instruction.Op0Register = Register.CS; instruction.CodeSize = CodeSize.Code16; instruction.Length = 1; } else if (code <= Code.DeclareQword) { instruction = default; instruction.Code = code; instruction.DeclareDataCount = 1; Assert.Equal(64, bitness); instruction.CodeSize = CodeSize.Code64; switch (code) { case Code.DeclareByte: Assert.Equal("66", hexBytes); instruction.SetDeclareByteValue(0, 0x66); break; case Code.DeclareWord: Assert.Equal("6644", hexBytes); instruction.SetDeclareWordValue(0, 0x4466); break; case Code.DeclareDword: Assert.Equal("664422EE", hexBytes); instruction.SetDeclareDwordValue(0, 0xEE224466); break; case Code.DeclareQword: Assert.Equal("664422EE12345678", hexBytes); instruction.SetDeclareQwordValue(0, 0x78563412EE224466); break; default: throw new InvalidOperationException(); } } else { var decoder = CreateDecoder(bitness, codeBytes, options); instruction = decoder.Decode(); if (codeBytes.Length > 1 && codeBytes[0] == 0x9B && instruction.Length == 1) { instruction = decoder.Decode(); instruction.Code = instruction.Code switch { Code.Fnstenv_m14byte => Code.Fstenv_m14byte, Code.Fnstenv_m28byte => Code.Fstenv_m28byte, Code.Fnstcw_m2byte => Code.Fstcw_m2byte, Code.Fneni => Code.Feni, Code.Fndisi => Code.Fdisi, Code.Fnclex => Code.Fclex, Code.Fninit => Code.Finit, Code.Fnsetpm => Code.Fsetpm, Code.Fnsave_m94byte => Code.Fsave_m94byte, Code.Fnsave_m108byte => Code.Fsave_m108byte, Code.Fnstsw_m2byte => Code.Fstsw_m2byte, Code.Fnstsw_AX => Code.Fstsw_AX, Code.Fnstdw_AX => Code.Fstdw_AX, Code.Fnstsg_AX => Code.Fstsg_AX, _ => throw new InvalidOperationException(), }; } else { throw new InvalidOperationException(); } } } else { var decoder = CreateDecoder(bitness, codeBytes, options); instruction = decoder.Decode(); } Assert.Equal(code, instruction.Code); Assert.Equal(testCase.StackPointerIncrement, instruction.StackPointerIncrement); var info = new InstructionInfoFactory().GetInfo(instruction); Assert.Equal(testCase.Encoding, info.Encoding); Assert.Equal(testCase.CpuidFeatures, info.CpuidFeatures); Assert.Equal(testCase.RflagsRead, info.RflagsRead); Assert.Equal(testCase.RflagsUndefined, info.RflagsUndefined); Assert.Equal(testCase.RflagsWritten, info.RflagsWritten); Assert.Equal(testCase.RflagsCleared, info.RflagsCleared); Assert.Equal(testCase.RflagsSet, info.RflagsSet); Assert.Equal(testCase.IsPrivileged, info.IsPrivileged); Assert.Equal(testCase.IsStackInstruction, info.IsStackInstruction); Assert.Equal(testCase.IsSaveRestoreInstruction, info.IsSaveRestoreInstruction); Assert.Equal(testCase.FlowControl, info.FlowControl); Assert.Equal(testCase.Op0Access, info.Op0Access); Assert.Equal(testCase.Op1Access, info.Op1Access); Assert.Equal(testCase.Op2Access, info.Op2Access); Assert.Equal(testCase.Op3Access, info.Op3Access); Assert.Equal(testCase.Op4Access, info.Op4Access); Assert.Equal( new HashSet <UsedMemory>(testCase.UsedMemory, UsedMemoryEqualityComparer.Instance), new HashSet <UsedMemory>(info.GetUsedMemory(), UsedMemoryEqualityComparer.Instance)); Assert.Equal( new HashSet <UsedRegister>(GetUsedRegisters(testCase.UsedRegisters), UsedRegisterEqualityComparer.Instance), new HashSet <UsedRegister>(GetUsedRegisters(info.GetUsedRegisters()), UsedRegisterEqualityComparer.Instance)); Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1); Debug.Assert(instruction.OpCount <= IcedConstants.MaxOpCount); for (int i = 0; i < instruction.OpCount; i++) { switch (i) { case 0: Assert.Equal(testCase.Op0Access, info.GetOpAccess(i)); break; case 1: Assert.Equal(testCase.Op1Access, info.GetOpAccess(i)); break; case 2: Assert.Equal(testCase.Op2Access, info.GetOpAccess(i)); break; case 3: Assert.Equal(testCase.Op3Access, info.GetOpAccess(i)); break; case 4: Assert.Equal(testCase.Op4Access, info.GetOpAccess(i)); break; default: throw new InvalidOperationException(); } } for (int i = instruction.OpCount; i < IcedConstants.MaxOpCount; i++) { Assert.Equal(OpAccess.None, info.GetOpAccess(i)); } Assert.Equal(RflagsBits.None, info.RflagsWritten & (info.RflagsCleared | info.RflagsSet | info.RflagsUndefined)); Assert.Equal(RflagsBits.None, info.RflagsCleared & (info.RflagsWritten | info.RflagsSet | info.RflagsUndefined)); Assert.Equal(RflagsBits.None, info.RflagsSet & (info.RflagsWritten | info.RflagsCleared | info.RflagsUndefined)); Assert.Equal(RflagsBits.None, info.RflagsUndefined & (info.RflagsWritten | info.RflagsCleared | info.RflagsSet)); Assert.Equal(info.RflagsWritten | info.RflagsCleared | info.RflagsSet | info.RflagsUndefined, info.RflagsModified); var info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.None); CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: true); info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.NoMemoryUsage); CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: false); info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.NoRegisterUsage); CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: true); info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.NoRegisterUsage | InstructionInfoOptions.NoMemoryUsage); CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: false); Assert.Equal(info.Encoding, instruction.Code.Encoding()); #if ENCODER && OPCODE_INFO Assert.Equal(code.ToOpCode().Encoding, instruction.Code.Encoding()); #endif Assert.Equal(info.CpuidFeatures, instruction.Code.CpuidFeatures()); Assert.Equal(info.FlowControl, instruction.Code.FlowControl()); Assert.Equal(info.IsPrivileged, instruction.Code.IsPrivileged()); Assert.Equal(info.IsStackInstruction, instruction.Code.IsStackInstruction()); Assert.Equal(info.IsSaveRestoreInstruction, instruction.Code.IsSaveRestoreInstruction()); Assert.Equal(info.Encoding, instruction.Encoding); Assert.Equal(info.CpuidFeatures, instruction.CpuidFeatures); Assert.Equal(info.FlowControl, instruction.FlowControl); Assert.Equal(info.IsPrivileged, instruction.IsPrivileged); Assert.Equal(info.IsStackInstruction, instruction.IsStackInstruction); Assert.Equal(info.IsSaveRestoreInstruction, instruction.IsSaveRestoreInstruction); Assert.Equal(info.RflagsRead, instruction.RflagsRead); Assert.Equal(info.RflagsWritten, instruction.RflagsWritten); Assert.Equal(info.RflagsCleared, instruction.RflagsCleared); Assert.Equal(info.RflagsSet, instruction.RflagsSet); Assert.Equal(info.RflagsUndefined, instruction.RflagsUndefined); Assert.Equal(info.RflagsModified, instruction.RflagsModified); }
public override void Decode(Decoder decoder, ref Instruction instruction) { Debug.Assert(decoder.state.Encoding == EncodingKind.MVEX); instruction.InternalSetCodeNoCheck(code); Static.Assert(OpKind.Register == 0 ? 0 : -1); //instruction.Op0Kind = OpKind.Register; instruction.Op0Register = (int)decoder.state.reg + Register.K0; Static.Assert(OpKind.Register == 0 ? 0 : -1); //instruction.Op1Kind = OpKind.Register; instruction.Op1Register = (int)decoder.state.vvvv + Register.ZMM0; var mvex = new MvexInfo(code); var sss = decoder.state.Sss; if (decoder.state.mod == 3) { Static.Assert(OpKind.Register == 0 ? 0 : -1); //instruction.Op2Kind = OpKind.Register; instruction.Op2Register = (int)(decoder.state.rm + decoder.state.extraBaseRegisterBaseEVEX) + Register.ZMM0; if ((decoder.state.zs.flags & StateFlags.MvexEH) != 0) { if (mvex.CanUseSuppressAllExceptions) { if ((sss & 4) != 0) { instruction.InternalSetSuppressAllExceptions(); } if (mvex.CanUseRoundingControl) { Static.Assert((int)RoundingControl.None == 0 ? 0 : -1); Static.Assert((int)RoundingControl.RoundToNearest == 1 ? 0 : -1); Static.Assert((int)RoundingControl.RoundDown == 2 ? 0 : -1); Static.Assert((int)RoundingControl.RoundUp == 3 ? 0 : -1); Static.Assert((int)RoundingControl.RoundTowardZero == 4 ? 0 : -1); instruction.InternalRoundingControl = ((uint)sss & 3) + (uint)RoundingControl.RoundToNearest; } } else if (mvex.NoSaeRc && ((uint)sss & decoder.invalidCheckMask) != 0) { decoder.SetInvalidInstruction(); } } else { if ((mvex.InvalidSwizzleFns & (1U << sss) & decoder.invalidCheckMask) != 0) { decoder.SetInvalidInstruction(); } Debug.Assert((uint)sss <= 7); instruction.InternalSetMvexRegMemConv(MvexRegMemConv.RegSwizzleNone + sss); } } else { instruction.Op2Kind = OpKind.Memory; if ((decoder.state.zs.flags & StateFlags.MvexEH) != 0) { instruction.InternalSetIsMvexEvictionHint(); } if ((mvex.InvalidConvFns & (1U << sss) & decoder.invalidCheckMask) != 0) { decoder.SetInvalidInstruction(); } instruction.InternalSetMvexRegMemConv(MvexRegMemConv.MemConvNone + sss); decoder.ReadOpMem(ref instruction, mvex.GetTupleType(sss)); } if (((decoder.state.zs.extraRegisterBase | decoder.state.extraRegisterBaseEVEX) & decoder.invalidCheckMask) != 0) { decoder.SetInvalidInstruction(); } instruction.Op3Kind = OpKind.Immediate8; instruction.Immediate8 = (byte)decoder.ReadByte(); }
static OpCodeInfoTestCase ReadTestCase(string line, int lineNo) { var parts = line.Split(seps); if (parts.Length != 8) { throw new InvalidOperationException($"Invalid number of commas ({parts.Length - 1} commas)"); } var tc = new OpCodeInfoTestCase(); tc.LineNumber = lineNo; tc.IsInstruction = true; tc.GroupIndex = -1; tc.Code = ToCode(parts[0].Trim()); tc.Encoding = ToEncoding(parts[1].Trim()); tc.MandatoryPrefix = ToMandatoryPrefix(parts[2].Trim()); tc.Table = ToTable(parts[3].Trim()); tc.OpCode = ToOpCode(parts[4].Trim()); tc.OpCodeString = parts[5].Trim(); tc.InstructionString = parts[6].Trim().Replace('|', ','); bool gotVectorLength = false; bool gotW = false; foreach (var part in parts[7].Split(optsseps)) { var key = part.Trim(); if (key.Length == 0) { continue; } int index = key.IndexOf('='); if (index >= 0) { var value = key.Substring(index + 1); key = key.Substring(0, index); switch (key) { case OpCodeInfoKeys.GroupIndex: if (!uint.TryParse(value, out uint groupIndex) || groupIndex > 7) { throw new InvalidOperationException($"Invalid group index: {value}"); } tc.GroupIndex = (int)groupIndex; tc.IsGroup = true; break; case OpCodeInfoKeys.OpCodeOperandKind: var opParts = value.Split(opseps); tc.OpCount = opParts.Length; if (opParts.Length >= 1) { tc.Op0Kind = ToOpCodeOperandKind(opParts[0]); } if (opParts.Length >= 2) { tc.Op1Kind = ToOpCodeOperandKind(opParts[1]); } if (opParts.Length >= 3) { tc.Op2Kind = ToOpCodeOperandKind(opParts[2]); } if (opParts.Length >= 4) { tc.Op3Kind = ToOpCodeOperandKind(opParts[3]); } if (opParts.Length >= 5) { tc.Op4Kind = ToOpCodeOperandKind(opParts[4]); } Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1); if (opParts.Length >= 6) { throw new InvalidOperationException($"Invalid number of operands: '{value}'"); } break; case OpCodeInfoKeys.TupleType: tc.TupleType = ToTupleType(value.Trim()); break; default: throw new InvalidOperationException($"Invalid key: '{key}'"); } } else { switch (key) { case OpCodeInfoFlags.NotInstruction: tc.IsInstruction = false; break; case OpCodeInfoFlags.Bit16: tc.Mode16 = true; break; case OpCodeInfoFlags.Bit32: tc.Mode32 = true; break; case OpCodeInfoFlags.Bit64: tc.Mode64 = true; break; case OpCodeInfoFlags.Fwait: tc.Fwait = true; break; case OpCodeInfoFlags.OperandSize16: tc.OperandSize = 16; break; case OpCodeInfoFlags.OperandSize32: tc.OperandSize = 32; break; case OpCodeInfoFlags.OperandSize64: tc.OperandSize = 64; break; case OpCodeInfoFlags.AddressSize16: tc.AddressSize = 16; break; case OpCodeInfoFlags.AddressSize32: tc.AddressSize = 32; break; case OpCodeInfoFlags.AddressSize64: tc.AddressSize = 64; break; case OpCodeInfoFlags.LIG: tc.IsLIG = true; gotVectorLength = true; break; case OpCodeInfoFlags.L0: tc.L = 0; gotVectorLength = true; break; case OpCodeInfoFlags.L1: tc.L = 1; gotVectorLength = true; break; case OpCodeInfoFlags.L128: tc.L = 0; gotVectorLength = true; break; case OpCodeInfoFlags.L256: tc.L = 1; gotVectorLength = true; break; case OpCodeInfoFlags.L512: tc.L = 2; gotVectorLength = true; break; case OpCodeInfoFlags.WIG: tc.IsWIG = true; gotW = true; break; case OpCodeInfoFlags.WIG32: tc.W = 0; tc.IsWIG32 = true; gotW = true; break; case OpCodeInfoFlags.W0: tc.W = 0; gotW = true; break; case OpCodeInfoFlags.W1: tc.W = 1; gotW = true; break; case OpCodeInfoFlags.Broadcast: tc.CanBroadcast = true; break; case OpCodeInfoFlags.RoundingControl: tc.CanUseRoundingControl = true; break; case OpCodeInfoFlags.SuppressAllExceptions: tc.CanSuppressAllExceptions = true; break; case OpCodeInfoFlags.OpMaskRegister: tc.CanUseOpMaskRegister = true; break; case OpCodeInfoFlags.RequireNonZeroOpMaskRegister: tc.CanUseOpMaskRegister = true; tc.RequireNonZeroOpMaskRegister = true; break; case OpCodeInfoFlags.ZeroingMasking: tc.CanUseZeroingMasking = true; break; case OpCodeInfoFlags.LockPrefix: tc.CanUseLockPrefix = true; break; case OpCodeInfoFlags.XacquirePrefix: tc.CanUseXacquirePrefix = true; break; case OpCodeInfoFlags.XreleasePrefix: tc.CanUseXreleasePrefix = true; break; case OpCodeInfoFlags.RepPrefix: case OpCodeInfoFlags.RepePrefix: tc.CanUseRepPrefix = true; break; case OpCodeInfoFlags.RepnePrefix: tc.CanUseRepnePrefix = true; break; case OpCodeInfoFlags.BndPrefix: tc.CanUseBndPrefix = true; break; case OpCodeInfoFlags.HintTakenPrefix: tc.CanUseHintTakenPrefix = true; break; case OpCodeInfoFlags.NotrackPrefix: tc.CanUseNotrackPrefix = true; break; default: throw new InvalidOperationException($"Invalid key: '{key}'"); } } } switch (tc.Encoding) { case EncodingKind.Legacy: case EncodingKind.D3NOW: break; case EncodingKind.VEX: case EncodingKind.EVEX: case EncodingKind.XOP: if (!gotVectorLength) { throw new InvalidOperationException("Missing vector length: L0/L1/L128/L256/L512/LIG"); } if (!gotW) { throw new InvalidOperationException("Missing W bit: W0/W1/WIG/WIG32"); } break; default: throw new InvalidOperationException(); } return(tc); }
#pragma warning disable xUnit1026 // Theory methods should use all of their parameters void Test_all_OpCodeInfos(int lineNo, Code code, string opCodeString, string instructionString, OpCodeInfoTestCase tc) { #pragma warning restore xUnit1026 // Theory methods should use all of their parameters var info = tc.Code.ToOpCode(); Assert.Equal(tc.Code, info.Code); #pragma warning disable xUnit2006 // Do not use invalid string equality check // Show the full string without ellipses by using Equal<string>() instead of Equal() Assert.Equal <string>(tc.OpCodeString, info.ToOpCodeString()); Assert.Equal <string>(tc.InstructionString, info.ToInstructionString()); #pragma warning restore xUnit2006 // Do not use invalid string equality check Assert.True((object)info.ToInstructionString() == info.ToString()); Assert.Equal(tc.Mnemonic, info.Mnemonic); Assert.Equal(tc.Encoding, info.Encoding); Assert.Equal(tc.IsInstruction, info.IsInstruction); Assert.Equal(tc.Mode16, info.Mode16); Assert.Equal(tc.Mode16, info.IsAvailableInMode(16)); Assert.Equal(tc.Mode32, info.Mode32); Assert.Equal(tc.Mode32, info.IsAvailableInMode(32)); Assert.Equal(tc.Mode64, info.Mode64); Assert.Equal(tc.Mode64, info.IsAvailableInMode(64)); Assert.Equal(tc.Fwait, info.Fwait); Assert.Equal(tc.OperandSize, info.OperandSize); Assert.Equal(tc.AddressSize, info.AddressSize); Assert.Equal(tc.L, info.L); Assert.Equal(tc.W, info.W); Assert.Equal(tc.IsLIG, info.IsLIG); Assert.Equal(tc.IsWIG, info.IsWIG); Assert.Equal(tc.IsWIG32, info.IsWIG32); Assert.Equal(tc.TupleType, info.TupleType); Assert.Equal(tc.MemorySize, info.MemorySize); Assert.Equal(tc.BroadcastMemorySize, info.BroadcastMemorySize); Assert.Equal(tc.DecoderOption, info.DecoderOption); Assert.Equal(tc.CanBroadcast, info.CanBroadcast); Assert.Equal(tc.CanUseRoundingControl, info.CanUseRoundingControl); Assert.Equal(tc.CanSuppressAllExceptions, info.CanSuppressAllExceptions); Assert.Equal(tc.CanUseOpMaskRegister, info.CanUseOpMaskRegister); Assert.Equal(tc.RequireOpMaskRegister, info.RequireOpMaskRegister); if (tc.RequireOpMaskRegister) { Assert.True(info.CanUseOpMaskRegister); Assert.False(info.CanUseZeroingMasking); } Assert.Equal(tc.CanUseZeroingMasking, info.CanUseZeroingMasking); Assert.Equal(tc.CanUseLockPrefix, info.CanUseLockPrefix); Assert.Equal(tc.CanUseXacquirePrefix, info.CanUseXacquirePrefix); Assert.Equal(tc.CanUseXreleasePrefix, info.CanUseXreleasePrefix); Assert.Equal(tc.CanUseRepPrefix, info.CanUseRepPrefix); Assert.Equal(tc.CanUseRepnePrefix, info.CanUseRepnePrefix); Assert.Equal(tc.CanUseBndPrefix, info.CanUseBndPrefix); Assert.Equal(tc.CanUseHintTakenPrefix, info.CanUseHintTakenPrefix); Assert.Equal(tc.CanUseNotrackPrefix, info.CanUseNotrackPrefix); Assert.Equal(tc.IgnoresRoundingControl, info.IgnoresRoundingControl); Assert.Equal(tc.AmdLockRegBit, info.AmdLockRegBit); Assert.Equal(tc.DefaultOpSize64, info.DefaultOpSize64); Assert.Equal(tc.ForceOpSize64, info.ForceOpSize64); Assert.Equal(tc.IntelForceOpSize64, info.IntelForceOpSize64); Assert.Equal(tc.Cpl0 && !tc.Cpl1 && !tc.Cpl2 && !tc.Cpl3, info.MustBeCpl0); Assert.Equal(tc.Cpl0, info.Cpl0); Assert.Equal(tc.Cpl1, info.Cpl1); Assert.Equal(tc.Cpl2, info.Cpl2); Assert.Equal(tc.Cpl3, info.Cpl3); Assert.Equal(tc.IsInputOutput, info.IsInputOutput); Assert.Equal(tc.IsNop, info.IsNop); Assert.Equal(tc.IsReservedNop, info.IsReservedNop); Assert.Equal(tc.IsSerializingIntel, info.IsSerializingIntel); Assert.Equal(tc.IsSerializingAmd, info.IsSerializingAmd); Assert.Equal(tc.MayRequireCpl0, info.MayRequireCpl0); Assert.Equal(tc.IsCetTracked, info.IsCetTracked); Assert.Equal(tc.IsNonTemporal, info.IsNonTemporal); Assert.Equal(tc.IsFpuNoWait, info.IsFpuNoWait); Assert.Equal(tc.IgnoresModBits, info.IgnoresModBits); Assert.Equal(tc.No66, info.No66); Assert.Equal(tc.NFx, info.NFx); Assert.Equal(tc.RequiresUniqueRegNums, info.RequiresUniqueRegNums); Assert.Equal(tc.RequiresUniqueDestRegNum, info.RequiresUniqueDestRegNum); Assert.Equal(tc.IsPrivileged, info.IsPrivileged); Assert.Equal(tc.IsSaveRestore, info.IsSaveRestore); Assert.Equal(tc.IsStackInstruction, info.IsStackInstruction); Assert.Equal(tc.IgnoresSegment, info.IgnoresSegment); Assert.Equal(tc.IsOpMaskReadWrite, info.IsOpMaskReadWrite); Assert.Equal(tc.RealMode, info.RealMode); Assert.Equal(tc.ProtectedMode, info.ProtectedMode); Assert.Equal(tc.Virtual8086Mode, info.Virtual8086Mode); Assert.Equal(tc.CompatibilityMode, info.CompatibilityMode); Assert.Equal(tc.LongMode, info.LongMode); Assert.Equal(tc.UseOutsideSmm, info.UseOutsideSmm); Assert.Equal(tc.UseInSmm, info.UseInSmm); Assert.Equal(tc.UseOutsideEnclaveSgx, info.UseOutsideEnclaveSgx); Assert.Equal(tc.UseInEnclaveSgx1, info.UseInEnclaveSgx1); Assert.Equal(tc.UseInEnclaveSgx2, info.UseInEnclaveSgx2); Assert.Equal(tc.UseOutsideVmxOp, info.UseOutsideVmxOp); Assert.Equal(tc.UseInVmxRootOp, info.UseInVmxRootOp); Assert.Equal(tc.UseInVmxNonRootOp, info.UseInVmxNonRootOp); Assert.Equal(tc.UseOutsideSeam, info.UseOutsideSeam); Assert.Equal(tc.UseInSeam, info.UseInSeam); Assert.Equal(tc.TdxNonRootGenUd, info.TdxNonRootGenUd); Assert.Equal(tc.TdxNonRootGenVe, info.TdxNonRootGenVe); Assert.Equal(tc.TdxNonRootMayGenEx, info.TdxNonRootMayGenEx); Assert.Equal(tc.IntelVmExit, info.IntelVmExit); Assert.Equal(tc.IntelMayVmExit, info.IntelMayVmExit); Assert.Equal(tc.IntelSmmVmExit, info.IntelSmmVmExit); Assert.Equal(tc.AmdVmExit, info.AmdVmExit); Assert.Equal(tc.AmdMayVmExit, info.AmdMayVmExit); Assert.Equal(tc.TsxAbort, info.TsxAbort); Assert.Equal(tc.TsxImplAbort, info.TsxImplAbort); Assert.Equal(tc.TsxMayAbort, info.TsxMayAbort); Assert.Equal(tc.IntelDecoder16, info.IntelDecoder16); Assert.Equal(tc.IntelDecoder32, info.IntelDecoder32); Assert.Equal(tc.IntelDecoder64, info.IntelDecoder64); Assert.Equal(tc.AmdDecoder16, info.AmdDecoder16); Assert.Equal(tc.AmdDecoder32, info.AmdDecoder32); Assert.Equal(tc.AmdDecoder64, info.AmdDecoder64); Assert.Equal(tc.Table, info.Table); Assert.Equal(tc.MandatoryPrefix, info.MandatoryPrefix); Assert.Equal(tc.OpCode, info.OpCode); Assert.Equal(tc.OpCodeLength, info.OpCodeLength); Assert.Equal(tc.IsGroup, info.IsGroup); Assert.Equal(tc.GroupIndex, info.GroupIndex); Assert.Equal(tc.IsRmGroup, info.IsRmGroup); Assert.Equal(tc.RmGroupIndex, info.RmGroupIndex); Assert.Equal(tc.OpCount, info.OpCount); Assert.Equal(tc.Op0Kind, info.Op0Kind); Assert.Equal(tc.Op1Kind, info.Op1Kind); Assert.Equal(tc.Op2Kind, info.Op2Kind); Assert.Equal(tc.Op3Kind, info.Op3Kind); Assert.Equal(tc.Op4Kind, info.Op4Kind); Assert.Equal(tc.Op0Kind, info.GetOpKind(0)); Assert.Equal(tc.Op1Kind, info.GetOpKind(1)); Assert.Equal(tc.Op2Kind, info.GetOpKind(2)); Assert.Equal(tc.Op3Kind, info.GetOpKind(3)); Assert.Equal(tc.Op4Kind, info.GetOpKind(4)); Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1); for (int i = tc.OpCount; i < IcedConstants.MaxOpCount; i++) { Assert.Equal(OpCodeOperandKind.None, info.GetOpKind(i)); } }
void Write_all_properties() { Instruction instruction = default; instruction.IP = 0x8A6BD04A9B683A92; instruction.IP16 = ushort.MinValue; Assert.Equal(ushort.MinValue, instruction.IP16); Assert.Equal(ushort.MinValue, instruction.IP32); Assert.Equal(ushort.MinValue, instruction.IP); instruction.IP = 0x8A6BD04A9B683A92; instruction.IP16 = ushort.MaxValue; Assert.Equal(ushort.MaxValue, instruction.IP16); Assert.Equal(ushort.MaxValue, instruction.IP32); Assert.Equal(ushort.MaxValue, instruction.IP); instruction.IP = 0x8A6BD04A9B683A92; instruction.IP32 = uint.MinValue; Assert.Equal(ushort.MinValue, instruction.IP16); Assert.Equal(uint.MinValue, instruction.IP32); Assert.Equal(uint.MinValue, instruction.IP); instruction.IP = 0x8A6BD04A9B683A92; instruction.IP32 = uint.MaxValue; Assert.Equal(ushort.MaxValue, instruction.IP16); Assert.Equal(uint.MaxValue, instruction.IP32); Assert.Equal(uint.MaxValue, instruction.IP); instruction.IP = ulong.MinValue; Assert.Equal(ushort.MinValue, instruction.IP16); Assert.Equal(uint.MinValue, instruction.IP32); Assert.Equal(ulong.MinValue, instruction.IP); instruction.IP = ulong.MaxValue; Assert.Equal(ushort.MaxValue, instruction.IP16); Assert.Equal(uint.MaxValue, instruction.IP32); Assert.Equal(ulong.MaxValue, instruction.IP); instruction.NextIP = 0x8A6BD04A9B683A92; instruction.NextIP16 = ushort.MinValue; Assert.Equal(ushort.MinValue, instruction.NextIP16); Assert.Equal(ushort.MinValue, instruction.NextIP32); Assert.Equal(ushort.MinValue, instruction.NextIP); instruction.NextIP = 0x8A6BD04A9B683A92; instruction.NextIP16 = ushort.MaxValue; Assert.Equal(ushort.MaxValue, instruction.NextIP16); Assert.Equal(ushort.MaxValue, instruction.NextIP32); Assert.Equal(ushort.MaxValue, instruction.NextIP); instruction.NextIP = 0x8A6BD04A9B683A92; instruction.NextIP32 = uint.MinValue; Assert.Equal(ushort.MinValue, instruction.NextIP16); Assert.Equal(uint.MinValue, instruction.NextIP32); Assert.Equal(uint.MinValue, instruction.NextIP); instruction.NextIP = 0x8A6BD04A9B683A92; instruction.NextIP32 = uint.MaxValue; Assert.Equal(ushort.MaxValue, instruction.NextIP16); Assert.Equal(uint.MaxValue, instruction.NextIP32); Assert.Equal(uint.MaxValue, instruction.NextIP); instruction.NextIP = ulong.MinValue; Assert.Equal(ushort.MinValue, instruction.NextIP16); Assert.Equal(uint.MinValue, instruction.NextIP32); Assert.Equal(ulong.MinValue, instruction.NextIP); instruction.NextIP = ulong.MaxValue; Assert.Equal(ushort.MaxValue, instruction.NextIP16); Assert.Equal(uint.MaxValue, instruction.NextIP32); Assert.Equal(ulong.MaxValue, instruction.NextIP); instruction.MemoryDisplacement32 = uint.MinValue; Assert.Equal(uint.MinValue, instruction.MemoryDisplacement32); Assert.Equal(uint.MinValue, instruction.MemoryDisplacement64); instruction.MemoryDisplacement32 = uint.MaxValue; Assert.Equal(uint.MaxValue, instruction.MemoryDisplacement32); Assert.Equal(uint.MaxValue, instruction.MemoryDisplacement64); instruction.MemoryDisplacement64 = ulong.MinValue; Assert.Equal(uint.MinValue, instruction.MemoryDisplacement32); Assert.Equal(ulong.MinValue, instruction.MemoryDisplacement64); instruction.MemoryDisplacement64 = ulong.MaxValue; Assert.Equal(uint.MaxValue, instruction.MemoryDisplacement32); Assert.Equal(ulong.MaxValue, instruction.MemoryDisplacement64); instruction.MemoryDisplacement64 = 0x1234_5678_9ABC_DEF1; instruction.MemoryDisplacement32 = 0x5AA5_4321; Assert.Equal(0x5AA5_4321U, instruction.MemoryDisplacement32); Assert.Equal(0x5AA5_4321U, instruction.MemoryDisplacement64); instruction.Immediate8 = byte.MinValue; Assert.Equal(byte.MinValue, instruction.Immediate8); instruction.Immediate8 = byte.MaxValue; Assert.Equal(byte.MaxValue, instruction.Immediate8); instruction.Immediate8_2nd = byte.MinValue; Assert.Equal(byte.MinValue, instruction.Immediate8_2nd); instruction.Immediate8_2nd = byte.MaxValue; Assert.Equal(byte.MaxValue, instruction.Immediate8_2nd); instruction.Immediate16 = ushort.MinValue; Assert.Equal(ushort.MinValue, instruction.Immediate16); instruction.Immediate16 = ushort.MaxValue; Assert.Equal(ushort.MaxValue, instruction.Immediate16); instruction.Immediate32 = uint.MinValue; Assert.Equal(uint.MinValue, instruction.Immediate32); instruction.Immediate32 = uint.MaxValue; Assert.Equal(uint.MaxValue, instruction.Immediate32); instruction.Immediate64 = ulong.MinValue; Assert.Equal(ulong.MinValue, instruction.Immediate64); instruction.Immediate64 = ulong.MaxValue; Assert.Equal(ulong.MaxValue, instruction.Immediate64); instruction.Immediate8to16 = sbyte.MinValue; Assert.Equal(sbyte.MinValue, instruction.Immediate8to16); instruction.Immediate8to16 = sbyte.MaxValue; Assert.Equal(sbyte.MaxValue, instruction.Immediate8to16); instruction.Immediate8to32 = sbyte.MinValue; Assert.Equal(sbyte.MinValue, instruction.Immediate8to32); instruction.Immediate8to32 = sbyte.MaxValue; Assert.Equal(sbyte.MaxValue, instruction.Immediate8to32); instruction.Immediate8to64 = sbyte.MinValue; Assert.Equal(sbyte.MinValue, instruction.Immediate8to64); instruction.Immediate8to64 = sbyte.MaxValue; Assert.Equal(sbyte.MaxValue, instruction.Immediate8to64); instruction.Immediate32to64 = int.MinValue; Assert.Equal(int.MinValue, instruction.Immediate32to64); instruction.Immediate32to64 = int.MaxValue; Assert.Equal(int.MaxValue, instruction.Immediate32to64); instruction.Op0Kind = OpKind.NearBranch16; instruction.NearBranch16 = ushort.MinValue; Assert.Equal(ushort.MinValue, instruction.NearBranch16); Assert.Equal(ushort.MinValue, instruction.NearBranchTarget); instruction.NearBranch16 = ushort.MaxValue; Assert.Equal(ushort.MaxValue, instruction.NearBranch16); Assert.Equal(ushort.MaxValue, instruction.NearBranchTarget); instruction.Op0Kind = OpKind.NearBranch32; instruction.NearBranch32 = uint.MinValue; Assert.Equal(uint.MinValue, instruction.NearBranch32); Assert.Equal(uint.MinValue, instruction.NearBranchTarget); instruction.NearBranch32 = uint.MaxValue; Assert.Equal(uint.MaxValue, instruction.NearBranch32); Assert.Equal(uint.MaxValue, instruction.NearBranchTarget); instruction.Op0Kind = OpKind.NearBranch64; instruction.NearBranch64 = ulong.MinValue; Assert.Equal(ulong.MinValue, instruction.NearBranch64); Assert.Equal(ulong.MinValue, instruction.NearBranchTarget); instruction.NearBranch64 = ulong.MaxValue; Assert.Equal(ulong.MaxValue, instruction.NearBranch64); Assert.Equal(ulong.MaxValue, instruction.NearBranchTarget); instruction.FarBranch16 = ushort.MinValue; Assert.Equal(ushort.MinValue, instruction.FarBranch16); instruction.FarBranch16 = ushort.MaxValue; Assert.Equal(ushort.MaxValue, instruction.FarBranch16); instruction.FarBranch32 = uint.MinValue; Assert.Equal(uint.MinValue, instruction.FarBranch32); instruction.FarBranch32 = uint.MaxValue; Assert.Equal(uint.MaxValue, instruction.FarBranch32); instruction.FarBranchSelector = ushort.MinValue; Assert.Equal(ushort.MinValue, instruction.FarBranchSelector); instruction.FarBranchSelector = ushort.MaxValue; Assert.Equal(ushort.MaxValue, instruction.FarBranchSelector); instruction.HasXacquirePrefix = false; Assert.False(instruction.HasXacquirePrefix); instruction.HasXacquirePrefix = true; Assert.True(instruction.HasXacquirePrefix); instruction.HasXreleasePrefix = false; Assert.False(instruction.HasXreleasePrefix); instruction.HasXreleasePrefix = true; Assert.True(instruction.HasXreleasePrefix); instruction.HasRepPrefix = false; Assert.False(instruction.HasRepPrefix); Assert.False(instruction.HasRepePrefix); instruction.HasRepPrefix = true; Assert.True(instruction.HasRepPrefix); Assert.True(instruction.HasRepePrefix); instruction.HasRepePrefix = false; Assert.False(instruction.HasRepPrefix); Assert.False(instruction.HasRepePrefix); instruction.HasRepePrefix = true; Assert.True(instruction.HasRepPrefix); Assert.True(instruction.HasRepePrefix); instruction.HasRepnePrefix = false; Assert.False(instruction.HasRepnePrefix); instruction.HasRepnePrefix = true; Assert.True(instruction.HasRepnePrefix); instruction.HasLockPrefix = false; Assert.False(instruction.HasLockPrefix); instruction.HasLockPrefix = true; Assert.True(instruction.HasLockPrefix); instruction.IsBroadcast = false; Assert.False(instruction.IsBroadcast); instruction.IsBroadcast = true; Assert.True(instruction.IsBroadcast); instruction.SuppressAllExceptions = false; Assert.False(instruction.SuppressAllExceptions); instruction.SuppressAllExceptions = true; Assert.True(instruction.SuppressAllExceptions); for (int i = 0; i <= IcedConstants.MaxInstructionLength; i++) { instruction.Length = i; Assert.Equal(i, instruction.Length); } foreach (var codeSize in GetCodeSizeValues()) { instruction.CodeSize = codeSize; Assert.Equal(codeSize, instruction.CodeSize); } foreach (var code in GetCodeValues()) { instruction.Code = code; Assert.Equal(code, instruction.Code); } foreach (var code in GetCodeValues()) { instruction.InternalSetCodeNoCheck(code); Assert.Equal(code, instruction.Code); } Assert.Throws <ArgumentOutOfRangeException>(() => instruction.Code = (Code)(-1)); Assert.Throws <ArgumentOutOfRangeException>(() => instruction.Code = (Code)IcedConstants.CodeEnumCount); Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1); foreach (var opKind in GetOpKindValues()) { instruction.Op0Kind = opKind; Assert.Equal(opKind, instruction.Op0Kind); } foreach (var opKind in GetOpKindValues()) { instruction.Op1Kind = opKind; Assert.Equal(opKind, instruction.Op1Kind); } foreach (var opKind in GetOpKindValues()) { instruction.Op2Kind = opKind; Assert.Equal(opKind, instruction.Op2Kind); } foreach (var opKind in GetOpKindValues()) { instruction.Op3Kind = opKind; Assert.Equal(opKind, instruction.Op3Kind); } foreach (var opKind in GetOpKindValues()) { if (opKind == OpKind.Immediate8) { instruction.Op4Kind = opKind; Assert.Equal(opKind, instruction.Op4Kind); } else { Assert.Throws <ArgumentOutOfRangeException>(() => instruction.Op4Kind = opKind); } } foreach (var opKind in GetOpKindValues()) { instruction.SetOpKind(0, opKind); Assert.Equal(opKind, instruction.Op0Kind); Assert.Equal(opKind, instruction.GetOpKind(0)); } foreach (var opKind in GetOpKindValues()) { instruction.SetOpKind(1, opKind); Assert.Equal(opKind, instruction.Op1Kind); Assert.Equal(opKind, instruction.GetOpKind(1)); } foreach (var opKind in GetOpKindValues()) { instruction.SetOpKind(2, opKind); Assert.Equal(opKind, instruction.Op2Kind); Assert.Equal(opKind, instruction.GetOpKind(2)); } foreach (var opKind in GetOpKindValues()) { instruction.SetOpKind(3, opKind); Assert.Equal(opKind, instruction.Op3Kind); Assert.Equal(opKind, instruction.GetOpKind(3)); } foreach (var opKind in GetOpKindValues()) { if (opKind == OpKind.Immediate8) { instruction.SetOpKind(4, opKind); Assert.Equal(opKind, instruction.Op4Kind); Assert.Equal(opKind, instruction.GetOpKind(4)); } else { Assert.Throws <ArgumentOutOfRangeException>(() => instruction.SetOpKind(4, opKind)); } } var segValues = new Register[] { Register.ES, Register.CS, Register.SS, Register.DS, Register.FS, Register.GS, Register.None, }; foreach (var seg in segValues) { instruction.SegmentPrefix = seg; Assert.Equal(seg, instruction.SegmentPrefix); if (instruction.SegmentPrefix == Register.None) { Assert.False(instruction.HasSegmentPrefix); } else { Assert.True(instruction.HasSegmentPrefix); } } var displSizes = new int[] { 8, 4, 2, 1, 0 }; foreach (var displSize in displSizes) { instruction.MemoryDisplSize = displSize; Assert.Equal(displSize, instruction.MemoryDisplSize); } var scaleValues = new int[] { 8, 4, 2, 1 }; foreach (var scaleValue in scaleValues) { instruction.MemoryIndexScale = scaleValue; Assert.Equal(scaleValue, instruction.MemoryIndexScale); } foreach (var reg in GetRegisterValues()) { instruction.MemoryBase = reg; Assert.Equal(reg, instruction.MemoryBase); } foreach (var reg in GetRegisterValues()) { instruction.MemoryIndex = reg; Assert.Equal(reg, instruction.MemoryIndex); } foreach (var reg in GetRegisterValues()) { instruction.Op0Register = reg; Assert.Equal(reg, instruction.Op0Register); } foreach (var reg in GetRegisterValues()) { instruction.Op1Register = reg; Assert.Equal(reg, instruction.Op1Register); } foreach (var reg in GetRegisterValues()) { instruction.Op2Register = reg; Assert.Equal(reg, instruction.Op2Register); } foreach (var reg in GetRegisterValues()) { instruction.Op3Register = reg; Assert.Equal(reg, instruction.Op3Register); } foreach (var reg in GetRegisterValues()) { if (reg == Register.None) { instruction.Op4Register = reg; Assert.Equal(reg, instruction.Op4Register); } else { Assert.Throws <ArgumentOutOfRangeException>(() => instruction.Op4Register = reg); } } foreach (var reg in GetRegisterValues()) { instruction.SetOpRegister(0, reg); Assert.Equal(reg, instruction.Op0Register); Assert.Equal(reg, instruction.GetOpRegister(0)); } foreach (var reg in GetRegisterValues()) { instruction.SetOpRegister(1, reg); Assert.Equal(reg, instruction.Op1Register); Assert.Equal(reg, instruction.GetOpRegister(1)); } foreach (var reg in GetRegisterValues()) { instruction.SetOpRegister(2, reg); Assert.Equal(reg, instruction.Op2Register); Assert.Equal(reg, instruction.GetOpRegister(2)); } foreach (var reg in GetRegisterValues()) { instruction.SetOpRegister(3, reg); Assert.Equal(reg, instruction.Op3Register); Assert.Equal(reg, instruction.GetOpRegister(3)); } foreach (var reg in GetRegisterValues()) { if (reg == Register.None) { instruction.SetOpRegister(4, reg); Assert.Equal(reg, instruction.Op4Register); Assert.Equal(reg, instruction.GetOpRegister(4)); } else { Assert.Throws <ArgumentOutOfRangeException>(() => instruction.SetOpRegister(4, reg)); } } var opMasks = new Register[] { Register.K1, Register.K2, Register.K3, Register.K4, Register.K5, Register.K6, Register.K7, Register.None, }; foreach (var opMask in opMasks) { instruction.OpMask = opMask; Assert.Equal(opMask, instruction.OpMask); Assert.Equal(opMask != Register.None, instruction.HasOpMask); } instruction.ZeroingMasking = false; Assert.False(instruction.ZeroingMasking); Assert.True(instruction.MergingMasking); instruction.ZeroingMasking = true; Assert.True(instruction.ZeroingMasking); Assert.False(instruction.MergingMasking); instruction.MergingMasking = false; Assert.False(instruction.MergingMasking); Assert.True(instruction.ZeroingMasking); instruction.MergingMasking = true; Assert.True(instruction.MergingMasking); Assert.False(instruction.ZeroingMasking); foreach (var rc in GetRoundingControlValues()) { instruction.RoundingControl = rc; Assert.Equal(rc, instruction.RoundingControl); } foreach (var reg in GetRegisterValues()) { instruction.MemoryBase = reg; Assert.Equal(reg == Register.RIP || reg == Register.EIP, instruction.IsIPRelativeMemoryOperand); } instruction.MemoryBase = Register.EIP; instruction.NextIP = 0x123456709EDCBA98; instruction.MemoryDisplacement64 = 0x876543219ABCDEF5; Assert.True(instruction.IsIPRelativeMemoryOperand); Assert.Equal(0x9ABCDEF5UL, instruction.IPRelativeMemoryAddress); instruction.MemoryBase = Register.RIP; instruction.NextIP = 0x123456709EDCBA98; instruction.MemoryDisplacement64 = 0x876543219ABCDEF5; Assert.True(instruction.IsIPRelativeMemoryOperand); Assert.Equal(0x876543219ABCDEF5UL, instruction.IPRelativeMemoryAddress); instruction.DeclareDataCount = 1; Assert.Equal(1, instruction.DeclareDataCount); instruction.DeclareDataCount = 15; Assert.Equal(15, instruction.DeclareDataCount); instruction.DeclareDataCount = 16; Assert.Equal(16, instruction.DeclareDataCount); }
#pragma warning disable xUnit1026 // Theory methods should use all of their parameters void Test_all_OpCodeInfos(int lineNo, Code code, string opCodeString, string instructionString, OpCodeInfoTestCase tc) { #pragma warning restore xUnit1026 // Theory methods should use all of their parameters var info = tc.Code.ToOpCode(); Assert.Equal(tc.Code, info.Code); #pragma warning disable xUnit2006 // Do not use invalid string equality check // Show the full string without ellipses by using Equal<string>() instead of Equal() Assert.Equal <string>(tc.OpCodeString, info.ToOpCodeString()); Assert.Equal <string>(tc.InstructionString, info.ToInstructionString()); #pragma warning restore xUnit2006 // Do not use invalid string equality check Assert.True((object)info.ToInstructionString() == info.ToString()); Assert.Equal(tc.Encoding, info.Encoding); Assert.Equal(tc.IsInstruction, info.IsInstruction); Assert.Equal(tc.Mode16, info.Mode16); Assert.Equal(tc.Mode16, info.IsAvailableInMode(16)); Assert.Equal(tc.Mode32, info.Mode32); Assert.Equal(tc.Mode32, info.IsAvailableInMode(32)); Assert.Equal(tc.Mode64, info.Mode64); Assert.Equal(tc.Mode64, info.IsAvailableInMode(64)); Assert.Equal(tc.Fwait, info.Fwait); Assert.Equal(tc.OperandSize, info.OperandSize); Assert.Equal(tc.AddressSize, info.AddressSize); Assert.Equal(tc.L, info.L); Assert.Equal(tc.W, info.W); Assert.Equal(tc.IsLIG, info.IsLIG); Assert.Equal(tc.IsWIG, info.IsWIG); Assert.Equal(tc.IsWIG32, info.IsWIG32); Assert.Equal(tc.TupleType, info.TupleType); Assert.Equal(tc.CanBroadcast, info.CanBroadcast); Assert.Equal(tc.CanUseRoundingControl, info.CanUseRoundingControl); Assert.Equal(tc.CanSuppressAllExceptions, info.CanSuppressAllExceptions); Assert.Equal(tc.CanUseOpMaskRegister, info.CanUseOpMaskRegister); Assert.Equal(tc.RequireNonZeroOpMaskRegister, info.RequireNonZeroOpMaskRegister); if (tc.RequireNonZeroOpMaskRegister) { Assert.True(info.CanUseOpMaskRegister); Assert.False(info.CanUseZeroingMasking); } Assert.Equal(tc.CanUseZeroingMasking, info.CanUseZeroingMasking); Assert.Equal(tc.CanUseLockPrefix, info.CanUseLockPrefix); Assert.Equal(tc.CanUseXacquirePrefix, info.CanUseXacquirePrefix); Assert.Equal(tc.CanUseXreleasePrefix, info.CanUseXreleasePrefix); Assert.Equal(tc.CanUseRepPrefix, info.CanUseRepPrefix); Assert.Equal(tc.CanUseRepnePrefix, info.CanUseRepnePrefix); Assert.Equal(tc.CanUseBndPrefix, info.CanUseBndPrefix); Assert.Equal(tc.CanUseHintTakenPrefix, info.CanUseHintTakenPrefix); Assert.Equal(tc.CanUseNotrackPrefix, info.CanUseNotrackPrefix); Assert.Equal(tc.Table, info.Table); Assert.Equal(tc.MandatoryPrefix, info.MandatoryPrefix); Assert.Equal(tc.OpCode, info.OpCode); Assert.Equal(tc.IsGroup, info.IsGroup); Assert.Equal(tc.GroupIndex, info.GroupIndex); Assert.Equal(tc.OpCount, info.OpCount); Assert.Equal(tc.Op0Kind, info.Op0Kind); Assert.Equal(tc.Op1Kind, info.Op1Kind); Assert.Equal(tc.Op2Kind, info.Op2Kind); Assert.Equal(tc.Op3Kind, info.Op3Kind); Assert.Equal(tc.Op4Kind, info.Op4Kind); Assert.Equal(tc.Op0Kind, info.GetOpKind(0)); Assert.Equal(tc.Op1Kind, info.GetOpKind(1)); Assert.Equal(tc.Op2Kind, info.GetOpKind(2)); Assert.Equal(tc.Op3Kind, info.GetOpKind(3)); Assert.Equal(tc.Op4Kind, info.GetOpKind(4)); Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1); for (int i = tc.OpCount; i < IcedConstants.MaxOpCount; i++) { Assert.Equal(OpCodeOperandKind.None, info.GetOpKind(i)); } }
protected void TestInstructionInfo(int bitness, string hexBytes, Code code, DecoderOptions options, int lineNo, InstructionInfoTestCase testCase) { var codeBytes = HexUtils.ToByteArray(hexBytes); Instruction instruction; if (testCase.IsSpecial) { if (bitness == 16 && code == Code.Popw_CS && hexBytes == "0F") { instruction = default; instruction.Code = Code.Popw_CS; instruction.Op0Kind = OpKind.Register; instruction.Op0Register = Register.CS; instruction.CodeSize = CodeSize.Code16; instruction.Length = 1; } else if (code <= Code.DeclareQword) { instruction = default; instruction.Code = code; instruction.DeclareDataCount = 1; Assert.Equal(64, bitness); instruction.CodeSize = CodeSize.Code64; switch (code) { case Code.DeclareByte: Assert.Equal("66", hexBytes); instruction.SetDeclareByteValue(0, 0x66); break; case Code.DeclareWord: Assert.Equal("6644", hexBytes); instruction.SetDeclareWordValue(0, 0x4466); break; case Code.DeclareDword: Assert.Equal("664422EE", hexBytes); instruction.SetDeclareDwordValue(0, 0xEE224466); break; case Code.DeclareQword: Assert.Equal("664422EE12345678", hexBytes); instruction.SetDeclareQwordValue(0, 0x78563412EE224466); break; default: throw new InvalidOperationException(); } } else { var decoder = CreateDecoder(bitness, codeBytes, options); instruction = decoder.Decode(); if (codeBytes.Length > 1 && codeBytes[0] == 0x9B && instruction.Length == 1) { instruction = decoder.Decode(); instruction.Code = instruction.Code switch { Code.Fnstenv_m14byte => Code.Fstenv_m14byte, Code.Fnstenv_m28byte => Code.Fstenv_m28byte, Code.Fnstcw_m2byte => Code.Fstcw_m2byte, Code.Fneni => Code.Feni, Code.Fndisi => Code.Fdisi, Code.Fnclex => Code.Fclex, Code.Fninit => Code.Finit, Code.Fnsetpm => Code.Fsetpm, Code.Fnsave_m94byte => Code.Fsave_m94byte, Code.Fnsave_m108byte => Code.Fsave_m108byte, Code.Fnstsw_m2byte => Code.Fstsw_m2byte, Code.Fnstsw_AX => Code.Fstsw_AX, _ => throw new InvalidOperationException(), }; } else { throw new InvalidOperationException(); } } } else { var decoder = CreateDecoder(bitness, codeBytes, options); instruction = decoder.Decode(); } Assert.Equal(code, instruction.Code); Assert.Equal(testCase.StackPointerIncrement, instruction.StackPointerIncrement); var info = new InstructionInfoFactory().GetInfo(instruction); Assert.Equal(testCase.Encoding, info.Encoding); Assert.Equal(testCase.CpuidFeatures, info.CpuidFeatures); Assert.Equal(testCase.RflagsRead, info.RflagsRead); Assert.Equal(testCase.RflagsUndefined, info.RflagsUndefined); Assert.Equal(testCase.RflagsWritten, info.RflagsWritten); Assert.Equal(testCase.RflagsCleared, info.RflagsCleared); Assert.Equal(testCase.RflagsSet, info.RflagsSet); Assert.Equal(testCase.IsPrivileged, info.IsPrivileged); Assert.Equal(testCase.IsProtectedMode, info.IsProtectedMode); Assert.Equal(testCase.IsStackInstruction, info.IsStackInstruction); Assert.Equal(testCase.IsSaveRestoreInstruction, info.IsSaveRestoreInstruction); Assert.Equal(testCase.FlowControl, info.FlowControl); Assert.Equal(testCase.Op0Access, info.Op0Access); Assert.Equal(testCase.Op1Access, info.Op1Access); Assert.Equal(testCase.Op2Access, info.Op2Access); Assert.Equal(testCase.Op3Access, info.Op3Access); Assert.Equal(testCase.Op4Access, info.Op4Access); Assert.Equal( new HashSet <UsedMemory>(testCase.UsedMemory, UsedMemoryEqualityComparer.Instance), new HashSet <UsedMemory>(info.GetUsedMemory(), UsedMemoryEqualityComparer.Instance)); Assert.Equal( new HashSet <UsedRegister>(GetUsedRegisters(testCase.UsedRegisters), UsedRegisterEqualityComparer.Instance), new HashSet <UsedRegister>(GetUsedRegisters(info.GetUsedRegisters()), UsedRegisterEqualityComparer.Instance)); Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1); Debug.Assert(instruction.OpCount <= IcedConstants.MaxOpCount); for (int i = 0; i < instruction.OpCount; i++) { switch (i) { case 0: Assert.Equal(testCase.Op0Access, info.GetOpAccess(i)); break; case 1: Assert.Equal(testCase.Op1Access, info.GetOpAccess(i)); break; case 2: Assert.Equal(testCase.Op2Access, info.GetOpAccess(i)); break; case 3: Assert.Equal(testCase.Op3Access, info.GetOpAccess(i)); break; case 4: Assert.Equal(testCase.Op4Access, info.GetOpAccess(i)); break; default: throw new InvalidOperationException(); } } for (int i = instruction.OpCount; i < IcedConstants.MaxOpCount; i++) { Assert.Equal(OpAccess.None, info.GetOpAccess(i)); } Assert.Equal(RflagsBits.None, info.RflagsWritten & (info.RflagsCleared | info.RflagsSet | info.RflagsUndefined)); Assert.Equal(RflagsBits.None, info.RflagsCleared & (info.RflagsWritten | info.RflagsSet | info.RflagsUndefined)); Assert.Equal(RflagsBits.None, info.RflagsSet & (info.RflagsWritten | info.RflagsCleared | info.RflagsUndefined)); Assert.Equal(RflagsBits.None, info.RflagsUndefined & (info.RflagsWritten | info.RflagsCleared | info.RflagsSet)); Assert.Equal(info.RflagsWritten | info.RflagsCleared | info.RflagsSet | info.RflagsUndefined, info.RflagsModified); var info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.None); CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: true); info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.NoMemoryUsage); CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: false); info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.NoRegisterUsage); CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: true); info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.NoRegisterUsage | InstructionInfoOptions.NoMemoryUsage); CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: false); Assert.Equal(info.Encoding, instruction.Code.Encoding()); #if ENCODER && OPCODE_INFO Assert.Equal(code.ToOpCode().Encoding, instruction.Code.Encoding()); #endif var cf = instruction.Code.CpuidFeatures(); if (cf.Length == 1 && cf[0] == CpuidFeature.AVX && instruction.Op1Kind == OpKind.Register && (code == Code.VEX_Vbroadcastss_xmm_xmmm32 || code == Code.VEX_Vbroadcastss_ymm_xmmm32 || code == Code.VEX_Vbroadcastsd_ymm_xmmm64)) { cf = new[] { CpuidFeature.AVX2 } } ; Assert.Equal(info.CpuidFeatures, cf); Assert.Equal(info.FlowControl, instruction.Code.FlowControl()); Assert.Equal(info.IsProtectedMode, instruction.Code.IsProtectedMode()); Assert.Equal(info.IsPrivileged, instruction.Code.IsPrivileged()); Assert.Equal(info.IsStackInstruction, instruction.Code.IsStackInstruction()); Assert.Equal(info.IsSaveRestoreInstruction, instruction.Code.IsSaveRestoreInstruction()); Assert.Equal(info.Encoding, instruction.Encoding); Assert.Equal(info.CpuidFeatures, instruction.CpuidFeatures); Assert.Equal(info.FlowControl, instruction.FlowControl); Assert.Equal(info.IsProtectedMode, instruction.IsProtectedMode); Assert.Equal(info.IsPrivileged, instruction.IsPrivileged); Assert.Equal(info.IsStackInstruction, instruction.IsStackInstruction); Assert.Equal(info.IsSaveRestoreInstruction, instruction.IsSaveRestoreInstruction); Assert.Equal(info.RflagsRead, instruction.RflagsRead); Assert.Equal(info.RflagsWritten, instruction.RflagsWritten); Assert.Equal(info.RflagsCleared, instruction.RflagsCleared); Assert.Equal(info.RflagsSet, instruction.RflagsSet); Assert.Equal(info.RflagsUndefined, instruction.RflagsUndefined); Assert.Equal(info.RflagsModified, instruction.RflagsModified); } void CheckEqual(ref InstructionInfo info1, ref InstructionInfo info2, bool hasRegs2, bool hasMem2) { if (hasRegs2) { Assert.Equal(info1.GetUsedRegisters(), info2.GetUsedRegisters(), UsedRegisterEqualityComparer.Instance); } else { Assert.Empty(info2.GetUsedRegisters()); } if (hasMem2) { Assert.Equal(info1.GetUsedMemory(), info2.GetUsedMemory(), UsedMemoryEqualityComparer.Instance); } else { Assert.Empty(info2.GetUsedMemory()); } Assert.Equal(info1.IsProtectedMode, info2.IsProtectedMode); Assert.Equal(info1.IsPrivileged, info2.IsPrivileged); Assert.Equal(info1.IsStackInstruction, info2.IsStackInstruction); Assert.Equal(info1.IsSaveRestoreInstruction, info2.IsSaveRestoreInstruction); Assert.Equal(info1.Encoding, info2.Encoding); Assert.Equal(info1.CpuidFeatures, info2.CpuidFeatures); Assert.Equal(info1.FlowControl, info2.FlowControl); Assert.Equal(info1.Op0Access, info2.Op0Access); Assert.Equal(info1.Op1Access, info2.Op1Access); Assert.Equal(info1.Op2Access, info2.Op2Access); Assert.Equal(info1.Op3Access, info2.Op3Access); Assert.Equal(info1.Op4Access, info2.Op4Access); Assert.Equal(info1.RflagsRead, info2.RflagsRead); Assert.Equal(info1.RflagsWritten, info2.RflagsWritten); Assert.Equal(info1.RflagsCleared, info2.RflagsCleared); Assert.Equal(info1.RflagsSet, info2.RflagsSet); Assert.Equal(info1.RflagsUndefined, info2.RflagsUndefined); Assert.Equal(info1.RflagsModified, info2.RflagsModified); } IEnumerable <UsedRegister> GetUsedRegisters(IEnumerable <UsedRegister> usedRegisterIterator) { var read = new List <Register>(); var write = new List <Register>(); var condRead = new List <Register>(); var condWrite = new List <Register>(); foreach (var info in usedRegisterIterator) { switch (info.Access) { case OpAccess.Read: read.Add(info.Register); break; case OpAccess.CondRead: condRead.Add(info.Register); break; case OpAccess.Write: write.Add(info.Register); break; case OpAccess.CondWrite: condWrite.Add(info.Register); break; case OpAccess.ReadWrite: read.Add(info.Register); write.Add(info.Register); break; case OpAccess.ReadCondWrite: read.Add(info.Register); condWrite.Add(info.Register); break; case OpAccess.None: case OpAccess.NoMemAccess: default: throw new InvalidOperationException(); } } foreach (var reg in GetRegisters(read)) { yield return(new UsedRegister(reg, OpAccess.Read)); } foreach (var reg in GetRegisters(write)) { yield return(new UsedRegister(reg, OpAccess.Write)); } foreach (var reg in GetRegisters(condRead)) { yield return(new UsedRegister(reg, OpAccess.CondRead)); } foreach (var reg in GetRegisters(condWrite)) { yield return(new UsedRegister(reg, OpAccess.CondWrite)); } } IEnumerable <Register> GetRegisters(List <Register> regs) { if (regs.Count <= 1) { return(regs); } regs.Sort(RegisterSorter); var hash = new HashSet <Register>(); int index; foreach (var reg in regs) { if (Register.EAX <= reg && reg <= Register.R15D) { index = reg - Register.EAX; if (hash.Contains(Register.RAX + index)) { continue; } } else if (Register.AX <= reg && reg <= Register.R15W) { index = reg - Register.AX; if (hash.Contains(Register.RAX + index)) { continue; } if (hash.Contains(Register.EAX + index)) { continue; } } else if (Register.AL <= reg && reg <= Register.R15L) { index = reg - Register.AL; if (Register.AH <= reg && reg <= Register.BH) { index -= 4; } if (hash.Contains(Register.RAX + index)) { continue; } if (hash.Contains(Register.EAX + index)) { continue; } if (hash.Contains(Register.AX + index)) { continue; } } else if (Register.YMM0 <= reg && reg <= IcedConstants.YMM_last) { index = reg - Register.YMM0; if (hash.Contains(Register.ZMM0 + index)) { continue; } } else if (Register.XMM0 <= reg && reg <= IcedConstants.XMM_last) { index = reg - Register.XMM0; if (hash.Contains(Register.ZMM0 + index)) { continue; } if (hash.Contains(Register.YMM0 + index)) { continue; } } hash.Add(reg); } foreach (var info in lowRegs) { if (hash.Contains(info.rl) && hash.Contains(info.rh)) { hash.Remove(info.rl); hash.Remove(info.rh); hash.Add(info.rx); } } return(hash); }