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);
Beispiel #2
0
        protected void TestInstructionInfo(int bitness, string hexBytes, Code code, int lineNo, InstructionInfoTestCase testCase)
        {
            var decoder = CreateDecoder(bitness, hexBytes);
            var instr   = decoder.Decode();

            Assert.Equal(code, instr.Code);

            Assert.Equal(testCase.StackPointerIncrement, instr.StackPointerIncrement);

            var info = instr.GetInfo();

            Assert.Equal(testCase.Encoding, info.Encoding);
            Assert.Equal(testCase.CpuidFeature, info.CpuidFeature);
            Assert.Equal(testCase.RflagsRead, info.RflagsRead);
            Assert.Equal(testCase.RflagsUndefined, info.RflagsUndefined);
            Assert.Equal(testCase.RflagsWritten, info.RflagsWritten);
            Assert.Equal(testCase.RflagsCleared, info.RflagsCleared);
            Assert.Equal(testCase.RflagsSet, info.RflagsSet);
            Assert.Equal(testCase.Privileged, info.Privileged);
            Assert.Equal(testCase.ProtectedMode, info.ProtectedMode);
            Assert.Equal(testCase.StackInstruction, info.StackInstruction);
            Assert.Equal(testCase.SaveRestoreInstruction, info.SaveRestoreInstruction);
            Assert.Equal(testCase.FlowControl, info.FlowControl);
            Assert.Equal(testCase.Op0Access, info.Op0Access);
            Assert.Equal(testCase.Op1Access, info.Op1Access);
            Assert.Equal(testCase.Op2Access, info.Op2Access);
            Assert.Equal(testCase.Op3Access, info.Op3Access);
            Assert.Equal(
                new HashSet <UsedMemory>(testCase.UsedMemory, UsedMemoryEqualityComparer.Instance),
                new HashSet <UsedMemory>(info.GetUsedMemory(), UsedMemoryEqualityComparer.Instance));
            Assert.Equal(
                new HashSet <UsedRegister>(GetUsedRegisters(testCase.UsedRegisters), UsedRegisterEqualityComparer.Instance),
                new HashSet <UsedRegister>(GetUsedRegisters(info.GetUsedRegisters()), UsedRegisterEqualityComparer.Instance));
            Assert.Equal(info.GetUsedMemory(), instr.GetUsedMemory(), UsedMemoryEqualityComparer.Instance);
            Assert.Equal(info.GetUsedRegisters(), instr.GetUsedRegisters(), UsedRegisterEqualityComparer.Instance);

            const int MAX_OP_COUNT = 4;

            Debug.Assert(instr.OpCount <= MAX_OP_COUNT);
            for (int i = 0; i < instr.OpCount; i++)
            {
                switch (i)
                {
                case 0:
                    Assert.Equal(testCase.Op0Access, info.GetOpAccess(i));
                    break;

                case 1:
                    Assert.Equal(testCase.Op1Access, info.GetOpAccess(i));
                    break;

                case 2:
                    Assert.Equal(testCase.Op2Access, info.GetOpAccess(i));
                    break;

                case 3:
                    Assert.Equal(testCase.Op3Access, info.GetOpAccess(i));
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }
            for (int i = instr.OpCount; i < MAX_OP_COUNT; i++)
            {
                Assert.Equal(OpAccess.None, info.GetOpAccess(i));
            }

            Assert.Equal(RflagsBits.None, info.RflagsWritten & (info.RflagsCleared | info.RflagsSet | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsCleared & (info.RflagsWritten | info.RflagsSet | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsSet & (info.RflagsWritten | info.RflagsCleared | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsUndefined & (info.RflagsWritten | info.RflagsCleared | info.RflagsSet));
            Assert.Equal(info.RflagsWritten | info.RflagsCleared | info.RflagsSet | info.RflagsUndefined, info.RflagsModified);

            var info2 = new InstructionInfoFactory().GetInfo(ref instr);

            CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: true);
            info2 = new InstructionInfoFactory().GetInfo(ref instr, InstructionInfoOptions.NoMemoryUsage);
            CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: false);
            info2 = new InstructionInfoFactory().GetInfo(ref instr, InstructionInfoOptions.NoRegisterUsage);
            CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: true);
            info2 = new InstructionInfoFactory().GetInfo(ref instr, InstructionInfoOptions.NoRegisterUsage | InstructionInfoOptions.NoMemoryUsage);
            CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: false);

            Assert.Equal(info.Encoding, instr.Code.Encoding());
            var cf = instr.Code.CpuidFeature();

            if (cf == CpuidFeature.AVX && instr.Op1Kind == OpKind.Register && (code == Code.VEX_Vbroadcastss_VX_WX || code == Code.VEX_Vbroadcastss_VY_WX || code == Code.VEX_Vbroadcastsd_VY_WX))
            {
                cf = CpuidFeature.AVX2;
            }
            Assert.Equal(info.CpuidFeature, cf);
            Assert.Equal(info.FlowControl, instr.Code.FlowControl());
            Assert.Equal(info.ProtectedMode, instr.Code.ProtectedMode());
            Assert.Equal(info.Privileged, instr.Code.Privileged());
            Assert.Equal(info.StackInstruction, instr.Code.StackInstruction());
            Assert.Equal(info.SaveRestoreInstruction, instr.Code.SaveRestoreInstruction());

            Assert.Equal(info.Encoding, instr.Encoding);
            Assert.Equal(info.CpuidFeature, instr.CpuidFeature);
            Assert.Equal(info.FlowControl, instr.FlowControl);
            Assert.Equal(info.ProtectedMode, instr.ProtectedMode);
            Assert.Equal(info.Privileged, instr.Privileged);
            Assert.Equal(info.StackInstruction, instr.StackInstruction);
            Assert.Equal(info.SaveRestoreInstruction, instr.SaveRestoreInstruction);
            Assert.Equal(info.RflagsRead, instr.RflagsRead);
            Assert.Equal(info.RflagsWritten, instr.RflagsWritten);
            Assert.Equal(info.RflagsCleared, instr.RflagsCleared);
            Assert.Equal(info.RflagsSet, instr.RflagsSet);
            Assert.Equal(info.RflagsUndefined, instr.RflagsUndefined);
            Assert.Equal(info.RflagsModified, instr.RflagsModified);
        }
Beispiel #3
0
        protected void TestInstructionInfo(int bitness, string hexBytes, Code code, DecoderOptions options, int lineNo, InstructionInfoTestCase testCase)
        {
            var         codeBytes = HexUtils.ToByteArray(hexBytes);
            Instruction instr;

            if (bitness == 16 && code == Code.Popw_CS && hexBytes == "0F")
            {
                instr             = default;
                instr.Code        = Code.Popw_CS;
                instr.Op0Kind     = OpKind.Register;
                instr.Op0Register = Register.CS;
                instr.CodeSize    = CodeSize.Code16;
                instr.ByteLength  = 1;
            }
            else if (code >= Code.DeclareByte)
            {
                instr                  = default;
                instr.Code             = code;
                instr.DeclareDataCount = 1;
                Assert.Equal(64, bitness);
                instr.CodeSize = CodeSize.Code64;
                switch (code)
                {
                case Code.DeclareByte:
                    Assert.Equal("66", hexBytes);
                    instr.SetDeclareByteValue(0, 0x66);
                    break;

                case Code.DeclareWord:
                    Assert.Equal("6644", hexBytes);
                    instr.SetDeclareWordValue(0, 0x4466);
                    break;

                case Code.DeclareDword:
                    Assert.Equal("664422EE", hexBytes);
                    instr.SetDeclareDwordValue(0, 0xEE224466);
                    break;

                case Code.DeclareQword:
                    Assert.Equal("664422EE12345678", hexBytes);
                    instr.SetDeclareQwordValue(0, 0x78563412EE224466);
                    break;

                default: throw new InvalidOperationException();
                }
            }
            else
            {
                var decoder = CreateDecoder(bitness, codeBytes, options);
                instr = decoder.Decode();
                if (codeBytes.Length != 1 && codeBytes[0] == 0x9B && instr.ByteLength == 1)
                {
                    instr = decoder.Decode();
                    switch (instr.Code)
                    {
                    case Code.Fnstenv_m14byte: instr.Code = Code.Fstenv_m14byte; break;

                    case Code.Fnstenv_m28byte: instr.Code = Code.Fstenv_m28byte; break;

                    case Code.Fnstcw_m16: instr.Code = Code.Fstcw_m16; break;

                    case Code.Fneni: instr.Code = Code.Feni; break;

                    case Code.Fndisi: instr.Code = Code.Fdisi; break;

                    case Code.Fnclex: instr.Code = Code.Fclex; break;

                    case Code.Fninit: instr.Code = Code.Finit; break;

                    case Code.Fnsetpm: instr.Code = Code.Fsetpm; break;

                    case Code.Fnsave_m94byte: instr.Code = Code.Fsave_m94byte; break;

                    case Code.Fnsave_m108byte: instr.Code = Code.Fsave_m108byte; break;

                    case Code.Fnstsw_m16: instr.Code = Code.Fstsw_m16; break;

                    case Code.Fnstsw_AX: instr.Code = Code.Fstsw_AX; break;

                    default:
                        Assert.False(true, $"Invalid FPU instr Code value: {instr.Code}");
                        break;
                    }
                }
            }
            Assert.Equal(code, instr.Code);

            Assert.Equal(testCase.StackPointerIncrement, instr.StackPointerIncrement);

            var info = instr.GetInfo();

            Assert.Equal(testCase.Encoding, info.Encoding);
            Assert.Equal(testCase.CpuidFeatures, info.CpuidFeatures);
            Assert.Equal(testCase.RflagsRead, info.RflagsRead);
            Assert.Equal(testCase.RflagsUndefined, info.RflagsUndefined);
            Assert.Equal(testCase.RflagsWritten, info.RflagsWritten);
            Assert.Equal(testCase.RflagsCleared, info.RflagsCleared);
            Assert.Equal(testCase.RflagsSet, info.RflagsSet);
            Assert.Equal(testCase.IsPrivileged, info.IsPrivileged);
            Assert.Equal(testCase.IsProtectedMode, info.IsProtectedMode);
            Assert.Equal(testCase.IsStackInstruction, info.IsStackInstruction);
            Assert.Equal(testCase.IsSaveRestoreInstruction, info.IsSaveRestoreInstruction);
            Assert.Equal(testCase.FlowControl, info.FlowControl);
            Assert.Equal(testCase.Op0Access, info.Op0Access);
            Assert.Equal(testCase.Op1Access, info.Op1Access);
            Assert.Equal(testCase.Op2Access, info.Op2Access);
            Assert.Equal(testCase.Op3Access, info.Op3Access);
            Assert.Equal(testCase.Op4Access, info.Op4Access);
            Assert.Equal(
                new HashSet <UsedMemory>(testCase.UsedMemory, UsedMemoryEqualityComparer.Instance),
                new HashSet <UsedMemory>(info.GetUsedMemory(), UsedMemoryEqualityComparer.Instance));
            Assert.Equal(
                new HashSet <UsedRegister>(GetUsedRegisters(testCase.UsedRegisters), UsedRegisterEqualityComparer.Instance),
                new HashSet <UsedRegister>(GetUsedRegisters(info.GetUsedRegisters()), UsedRegisterEqualityComparer.Instance));
            Assert.Equal(info.GetUsedMemory(), instr.GetUsedMemory(), UsedMemoryEqualityComparer.Instance);
            Assert.Equal(info.GetUsedRegisters(), instr.GetUsedRegisters(), UsedRegisterEqualityComparer.Instance);

            Debug.Assert(Iced.Intel.DecoderConstants.MaxOpCount == 5);
            Debug.Assert(instr.OpCount <= Iced.Intel.DecoderConstants.MaxOpCount);
            for (int i = 0; i < instr.OpCount; i++)
            {
                switch (i)
                {
                case 0:
                    Assert.Equal(testCase.Op0Access, info.GetOpAccess(i));
                    break;

                case 1:
                    Assert.Equal(testCase.Op1Access, info.GetOpAccess(i));
                    break;

                case 2:
                    Assert.Equal(testCase.Op2Access, info.GetOpAccess(i));
                    break;

                case 3:
                    Assert.Equal(testCase.Op3Access, info.GetOpAccess(i));
                    break;

                case 4:
                    Assert.Equal(testCase.Op4Access, info.GetOpAccess(i));
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }
            for (int i = instr.OpCount; i < Iced.Intel.DecoderConstants.MaxOpCount; i++)
            {
                Assert.Equal(OpAccess.None, info.GetOpAccess(i));
            }

            Assert.Equal(RflagsBits.None, info.RflagsWritten & (info.RflagsCleared | info.RflagsSet | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsCleared & (info.RflagsWritten | info.RflagsSet | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsSet & (info.RflagsWritten | info.RflagsCleared | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsUndefined & (info.RflagsWritten | info.RflagsCleared | info.RflagsSet));
            Assert.Equal(info.RflagsWritten | info.RflagsCleared | info.RflagsSet | info.RflagsUndefined, info.RflagsModified);

            var info2 = new InstructionInfoFactory().GetInfo(ref instr);

            CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: true);
            info2 = new InstructionInfoFactory().GetInfo(ref instr, InstructionInfoOptions.NoMemoryUsage);
            CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: false);
            info2 = new InstructionInfoFactory().GetInfo(ref instr, InstructionInfoOptions.NoRegisterUsage);
            CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: true);
            info2 = new InstructionInfoFactory().GetInfo(ref instr, InstructionInfoOptions.NoRegisterUsage | InstructionInfoOptions.NoMemoryUsage);
            CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: false);

            Assert.Equal(info.Encoding, instr.Code.Encoding());
            var cf = instr.Code.CpuidFeatures();

            if (cf.Length == 1 && cf[0] == CpuidFeature.AVX && instr.Op1Kind == OpKind.Register && (code == Code.VEX_Vbroadcastss_xmm_xmmm32 || code == Code.VEX_Vbroadcastss_ymm_xmmm32 || code == Code.VEX_Vbroadcastsd_ymm_xmmm64))
            {
                cf = new[] { CpuidFeature.AVX2 }
            }
            ;
            Assert.Equal(info.CpuidFeatures, cf);
            Assert.Equal(info.FlowControl, instr.Code.FlowControl());
            Assert.Equal(info.IsProtectedMode, instr.Code.IsProtectedMode());
            Assert.Equal(info.IsPrivileged, instr.Code.IsPrivileged());
            Assert.Equal(info.IsStackInstruction, instr.Code.IsStackInstruction());
            Assert.Equal(info.IsSaveRestoreInstruction, instr.Code.IsSaveRestoreInstruction());

            Assert.Equal(info.Encoding, instr.Encoding);
            Assert.Equal(info.CpuidFeatures, instr.CpuidFeatures);
            Assert.Equal(info.FlowControl, instr.FlowControl);
            Assert.Equal(info.IsProtectedMode, instr.IsProtectedMode);
            Assert.Equal(info.IsPrivileged, instr.IsPrivileged);
            Assert.Equal(info.IsStackInstruction, instr.IsStackInstruction);
            Assert.Equal(info.IsSaveRestoreInstruction, instr.IsSaveRestoreInstruction);
            Assert.Equal(info.RflagsRead, instr.RflagsRead);
            Assert.Equal(info.RflagsWritten, instr.RflagsWritten);
            Assert.Equal(info.RflagsCleared, instr.RflagsCleared);
            Assert.Equal(info.RflagsSet, instr.RflagsSet);
            Assert.Equal(info.RflagsUndefined, instr.RflagsUndefined);
            Assert.Equal(info.RflagsModified, instr.RflagsModified);
        }

        void CheckEqual(ref InstructionInfo info1, ref InstructionInfo info2, bool hasRegs2, bool hasMem2)
        {
            if (hasRegs2)
            {
                Assert.Equal(info1.GetUsedRegisters(), info2.GetUsedRegisters(), UsedRegisterEqualityComparer.Instance);
            }
            else
            {
                Assert.Empty(info2.GetUsedRegisters());
            }
            if (hasMem2)
            {
                Assert.Equal(info1.GetUsedMemory(), info2.GetUsedMemory(), UsedMemoryEqualityComparer.Instance);
            }
            else
            {
                Assert.Empty(info2.GetUsedMemory());
            }
            Assert.Equal(info1.IsProtectedMode, info2.IsProtectedMode);
            Assert.Equal(info1.IsPrivileged, info2.IsPrivileged);
            Assert.Equal(info1.IsStackInstruction, info2.IsStackInstruction);
            Assert.Equal(info1.IsSaveRestoreInstruction, info2.IsSaveRestoreInstruction);
            Assert.Equal(info1.Encoding, info2.Encoding);
            Assert.Equal(info1.CpuidFeatures, info2.CpuidFeatures);
            Assert.Equal(info1.FlowControl, info2.FlowControl);
            Assert.Equal(info1.Op0Access, info2.Op0Access);
            Assert.Equal(info1.Op1Access, info2.Op1Access);
            Assert.Equal(info1.Op2Access, info2.Op2Access);
            Assert.Equal(info1.Op3Access, info2.Op3Access);
            Assert.Equal(info1.Op4Access, info2.Op4Access);
            Assert.Equal(info1.RflagsRead, info2.RflagsRead);
            Assert.Equal(info1.RflagsWritten, info2.RflagsWritten);
            Assert.Equal(info1.RflagsCleared, info2.RflagsCleared);
            Assert.Equal(info1.RflagsSet, info2.RflagsSet);
            Assert.Equal(info1.RflagsUndefined, info2.RflagsUndefined);
            Assert.Equal(info1.RflagsModified, info2.RflagsModified);
        }

        IEnumerable <UsedRegister> GetUsedRegisters(IEnumerable <UsedRegister> usedRegisterIterator)
        {
            var read      = new List <Register>();
            var write     = new List <Register>();
            var condRead  = new List <Register>();
            var condWrite = new List <Register>();

            foreach (var info in usedRegisterIterator)
            {
                switch (info.Access)
                {
                case OpAccess.Read:
                    read.Add(info.Register);
                    break;

                case OpAccess.CondRead:
                    condRead.Add(info.Register);
                    break;

                case OpAccess.Write:
                    write.Add(info.Register);
                    break;

                case OpAccess.CondWrite:
                    condWrite.Add(info.Register);
                    break;

                case OpAccess.ReadWrite:
                    read.Add(info.Register);
                    write.Add(info.Register);
                    break;

                case OpAccess.ReadCondWrite:
                    read.Add(info.Register);
                    condWrite.Add(info.Register);
                    break;

                case OpAccess.None:
                case OpAccess.NoMemAccess:
                default:
                    throw new InvalidOperationException();
                }
            }

            foreach (var reg in GetRegisters(read))
            {
                yield return(new UsedRegister(reg, OpAccess.Read));
            }
            foreach (var reg in GetRegisters(write))
            {
                yield return(new UsedRegister(reg, OpAccess.Write));
            }
            foreach (var reg in GetRegisters(condRead))
            {
                yield return(new UsedRegister(reg, OpAccess.CondRead));
            }
            foreach (var reg in GetRegisters(condWrite))
            {
                yield return(new UsedRegister(reg, OpAccess.CondWrite));
            }
        }

        IEnumerable <Register> GetRegisters(List <Register> regs)
        {
            if (regs.Count <= 1)
            {
                return(regs);
            }

            regs.Sort(RegisterSorter);

            var hash = new HashSet <Register>();
            int index;

            foreach (var reg in regs)
            {
                if (Register.EAX <= reg && reg <= Register.R15D)
                {
                    index = reg - Register.EAX;
                    if (hash.Contains(Register.RAX + index))
                    {
                        continue;
                    }
                }
                else if (Register.AX <= reg && reg <= Register.R15W)
                {
                    index = reg - Register.AX;
                    if (hash.Contains(Register.RAX + index))
                    {
                        continue;
                    }
                    if (hash.Contains(Register.EAX + index))
                    {
                        continue;
                    }
                }
                else if (Register.AL <= reg && reg <= Register.R15L)
                {
                    index = reg - Register.AL;
                    if (Register.AH <= reg && reg <= Register.BH)
                    {
                        index -= 4;
                    }
                    if (hash.Contains(Register.RAX + index))
                    {
                        continue;
                    }
                    if (hash.Contains(Register.EAX + index))
                    {
                        continue;
                    }
                    if (hash.Contains(Register.AX + index))
                    {
                        continue;
                    }
                }
                else if (Register.YMM0 <= reg && reg <= Register.YMM0 + InstructionInfoConstants.VMM_count - 1)
                {
                    index = reg - Register.YMM0;
                    if (hash.Contains(Register.ZMM0 + index))
                    {
                        continue;
                    }
                }
                else if (Register.XMM0 <= reg && reg <= Register.XMM0 + InstructionInfoConstants.VMM_count - 1)
                {
                    index = reg - Register.XMM0;
                    if (hash.Contains(Register.ZMM0 + index))
                    {
                        continue;
                    }
                    if (hash.Contains(Register.YMM0 + index))
                    {
                        continue;
                    }
                }
                hash.Add(reg);
            }

            foreach (var info in lowRegs)
            {
                if (hash.Contains(info.rl) && hash.Contains(info.rh))
                {
                    hash.Remove(info.rl);
                    hash.Remove(info.rh);
                    hash.Add(info.rx);
                }
            }

            return(hash);
        }
Beispiel #4
0
        protected void TestInstructionInfo(int bitness, string hexBytes, Code code, DecoderOptions options, int lineNo, InstructionInfoTestCase testCase)
        {
            var         codeBytes = HexUtils.ToByteArray(hexBytes);
            Instruction instruction;

            if (testCase.IsSpecial)
            {
                if (bitness == 16 && code == Code.Popw_CS && hexBytes == "0F")
                {
                    instruction             = default;
                    instruction.Code        = Code.Popw_CS;
                    instruction.Op0Kind     = OpKind.Register;
                    instruction.Op0Register = Register.CS;
                    instruction.CodeSize    = CodeSize.Code16;
                    instruction.Length      = 1;
                }
                else if (code <= Code.DeclareQword)
                {
                    instruction                  = default;
                    instruction.Code             = code;
                    instruction.DeclareDataCount = 1;
                    Assert.Equal(64, bitness);
                    instruction.CodeSize = CodeSize.Code64;
                    switch (code)
                    {
                    case Code.DeclareByte:
                        Assert.Equal("66", hexBytes);
                        instruction.SetDeclareByteValue(0, 0x66);
                        break;

                    case Code.DeclareWord:
                        Assert.Equal("6644", hexBytes);
                        instruction.SetDeclareWordValue(0, 0x4466);
                        break;

                    case Code.DeclareDword:
                        Assert.Equal("664422EE", hexBytes);
                        instruction.SetDeclareDwordValue(0, 0xEE224466);
                        break;

                    case Code.DeclareQword:
                        Assert.Equal("664422EE12345678", hexBytes);
                        instruction.SetDeclareQwordValue(0, 0x78563412EE224466);
                        break;

                    default: throw new InvalidOperationException();
                    }
                }
                else
                {
                    var decoder = CreateDecoder(bitness, codeBytes, options);
                    instruction = decoder.Decode();
                    if (codeBytes.Length > 1 && codeBytes[0] == 0x9B && instruction.Length == 1)
                    {
                        instruction      = decoder.Decode();
                        instruction.Code = instruction.Code switch {
                            Code.Fnstenv_m14byte => Code.Fstenv_m14byte,
                            Code.Fnstenv_m28byte => Code.Fstenv_m28byte,
                            Code.Fnstcw_m2byte => Code.Fstcw_m2byte,
                            Code.Fneni => Code.Feni,
                            Code.Fndisi => Code.Fdisi,
                            Code.Fnclex => Code.Fclex,
                            Code.Fninit => Code.Finit,
                            Code.Fnsetpm => Code.Fsetpm,
                            Code.Fnsave_m94byte => Code.Fsave_m94byte,
                            Code.Fnsave_m108byte => Code.Fsave_m108byte,
                            Code.Fnstsw_m2byte => Code.Fstsw_m2byte,
                            Code.Fnstsw_AX => Code.Fstsw_AX,
                            Code.Fnstdw_AX => Code.Fstdw_AX,
                            Code.Fnstsg_AX => Code.Fstsg_AX,
                            _ => throw new InvalidOperationException(),
                        };
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }
                }
            }
            else
            {
                var decoder = CreateDecoder(bitness, codeBytes, options);
                instruction = decoder.Decode();
            }
            Assert.Equal(code, instruction.Code);

            Assert.Equal(testCase.StackPointerIncrement, instruction.StackPointerIncrement);

            var info = new InstructionInfoFactory().GetInfo(instruction);

            Assert.Equal(testCase.Encoding, info.Encoding);
            Assert.Equal(testCase.CpuidFeatures, info.CpuidFeatures);
            Assert.Equal(testCase.RflagsRead, info.RflagsRead);
            Assert.Equal(testCase.RflagsUndefined, info.RflagsUndefined);
            Assert.Equal(testCase.RflagsWritten, info.RflagsWritten);
            Assert.Equal(testCase.RflagsCleared, info.RflagsCleared);
            Assert.Equal(testCase.RflagsSet, info.RflagsSet);
            Assert.Equal(testCase.IsPrivileged, info.IsPrivileged);
            Assert.Equal(testCase.IsStackInstruction, info.IsStackInstruction);
            Assert.Equal(testCase.IsSaveRestoreInstruction, info.IsSaveRestoreInstruction);
            Assert.Equal(testCase.FlowControl, info.FlowControl);
            Assert.Equal(testCase.Op0Access, info.Op0Access);
            Assert.Equal(testCase.Op1Access, info.Op1Access);
            Assert.Equal(testCase.Op2Access, info.Op2Access);
            Assert.Equal(testCase.Op3Access, info.Op3Access);
            Assert.Equal(testCase.Op4Access, info.Op4Access);
            Assert.Equal(
                new HashSet <UsedMemory>(testCase.UsedMemory, UsedMemoryEqualityComparer.Instance),
                new HashSet <UsedMemory>(info.GetUsedMemory(), UsedMemoryEqualityComparer.Instance));
            Assert.Equal(
                new HashSet <UsedRegister>(GetUsedRegisters(testCase.UsedRegisters), UsedRegisterEqualityComparer.Instance),
                new HashSet <UsedRegister>(GetUsedRegisters(info.GetUsedRegisters()), UsedRegisterEqualityComparer.Instance));

            Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1);
            Debug.Assert(instruction.OpCount <= IcedConstants.MaxOpCount);
            for (int i = 0; i < instruction.OpCount; i++)
            {
                switch (i)
                {
                case 0:
                    Assert.Equal(testCase.Op0Access, info.GetOpAccess(i));
                    break;

                case 1:
                    Assert.Equal(testCase.Op1Access, info.GetOpAccess(i));
                    break;

                case 2:
                    Assert.Equal(testCase.Op2Access, info.GetOpAccess(i));
                    break;

                case 3:
                    Assert.Equal(testCase.Op3Access, info.GetOpAccess(i));
                    break;

                case 4:
                    Assert.Equal(testCase.Op4Access, info.GetOpAccess(i));
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }
            for (int i = instruction.OpCount; i < IcedConstants.MaxOpCount; i++)
            {
                Assert.Equal(OpAccess.None, info.GetOpAccess(i));
            }

            Assert.Equal(RflagsBits.None, info.RflagsWritten & (info.RflagsCleared | info.RflagsSet | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsCleared & (info.RflagsWritten | info.RflagsSet | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsSet & (info.RflagsWritten | info.RflagsCleared | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsUndefined & (info.RflagsWritten | info.RflagsCleared | info.RflagsSet));
            Assert.Equal(info.RflagsWritten | info.RflagsCleared | info.RflagsSet | info.RflagsUndefined, info.RflagsModified);

            var info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.None);

            CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: true);
            info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.NoMemoryUsage);
            CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: false);
            info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.NoRegisterUsage);
            CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: true);
            info2 = new InstructionInfoFactory().GetInfo(instruction, InstructionInfoOptions.NoRegisterUsage | InstructionInfoOptions.NoMemoryUsage);
            CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: false);

            Assert.Equal(info.Encoding, instruction.Code.Encoding());
#if ENCODER && OPCODE_INFO
            Assert.Equal(code.ToOpCode().Encoding, instruction.Code.Encoding());
#endif
            Assert.Equal(info.CpuidFeatures, instruction.Code.CpuidFeatures());
            Assert.Equal(info.FlowControl, instruction.Code.FlowControl());
            Assert.Equal(info.IsPrivileged, instruction.Code.IsPrivileged());
            Assert.Equal(info.IsStackInstruction, instruction.Code.IsStackInstruction());
            Assert.Equal(info.IsSaveRestoreInstruction, instruction.Code.IsSaveRestoreInstruction());

            Assert.Equal(info.Encoding, instruction.Encoding);
            Assert.Equal(info.CpuidFeatures, instruction.CpuidFeatures);
            Assert.Equal(info.FlowControl, instruction.FlowControl);
            Assert.Equal(info.IsPrivileged, instruction.IsPrivileged);
            Assert.Equal(info.IsStackInstruction, instruction.IsStackInstruction);
            Assert.Equal(info.IsSaveRestoreInstruction, instruction.IsSaveRestoreInstruction);
            Assert.Equal(info.RflagsRead, instruction.RflagsRead);
            Assert.Equal(info.RflagsWritten, instruction.RflagsWritten);
            Assert.Equal(info.RflagsCleared, instruction.RflagsCleared);
            Assert.Equal(info.RflagsSet, instruction.RflagsSet);
            Assert.Equal(info.RflagsUndefined, instruction.RflagsUndefined);
            Assert.Equal(info.RflagsModified, instruction.RflagsModified);
        }
Beispiel #5
0
 void Test32_InstructionInfo(string hexBytes, Code code, DecoderOptions options, int lineNo, InstructionInfoTestCase testCase) =>
 TestInstructionInfo(32, hexBytes, code, options, lineNo, testCase);
Beispiel #6
0
 void Test16_InstructionInfo(string hexBytes, Code code, int lineNo, InstructionInfoTestCase testCase) =>
 TestInstructionInfo(16, hexBytes, code, lineNo, testCase);
        protected void TestInstructionInfo(int bitness, string hexBytes, Code code, DecoderOptions options, int lineNo, InstructionInfoTestCase testCase)
        {
            var         codeBytes = HexUtils.ToByteArray(hexBytes);
            Instruction instr;

            if (bitness == 16 && code == Code.Popw_CS && hexBytes == "0F")
            {
                instr             = default;
                instr.Code        = Code.Popw_CS;
                instr.Op0Kind     = OpKind.Register;
                instr.Op0Register = Register.CS;
                instr.CodeSize    = CodeSize.Code16;
                instr.ByteLength  = 1;
            }
            else
            {
                var decoder = CreateDecoder(bitness, codeBytes, options);
                instr = decoder.Decode();
                if (codeBytes.Length != 1 && codeBytes[0] == 0x9B && instr.ByteLength == 1)
                {
                    instr = decoder.Decode();
                    switch (instr.Code)
                    {
                    case Code.Fnstenv_m14byte: instr.Code = Code.Fstenv_m14byte; break;

                    case Code.Fnstenv_m28byte: instr.Code = Code.Fstenv_m28byte; break;

                    case Code.Fnstcw_m16: instr.Code = Code.Fstcw_m16; break;

                    case Code.Fneni: instr.Code = Code.Feni; break;

                    case Code.Fndisi: instr.Code = Code.Fdisi; break;

                    case Code.Fnclex: instr.Code = Code.Fclex; break;

                    case Code.Fninit: instr.Code = Code.Finit; break;

                    case Code.Fnsetpm: instr.Code = Code.Fsetpm; break;

                    case Code.Fnsave_m94byte: instr.Code = Code.Fsave_m94byte; break;

                    case Code.Fnsave_m108byte: instr.Code = Code.Fsave_m108byte; break;

                    case Code.Fnstsw_m16: instr.Code = Code.Fstsw_m16; break;

                    case Code.Fnstsw_AX: instr.Code = Code.Fstsw_AX; break;

                    default:
                        Assert.False(true, $"Invalid FPU instr Code value: {instr.Code}");
                        break;
                    }
                }
            }
            Assert.Equal(code, instr.Code);

            Assert.Equal(testCase.StackPointerIncrement, instr.StackPointerIncrement);

            var info = instr.GetInfo();

            Assert.Equal(testCase.Encoding, info.Encoding);
            Assert.Equal(testCase.CpuidFeature, info.CpuidFeature);
            Assert.Equal(testCase.RflagsRead, info.RflagsRead);
            Assert.Equal(testCase.RflagsUndefined, info.RflagsUndefined);
            Assert.Equal(testCase.RflagsWritten, info.RflagsWritten);
            Assert.Equal(testCase.RflagsCleared, info.RflagsCleared);
            Assert.Equal(testCase.RflagsSet, info.RflagsSet);
            Assert.Equal(testCase.Privileged, info.Privileged);
            Assert.Equal(testCase.ProtectedMode, info.ProtectedMode);
            Assert.Equal(testCase.StackInstruction, info.StackInstruction);
            Assert.Equal(testCase.SaveRestoreInstruction, info.SaveRestoreInstruction);
            Assert.Equal(testCase.FlowControl, info.FlowControl);
            Assert.Equal(testCase.Op0Access, info.Op0Access);
            Assert.Equal(testCase.Op1Access, info.Op1Access);
            Assert.Equal(testCase.Op2Access, info.Op2Access);
            Assert.Equal(testCase.Op3Access, info.Op3Access);
            Assert.Equal(testCase.Op4Access, info.Op4Access);
            Assert.Equal(
                new HashSet <UsedMemory>(testCase.UsedMemory, UsedMemoryEqualityComparer.Instance),
                new HashSet <UsedMemory>(info.GetUsedMemory(), UsedMemoryEqualityComparer.Instance));
            Assert.Equal(
                new HashSet <UsedRegister>(GetUsedRegisters(testCase.UsedRegisters), UsedRegisterEqualityComparer.Instance),
                new HashSet <UsedRegister>(GetUsedRegisters(info.GetUsedRegisters()), UsedRegisterEqualityComparer.Instance));
            Assert.Equal(info.GetUsedMemory(), instr.GetUsedMemory(), UsedMemoryEqualityComparer.Instance);
            Assert.Equal(info.GetUsedRegisters(), instr.GetUsedRegisters(), UsedRegisterEqualityComparer.Instance);

            Debug.Assert(Iced.Intel.DecoderConstants.MaxOpCount == 5);
            Debug.Assert(instr.OpCount <= Iced.Intel.DecoderConstants.MaxOpCount);
            for (int i = 0; i < instr.OpCount; i++)
            {
                switch (i)
                {
                case 0:
                    Assert.Equal(testCase.Op0Access, info.GetOpAccess(i));
                    break;

                case 1:
                    Assert.Equal(testCase.Op1Access, info.GetOpAccess(i));
                    break;

                case 2:
                    Assert.Equal(testCase.Op2Access, info.GetOpAccess(i));
                    break;

                case 3:
                    Assert.Equal(testCase.Op3Access, info.GetOpAccess(i));
                    break;

                case 4:
                    Assert.Equal(testCase.Op4Access, info.GetOpAccess(i));
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }
            for (int i = instr.OpCount; i < Iced.Intel.DecoderConstants.MaxOpCount; i++)
            {
                Assert.Equal(OpAccess.None, info.GetOpAccess(i));
            }

            Assert.Equal(RflagsBits.None, info.RflagsWritten & (info.RflagsCleared | info.RflagsSet | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsCleared & (info.RflagsWritten | info.RflagsSet | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsSet & (info.RflagsWritten | info.RflagsCleared | info.RflagsUndefined));
            Assert.Equal(RflagsBits.None, info.RflagsUndefined & (info.RflagsWritten | info.RflagsCleared | info.RflagsSet));
            Assert.Equal(info.RflagsWritten | info.RflagsCleared | info.RflagsSet | info.RflagsUndefined, info.RflagsModified);

            var info2 = new InstructionInfoFactory().GetInfo(ref instr);

            CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: true);
            info2 = new InstructionInfoFactory().GetInfo(ref instr, InstructionInfoOptions.NoMemoryUsage);
            CheckEqual(ref info, ref info2, hasRegs2: true, hasMem2: false);
            info2 = new InstructionInfoFactory().GetInfo(ref instr, InstructionInfoOptions.NoRegisterUsage);
            CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: true);
            info2 = new InstructionInfoFactory().GetInfo(ref instr, InstructionInfoOptions.NoRegisterUsage | InstructionInfoOptions.NoMemoryUsage);
            CheckEqual(ref info, ref info2, hasRegs2: false, hasMem2: false);

            Assert.Equal(info.Encoding, instr.Code.Encoding());
            var cf = instr.Code.CpuidFeature();

            if (cf == CpuidFeature.AVX && instr.Op1Kind == OpKind.Register && (code == Code.VEX_Vbroadcastss_xmm_xmmm32 || code == Code.VEX_Vbroadcastss_ymm_xmmm32 || code == Code.VEX_Vbroadcastsd_ymm_xmmm64))
            {
                cf = CpuidFeature.AVX2;
            }
            Assert.Equal(info.CpuidFeature, cf);
            Assert.Equal(info.FlowControl, instr.Code.FlowControl());
            Assert.Equal(info.ProtectedMode, instr.Code.ProtectedMode());
            Assert.Equal(info.Privileged, instr.Code.Privileged());
            Assert.Equal(info.StackInstruction, instr.Code.StackInstruction());
            Assert.Equal(info.SaveRestoreInstruction, instr.Code.SaveRestoreInstruction());

            Assert.Equal(info.Encoding, instr.Encoding);
            Assert.Equal(info.CpuidFeature, instr.CpuidFeature);
            Assert.Equal(info.FlowControl, instr.FlowControl);
            Assert.Equal(info.ProtectedMode, instr.ProtectedMode);
            Assert.Equal(info.Privileged, instr.Privileged);
            Assert.Equal(info.StackInstruction, instr.StackInstruction);
            Assert.Equal(info.SaveRestoreInstruction, instr.SaveRestoreInstruction);
            Assert.Equal(info.RflagsRead, instr.RflagsRead);
            Assert.Equal(info.RflagsWritten, instr.RflagsWritten);
            Assert.Equal(info.RflagsCleared, instr.RflagsCleared);
            Assert.Equal(info.RflagsSet, instr.RflagsSet);
            Assert.Equal(info.RflagsUndefined, instr.RflagsUndefined);
            Assert.Equal(info.RflagsModified, instr.RflagsModified);
        }
Beispiel #8
0
        static (string hexBytes, Code code, DecoderOptions options, InstructionInfoTestCase testCase) ParseLine(string line, int bitness, Dictionary <string, Register> toRegister)
        {
            Static.Assert(MiscInstrInfoTestConstants.InstrInfoElemsPerLine == 5 ? 0 : -1);
            var elems = line.Split(commaSeparator, MiscInstrInfoTestConstants.InstrInfoElemsPerLine);

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

            var testCase = new InstructionInfoTestCase();

            var hexBytes = ToHexBytes(elems[0].Trim());
            var code     = ToEnumConverter.GetCode(elems[1].Trim());

            testCase.Encoding = ToEnumConverter.GetEncodingKind(elems[2].Trim());
            var cpuidFeatureStrings = elems[3].Trim().Split(new[] { ';' });

            var cpuidFeatures = new CpuidFeature[cpuidFeatureStrings.Length];

            testCase.CpuidFeatures = cpuidFeatures;
            for (int i = 0; i < cpuidFeatures.Length; i++)
            {
                cpuidFeatures[i] = ToEnumConverter.GetCpuidFeature(cpuidFeatureStrings[i]);
            }

            var options = DecoderOptions.None;

            foreach (var keyValue in elems[4].Split(spaceSeparator, StringSplitOptions.RemoveEmptyEntries))
            {
                string key, value;
                int    index = keyValue.IndexOf('=');
                if (index >= 0)
                {
                    key   = keyValue.Substring(0, index);
                    value = keyValue.Substring(index + 1);
                }
                else
                {
                    key   = keyValue;
                    value = string.Empty;
                }

                switch (key)
                {
                case InstructionInfoKeys.IsProtectedMode:
                    if (value != string.Empty)
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    testCase.IsProtectedMode = true;
                    break;

                case InstructionInfoKeys.IsPrivileged:
                    if (value != string.Empty)
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    testCase.IsPrivileged = true;
                    break;

                case InstructionInfoKeys.IsSaveRestoreInstruction:
                    if (value != string.Empty)
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    testCase.IsSaveRestoreInstruction = true;
                    break;

                case InstructionInfoKeys.IsStackInstruction:
                    if (!int.TryParse(value, out testCase.StackPointerIncrement))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    testCase.IsStackInstruction = true;
                    break;

                case InstructionInfoKeys.IsSpecial:
                    if (value != string.Empty)
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    testCase.IsSpecial = true;
                    break;

                case InstructionInfoKeys.RflagsRead:
                    if (!ParseRflags(value, ref testCase.RflagsRead))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.RflagsUndefined:
                    if (!ParseRflags(value, ref testCase.RflagsUndefined))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.RflagsWritten:
                    if (!ParseRflags(value, ref testCase.RflagsWritten))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.RflagsCleared:
                    if (!ParseRflags(value, ref testCase.RflagsCleared))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.RflagsSet:
                    if (!ParseRflags(value, ref testCase.RflagsSet))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.FlowControl:
                    if (!ToEnumConverter.TryFlowControl(value, out testCase.FlowControl))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.Op0Access:
                    if (!InstructionInfoDicts.ToAccess.TryGetValue(value, out testCase.Op0Access))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.Op1Access:
                    if (!InstructionInfoDicts.ToAccess.TryGetValue(value, out testCase.Op1Access))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.Op2Access:
                    if (!InstructionInfoDicts.ToAccess.TryGetValue(value, out testCase.Op2Access))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.Op3Access:
                    if (!InstructionInfoDicts.ToAccess.TryGetValue(value, out testCase.Op3Access))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.Op4Access:
                    if (!InstructionInfoDicts.ToAccess.TryGetValue(value, out testCase.Op4Access))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.ReadRegister:
                    if (!AddRegisters(toRegister, value, OpAccess.Read, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.CondReadRegister:
                    if (!AddRegisters(toRegister, value, OpAccess.CondRead, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.WriteRegister:
                    if (!AddRegisters(toRegister, value, OpAccess.Write, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.CondWriteRegister:
                    if (!AddRegisters(toRegister, value, OpAccess.CondWrite, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.ReadWriteRegister:
                    if (!AddRegisters(toRegister, value, OpAccess.ReadWrite, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.ReadCondWriteRegister:
                    if (!AddRegisters(toRegister, value, OpAccess.ReadCondWrite, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.ReadMemory:
                    if (!AddMemory(bitness, toRegister, value, OpAccess.Read, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.CondReadMemory:
                    if (!AddMemory(bitness, toRegister, value, OpAccess.CondRead, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.ReadWriteMemory:
                    if (!AddMemory(bitness, toRegister, value, OpAccess.ReadWrite, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.ReadCondWriteMemory:
                    if (!AddMemory(bitness, toRegister, value, OpAccess.ReadCondWrite, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.WriteMemory:
                    if (!AddMemory(bitness, toRegister, value, OpAccess.Write, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.CondWriteMemory:
                    if (!AddMemory(bitness, toRegister, value, OpAccess.CondWrite, testCase))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                case InstructionInfoKeys.DecoderOptions:
                    if (!TryParseDecoderOptions(value.Split(semicolonSeparator), ref options))
                    {
                        throw new Exception($"Invalid key-value value, '{keyValue}'");
                    }
                    break;

                default:
                    throw new Exception($"Invalid key-value value, '{keyValue}'");
                }
            }

            return(hexBytes, code, options, testCase);
        }
Beispiel #9
0
        static bool AddRegisters(Dictionary <string, Register> toRegister, string value, OpAccess access, InstructionInfoTestCase testCase)
        {
            foreach (var tmp in value.Split(semicolonSeparator, StringSplitOptions.RemoveEmptyEntries))
            {
                var regString = tmp.Trim();
                if (!toRegister.TryGetValue(regString, out var reg))
                {
                    return(false);
                }

                if (testCase.Encoding != EncodingKind.Legacy && testCase.Encoding != EncodingKind.D3NOW)
                {
                    switch (access)
                    {
                    case OpAccess.None:
                    case OpAccess.Read:
                    case OpAccess.NoMemAccess:
                    case OpAccess.CondRead:
                        break;

                    case OpAccess.Write:
                    case OpAccess.CondWrite:
                    case OpAccess.ReadWrite:
                    case OpAccess.ReadCondWrite:
                        if (Register.XMM0 <= reg && reg <= IcedConstants.VMM_last && !regString.StartsWith(MiscInstrInfoTestConstants.VMM_prefix, StringComparison.OrdinalIgnoreCase))
                        {
                            throw new Exception($"Register {regString} is written ({access}) but {MiscInstrInfoTestConstants.VMM_prefix} pseudo register should be used instead");
                        }
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }
                testCase.UsedRegisters.Add(new UsedRegister(reg, access));
            }
            return(true);
        }
Beispiel #10
0
        static bool AddMemory(int bitness, Dictionary <string, Register> toRegister, string value, OpAccess access, InstructionInfoTestCase testCase)
        {
            var elems = value.Split(semicolonSeparator);

            if (elems.Length != 2)
            {
                return(false);
            }
            var expr = elems[0].Trim();

            if (!ToEnumConverter.TryMemorySize(elems[1].Trim(), out var memorySize))
            {
                return(false);
            }

            if (!TryParseMemExpr(toRegister, expr, out var segReg, out var baseReg, out var indexReg, out int scale, out ulong displ))
            {
                return(false);
            }

            switch (bitness)
            {
            case 16:
                if (!(short.MinValue <= (long)displ && (long)displ <= short.MaxValue) && displ > ushort.MaxValue)
                {
                    return(false);
                }
                displ = (ushort)displ;
                break;

            case 32:
                if (!(int.MinValue <= (long)displ && (long)displ <= int.MaxValue) && displ > uint.MaxValue)
                {
                    return(false);
                }
                displ = (uint)displ;
                break;

            case 64:
                break;

            default:
                throw new InvalidOperationException();
            }

            if (access != OpAccess.NoMemAccess)
            {
                testCase.UsedMemory.Add(new UsedMemory(segReg, baseReg, indexReg, scale, displ, memorySize, access));
            }

            return(true);
        }