void DecoderTestMisc(int bitness, int lineNo, string hexBytes, DecoderTestCase tc) => DecoderTestBase(bitness, lineNo, hexBytes, tc);
static void ReadOpKind(DecoderTestCase tc, int operand, string value, out OpKind opKind, ref Register opRegister) { var parts = value.Split(opKindSeps); switch (parts[0]) { case OpKind_Register: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opRegister = ToRegister(parts[1]); opKind = OpKind.Register; break; case OpKind_NearBranch16: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.NearBranch16; tc.NearBranch = ToUInt16(parts[1]); break; case OpKind_NearBranch32: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.NearBranch32; tc.NearBranch = ToUInt32(parts[1]); break; case OpKind_NearBranch64: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.NearBranch64; tc.NearBranch = ToUInt64(parts[1]); break; case OpKind_FarBranch16: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } opKind = OpKind.FarBranch16; tc.FarBranchSelector = ToUInt16(parts[1]); tc.FarBranch = ToUInt16(parts[2]); break; case OpKind_FarBranch32: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } opKind = OpKind.FarBranch32; tc.FarBranchSelector = ToUInt16(parts[1]); tc.FarBranch = ToUInt32(parts[2]); break; case OpKind_Immediate8: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.Immediate8; tc.Immediate = ToUInt8(parts[1]); break; case OpKind_Immediate16: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.Immediate16; tc.Immediate = ToUInt16(parts[1]); break; case OpKind_Immediate32: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.Immediate32; tc.Immediate = ToUInt32(parts[1]); break; case OpKind_Immediate64: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.Immediate64; tc.Immediate = ToUInt64(parts[1]); break; case OpKind_Immediate8to16: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.Immediate8to16; tc.Immediate = ToUInt16(parts[1]); break; case OpKind_Immediate8to32: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.Immediate8to32; tc.Immediate = ToUInt32(parts[1]); break; case OpKind_Immediate8to64: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.Immediate8to64; tc.Immediate = ToUInt64(parts[1]); break; case OpKind_Immediate32to64: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.Immediate32to64; tc.Immediate = ToUInt64(parts[1]); break; case OpKind_Immediate8_2nd: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.Immediate8_2nd; tc.Immediate_2nd = ToUInt8(parts[1]); break; case OpKind_MemorySegSI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } opKind = OpKind.MemorySegSI; tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case OpKind_MemorySegESI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } opKind = OpKind.MemorySegESI; tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case OpKind_MemorySegRSI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } opKind = OpKind.MemorySegRSI; tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case OpKind_MemorySegDI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } opKind = OpKind.MemorySegDI; tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case OpKind_MemorySegEDI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } opKind = OpKind.MemorySegEDI; tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case OpKind_MemorySegRDI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } opKind = OpKind.MemorySegRDI; tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case OpKind_MemoryESDI: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.MemoryESDI; tc.MemorySize = ToMemorySize(parts[1]); break; case OpKind_MemoryESEDI: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.MemoryESEDI; tc.MemorySize = ToMemorySize(parts[1]); break; case OpKind_MemoryESRDI: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } opKind = OpKind.MemoryESRDI; tc.MemorySize = ToMemorySize(parts[1]); break; case OpKind_Memory64: if (parts.Length != 4) { throw new InvalidOperationException($"Operand {operand}: expected 4 values, actual = {parts.Length}"); } opKind = OpKind.Memory64; tc.MemorySegment = ToRegister(parts[1]); tc.MemoryAddress64 = ToUInt64(parts[2]); tc.MemorySize = ToMemorySize(parts[3]); break; case OpKind_Memory: if (parts.Length != 8) { throw new InvalidOperationException($"Operand {operand}: expected 8 values, actual = {parts.Length}"); } opKind = OpKind.Memory; tc.MemorySegment = ToRegister(parts[1]); tc.MemoryBase = ToRegister(parts[2]); tc.MemoryIndex = ToRegister(parts[3]); tc.MemoryIndexScale = ToInt32(parts[4]); tc.MemoryDisplacement = ToUInt32(parts[5]); tc.MemoryDisplSize = ToInt32(parts[6]); tc.MemorySize = ToMemorySize(parts[7]); break; default: throw new InvalidOperationException($"Invalid opkind: '{parts[0]}'"); } }
static DecoderTestCase ReadTestCase(int bitness, string line, int lineNo) { var parts = line.Split(seps); if (parts.Length != 5) { throw new InvalidOperationException($"Invalid number of commas ({parts.Length - 1} commas)"); } var tc = new DecoderTestCase(); tc.LineNumber = lineNo; tc.Bitness = bitness; tc.HexBytes = ToHexBytes(parts[0].Trim()); tc.EncodedHexBytes = tc.HexBytes; tc.Code = ToCode(parts[1].Trim()); tc.Mnemonic = ToMnemonic(parts[2].Trim()); tc.OpCount = ToInt32(parts[3].Trim()); var rest = parts[4].Split(extraSeps); foreach (var tmp in rest) { if (tmp == string.Empty) { continue; } var key = tmp; string value; int index = key.IndexOf('='); if (index >= 0) { value = key.Substring(index + 1); key = key.Substring(0, index); } else { value = null; } switch (key) { case Broadcast: tc.IsBroadcast = true; break; case Xacquire: tc.HasXacquirePrefix = true; break; case Xrelease: tc.HasXreleasePrefix = true; break; case Rep: case Repe: tc.HasRepePrefix = true; break; case Repne: tc.HasRepnePrefix = true; break; case Lock: tc.HasLockPrefix = true; break; case ZeroingMasking: tc.ZeroingMasking = true; break; case SuppressAllExceptions: tc.SuppressAllExceptions = true; break; case Vsib32: tc.VsibBitness = 32; break; case Vsib64: tc.VsibBitness = 64; break; case RoundToNearest: tc.RoundingControl = RoundingControl.RoundToNearest; break; case RoundDown: tc.RoundingControl = RoundingControl.RoundDown; break; case RoundUp: tc.RoundingControl = RoundingControl.RoundUp; break; case RoundTowardZero: tc.RoundingControl = RoundingControl.RoundTowardZero; break; case Op0Kind: if (tc.OpCount < 1) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 1"); } ReadOpKind(tc, 0, value, out tc.Op0Kind, ref tc.Op0Register); break; case Op1Kind: if (tc.OpCount < 2) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 2"); } ReadOpKind(tc, 1, value, out tc.Op1Kind, ref tc.Op1Register); break; case Op2Kind: if (tc.OpCount < 3) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 3"); } ReadOpKind(tc, 2, value, out tc.Op2Kind, ref tc.Op2Register); break; case Op3Kind: if (tc.OpCount < 4) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 4"); } ReadOpKind(tc, 3, value, out tc.Op3Kind, ref tc.Op3Register); break; case Op4Kind: if (tc.OpCount < 5) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 5"); } ReadOpKind(tc, 4, value, out tc.Op4Kind, ref tc.Op4Register); break; case EncodedHexBytes: if (string.IsNullOrWhiteSpace(value)) { throw new InvalidOperationException($"Invalid encoded hex bytes: '{value}'"); } tc.EncodedHexBytes = value; break; case DecoderOptions_AMD: tc.DecoderOptions |= DecoderOptions.AMD; break; case DecoderOptions_ForceReservedNop: tc.DecoderOptions |= DecoderOptions.ForceReservedNop; break; case DecoderOptions_Cflsh: tc.DecoderOptions |= DecoderOptions.Cflsh; break; case DecoderOptions_Umov: tc.DecoderOptions |= DecoderOptions.Umov; break; case DecoderOptions_Ecr: tc.DecoderOptions |= DecoderOptions.Ecr; break; case DecoderOptions_Xbts: tc.DecoderOptions |= DecoderOptions.Xbts; break; case DecoderOptions_Cmpxchg486A: tc.DecoderOptions |= DecoderOptions.Cmpxchg486A; break; case DecoderOptions_Zalloc: tc.DecoderOptions |= DecoderOptions.Zalloc; break; case DecoderOptions_OldFpu: tc.DecoderOptions |= DecoderOptions.OldFpu; break; case DecoderOptions_Pcommit: tc.DecoderOptions |= DecoderOptions.Pcommit; break; case DecoderOptions_Loadall286: tc.DecoderOptions |= DecoderOptions.Loadall286; break; case DecoderOptions_Loadall386: tc.DecoderOptions |= DecoderOptions.Loadall386; break; case DecoderOptions_Cl1invmb: tc.DecoderOptions |= DecoderOptions.Cl1invmb; break; case DecoderOptions_MovTr: tc.DecoderOptions |= DecoderOptions.MovTr; break; case DecoderOptions_NoPause: tc.DecoderOptions |= DecoderOptions.NoPause; break; case DecoderOptions_NoWbnoinvd: tc.DecoderOptions |= DecoderOptions.NoWbnoinvd; break; case DecoderOptions_NoLockMovCR0: tc.DecoderOptions |= DecoderOptions.NoLockMovCR0; break; case DecoderOptions_NoMPFX_0FB8: tc.DecoderOptions |= DecoderOptions.NoMPFX_0FB8; break; case DecoderOptions_NoMPFX_0FBC: tc.DecoderOptions |= DecoderOptions.NoMPFX_0FBC; break; case DecoderOptions_NoMPFX_0FBD: tc.DecoderOptions |= DecoderOptions.NoMPFX_0FBD; break; case DecoderOptions_NoLahfSahf64: tc.DecoderOptions |= DecoderOptions.NoLahfSahf64; break; case DecoderOptions_NoInvalidCheck: tc.DecoderOptions |= DecoderOptions.NoInvalidCheck; break; case SegmentPrefix_ES: tc.SegmentPrefix = Register.ES; break; case SegmentPrefix_CS: tc.SegmentPrefix = Register.CS; break; case SegmentPrefix_SS: tc.SegmentPrefix = Register.SS; break; case SegmentPrefix_DS: tc.SegmentPrefix = Register.DS; break; case SegmentPrefix_FS: tc.SegmentPrefix = Register.FS; break; case SegmentPrefix_GS: tc.SegmentPrefix = Register.GS; break; case OpMask_k1: tc.OpMask = Register.K1; break; case OpMask_k2: tc.OpMask = Register.K2; break; case OpMask_k3: tc.OpMask = Register.K3; break; case OpMask_k4: tc.OpMask = Register.K4; break; case OpMask_k5: tc.OpMask = Register.K5; break; case OpMask_k6: tc.OpMask = Register.K6; break; case OpMask_k7: tc.OpMask = Register.K7; break; case ConstantOffsets: if (!TryParseConstantOffsets(value, out tc.ConstantOffsets)) { throw new InvalidOperationException($"Invalid ConstantOffsets: '{value}'"); } break; default: throw new InvalidOperationException($"Invalid key '{key}'"); } } return(tc); }
static DecoderTestCase ReadTestCase(int bitness, string line, int lineNumber) { var parts = line.Split(seps); if (parts.Length != 5) { throw new InvalidOperationException($"Invalid number of commas ({parts.Length - 1} commas)"); } var tc = new DecoderTestCase(); tc.LineNumber = lineNumber; tc.TestOptions = DecoderTestOptions.None; tc.Bitness = bitness; tc.HexBytes = ToHexBytes(parts[0].Trim()); tc.EncodedHexBytes = tc.HexBytes; var code = parts[1].Trim(); if (CodeUtils.IsIgnored(code)) { return(null); } tc.Code = ToCode(code); tc.Mnemonic = ToMnemonic(parts[2].Trim()); tc.OpCount = NumberConverter.ToInt32(parts[3].Trim()); tc.DecoderError = tc.Code == Code.INVALID ? DecoderError.InvalidInstruction : DecoderError.None; bool foundCode = false; foreach (var tmp in parts[4].Split(extraSeps)) { if (tmp == string.Empty) { continue; } var key = tmp; string value; int index = key.IndexOf('='); if (index >= 0) { value = key.Substring(index + 1); key = key.Substring(0, index); } else { value = null; } switch (key) { case DecoderTestParserConstants.DecoderError: if (value is null) { throw new InvalidOperationException($"Missing decoder error value"); } if (!ToEnumConverter.TryDecoderError(value, out tc.DecoderError)) { throw new InvalidOperationException($"Invalid decoder error value: {value}"); } break; case DecoderTestParserConstants.Broadcast: tc.IsBroadcast = true; break; case DecoderTestParserConstants.Xacquire: tc.HasXacquirePrefix = true; break; case DecoderTestParserConstants.Xrelease: tc.HasXreleasePrefix = true; break; case DecoderTestParserConstants.Rep: case DecoderTestParserConstants.Repe: tc.HasRepePrefix = true; break; case DecoderTestParserConstants.Repne: tc.HasRepnePrefix = true; break; case DecoderTestParserConstants.Lock: tc.HasLockPrefix = true; break; case DecoderTestParserConstants.ZeroingMasking: tc.ZeroingMasking = true; break; case DecoderTestParserConstants.SuppressAllExceptions: tc.SuppressAllExceptions = true; break; case DecoderTestParserConstants.Vsib32: tc.VsibBitness = 32; break; case DecoderTestParserConstants.Vsib64: tc.VsibBitness = 64; break; case DecoderTestParserConstants.RoundToNearest: tc.RoundingControl = RoundingControl.RoundToNearest; break; case DecoderTestParserConstants.RoundDown: tc.RoundingControl = RoundingControl.RoundDown; break; case DecoderTestParserConstants.RoundUp: tc.RoundingControl = RoundingControl.RoundUp; break; case DecoderTestParserConstants.RoundTowardZero: tc.RoundingControl = RoundingControl.RoundTowardZero; break; case DecoderTestParserConstants.Op0Kind: if (tc.OpCount < 1) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 1"); } ReadOpKind(tc, 0, value); break; case DecoderTestParserConstants.Op1Kind: if (tc.OpCount < 2) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 2"); } ReadOpKind(tc, 1, value); break; case DecoderTestParserConstants.Op2Kind: if (tc.OpCount < 3) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 3"); } ReadOpKind(tc, 2, value); break; case DecoderTestParserConstants.Op3Kind: if (tc.OpCount < 4) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 4"); } ReadOpKind(tc, 3, value); break; case DecoderTestParserConstants.Op4Kind: if (tc.OpCount < 5) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 5"); } ReadOpKind(tc, 4, value); break; case DecoderTestParserConstants.EncodedHexBytes: if (string.IsNullOrWhiteSpace(value)) { throw new InvalidOperationException($"Invalid encoded hex bytes: '{value}'"); } tc.EncodedHexBytes = ToHexBytes(value); break; case DecoderTestParserConstants.Code: if (string.IsNullOrWhiteSpace(value)) { throw new InvalidOperationException($"Invalid Code value: '{value}'"); } if (CodeUtils.IsIgnored(value)) { return(null); } foundCode = true; break; case DecoderTestParserConstants.DecoderOptions_AMD: tc.DecoderOptions |= DecoderOptions.AMD; break; case DecoderTestParserConstants.DecoderOptions_ForceReservedNop: tc.DecoderOptions |= DecoderOptions.ForceReservedNop; break; case DecoderTestParserConstants.DecoderOptions_Umov: tc.DecoderOptions |= DecoderOptions.Umov; break; case DecoderTestParserConstants.DecoderOptions_Xbts: tc.DecoderOptions |= DecoderOptions.Xbts; break; case DecoderTestParserConstants.DecoderOptions_Cmpxchg486A: tc.DecoderOptions |= DecoderOptions.Cmpxchg486A; break; case DecoderTestParserConstants.DecoderOptions_OldFpu: tc.DecoderOptions |= DecoderOptions.OldFpu; break; case DecoderTestParserConstants.DecoderOptions_Pcommit: tc.DecoderOptions |= DecoderOptions.Pcommit; break; case DecoderTestParserConstants.DecoderOptions_Loadall286: tc.DecoderOptions |= DecoderOptions.Loadall286; break; case DecoderTestParserConstants.DecoderOptions_Loadall386: tc.DecoderOptions |= DecoderOptions.Loadall386; break; case DecoderTestParserConstants.DecoderOptions_Cl1invmb: tc.DecoderOptions |= DecoderOptions.Cl1invmb; break; case DecoderTestParserConstants.DecoderOptions_MovTr: tc.DecoderOptions |= DecoderOptions.MovTr; break; case DecoderTestParserConstants.DecoderOptions_Jmpe: tc.DecoderOptions |= DecoderOptions.Jmpe; break; case DecoderTestParserConstants.DecoderOptions_NoPause: tc.DecoderOptions |= DecoderOptions.NoPause; break; case DecoderTestParserConstants.DecoderOptions_NoWbnoinvd: tc.DecoderOptions |= DecoderOptions.NoWbnoinvd; break; case DecoderTestParserConstants.DecoderOptions_NoLockMovCR0: tc.DecoderOptions |= DecoderOptions.NoLockMovCR0; break; case DecoderTestParserConstants.DecoderOptions_NoMPFX_0FBC: tc.DecoderOptions |= DecoderOptions.NoMPFX_0FBC; break; case DecoderTestParserConstants.DecoderOptions_NoMPFX_0FBD: tc.DecoderOptions |= DecoderOptions.NoMPFX_0FBD; break; case DecoderTestParserConstants.DecoderOptions_NoLahfSahf64: tc.DecoderOptions |= DecoderOptions.NoLahfSahf64; break; case DecoderTestParserConstants.DecoderOptions_NoInvalidCheck: tc.DecoderOptions |= DecoderOptions.NoInvalidCheck; break; case DecoderTestParserConstants.DecoderOptions_MPX: tc.DecoderOptions |= DecoderOptions.MPX; break; case DecoderTestParserConstants.SegmentPrefix_ES: tc.SegmentPrefix = Register.ES; break; case DecoderTestParserConstants.SegmentPrefix_CS: tc.SegmentPrefix = Register.CS; break; case DecoderTestParserConstants.SegmentPrefix_SS: tc.SegmentPrefix = Register.SS; break; case DecoderTestParserConstants.SegmentPrefix_DS: tc.SegmentPrefix = Register.DS; break; case DecoderTestParserConstants.SegmentPrefix_FS: tc.SegmentPrefix = Register.FS; break; case DecoderTestParserConstants.SegmentPrefix_GS: tc.SegmentPrefix = Register.GS; break; case DecoderTestParserConstants.OpMask_k1: tc.OpMask = Register.K1; break; case DecoderTestParserConstants.OpMask_k2: tc.OpMask = Register.K2; break; case DecoderTestParserConstants.OpMask_k3: tc.OpMask = Register.K3; break; case DecoderTestParserConstants.OpMask_k4: tc.OpMask = Register.K4; break; case DecoderTestParserConstants.OpMask_k5: tc.OpMask = Register.K5; break; case DecoderTestParserConstants.OpMask_k6: tc.OpMask = Register.K6; break; case DecoderTestParserConstants.OpMask_k7: tc.OpMask = Register.K7; break; case DecoderTestParserConstants.ConstantOffsets: if (!TryParseConstantOffsets(value, out tc.ConstantOffsets)) { throw new InvalidOperationException($"Invalid ConstantOffsets: '{value}'"); } break; case DecoderTestParserConstants.DecoderTestOptions_NoEncode: tc.TestOptions |= DecoderTestOptions.NoEncode; break; case DecoderTestParserConstants.DecoderTestOptions_NoOptDisableTest: tc.TestOptions |= DecoderTestOptions.NoOptDisableTest; break; default: throw new InvalidOperationException($"Invalid key '{key}'"); } } if (tc.Code == Code.INVALID && !foundCode) { throw new InvalidOperationException($"Test case decodes to {nameof(Code.INVALID)} but there's no {DecoderTestParserConstants.Code}=xxx showing the original {nameof(Code)} value so it can be filtered out if needed"); } return(tc); }
static void ReadOpKind(DecoderTestCase tc, int operand, string value) { var parts = value.Split(opKindSeps); switch (parts[0]) { case DecoderTestParserConstants.OpKind_Register: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpRegister(operand, ToRegister(parts[1])); tc.SetOpKind(operand, OpKind.Register); break; case DecoderTestParserConstants.OpKind_NearBranch16: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.NearBranch16); tc.NearBranch = NumberConverter.ToUInt16(parts[1]); break; case DecoderTestParserConstants.OpKind_NearBranch32: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.NearBranch32); tc.NearBranch = NumberConverter.ToUInt32(parts[1]); break; case DecoderTestParserConstants.OpKind_NearBranch64: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.NearBranch64); tc.NearBranch = NumberConverter.ToUInt64(parts[1]); break; case DecoderTestParserConstants.OpKind_FarBranch16: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.FarBranch16); tc.FarBranchSelector = NumberConverter.ToUInt16(parts[1]); tc.FarBranch = NumberConverter.ToUInt16(parts[2]); break; case DecoderTestParserConstants.OpKind_FarBranch32: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.FarBranch32); tc.FarBranchSelector = NumberConverter.ToUInt16(parts[1]); tc.FarBranch = NumberConverter.ToUInt32(parts[2]); break; case DecoderTestParserConstants.OpKind_Immediate8: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.Immediate8); tc.Immediate = NumberConverter.ToUInt8(parts[1]); break; case DecoderTestParserConstants.OpKind_Immediate16: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.Immediate16); tc.Immediate = NumberConverter.ToUInt16(parts[1]); break; case DecoderTestParserConstants.OpKind_Immediate32: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.Immediate32); tc.Immediate = NumberConverter.ToUInt32(parts[1]); break; case DecoderTestParserConstants.OpKind_Immediate64: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.Immediate64); tc.Immediate = NumberConverter.ToUInt64(parts[1]); break; case DecoderTestParserConstants.OpKind_Immediate8to16: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.Immediate8to16); tc.Immediate = NumberConverter.ToUInt16(parts[1]); break; case DecoderTestParserConstants.OpKind_Immediate8to32: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.Immediate8to32); tc.Immediate = NumberConverter.ToUInt32(parts[1]); break; case DecoderTestParserConstants.OpKind_Immediate8to64: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.Immediate8to64); tc.Immediate = NumberConverter.ToUInt64(parts[1]); break; case DecoderTestParserConstants.OpKind_Immediate32to64: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.Immediate32to64); tc.Immediate = NumberConverter.ToUInt64(parts[1]); break; case DecoderTestParserConstants.OpKind_Immediate8_2nd: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.Immediate8_2nd); tc.Immediate_2nd = NumberConverter.ToUInt8(parts[1]); break; case DecoderTestParserConstants.OpKind_MemorySegSI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.MemorySegSI); tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case DecoderTestParserConstants.OpKind_MemorySegESI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.MemorySegESI); tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case DecoderTestParserConstants.OpKind_MemorySegRSI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.MemorySegRSI); tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case DecoderTestParserConstants.OpKind_MemorySegDI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.MemorySegDI); tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case DecoderTestParserConstants.OpKind_MemorySegEDI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.MemorySegEDI); tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case DecoderTestParserConstants.OpKind_MemorySegRDI: if (parts.Length != 3) { throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.MemorySegRDI); tc.MemorySegment = ToRegister(parts[1]); tc.MemorySize = ToMemorySize(parts[2]); break; case DecoderTestParserConstants.OpKind_MemoryESDI: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.MemoryESDI); tc.MemorySize = ToMemorySize(parts[1]); break; case DecoderTestParserConstants.OpKind_MemoryESEDI: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.MemoryESEDI); tc.MemorySize = ToMemorySize(parts[1]); break; case DecoderTestParserConstants.OpKind_MemoryESRDI: if (parts.Length != 2) { throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.MemoryESRDI); tc.MemorySize = ToMemorySize(parts[1]); break; case DecoderTestParserConstants.OpKind_Memory: if (parts.Length != 8) { throw new InvalidOperationException($"Operand {operand}: expected 8 values, actual = {parts.Length}"); } tc.SetOpKind(operand, OpKind.Memory); tc.MemorySegment = ToRegister(parts[1]); tc.MemoryBase = ToRegister(parts[2]); tc.MemoryIndex = ToRegister(parts[3]); tc.MemoryIndexScale = NumberConverter.ToInt32(parts[4]); tc.MemoryDisplacement = NumberConverter.ToUInt64(parts[5]); tc.MemoryDisplSize = NumberConverter.ToInt32(parts[6]); tc.MemorySize = ToMemorySize(parts[7]); break; default: throw new InvalidOperationException($"Invalid opkind: '{parts[0]}'"); } }
static DecoderTestCase ReadTestCase(int bitness, string line, int lineNumber) { var parts = line.Split(seps); if (parts.Length != 5) { throw new InvalidOperationException($"Invalid number of commas ({parts.Length - 1} commas)"); } var tc = new DecoderTestCase(); tc.LineNumber = lineNumber; tc.TestOptions = DecoderTestOptions.None; tc.Bitness = bitness; tc.IP = bitness switch { 16 => DecoderConstants.DEFAULT_IP16, 32 => DecoderConstants.DEFAULT_IP32, 64 => DecoderConstants.DEFAULT_IP64, _ => throw new InvalidOperationException(), }; tc.HexBytes = ToHexBytes(parts[0].Trim()); tc.EncodedHexBytes = tc.HexBytes; var code = parts[1].Trim(); if (CodeUtils.IsIgnored(code)) { return(null); } tc.Code = ToCode(code); tc.Mnemonic = ToMnemonic(parts[2].Trim()); tc.OpCount = NumberConverter.ToInt32(parts[3].Trim()); tc.DecoderError = tc.Code == Code.INVALID ? DecoderError.InvalidInstruction : DecoderError.None; bool foundCode = false; foreach (var tmp in parts[4].Split(extraSeps)) { if (tmp == string.Empty) { continue; } var key = tmp; string value; int index = key.IndexOf('='); if (index >= 0) { value = key.Substring(index + 1); key = key.Substring(0, index); } else { value = null; } switch (key) { case DecoderTestParserConstants.DecoderError: if (value is null) { throw new InvalidOperationException($"Missing decoder error value"); } if (!ToEnumConverter.TryDecoderError(value, out tc.DecoderError)) { throw new InvalidOperationException($"Invalid decoder error value: {value}"); } break; case DecoderTestParserConstants.Broadcast: tc.IsBroadcast = true; break; case DecoderTestParserConstants.Xacquire: tc.HasXacquirePrefix = true; break; case DecoderTestParserConstants.Xrelease: tc.HasXreleasePrefix = true; break; case DecoderTestParserConstants.Rep: case DecoderTestParserConstants.Repe: tc.HasRepePrefix = true; break; case DecoderTestParserConstants.Repne: tc.HasRepnePrefix = true; break; case DecoderTestParserConstants.Lock: tc.HasLockPrefix = true; break; case DecoderTestParserConstants.ZeroingMasking: tc.ZeroingMasking = true; break; case DecoderTestParserConstants.SuppressAllExceptions: tc.SuppressAllExceptions = true; break; case DecoderTestParserConstants.Vsib32: tc.VsibBitness = 32; break; case DecoderTestParserConstants.Vsib64: tc.VsibBitness = 64; break; case DecoderTestParserConstants.RoundToNearest: tc.RoundingControl = RoundingControl.RoundToNearest; break; case DecoderTestParserConstants.RoundDown: tc.RoundingControl = RoundingControl.RoundDown; break; case DecoderTestParserConstants.RoundUp: tc.RoundingControl = RoundingControl.RoundUp; break; case DecoderTestParserConstants.RoundTowardZero: tc.RoundingControl = RoundingControl.RoundTowardZero; break; case DecoderTestParserConstants.Op0Kind: if (tc.OpCount < 1) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 1"); } ReadOpKind(tc, 0, value); break; case DecoderTestParserConstants.Op1Kind: if (tc.OpCount < 2) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 2"); } ReadOpKind(tc, 1, value); break; case DecoderTestParserConstants.Op2Kind: if (tc.OpCount < 3) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 3"); } ReadOpKind(tc, 2, value); break; case DecoderTestParserConstants.Op3Kind: if (tc.OpCount < 4) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 4"); } ReadOpKind(tc, 3, value); break; case DecoderTestParserConstants.Op4Kind: if (tc.OpCount < 5) { throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 5"); } ReadOpKind(tc, 4, value); break; case DecoderTestParserConstants.EncodedHexBytes: if (string.IsNullOrWhiteSpace(value)) { throw new InvalidOperationException($"Invalid encoded hex bytes: '{value}'"); } tc.EncodedHexBytes = ToHexBytes(value); break; case DecoderTestParserConstants.Code: if (string.IsNullOrWhiteSpace(value)) { throw new InvalidOperationException($"Invalid Code value: '{value}'"); } if (CodeUtils.IsIgnored(value)) { return(null); } foundCode = true; break; case DecoderTestParserConstants.DecoderOptions: if (string.IsNullOrWhiteSpace(value)) { throw new InvalidOperationException($"Invalid DecoderOption value: '{value}'"); } if (!TryParseDecoderOptions(value.Split(semicolonSeparator), ref tc.DecoderOptions)) { throw new Exception($"Invalid DecoderOptions value, '{value}'"); } break; case DecoderTestParserConstants.IP: if (string.IsNullOrWhiteSpace(value)) { throw new InvalidOperationException($"Invalid IP value: '{value}'"); } tc.IP = NumberConverter.ToUInt64(value); break; case DecoderTestParserConstants.EvictionHint: #if MVEX tc.Mvex.EvictionHint = true; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_RegSwizzleNone: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.RegSwizzleNone; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_RegSwizzleCdab: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.RegSwizzleCdab; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_RegSwizzleBadc: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.RegSwizzleBadc; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_RegSwizzleDacb: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.RegSwizzleDacb; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_RegSwizzleAaaa: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.RegSwizzleAaaa; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_RegSwizzleBbbb: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.RegSwizzleBbbb; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_RegSwizzleCccc: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.RegSwizzleCccc; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_RegSwizzleDddd: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.RegSwizzleDddd; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_MemConvNone: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.MemConvNone; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_MemConvBroadcast1: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.MemConvBroadcast1; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_MemConvBroadcast4: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.MemConvBroadcast4; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_MemConvFloat16: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.MemConvFloat16; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_MemConvUint8: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.MemConvUint8; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_MemConvSint8: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.MemConvSint8; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_MemConvUint16: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.MemConvUint16; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.MVEX_MemConvSint16: #if MVEX tc.Mvex.RegMemConv = MvexRegMemConv.MemConvSint16; break; #else throw new InvalidOperationException(); #endif case DecoderTestParserConstants.SegmentPrefix_ES: tc.SegmentPrefix = Register.ES; break; case DecoderTestParserConstants.SegmentPrefix_CS: tc.SegmentPrefix = Register.CS; break; case DecoderTestParserConstants.SegmentPrefix_SS: tc.SegmentPrefix = Register.SS; break; case DecoderTestParserConstants.SegmentPrefix_DS: tc.SegmentPrefix = Register.DS; break; case DecoderTestParserConstants.SegmentPrefix_FS: tc.SegmentPrefix = Register.FS; break; case DecoderTestParserConstants.SegmentPrefix_GS: tc.SegmentPrefix = Register.GS; break; case DecoderTestParserConstants.OpMask_k1: tc.OpMask = Register.K1; break; case DecoderTestParserConstants.OpMask_k2: tc.OpMask = Register.K2; break; case DecoderTestParserConstants.OpMask_k3: tc.OpMask = Register.K3; break; case DecoderTestParserConstants.OpMask_k4: tc.OpMask = Register.K4; break; case DecoderTestParserConstants.OpMask_k5: tc.OpMask = Register.K5; break; case DecoderTestParserConstants.OpMask_k6: tc.OpMask = Register.K6; break; case DecoderTestParserConstants.OpMask_k7: tc.OpMask = Register.K7; break; case DecoderTestParserConstants.ConstantOffsets: if (!TryParseConstantOffsets(value, out tc.ConstantOffsets)) { throw new InvalidOperationException($"Invalid ConstantOffsets: '{value}'"); } break; case DecoderTestParserConstants.DecoderTestOptions_NoEncode: tc.TestOptions |= DecoderTestOptions.NoEncode; break; case DecoderTestParserConstants.DecoderTestOptions_NoOptDisableTest: tc.TestOptions |= DecoderTestOptions.NoOptDisableTest; break; default: throw new InvalidOperationException($"Invalid key '{key}'"); } } if (tc.Code == Code.INVALID && !foundCode) { throw new InvalidOperationException($"Test case decodes to {nameof(Code.INVALID)} but there's no {DecoderTestParserConstants.Code}=xxx showing the original {nameof(Code)} value so it can be filtered out if needed"); } return(tc); }