Exemple #1
0
        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 codeStr = parts[2].Trim();

            if (CodeUtils.IsIgnored(codeStr))
            {
                return(null);
            }
            var code = ToCode(codeStr);

            var properties = new List <(OptionsProps property, object value)>();

            foreach (var part in parts[3].Split(optsseps, StringSplitOptions.RemoveEmptyEntries))
            {
                properties.Add(OptionsParser.ParseOption(part));
            }

            return(new OptionsInstructionInfo(bitness, hexBytes, code, properties));
        }
Exemple #2
0
        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 (string hexBytes, Code code, DecoderOptions options, InstructionInfoTestCase testCase) ParseLine(string line, int bitness, Dictionary <string, Register> toRegister)
        {
            Static.Assert(MiscInstrInfoTestConstants.InstrInfoElemsPerLine == 5 ? 0 : -1);
            var elems = line.Split(commaSeparator, MiscInstrInfoTestConstants.InstrInfoElemsPerLine);

            if (elems.Length != MiscInstrInfoTestConstants.InstrInfoElemsPerLine)
            {
                throw new Exception($"Expected {MiscInstrInfoTestConstants.InstrInfoElemsPerLine - 1} commas");
            }

            var testCase = new InstructionInfoTestCase();

            testCase.IP = bitness switch {
                16 => DecoderConstants.DEFAULT_IP16,
                32 => DecoderConstants.DEFAULT_IP32,
                64 => DecoderConstants.DEFAULT_IP64,
                _ => throw new InvalidOperationException(),
            };

            var hexBytes = ToHexBytes(elems[0].Trim());
            var codeStr  = elems[1].Trim();

            if (CodeUtils.IsIgnored(codeStr))
            {
                return(default);
Exemple #4
0
        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);
        }
Exemple #5
0
        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 SymbolOptionsTestCase?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();

            if (CodeUtils.IsIgnored(elems[1].Trim()))
            {
                return(null);
            }
            var bitness         = NumberConverter.ToInt32(elems[2].Trim());
            var formattedString = elems[3].Trim().Replace('|', ',');
            var flags           = SymbolTestFlags.None;

            foreach (var value in elems[4].Split(spaceSeparator, StringSplitOptions.RemoveEmptyEntries))
            {
                if (!Dicts.ToSymbolTestFlags.TryGetValue(value, out var f))
                {
                    throw new InvalidOperationException($"Invalid flags value: {value}");
                }
                flags |= f;
            }
            return(new SymbolOptionsTestCase(hexBytes, bitness, formattedString, flags));
        }
        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 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));
        }
Exemple #10
0
        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();

            Assert.Equal(tested.Length, codeNames.Length);
            for (int i = 0; i < tested.Length; i++)
            {
                if (!tested[i] && !CodeUtils.IsIgnored(codeNames[i]))
                {
                    sb.Append(codeNames[i] + " ");
                    missing++;
                }
            }
            Assert.Equal("0 ins ", $"{missing} ins " + sb.ToString());
        }
Exemple #11
0
        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 OpCodeInfoTestCase ReadTestCase(string line, int lineNo)
        {
            var parts = line.Split(seps);

            if (parts.Length != 8)
            {
                throw new InvalidOperationException($"Invalid number of commas ({parts.Length - 1} commas)");
            }

            var tc = new OpCodeInfoTestCase();

            tc.LineNumber    = lineNo;
            tc.IsInstruction = true;
            tc.GroupIndex    = -1;

            var code = parts[0].Trim();

            if (CodeUtils.IsIgnored(code))
            {
                return(null);
            }
            tc.Code              = ToCode(code);
            tc.Encoding          = ToEncoding(parts[1].Trim());
            tc.MandatoryPrefix   = ToMandatoryPrefix(parts[2].Trim());
            tc.Table             = ToTable(parts[3].Trim());
            tc.OpCode            = ToOpCode(parts[4].Trim(), out tc.OpCodeLength);
            tc.OpCodeString      = parts[5].Trim();
            tc.InstructionString = parts[6].Trim().Replace('|', ',');

            bool gotVectorLength = false;
            bool gotW            = false;

            foreach (var part in parts[7].Split(optsseps))
            {
                var key = part.Trim();
                if (key.Length == 0)
                {
                    continue;
                }
                int index = key.IndexOf('=');
                if (index >= 0)
                {
                    var value = key.Substring(index + 1);
                    key = key.Substring(0, index);
                    switch (key)
                    {
                    case OpCodeInfoKeys.GroupIndex:
                        if (!uint.TryParse(value, out uint groupIndex) || groupIndex > 7)
                        {
                            throw new InvalidOperationException($"Invalid group index: {value}");
                        }
                        tc.GroupIndex = (int)groupIndex;
                        tc.IsGroup    = true;
                        break;

                    case OpCodeInfoKeys.RmGroupIndex:
                        if (!uint.TryParse(value, out uint rmGroupIndex) || rmGroupIndex > 7)
                        {
                            throw new InvalidOperationException($"Invalid group index: {value}");
                        }
                        tc.RmGroupIndex = (int)rmGroupIndex;
                        tc.IsRmGroup    = true;
                        break;

                    case OpCodeInfoKeys.OpCodeOperandKind:
                        var opParts = value.Split(opseps);
                        tc.OpCount = opParts.Length;
                        if (opParts.Length >= 1)
                        {
                            tc.Op0Kind = ToOpCodeOperandKind(opParts[0]);
                        }
                        if (opParts.Length >= 2)
                        {
                            tc.Op1Kind = ToOpCodeOperandKind(opParts[1]);
                        }
                        if (opParts.Length >= 3)
                        {
                            tc.Op2Kind = ToOpCodeOperandKind(opParts[2]);
                        }
                        if (opParts.Length >= 4)
                        {
                            tc.Op3Kind = ToOpCodeOperandKind(opParts[3]);
                        }
                        if (opParts.Length >= 5)
                        {
                            tc.Op4Kind = ToOpCodeOperandKind(opParts[4]);
                        }
                        Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1);
                        if (opParts.Length >= 6)
                        {
                            throw new InvalidOperationException($"Invalid number of operands: '{value}'");
                        }
                        break;

                    case OpCodeInfoKeys.TupleType:
                        tc.TupleType = ToTupleType(value.Trim());
                        break;

                    case OpCodeInfoKeys.DecoderOption:
                        tc.DecoderOption = ToDecoderOptions(value.Trim());
                        break;

                    default:
                        throw new InvalidOperationException($"Invalid key: '{key}'");
                    }
                }
                else
                {
                    switch (key)
                    {
                    case OpCodeInfoFlags.NoInstruction:
                        tc.IsInstruction = false;
                        break;

                    case OpCodeInfoFlags.Bit16:
                        tc.Mode16 = true;
                        break;

                    case OpCodeInfoFlags.Bit32:
                        tc.Mode32 = true;
                        break;

                    case OpCodeInfoFlags.Bit64:
                        tc.Mode64 = true;
                        break;

                    case OpCodeInfoFlags.Fwait:
                        tc.Fwait = true;
                        break;

                    case OpCodeInfoFlags.OperandSize16:
                        tc.OperandSize = 16;
                        break;

                    case OpCodeInfoFlags.OperandSize32:
                        tc.OperandSize = 32;
                        break;

                    case OpCodeInfoFlags.OperandSize64:
                        tc.OperandSize = 64;
                        break;

                    case OpCodeInfoFlags.AddressSize16:
                        tc.AddressSize = 16;
                        break;

                    case OpCodeInfoFlags.AddressSize32:
                        tc.AddressSize = 32;
                        break;

                    case OpCodeInfoFlags.AddressSize64:
                        tc.AddressSize = 64;
                        break;

                    case OpCodeInfoFlags.LIG:
                        tc.IsLIG        = true;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.L0:
                        tc.L            = 0;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.L1:
                        tc.L            = 1;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.L128:
                        tc.L            = 0;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.L256:
                        tc.L            = 1;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.L512:
                        tc.L            = 2;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.WIG:
                        tc.IsWIG = true;
                        gotW     = true;
                        break;

                    case OpCodeInfoFlags.WIG32:
                        tc.W       = 0;
                        tc.IsWIG32 = true;
                        gotW       = true;
                        break;

                    case OpCodeInfoFlags.W0:
                        tc.W = 0;
                        gotW = true;
                        break;

                    case OpCodeInfoFlags.W1:
                        tc.W = 1;
                        gotW = true;
                        break;

                    case OpCodeInfoFlags.Broadcast:
                        tc.CanBroadcast = true;
                        break;

                    case OpCodeInfoFlags.RoundingControl:
                        tc.CanUseRoundingControl = true;
                        break;

                    case OpCodeInfoFlags.SuppressAllExceptions:
                        tc.CanSuppressAllExceptions = true;
                        break;

                    case OpCodeInfoFlags.OpMaskRegister:
                        tc.CanUseOpMaskRegister = true;
                        break;

                    case OpCodeInfoFlags.RequireOpMaskRegister:
                        tc.CanUseOpMaskRegister  = true;
                        tc.RequireOpMaskRegister = true;
                        break;

                    case OpCodeInfoFlags.ZeroingMasking:
                        tc.CanUseZeroingMasking = true;
                        break;

                    case OpCodeInfoFlags.Lock:
                        tc.CanUseLockPrefix = true;
                        break;

                    case OpCodeInfoFlags.Xacquire:
                        tc.CanUseXacquirePrefix = true;
                        break;

                    case OpCodeInfoFlags.Xrelease:
                        tc.CanUseXreleasePrefix = true;
                        break;

                    case OpCodeInfoFlags.Rep:
                    case OpCodeInfoFlags.Repe:
                        tc.CanUseRepPrefix = true;
                        break;

                    case OpCodeInfoFlags.Repne:
                        tc.CanUseRepnePrefix = true;
                        break;

                    case OpCodeInfoFlags.Bnd:
                        tc.CanUseBndPrefix = true;
                        break;

                    case OpCodeInfoFlags.HintTaken:
                        tc.CanUseHintTakenPrefix = true;
                        break;

                    case OpCodeInfoFlags.Notrack:
                        tc.CanUseNotrackPrefix = true;
                        break;

                    case OpCodeInfoFlags.IgnoresRoundingControl:
                        tc.IgnoresRoundingControl = true;
                        break;

                    case OpCodeInfoFlags.AmdLockRegBit:
                        tc.AmdLockRegBit = true;
                        break;

                    case OpCodeInfoFlags.DefaultOpSize64:
                        tc.DefaultOpSize64 = true;
                        break;

                    case OpCodeInfoFlags.ForceOpSize64:
                        tc.ForceOpSize64 = true;
                        break;

                    case OpCodeInfoFlags.IntelForceOpSize64:
                        tc.IntelForceOpSize64 = true;
                        break;

                    case OpCodeInfoFlags.Cpl0:
                        tc.Cpl0 = true;
                        break;

                    case OpCodeInfoFlags.Cpl1:
                        tc.Cpl1 = true;
                        break;

                    case OpCodeInfoFlags.Cpl2:
                        tc.Cpl2 = true;
                        break;

                    case OpCodeInfoFlags.Cpl3:
                        tc.Cpl3 = true;
                        break;

                    case OpCodeInfoFlags.InputOutput:
                        tc.IsInputOutput = true;
                        break;

                    case OpCodeInfoFlags.Nop:
                        tc.IsNop = true;
                        break;

                    case OpCodeInfoFlags.ReservedNop:
                        tc.IsReservedNop = true;
                        break;

                    case OpCodeInfoFlags.SerializingIntel:
                        tc.IsSerializingIntel = true;
                        break;

                    case OpCodeInfoFlags.SerializingAmd:
                        tc.IsSerializingAmd = true;
                        break;

                    case OpCodeInfoFlags.MayRequireCpl0:
                        tc.MayRequireCpl0 = true;
                        break;

                    case OpCodeInfoFlags.CetTracked:
                        tc.IsCetTracked = true;
                        break;

                    case OpCodeInfoFlags.NonTemporal:
                        tc.IsNonTemporal = true;
                        break;

                    case OpCodeInfoFlags.FpuNoWait:
                        tc.IsFpuNoWait = true;
                        break;

                    case OpCodeInfoFlags.IgnoresModBits:
                        tc.IgnoresModBits = true;
                        break;

                    case OpCodeInfoFlags.No66:
                        tc.No66 = true;
                        break;

                    case OpCodeInfoFlags.NFx:
                        tc.NFx = true;
                        break;

                    case OpCodeInfoFlags.RequiresUniqueRegNums:
                        tc.RequiresUniqueRegNums = true;
                        break;

                    case OpCodeInfoFlags.Privileged:
                        tc.IsPrivileged = true;
                        break;

                    case OpCodeInfoFlags.SaveRestore:
                        tc.IsSaveRestore = true;
                        break;

                    case OpCodeInfoFlags.StackInstruction:
                        tc.IsStackInstruction = true;
                        break;

                    case OpCodeInfoFlags.IgnoresSegment:
                        tc.IgnoresSegment = true;
                        break;

                    case OpCodeInfoFlags.OpMaskReadWrite:
                        tc.IsOpMaskReadWrite = true;
                        break;

                    case OpCodeInfoFlags.RealMode:
                        tc.RealMode = true;
                        break;

                    case OpCodeInfoFlags.ProtectedMode:
                        tc.ProtectedMode = true;
                        break;

                    case OpCodeInfoFlags.Virtual8086Mode:
                        tc.Virtual8086Mode = true;
                        break;

                    case OpCodeInfoFlags.CompatibilityMode:
                        tc.CompatibilityMode = true;
                        break;

                    case OpCodeInfoFlags.LongMode:
                        tc.LongMode = true;
                        break;

                    case OpCodeInfoFlags.UseOutsideSmm:
                        tc.UseOutsideSmm = true;
                        break;

                    case OpCodeInfoFlags.UseInSmm:
                        tc.UseInSmm = true;
                        break;

                    case OpCodeInfoFlags.UseOutsideEnclaveSgx:
                        tc.UseOutsideEnclaveSgx = true;
                        break;

                    case OpCodeInfoFlags.UseInEnclaveSgx1:
                        tc.UseInEnclaveSgx1 = true;
                        break;

                    case OpCodeInfoFlags.UseInEnclaveSgx2:
                        tc.UseInEnclaveSgx2 = true;
                        break;

                    case OpCodeInfoFlags.UseOutsideVmxOp:
                        tc.UseOutsideVmxOp = true;
                        break;

                    case OpCodeInfoFlags.UseInVmxRootOp:
                        tc.UseInVmxRootOp = true;
                        break;

                    case OpCodeInfoFlags.UseInVmxNonRootOp:
                        tc.UseInVmxNonRootOp = true;
                        break;

                    case OpCodeInfoFlags.UseOutsideSeam:
                        tc.UseOutsideSeam = true;
                        break;

                    case OpCodeInfoFlags.UseInSeam:
                        tc.UseInSeam = true;
                        break;

                    case OpCodeInfoFlags.TdxNonRootGenUd:
                        tc.TdxNonRootGenUd = true;
                        break;

                    case OpCodeInfoFlags.TdxNonRootGenVe:
                        tc.TdxNonRootGenVe = true;
                        break;

                    case OpCodeInfoFlags.TdxNonRootMayGenEx:
                        tc.TdxNonRootMayGenEx = true;
                        break;

                    case OpCodeInfoFlags.IntelVmExit:
                        tc.IntelVmExit = true;
                        break;

                    case OpCodeInfoFlags.IntelMayVmExit:
                        tc.IntelMayVmExit = true;
                        break;

                    case OpCodeInfoFlags.IntelSmmVmExit:
                        tc.IntelSmmVmExit = true;
                        break;

                    case OpCodeInfoFlags.AmdVmExit:
                        tc.AmdVmExit = true;
                        break;

                    case OpCodeInfoFlags.AmdMayVmExit:
                        tc.AmdMayVmExit = true;
                        break;

                    case OpCodeInfoFlags.TsxAbort:
                        tc.TsxAbort = true;
                        break;

                    case OpCodeInfoFlags.TsxImplAbort:
                        tc.TsxImplAbort = true;
                        break;

                    case OpCodeInfoFlags.TsxMayAbort:
                        tc.TsxMayAbort = true;
                        break;

                    case OpCodeInfoFlags.IntelDecoder16:
                        tc.IntelDecoder16 = true;
                        break;

                    case OpCodeInfoFlags.IntelDecoder32:
                        tc.IntelDecoder32 = true;
                        break;

                    case OpCodeInfoFlags.IntelDecoder64:
                        tc.IntelDecoder64 = true;
                        break;

                    case OpCodeInfoFlags.AmdDecoder16:
                        tc.AmdDecoder16 = true;
                        break;

                    case OpCodeInfoFlags.AmdDecoder32:
                        tc.AmdDecoder32 = true;
                        break;

                    case OpCodeInfoFlags.AmdDecoder64:
                        tc.AmdDecoder64 = true;
                        break;

                    default:
                        throw new InvalidOperationException($"Invalid key: '{key}'");
                    }
                }
            }
            switch (tc.Encoding)
            {
            case EncodingKind.Legacy:
            case EncodingKind.D3NOW:
                break;

            case EncodingKind.VEX:
            case EncodingKind.EVEX:
            case EncodingKind.XOP:
                if (!gotVectorLength)
                {
                    throw new InvalidOperationException("Missing vector length: L0/L1/L128/L256/L512/LIG");
                }
                if (!gotW)
                {
                    throw new InvalidOperationException("Missing W bit: W0/W1/WIG/WIG32");
                }
                break;

            default:
                throw new InvalidOperationException();
            }

            return(tc);
        }
Exemple #13
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.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 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 codeStr  = elems[2].Trim();

            if (CodeUtils.IsIgnored(codeStr))
            {
                return(null);
            }
            var code = ToEnumConverter.GetCode(codeStr);

            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));
        }
Exemple #15
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);
        }
Exemple #16
0
        static OpCodeInfoTestCase ReadTestCase(string line, int lineNo)
        {
            var parts = line.Split(seps);

            if (parts.Length != 8)
            {
                throw new InvalidOperationException($"Invalid number of commas ({parts.Length - 1} commas)");
            }

            var tc = new OpCodeInfoTestCase();

            tc.LineNumber    = lineNo;
            tc.IsInstruction = true;
            tc.GroupIndex    = -1;

            var code = parts[0].Trim();

            if (CodeUtils.IsIgnored(code))
            {
                return(null);
            }
            tc.Code              = ToCode(code);
            tc.Encoding          = ToEncoding(parts[1].Trim());
            tc.MandatoryPrefix   = ToMandatoryPrefix(parts[2].Trim());
            tc.Table             = ToTable(parts[3].Trim());
            tc.OpCode            = ToOpCode(parts[4].Trim());
            tc.OpCodeString      = parts[5].Trim();
            tc.InstructionString = parts[6].Trim().Replace('|', ',');

            bool gotVectorLength = false;
            bool gotW            = false;

            foreach (var part in parts[7].Split(optsseps))
            {
                var key = part.Trim();
                if (key.Length == 0)
                {
                    continue;
                }
                int index = key.IndexOf('=');
                if (index >= 0)
                {
                    var value = key.Substring(index + 1);
                    key = key.Substring(0, index);
                    switch (key)
                    {
                    case OpCodeInfoKeys.GroupIndex:
                        if (!uint.TryParse(value, out uint groupIndex) || groupIndex > 7)
                        {
                            throw new InvalidOperationException($"Invalid group index: {value}");
                        }
                        tc.GroupIndex = (int)groupIndex;
                        tc.IsGroup    = true;
                        break;

                    case OpCodeInfoKeys.OpCodeOperandKind:
                        var opParts = value.Split(opseps);
                        tc.OpCount = opParts.Length;
                        if (opParts.Length >= 1)
                        {
                            tc.Op0Kind = ToOpCodeOperandKind(opParts[0]);
                        }
                        if (opParts.Length >= 2)
                        {
                            tc.Op1Kind = ToOpCodeOperandKind(opParts[1]);
                        }
                        if (opParts.Length >= 3)
                        {
                            tc.Op2Kind = ToOpCodeOperandKind(opParts[2]);
                        }
                        if (opParts.Length >= 4)
                        {
                            tc.Op3Kind = ToOpCodeOperandKind(opParts[3]);
                        }
                        if (opParts.Length >= 5)
                        {
                            tc.Op4Kind = ToOpCodeOperandKind(opParts[4]);
                        }
                        Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1);
                        if (opParts.Length >= 6)
                        {
                            throw new InvalidOperationException($"Invalid number of operands: '{value}'");
                        }
                        break;

                    case OpCodeInfoKeys.TupleType:
                        tc.TupleType = ToTupleType(value.Trim());
                        break;

                    default:
                        throw new InvalidOperationException($"Invalid key: '{key}'");
                    }
                }
                else
                {
                    switch (key)
                    {
                    case OpCodeInfoFlags.NotInstruction:
                        tc.IsInstruction = false;
                        break;

                    case OpCodeInfoFlags.Bit16:
                        tc.Mode16 = true;
                        break;

                    case OpCodeInfoFlags.Bit32:
                        tc.Mode32 = true;
                        break;

                    case OpCodeInfoFlags.Bit64:
                        tc.Mode64 = true;
                        break;

                    case OpCodeInfoFlags.Fwait:
                        tc.Fwait = true;
                        break;

                    case OpCodeInfoFlags.OperandSize16:
                        tc.OperandSize = 16;
                        break;

                    case OpCodeInfoFlags.OperandSize32:
                        tc.OperandSize = 32;
                        break;

                    case OpCodeInfoFlags.OperandSize64:
                        tc.OperandSize = 64;
                        break;

                    case OpCodeInfoFlags.AddressSize16:
                        tc.AddressSize = 16;
                        break;

                    case OpCodeInfoFlags.AddressSize32:
                        tc.AddressSize = 32;
                        break;

                    case OpCodeInfoFlags.AddressSize64:
                        tc.AddressSize = 64;
                        break;

                    case OpCodeInfoFlags.LIG:
                        tc.IsLIG        = true;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.L0:
                        tc.L            = 0;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.L1:
                        tc.L            = 1;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.L128:
                        tc.L            = 0;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.L256:
                        tc.L            = 1;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.L512:
                        tc.L            = 2;
                        gotVectorLength = true;
                        break;

                    case OpCodeInfoFlags.WIG:
                        tc.IsWIG = true;
                        gotW     = true;
                        break;

                    case OpCodeInfoFlags.WIG32:
                        tc.W       = 0;
                        tc.IsWIG32 = true;
                        gotW       = true;
                        break;

                    case OpCodeInfoFlags.W0:
                        tc.W = 0;
                        gotW = true;
                        break;

                    case OpCodeInfoFlags.W1:
                        tc.W = 1;
                        gotW = true;
                        break;

                    case OpCodeInfoFlags.Broadcast:
                        tc.CanBroadcast = true;
                        break;

                    case OpCodeInfoFlags.RoundingControl:
                        tc.CanUseRoundingControl = true;
                        break;

                    case OpCodeInfoFlags.SuppressAllExceptions:
                        tc.CanSuppressAllExceptions = true;
                        break;

                    case OpCodeInfoFlags.OpMaskRegister:
                        tc.CanUseOpMaskRegister = true;
                        break;

                    case OpCodeInfoFlags.RequireNonZeroOpMaskRegister:
                        tc.CanUseOpMaskRegister         = true;
                        tc.RequireNonZeroOpMaskRegister = true;
                        break;

                    case OpCodeInfoFlags.ZeroingMasking:
                        tc.CanUseZeroingMasking = true;
                        break;

                    case OpCodeInfoFlags.LockPrefix:
                        tc.CanUseLockPrefix = true;
                        break;

                    case OpCodeInfoFlags.XacquirePrefix:
                        tc.CanUseXacquirePrefix = true;
                        break;

                    case OpCodeInfoFlags.XreleasePrefix:
                        tc.CanUseXreleasePrefix = true;
                        break;

                    case OpCodeInfoFlags.RepPrefix:
                    case OpCodeInfoFlags.RepePrefix:
                        tc.CanUseRepPrefix = true;
                        break;

                    case OpCodeInfoFlags.RepnePrefix:
                        tc.CanUseRepnePrefix = true;
                        break;

                    case OpCodeInfoFlags.BndPrefix:
                        tc.CanUseBndPrefix = true;
                        break;

                    case OpCodeInfoFlags.HintTakenPrefix:
                        tc.CanUseHintTakenPrefix = true;
                        break;

                    case OpCodeInfoFlags.NotrackPrefix:
                        tc.CanUseNotrackPrefix = true;
                        break;

                    default:
                        throw new InvalidOperationException($"Invalid key: '{key}'");
                    }
                }
            }
            switch (tc.Encoding)
            {
            case EncodingKind.Legacy:
            case EncodingKind.D3NOW:
                break;

            case EncodingKind.VEX:
            case EncodingKind.EVEX:
            case EncodingKind.XOP:
                if (!gotVectorLength)
                {
                    throw new InvalidOperationException("Missing vector length: L0/L1/L128/L256/L512/LIG");
                }
                if (!gotW)
                {
                    throw new InvalidOperationException("Missing W bit: W0/W1/WIG/WIG32");
                }
                break;

            default:
                throw new InvalidOperationException();
            }

            return(tc);
        }