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 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); }