public static HashSet <Code> Read(string name) { var filename = PathUtils.GetTestTextFilename(name, "Decoder"); int lineNumber = 0; var hash = new HashSet <Code>(); foreach (var line in File.ReadLines(filename)) { lineNumber++; if (line.Length == 0 || line[0] == '#') { continue; } var value = line.Trim(); if (CodeUtils.IsIgnored(value)) { continue; } if (!ToEnumConverter.TryCode(value, out var code)) { throw new InvalidOperationException($"Error parsing Code file '{filename}', line {lineNumber}: Invalid value: {value}"); } hash.Add(code); } return(hash); }
protected void TestOptionsBase(FormatterOptions options) { { int min = int.MaxValue, max = int.MinValue; foreach (var value in ToEnumConverter.GetNumberBaseValues()) { min = Math.Min(min, (int)value); max = Math.Max(max, (int)value); options.NumberBase = value; } Assert.Throws <ArgumentOutOfRangeException>(() => options.NumberBase = (NumberBase)(min - 1)); Assert.Throws <ArgumentOutOfRangeException>(() => options.NumberBase = (NumberBase)(max + 1)); Assert.Throws <ArgumentOutOfRangeException>(() => options.NumberBase = (NumberBase)int.MinValue); Assert.Throws <ArgumentOutOfRangeException>(() => options.NumberBase = (NumberBase)int.MaxValue); } { int min = int.MaxValue, max = int.MinValue; foreach (var value in ToEnumConverter.GetMemorySizeOptionsValues()) { min = Math.Min(min, (int)value); max = Math.Max(max, (int)value); options.MemorySizeOptions = value; } Assert.Throws <ArgumentOutOfRangeException>(() => options.MemorySizeOptions = (MemorySizeOptions)(min - 1)); Assert.Throws <ArgumentOutOfRangeException>(() => options.MemorySizeOptions = (MemorySizeOptions)(max + 1)); Assert.Throws <ArgumentOutOfRangeException>(() => options.MemorySizeOptions = (MemorySizeOptions)int.MinValue); Assert.Throws <ArgumentOutOfRangeException>(() => options.MemorySizeOptions = (MemorySizeOptions)int.MaxValue); } }
void Make_sure_all_Code_values_are_tested_exactly_once() { var tested = new bool[IcedConstants.CodeEnumCount]; foreach (var info in OpCodeInfoTestCases.OpCodeInfoTests) { Assert.False(tested[(int)info.Code]); tested[(int)info.Code] = true; } var sb = new StringBuilder(); var codeNames = ToEnumConverter.GetCodeNames(); for (int i = 0; i < tested.Length; i++) { if (!tested[i] && !CodeUtils.IsIgnored(codeNames[i])) { if (sb.Length > 0) { sb.Append(','); } sb.Append(codeNames[i]); } } Assert.Equal(string.Empty, sb.ToString()); }
static DecoderMemoryTestCase ReadTestCase(int bitness, string line, int lineNumber) { var parts = line.Split(colSep, StringSplitOptions.None); if (parts.Length != 11 && parts.Length != 12) { throw new InvalidOperationException(); } var tc = new DecoderMemoryTestCase(); tc.LineNumber = lineNumber; tc.Bitness = bitness; tc.HexBytes = parts[0].Trim(); tc.Code = ToEnumConverter.GetCode(parts[1].Trim()); tc.Register = ToEnumConverter.GetRegister(parts[2].Trim()); tc.SegmentPrefix = ToEnumConverter.GetRegister(parts[3].Trim()); tc.SegmentRegister = ToEnumConverter.GetRegister(parts[4].Trim()); tc.BaseRegister = ToEnumConverter.GetRegister(parts[5].Trim()); tc.IndexRegister = ToEnumConverter.GetRegister(parts[6].Trim()); tc.Scale = (int)ParseUInt32(parts[7].Trim()); tc.Displacement = ParseUInt32(parts[8].Trim()); tc.DisplacementSize = (int)ParseUInt32(parts[9].Trim()); var coStr = parts[10].Trim(); if (!DecoderTestParser.TryParseConstantOffsets(coStr, out tc.ConstantOffsets)) { throw new InvalidOperationException($"Invalid ConstantOffsets: '{coStr}'"); } tc.EncodedHexBytes = parts.Length > 11 ? parts[11].Trim() : tc.HexBytes; tc.DecoderOptions = DecoderOptions.None; tc.CanEncode = true; return(tc); }
static MnemonicOptionsTestCase ParseLine(string line) { var elems = line.Split(commaSeparator); if (elems.Length != 5) { throw new Exception($"Invalid number of commas: {elems.Length - 1}"); } var hexBytes = elems[0].Trim(); var code = ToEnumConverter.GetCode(elems[1].Trim()); var bitness = NumberConverter.ToInt32(elems[2].Trim()); var formattedString = elems[3].Trim().Replace('|', ','); var flags = FormatMnemonicOptions.None; foreach (var value in elems[4].Split(spaceSeparator, StringSplitOptions.RemoveEmptyEntries)) { if (!Dicts.ToFormatMnemonicOptions.TryGetValue(value, out var f)) { throw new InvalidOperationException($"Invalid flags value: {value}"); } flags |= f; } return(new MnemonicOptionsTestCase(hexBytes, code, bitness, formattedString, flags)); }
void Verify_encoding_is_part_of_Code_name() { var codeNames = ToEnumConverter.GetCodeNames(); for (int i = 0; i < IcedConstants.NumberOfCodeValues; i++) { var codeName = codeNames[i]; if (CodeUtils.IsIgnored(codeName)) { continue; } var code = (Code)i; var prefix = code.ToOpCode().Encoding switch { EncodingKind.Legacy => string.Empty, EncodingKind.VEX => "VEX_", EncodingKind.EVEX => "EVEX_", EncodingKind.XOP => "XOP_", EncodingKind.D3NOW => "D3NOW_", _ => throw new InvalidOperationException(), }; if (prefix != string.Empty) { Assert.StartsWith(prefix, codeName, StringComparison.Ordinal); } } }
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 IEnumerable <object[]> GetTestCases(int bitness, int stackAddressSize) { var toRegister = ToEnumConverter.CloneRegisterDict(); switch (stackAddressSize) { case 16: toRegister.Add(MiscInstrInfoTestConstants.XSP, Register.SP); toRegister.Add(MiscInstrInfoTestConstants.XBP, Register.BP); break; case 32: toRegister.Add(MiscInstrInfoTestConstants.XSP, Register.ESP); toRegister.Add(MiscInstrInfoTestConstants.XBP, Register.EBP); break; case 64: toRegister.Add(MiscInstrInfoTestConstants.XSP, Register.RSP); toRegister.Add(MiscInstrInfoTestConstants.XBP, Register.RBP); break; default: throw new InvalidOperationException(); } for (int i = 0; i < IcedConstants.VMM_count; i++) { toRegister.Add(MiscInstrInfoTestConstants.VMM_prefix + i.ToString(), IcedConstants.VMM_first + i); } var filename = PathUtils.GetTestTextFilename($"InstructionInfoTest_{bitness}.txt", "InstructionInfo"); Debug.Assert(File.Exists(filename)); int lineNo = 0; foreach (var line in File.ReadLines(filename)) { lineNo++; if (line.Length == 0 || line.StartsWith("#")) { continue; } (string hexBytes, Code code, DecoderOptions options, InstructionInfoTestCase testCase)info; try { info = ParseLine(line, bitness, toRegister); } catch (Exception ex) { throw new Exception($"Invalid line {lineNo} ({filename}): {ex.Message}"); } if (info.testCase is object) { yield return new object[5] { info.hexBytes, info.code, info.options, lineNo, info.testCase } } ; } }
static SymbolResolverTestCase ParseLine(string line) { var elems = line.Split(commaSeparator); const int SYM_RES_INDEX = 4; if (elems.Length < SYM_RES_INDEX) { throw new Exception($"Invalid number of commas: {elems.Length - 1}"); } var bitness = NumberConverter.ToInt32(elems[0].Trim()); var hexBytes = elems[1].Trim(); var code = ToEnumConverter.GetCode(elems[2].Trim()); var options = new List <(OptionsProps property, object value)>(); foreach (var part in elems[3].Split(spaceSeparator, StringSplitOptions.RemoveEmptyEntries)) { options.Add(OptionsParser.ParseOption(part)); } var symbolResults = new SymbolResultTestCase[elems.Length - SYM_RES_INDEX]; for (int i = 0; i < symbolResults.Length; i++) { var symParts = elems[SYM_RES_INDEX + i].Split(semicolonSeparator); if (symParts.Length != 5) { throw new Exception($"Invalid number of semicolons: {symParts.Length - 1}"); } var address = NumberConverter.ToUInt64(symParts[0].Trim()); var symbolAddress = NumberConverter.ToUInt64(symParts[1].Trim()); var addressSize = NumberConverter.ToInt32(symParts[2].Trim()); var symbolParts = symParts[3].Split(barSeparator); MemorySize?memorySize = null; var flags = SymbolFlags.None; foreach (var value in symParts[4].Split(spaceSeparator, StringSplitOptions.RemoveEmptyEntries)) { if (Dicts.ToSymbolFlags.TryGetValue(value, out var f)) { flags |= f; } else { if (!ToEnumConverter.TryMemorySize(value, out var memSize)) { throw new Exception($"Invalid value: {value}"); } memorySize = memSize; } } symbolResults[i] = new SymbolResultTestCase(address, symbolAddress, addressSize, flags, memorySize, symbolParts); } return(new SymbolResolverTestCase(bitness, hexBytes, code, options.ToArray(), symbolResults)); }
static MvexConvFn ToMvexConvFn(string value) { if (!ToEnumConverter.TryMvexConvFn(value, out var mvexConvFn)) { throw new InvalidOperationException($"Invalid MvexConvFn value: '{value}'"); } return(mvexConvFn); }
static DecoderOptions ToDecoderOptions(string value) { if (!ToEnumConverter.TryDecoderOptions(value, out var code)) { throw new InvalidOperationException($"Invalid DecoderOptions value: '{value}'"); } return(code); }
static MemorySize ToMemorySize(string value) { if (!ToEnumConverter.TryMemorySize(value, out var memSize)) { throw new InvalidOperationException($"Invalid MemorySize value: '{value}'"); } return(memSize); }
static Code ToCode(string value) { if (!ToEnumConverter.TryCode(value, out var code)) { throw new InvalidOperationException($"Invalid Code value: '{value}'"); } return(code); }
static TupleType ToTupleType(string value) { if (!ToEnumConverter.TryTupleType(value, out var code)) { throw new InvalidOperationException($"Invalid TupleType value: '{value}'"); } return(code); }
static MvexTupleTypeLutKind ToMvexTupleTypeLutKind(string value) { if (!ToEnumConverter.TryMvexTupleTypeLutKind(value, out var result)) { throw new InvalidOperationException($"Invalid MvexTupleTypeLutKind value: '{value}'"); } return(result); }
static OpCodeOperandKind ToOpCodeOperandKind(string value) { if (!ToEnumConverter.TryOpCodeOperandKind(value, out var code)) { throw new InvalidOperationException($"Invalid OpCodeOperandKind value: '{value}'"); } return(code); }
static Mnemonic ToMnemonic(string value) { if (!ToEnumConverter.TryMnemonic(value, out var mnemonic)) { throw new InvalidOperationException($"Invalid Mnemonic value: '{value}'"); } return(mnemonic); }
static VirtualAddressTestCase?ParseLine(string line) { var elems = line.Split(commaSeparator); if (elems.Length != 7) { throw new Exception($"Invalid number of commas: {elems.Length - 1}"); } var bitness = NumberConverter.ToInt32(elems[0].Trim()); if (CodeUtils.IsIgnored(elems[1].Trim())) { return(null); } var hexBytes = elems[2].Trim(); var operand = NumberConverter.ToInt32(elems[3].Trim()); var elementIndex = NumberConverter.ToInt32(elems[4].Trim()); var expectedValue = NumberConverter.ToUInt64(elems[5].Trim()); var registerValues = new List <(Register register, int elementIndex, int elementSize, ulong value)>(); foreach (var tmp in elems[6].Split(spaceSeparator, StringSplitOptions.RemoveEmptyEntries)) { var kv = tmp.Split(equalSeparator); if (kv.Length != 2) { throw new Exception($"Expected key=value: {tmp}"); } var key = kv[0]; var valueStr = kv[1]; Register register; int expectedElementIndex; int expectedElementSize; if (key.IndexOf(';') >= 0) { var parts = key.Split(semicolonSeparator); if (parts.Length != 3) { throw new Exception($"Invalid number of semicolons: {parts.Length - 1}"); } register = ToEnumConverter.GetRegister(parts[0]); expectedElementIndex = NumberConverter.ToInt32(parts[1]); expectedElementSize = NumberConverter.ToInt32(parts[2]); } else { register = ToEnumConverter.GetRegister(key); expectedElementIndex = 0; expectedElementSize = 0; } ulong value = NumberConverter.ToUInt64(valueStr); registerValues.Add((register, expectedElementIndex, expectedElementSize, value)); } return(new VirtualAddressTestCase(bitness, hexBytes, operand, elementIndex, expectedValue, registerValues.ToArray())); }
static Register ToRegister(string value) { if (value == string.Empty) { return(Register.None); } if (!ToEnumConverter.TryRegister(value, out var reg)) { throw new InvalidOperationException($"Invalid Register value: '{value}'"); } return(reg); }
static bool TryParseDecoderOptions(string[] stringOptions, ref DecoderOptions options) { foreach (var opt in stringOptions) { if (!ToEnumConverter.TryDecoderOptions(opt.Trim(), out var decOpts)) { return(false); } options |= decOpts; } return(true); }
static bool AddMemory(int bitness, Dictionary <string, Register> toRegister, string value, OpAccess access, InstructionInfoTestCase testCase) { var elems = value.Split(semicolonSeparator); if (elems.Length != 2) { return(false); } var expr = elems[0].Trim(); if (!ToEnumConverter.TryMemorySize(elems[1].Trim(), out var memorySize)) { return(false); } if (!TryParseMemExpr(toRegister, expr, out var segReg, out var baseReg, out var indexReg, out int scale, out ulong displ)) { return(false); } switch (bitness) { case 16: if (!(short.MinValue <= (long)displ && (long)displ <= short.MaxValue) && displ > ushort.MaxValue) { return(false); } displ = (ushort)displ; break; case 32: if (!(int.MinValue <= (long)displ && (long)displ <= int.MaxValue) && displ > uint.MaxValue) { return(false); } displ = (uint)displ; break; case 64: break; default: throw new InvalidOperationException(); } if (access != OpAccess.NoMemAccess) { testCase.UsedMemory.Add(new UsedMemory(segReg, baseReg, indexReg, scale, displ, memorySize, access)); } return(true); }
static DecoderMemoryTestCase ReadTestCase(int bitness, string line, int lineNumber) { var parts = line.Split(colSep, StringSplitOptions.None); if (parts.Length != 11 && parts.Length != 12) { throw new InvalidOperationException(); } var tc = new DecoderMemoryTestCase(); tc.LineNumber = lineNumber; tc.Bitness = bitness; tc.IP = bitness switch { 16 => DecoderConstants.DEFAULT_IP16, 32 => DecoderConstants.DEFAULT_IP32, 64 => DecoderConstants.DEFAULT_IP64, _ => throw new InvalidOperationException(), }; tc.HexBytes = parts[0].Trim(); var code = parts[1].Trim(); if (CodeUtils.IsIgnored(code)) { return(null); } tc.Code = ToEnumConverter.GetCode(code); tc.Register = ToEnumConverter.GetRegister(parts[2].Trim()); tc.SegmentPrefix = ToEnumConverter.GetRegister(parts[3].Trim()); tc.SegmentRegister = ToEnumConverter.GetRegister(parts[4].Trim()); tc.BaseRegister = ToEnumConverter.GetRegister(parts[5].Trim()); tc.IndexRegister = ToEnumConverter.GetRegister(parts[6].Trim()); tc.Scale = (int)NumberConverter.ToUInt32(parts[7].Trim()); tc.Displacement = NumberConverter.ToUInt64(parts[8].Trim()); tc.DisplacementSize = (int)NumberConverter.ToUInt32(parts[9].Trim()); var coStr = parts[10].Trim(); if (!DecoderTestParser.TryParseConstantOffsets(coStr, out tc.ConstantOffsets)) { throw new InvalidOperationException($"Invalid ConstantOffsets: '{coStr}'"); } tc.EncodedHexBytes = parts.Length > 11 ? parts[11].Trim() : tc.HexBytes; tc.DecoderOptions = DecoderOptions.None; tc.TestOptions = DecoderTestOptions.None; return(tc); }
static MnemonicOptionsTestCase?ParseLine(string line) { var elems = line.Split(commaSeparator); if (elems.Length != 5) { throw new Exception($"Invalid number of commas: {elems.Length - 1}"); } var hexBytes = elems[0].Trim(); var codeStr = elems[1].Trim(); if (CodeUtils.IsIgnored(codeStr)) { return(null); } var code = ToEnumConverter.GetCode(codeStr); var bitness = NumberConverter.ToInt32(elems[2].Trim()); var ip = bitness switch { 16 => DecoderConstants.DEFAULT_IP16, 32 => DecoderConstants.DEFAULT_IP32, 64 => DecoderConstants.DEFAULT_IP64, _ => throw new InvalidOperationException(), }; var formattedString = elems[3].Trim().Replace('|', ','); var flags = FormatMnemonicOptions.None; foreach (var value in elems[4].Split(spaceSeparator, StringSplitOptions.RemoveEmptyEntries)) { if (!Dicts.ToFormatMnemonicOptions.TryGetValue(value, out var f)) { throw new InvalidOperationException($"Invalid flags value: {value}"); } flags |= f; } return(new MnemonicOptionsTestCase(hexBytes, code, bitness, ip, formattedString, flags)); }
void Make_sure_all_Code_values_are_tested() { var tested = new bool[IcedConstants.NumberOfCodeValues]; foreach (var info in GetTests()) { tested[(int)(Code)info[1]] = true; } var sb = new StringBuilder(); int missing = 0; var codeNames = ToEnumConverter.GetCodeNames().ToArray(); Assert.Equal(tested.Length, codeNames.Length); for (int i = 0; i < tested.Length; i++) { if (!tested[i]) { sb.Append(codeNames[i] + " "); missing++; } } Assert.Equal("0 ins ", $"{missing} ins " + sb.ToString()); }
void Make_sure_all_Code_values_are_tested_in_16_32_64_bit_modes() { const byte T16 = 0x01; const byte T32 = 0x02; const byte T64 = 0x04; var tested = new byte[IcedConstants.NumberOfCodeValues]; tested[(int)Code.INVALID] = T16 | T32 | T64; foreach (var info in DecoderTestUtils.GetDecoderTests(includeOtherTests: false, includeInvalid: false)) { Assert.False(DecoderTestUtils.NotDecoded.Contains(info.Code), $"{info.Code} has a decoder test but it shouldn't be decoded"); tested[(int)info.Code] |= info.Bitness switch { 16 => T16, 32 => T32, 64 => T64, _ => throw new InvalidOperationException(), }; } #if ENCODER foreach (var info in NonDecodedInstructions.GetTests()) { tested[(int)info.instruction.Code] |= info.bitness switch { 16 => T16, 32 => T32, 64 => T64, _ => throw new InvalidOperationException(), }; } #else foreach (var code in NonDecodedCodeValues1632) { tested[(int)code] |= T16 | T32; } foreach (var code in NonDecodedCodeValues) { tested[(int)code] |= T16 | T32 | T64; } #endif foreach (var c in DecoderTestUtils.NotDecoded) { Assert.DoesNotContain(c, DecoderTestUtils.Code32Only); Assert.DoesNotContain(c, DecoderTestUtils.Code64Only); } foreach (var c in DecoderTestUtils.NotDecoded32Only) { tested[(int)c] ^= T64; } foreach (var c in DecoderTestUtils.NotDecoded64Only) { tested[(int)c] ^= T16 | T32; } foreach (var c in DecoderTestUtils.Code32Only) { Assert.DoesNotContain(c, DecoderTestUtils.Code64Only); tested[(int)c] ^= T64; } foreach (var c in DecoderTestUtils.Code64Only) { Assert.DoesNotContain(c, DecoderTestUtils.Code32Only); tested[(int)c] ^= T16 | T32; } var sb16 = new StringBuilder(); var sb32 = new StringBuilder(); var sb64 = new StringBuilder(); int missing16 = 0, missing32 = 0, missing64 = 0; var codeNames = ToEnumConverter.GetCodeNames(); Assert.Equal(tested.Length, codeNames.Length); for (int i = 0; i < tested.Length; i++) { if (tested[i] != (T16 | T32 | T64) && !CodeUtils.IsIgnored(codeNames[i])) { if ((tested[i] & T16) == 0) { sb16.Append(codeNames[i] + " "); missing16++; } if ((tested[i] & T32) == 0) { sb32.Append(codeNames[i] + " "); missing32++; } if ((tested[i] & T64) == 0) { sb64.Append(codeNames[i] + " "); missing64++; } } } Assert.Equal("16: 0 ins ", $"16: {missing16} ins " + sb16.ToString()); Assert.Equal("32: 0 ins ", $"32: {missing32} ins " + sb32.ToString()); Assert.Equal("64: 0 ins ", $"64: {missing64} ins " + sb64.ToString()); }
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); }
public static (OptionsProps property, object value) ParseOption(string keyValue) { var kv = keyValue.Split(kvseps, 2); if (kv.Length != 2) { throw new InvalidOperationException($"Expected key=value: '{keyValue}'"); } var valueStr = kv[1].Trim(); var prop = ToEnumConverter.GetOptionsProps(kv[0].Trim()); object value; switch (prop) { case OptionsProps.AddLeadingZeroToHexNumbers: case OptionsProps.AlwaysShowScale: case OptionsProps.AlwaysShowSegmentRegister: case OptionsProps.BranchLeadingZeroes: case OptionsProps.DisplacementLeadingZeroes: case OptionsProps.GasNakedRegisters: case OptionsProps.GasShowMnemonicSizeSuffix: case OptionsProps.GasSpaceAfterMemoryOperandComma: case OptionsProps.LeadingZeroes: case OptionsProps.MasmAddDsPrefix32: case OptionsProps.NasmShowSignExtendedImmediateSize: case OptionsProps.PreferST0: case OptionsProps.RipRelativeAddresses: case OptionsProps.ScaleBeforeIndex: case OptionsProps.ShowBranchSize: case OptionsProps.ShowSymbolAddress: case OptionsProps.ShowZeroDisplacements: case OptionsProps.SignedImmediateOperands: case OptionsProps.SignedMemoryDisplacements: case OptionsProps.SmallHexNumbersInDecimal: case OptionsProps.SpaceAfterMemoryBracket: case OptionsProps.SpaceAfterOperandSeparator: case OptionsProps.SpaceBetweenMemoryAddOperators: case OptionsProps.SpaceBetweenMemoryMulOperators: case OptionsProps.UppercaseAll: case OptionsProps.UppercaseDecorators: case OptionsProps.UppercaseHex: case OptionsProps.UppercaseKeywords: case OptionsProps.UppercaseMnemonics: case OptionsProps.UppercasePrefixes: case OptionsProps.UppercaseRegisters: case OptionsProps.UsePseudoOps: case OptionsProps.ShowUselessPrefixes: value = NumberConverter.ToBoolean(valueStr); break; case OptionsProps.BinaryDigitGroupSize: case OptionsProps.DecimalDigitGroupSize: case OptionsProps.FirstOperandCharIndex: case OptionsProps.HexDigitGroupSize: case OptionsProps.OctalDigitGroupSize: case OptionsProps.TabSize: value = NumberConverter.ToInt32(valueStr); break; case OptionsProps.IP: value = NumberConverter.ToUInt64(valueStr); break; case OptionsProps.BinaryPrefix: case OptionsProps.BinarySuffix: case OptionsProps.DecimalPrefix: case OptionsProps.DecimalSuffix: case OptionsProps.DigitSeparator: case OptionsProps.HexPrefix: case OptionsProps.HexSuffix: case OptionsProps.OctalPrefix: case OptionsProps.OctalSuffix: value = valueStr == "<null>" ? null : valueStr; break; case OptionsProps.MemorySizeOptions: value = ToEnumConverter.GetMemorySizeOptions(valueStr); break; case OptionsProps.NumberBase: value = ToEnumConverter.GetNumberBase(valueStr); break; case OptionsProps.CC_b: value = ToEnumConverter.GetCC_b(valueStr); break; case OptionsProps.CC_ae: value = ToEnumConverter.GetCC_ae(valueStr); break; case OptionsProps.CC_e: value = ToEnumConverter.GetCC_e(valueStr); break; case OptionsProps.CC_ne: value = ToEnumConverter.GetCC_ne(valueStr); break; case OptionsProps.CC_be: value = ToEnumConverter.GetCC_be(valueStr); break; case OptionsProps.CC_a: value = ToEnumConverter.GetCC_a(valueStr); break; case OptionsProps.CC_p: value = ToEnumConverter.GetCC_p(valueStr); break; case OptionsProps.CC_np: value = ToEnumConverter.GetCC_np(valueStr); break; case OptionsProps.CC_l: value = ToEnumConverter.GetCC_l(valueStr); break; case OptionsProps.CC_ge: value = ToEnumConverter.GetCC_ge(valueStr); break; case OptionsProps.CC_le: value = ToEnumConverter.GetCC_le(valueStr); break; case OptionsProps.CC_g: value = ToEnumConverter.GetCC_g(valueStr); break; case OptionsProps.DecoderOptions: value = ToEnumConverter.GetDecoderOptions(valueStr); break; default: throw new InvalidOperationException(); } return(prop, value); }
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 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 OptionsInstructionInfo ReadTestCase(string line, int lineNo) { var parts = line.Split(seps); if (parts.Length != 4) { throw new InvalidOperationException($"Invalid number of commas ({parts.Length - 1} commas)"); } int bitness = NumberConverter.ToInt32(parts[0].Trim()); var hexBytes = parts[1].Trim(); HexUtils.ToByteArray(hexBytes); var code = ToCode(parts[2].Trim()); var properties = new List <(OptionsProps property, object value)>(); foreach (var part in parts[3].Split(optsseps, StringSplitOptions.RemoveEmptyEntries)) { var kv = part.Split(kvseps, 2); if (kv.Length != 2) { throw new InvalidOperationException($"Expected key=value: '{part}'"); } var valueStr = kv[1].Trim(); var prop = ToEnumConverter.GetOptionsProps(kv[0].Trim()); object value; switch (prop) { case OptionsProps.AddLeadingZeroToHexNumbers: case OptionsProps.AlwaysShowScale: case OptionsProps.AlwaysShowSegmentRegister: case OptionsProps.BranchLeadingZeroes: case OptionsProps.DisplacementLeadingZeroes: case OptionsProps.GasNakedRegisters: case OptionsProps.GasShowMnemonicSizeSuffix: case OptionsProps.GasSpaceAfterMemoryOperandComma: case OptionsProps.LeadingZeroes: case OptionsProps.MasmAddDsPrefix32: case OptionsProps.NasmShowSignExtendedImmediateSize: case OptionsProps.PreferST0: case OptionsProps.RipRelativeAddresses: case OptionsProps.ScaleBeforeIndex: case OptionsProps.ShowBranchSize: case OptionsProps.ShowZeroDisplacements: case OptionsProps.SignedImmediateOperands: case OptionsProps.SignedMemoryDisplacements: case OptionsProps.SmallHexNumbersInDecimal: case OptionsProps.SpaceAfterMemoryBracket: case OptionsProps.SpaceAfterOperandSeparator: case OptionsProps.SpaceBetweenMemoryAddOperators: case OptionsProps.SpaceBetweenMemoryMulOperators: case OptionsProps.UppercaseAll: case OptionsProps.UppercaseDecorators: case OptionsProps.UppercaseHex: case OptionsProps.UppercaseKeywords: case OptionsProps.UppercaseMnemonics: case OptionsProps.UppercasePrefixes: case OptionsProps.UppercaseRegisters: case OptionsProps.UsePseudoOps: value = NumberConverter.ToBoolean(valueStr); break; case OptionsProps.BinaryDigitGroupSize: case OptionsProps.DecimalDigitGroupSize: case OptionsProps.FirstOperandCharIndex: case OptionsProps.HexDigitGroupSize: case OptionsProps.OctalDigitGroupSize: case OptionsProps.TabSize: value = NumberConverter.ToInt32(valueStr); break; case OptionsProps.IP: value = NumberConverter.ToUInt64(valueStr); break; case OptionsProps.BinaryPrefix: case OptionsProps.BinarySuffix: case OptionsProps.DecimalPrefix: case OptionsProps.DecimalSuffix: case OptionsProps.DigitSeparator: case OptionsProps.HexPrefix: case OptionsProps.HexSuffix: case OptionsProps.OctalPrefix: case OptionsProps.OctalSuffix: value = valueStr == "<null>" ? null : valueStr; break; case OptionsProps.MemorySizeOptions: value = ToEnumConverter.GetMemorySizeOptions(valueStr); break; case OptionsProps.NumberBase: value = ToEnumConverter.GetNumberBase(valueStr); break; default: throw new InvalidOperationException(); } properties.Add((prop, value)); } return(new OptionsInstructionInfo(bitness, hexBytes, code, properties)); }