Exemple #1
0
 void DecoderTestMisc(int bitness, int lineNo, string hexBytes, DecoderTestCase tc) =>
 DecoderTestBase(bitness, lineNo, hexBytes, tc);
Exemple #2
0
        static void ReadOpKind(DecoderTestCase tc, int operand, string value, out OpKind opKind, ref Register opRegister)
        {
            var parts = value.Split(opKindSeps);

            switch (parts[0])
            {
            case OpKind_Register:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opRegister = ToRegister(parts[1]);
                opKind     = OpKind.Register;
                break;

            case OpKind_NearBranch16:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind        = OpKind.NearBranch16;
                tc.NearBranch = ToUInt16(parts[1]);
                break;

            case OpKind_NearBranch32:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind        = OpKind.NearBranch32;
                tc.NearBranch = ToUInt32(parts[1]);
                break;

            case OpKind_NearBranch64:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind        = OpKind.NearBranch64;
                tc.NearBranch = ToUInt64(parts[1]);
                break;

            case OpKind_FarBranch16:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                opKind = OpKind.FarBranch16;
                tc.FarBranchSelector = ToUInt16(parts[1]);
                tc.FarBranch         = ToUInt16(parts[2]);
                break;

            case OpKind_FarBranch32:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                opKind = OpKind.FarBranch32;
                tc.FarBranchSelector = ToUInt16(parts[1]);
                tc.FarBranch         = ToUInt32(parts[2]);
                break;

            case OpKind_Immediate8:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind       = OpKind.Immediate8;
                tc.Immediate = ToUInt8(parts[1]);
                break;

            case OpKind_Immediate16:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind       = OpKind.Immediate16;
                tc.Immediate = ToUInt16(parts[1]);
                break;

            case OpKind_Immediate32:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind       = OpKind.Immediate32;
                tc.Immediate = ToUInt32(parts[1]);
                break;

            case OpKind_Immediate64:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind       = OpKind.Immediate64;
                tc.Immediate = ToUInt64(parts[1]);
                break;

            case OpKind_Immediate8to16:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind       = OpKind.Immediate8to16;
                tc.Immediate = ToUInt16(parts[1]);
                break;

            case OpKind_Immediate8to32:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind       = OpKind.Immediate8to32;
                tc.Immediate = ToUInt32(parts[1]);
                break;

            case OpKind_Immediate8to64:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind       = OpKind.Immediate8to64;
                tc.Immediate = ToUInt64(parts[1]);
                break;

            case OpKind_Immediate32to64:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind       = OpKind.Immediate32to64;
                tc.Immediate = ToUInt64(parts[1]);
                break;

            case OpKind_Immediate8_2nd:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind           = OpKind.Immediate8_2nd;
                tc.Immediate_2nd = ToUInt8(parts[1]);
                break;

            case OpKind_MemorySegSI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                opKind           = OpKind.MemorySegSI;
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case OpKind_MemorySegESI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                opKind           = OpKind.MemorySegESI;
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case OpKind_MemorySegRSI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                opKind           = OpKind.MemorySegRSI;
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case OpKind_MemorySegDI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                opKind           = OpKind.MemorySegDI;
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case OpKind_MemorySegEDI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                opKind           = OpKind.MemorySegEDI;
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case OpKind_MemorySegRDI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                opKind           = OpKind.MemorySegRDI;
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case OpKind_MemoryESDI:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind        = OpKind.MemoryESDI;
                tc.MemorySize = ToMemorySize(parts[1]);
                break;

            case OpKind_MemoryESEDI:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind        = OpKind.MemoryESEDI;
                tc.MemorySize = ToMemorySize(parts[1]);
                break;

            case OpKind_MemoryESRDI:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                opKind        = OpKind.MemoryESRDI;
                tc.MemorySize = ToMemorySize(parts[1]);
                break;

            case OpKind_Memory64:
                if (parts.Length != 4)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 4 values, actual = {parts.Length}");
                }
                opKind             = OpKind.Memory64;
                tc.MemorySegment   = ToRegister(parts[1]);
                tc.MemoryAddress64 = ToUInt64(parts[2]);
                tc.MemorySize      = ToMemorySize(parts[3]);
                break;

            case OpKind_Memory:
                if (parts.Length != 8)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 8 values, actual = {parts.Length}");
                }
                opKind                = OpKind.Memory;
                tc.MemorySegment      = ToRegister(parts[1]);
                tc.MemoryBase         = ToRegister(parts[2]);
                tc.MemoryIndex        = ToRegister(parts[3]);
                tc.MemoryIndexScale   = ToInt32(parts[4]);
                tc.MemoryDisplacement = ToUInt32(parts[5]);
                tc.MemoryDisplSize    = ToInt32(parts[6]);
                tc.MemorySize         = ToMemorySize(parts[7]);
                break;

            default:
                throw new InvalidOperationException($"Invalid opkind: '{parts[0]}'");
            }
        }
Exemple #3
0
        static DecoderTestCase ReadTestCase(int bitness, string line, int lineNo)
        {
            var parts = line.Split(seps);

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

            var tc = new DecoderTestCase();

            tc.LineNumber      = lineNo;
            tc.Bitness         = bitness;
            tc.HexBytes        = ToHexBytes(parts[0].Trim());
            tc.EncodedHexBytes = tc.HexBytes;
            tc.Code            = ToCode(parts[1].Trim());
            tc.Mnemonic        = ToMnemonic(parts[2].Trim());
            tc.OpCount         = ToInt32(parts[3].Trim());

            var rest = parts[4].Split(extraSeps);

            foreach (var tmp in rest)
            {
                if (tmp == string.Empty)
                {
                    continue;
                }
                var    key = tmp;
                string value;
                int    index = key.IndexOf('=');
                if (index >= 0)
                {
                    value = key.Substring(index + 1);
                    key   = key.Substring(0, index);
                }
                else
                {
                    value = null;
                }
                switch (key)
                {
                case Broadcast:
                    tc.IsBroadcast = true;
                    break;

                case Xacquire:
                    tc.HasXacquirePrefix = true;
                    break;

                case Xrelease:
                    tc.HasXreleasePrefix = true;
                    break;

                case Rep:
                case Repe:
                    tc.HasRepePrefix = true;
                    break;

                case Repne:
                    tc.HasRepnePrefix = true;
                    break;

                case Lock:
                    tc.HasLockPrefix = true;
                    break;

                case ZeroingMasking:
                    tc.ZeroingMasking = true;
                    break;

                case SuppressAllExceptions:
                    tc.SuppressAllExceptions = true;
                    break;

                case Vsib32:
                    tc.VsibBitness = 32;
                    break;

                case Vsib64:
                    tc.VsibBitness = 64;
                    break;

                case RoundToNearest:
                    tc.RoundingControl = RoundingControl.RoundToNearest;
                    break;

                case RoundDown:
                    tc.RoundingControl = RoundingControl.RoundDown;
                    break;

                case RoundUp:
                    tc.RoundingControl = RoundingControl.RoundUp;
                    break;

                case RoundTowardZero:
                    tc.RoundingControl = RoundingControl.RoundTowardZero;
                    break;

                case Op0Kind:
                    if (tc.OpCount < 1)
                    {
                        throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 1");
                    }
                    ReadOpKind(tc, 0, value, out tc.Op0Kind, ref tc.Op0Register);
                    break;

                case Op1Kind:
                    if (tc.OpCount < 2)
                    {
                        throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 2");
                    }
                    ReadOpKind(tc, 1, value, out tc.Op1Kind, ref tc.Op1Register);
                    break;

                case Op2Kind:
                    if (tc.OpCount < 3)
                    {
                        throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 3");
                    }
                    ReadOpKind(tc, 2, value, out tc.Op2Kind, ref tc.Op2Register);
                    break;

                case Op3Kind:
                    if (tc.OpCount < 4)
                    {
                        throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 4");
                    }
                    ReadOpKind(tc, 3, value, out tc.Op3Kind, ref tc.Op3Register);
                    break;

                case Op4Kind:
                    if (tc.OpCount < 5)
                    {
                        throw new InvalidOperationException($"Invalid OpCount: {tc.OpCount} < 5");
                    }
                    ReadOpKind(tc, 4, value, out tc.Op4Kind, ref tc.Op4Register);
                    break;

                case EncodedHexBytes:
                    if (string.IsNullOrWhiteSpace(value))
                    {
                        throw new InvalidOperationException($"Invalid encoded hex bytes: '{value}'");
                    }
                    tc.EncodedHexBytes = value;
                    break;

                case DecoderOptions_AMD:
                    tc.DecoderOptions |= DecoderOptions.AMD;
                    break;

                case DecoderOptions_ForceReservedNop:
                    tc.DecoderOptions |= DecoderOptions.ForceReservedNop;
                    break;

                case DecoderOptions_Cflsh:
                    tc.DecoderOptions |= DecoderOptions.Cflsh;
                    break;

                case DecoderOptions_Umov:
                    tc.DecoderOptions |= DecoderOptions.Umov;
                    break;

                case DecoderOptions_Ecr:
                    tc.DecoderOptions |= DecoderOptions.Ecr;
                    break;

                case DecoderOptions_Xbts:
                    tc.DecoderOptions |= DecoderOptions.Xbts;
                    break;

                case DecoderOptions_Cmpxchg486A:
                    tc.DecoderOptions |= DecoderOptions.Cmpxchg486A;
                    break;

                case DecoderOptions_Zalloc:
                    tc.DecoderOptions |= DecoderOptions.Zalloc;
                    break;

                case DecoderOptions_OldFpu:
                    tc.DecoderOptions |= DecoderOptions.OldFpu;
                    break;

                case DecoderOptions_Pcommit:
                    tc.DecoderOptions |= DecoderOptions.Pcommit;
                    break;

                case DecoderOptions_Loadall286:
                    tc.DecoderOptions |= DecoderOptions.Loadall286;
                    break;

                case DecoderOptions_Loadall386:
                    tc.DecoderOptions |= DecoderOptions.Loadall386;
                    break;

                case DecoderOptions_Cl1invmb:
                    tc.DecoderOptions |= DecoderOptions.Cl1invmb;
                    break;

                case DecoderOptions_MovTr:
                    tc.DecoderOptions |= DecoderOptions.MovTr;
                    break;

                case DecoderOptions_NoPause:
                    tc.DecoderOptions |= DecoderOptions.NoPause;
                    break;

                case DecoderOptions_NoWbnoinvd:
                    tc.DecoderOptions |= DecoderOptions.NoWbnoinvd;
                    break;

                case DecoderOptions_NoLockMovCR0:
                    tc.DecoderOptions |= DecoderOptions.NoLockMovCR0;
                    break;

                case DecoderOptions_NoMPFX_0FB8:
                    tc.DecoderOptions |= DecoderOptions.NoMPFX_0FB8;
                    break;

                case DecoderOptions_NoMPFX_0FBC:
                    tc.DecoderOptions |= DecoderOptions.NoMPFX_0FBC;
                    break;

                case DecoderOptions_NoMPFX_0FBD:
                    tc.DecoderOptions |= DecoderOptions.NoMPFX_0FBD;
                    break;

                case DecoderOptions_NoLahfSahf64:
                    tc.DecoderOptions |= DecoderOptions.NoLahfSahf64;
                    break;

                case DecoderOptions_NoInvalidCheck:
                    tc.DecoderOptions |= DecoderOptions.NoInvalidCheck;
                    break;

                case SegmentPrefix_ES:
                    tc.SegmentPrefix = Register.ES;
                    break;

                case SegmentPrefix_CS:
                    tc.SegmentPrefix = Register.CS;
                    break;

                case SegmentPrefix_SS:
                    tc.SegmentPrefix = Register.SS;
                    break;

                case SegmentPrefix_DS:
                    tc.SegmentPrefix = Register.DS;
                    break;

                case SegmentPrefix_FS:
                    tc.SegmentPrefix = Register.FS;
                    break;

                case SegmentPrefix_GS:
                    tc.SegmentPrefix = Register.GS;
                    break;

                case OpMask_k1:
                    tc.OpMask = Register.K1;
                    break;

                case OpMask_k2:
                    tc.OpMask = Register.K2;
                    break;

                case OpMask_k3:
                    tc.OpMask = Register.K3;
                    break;

                case OpMask_k4:
                    tc.OpMask = Register.K4;
                    break;

                case OpMask_k5:
                    tc.OpMask = Register.K5;
                    break;

                case OpMask_k6:
                    tc.OpMask = Register.K6;
                    break;

                case OpMask_k7:
                    tc.OpMask = Register.K7;
                    break;

                case ConstantOffsets:
                    if (!TryParseConstantOffsets(value, out tc.ConstantOffsets))
                    {
                        throw new InvalidOperationException($"Invalid ConstantOffsets: '{value}'");
                    }
                    break;

                default:
                    throw new InvalidOperationException($"Invalid key '{key}'");
                }
            }

            return(tc);
        }
Exemple #4
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);
        }
Exemple #5
0
        static void ReadOpKind(DecoderTestCase tc, int operand, string value)
        {
            var parts = value.Split(opKindSeps);

            switch (parts[0])
            {
            case DecoderTestParserConstants.OpKind_Register:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpRegister(operand, ToRegister(parts[1]));
                tc.SetOpKind(operand, OpKind.Register);
                break;

            case DecoderTestParserConstants.OpKind_NearBranch16:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.NearBranch16);
                tc.NearBranch = NumberConverter.ToUInt16(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_NearBranch32:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.NearBranch32);
                tc.NearBranch = NumberConverter.ToUInt32(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_NearBranch64:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.NearBranch64);
                tc.NearBranch = NumberConverter.ToUInt64(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_FarBranch16:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.FarBranch16);
                tc.FarBranchSelector = NumberConverter.ToUInt16(parts[1]);
                tc.FarBranch         = NumberConverter.ToUInt16(parts[2]);
                break;

            case DecoderTestParserConstants.OpKind_FarBranch32:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.FarBranch32);
                tc.FarBranchSelector = NumberConverter.ToUInt16(parts[1]);
                tc.FarBranch         = NumberConverter.ToUInt32(parts[2]);
                break;

            case DecoderTestParserConstants.OpKind_Immediate8:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.Immediate8);
                tc.Immediate = NumberConverter.ToUInt8(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_Immediate16:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.Immediate16);
                tc.Immediate = NumberConverter.ToUInt16(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_Immediate32:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.Immediate32);
                tc.Immediate = NumberConverter.ToUInt32(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_Immediate64:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.Immediate64);
                tc.Immediate = NumberConverter.ToUInt64(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_Immediate8to16:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.Immediate8to16);
                tc.Immediate = NumberConverter.ToUInt16(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_Immediate8to32:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.Immediate8to32);
                tc.Immediate = NumberConverter.ToUInt32(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_Immediate8to64:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.Immediate8to64);
                tc.Immediate = NumberConverter.ToUInt64(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_Immediate32to64:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.Immediate32to64);
                tc.Immediate = NumberConverter.ToUInt64(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_Immediate8_2nd:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.Immediate8_2nd);
                tc.Immediate_2nd = NumberConverter.ToUInt8(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_MemorySegSI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.MemorySegSI);
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case DecoderTestParserConstants.OpKind_MemorySegESI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.MemorySegESI);
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case DecoderTestParserConstants.OpKind_MemorySegRSI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.MemorySegRSI);
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case DecoderTestParserConstants.OpKind_MemorySegDI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.MemorySegDI);
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case DecoderTestParserConstants.OpKind_MemorySegEDI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.MemorySegEDI);
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case DecoderTestParserConstants.OpKind_MemorySegRDI:
                if (parts.Length != 3)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 3 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.MemorySegRDI);
                tc.MemorySegment = ToRegister(parts[1]);
                tc.MemorySize    = ToMemorySize(parts[2]);
                break;

            case DecoderTestParserConstants.OpKind_MemoryESDI:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.MemoryESDI);
                tc.MemorySize = ToMemorySize(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_MemoryESEDI:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.MemoryESEDI);
                tc.MemorySize = ToMemorySize(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_MemoryESRDI:
                if (parts.Length != 2)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 2 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.MemoryESRDI);
                tc.MemorySize = ToMemorySize(parts[1]);
                break;

            case DecoderTestParserConstants.OpKind_Memory:
                if (parts.Length != 8)
                {
                    throw new InvalidOperationException($"Operand {operand}: expected 8 values, actual = {parts.Length}");
                }
                tc.SetOpKind(operand, OpKind.Memory);
                tc.MemorySegment      = ToRegister(parts[1]);
                tc.MemoryBase         = ToRegister(parts[2]);
                tc.MemoryIndex        = ToRegister(parts[3]);
                tc.MemoryIndexScale   = NumberConverter.ToInt32(parts[4]);
                tc.MemoryDisplacement = NumberConverter.ToUInt64(parts[5]);
                tc.MemoryDisplSize    = NumberConverter.ToInt32(parts[6]);
                tc.MemorySize         = ToMemorySize(parts[7]);
                break;

            default:
                throw new InvalidOperationException($"Invalid opkind: '{parts[0]}'");
            }
        }
Exemple #6
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);
        }