Пример #1
0
        private static void ParseArgument([NotNull] IInstructionFetcher fetcher, OpCodeFlag flag, out int argument, out int argumentValue, out int argumentDisplacement, int argumentType, byte modrm)
        {
            var mod = (byte)((modrm >> 6) & 7);
            var reg = (byte)((modrm >> 3) & 7);
            var rm  = (byte)(modrm & 7);

            switch (argumentType)
            {
            case ARG_AX:
            case ARG_CX:
            case ARG_DX:
            case ARG_BX:
            case ARG_SP:
            case ARG_BP:
            case ARG_SI:
            case ARG_DI:
            case ARG_IP:
            case ARG_CS:
            case ARG_DS:
            case ARG_ES:
            case ARG_SS:
            case ARG_FLAGS:
                argument             = argumentType;
                argumentValue        = ARG_NONE;
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_AL:
            case ARG_CL:
            case ARG_DL:
            case ARG_BL:
            case ARG_AH:
            case ARG_CH:
            case ARG_DH:
            case ARG_BH:
                argument             = ARG_BYTE_REGISTER;
                argumentValue        = argumentType;
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_1:
                argument             = ARG_CONSTANT;
                argumentValue        = 1;
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_3:
                argument             = ARG_CONSTANT;
                argumentValue        = 3;
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_IB:
                argument             = ARG_CONSTANT;
                argumentValue        = fetcher.FetchU8();
                argumentDisplacement = ARG_NONE;
                if (flag.Has(OpCodeFlag.Signed))
                {
                    argumentValue = (sbyte)(byte)argumentValue;
                }
                break;

            case ARG_IW:
                argument             = ARG_CONSTANT;
                argumentValue        = fetcher.FetchU16();
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_JB:
                argument             = ARG_CONSTANT;
                argumentValue        = (sbyte)fetcher.FetchU8();
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_JW:
                argument             = ARG_CONSTANT;
                argumentValue        = fetcher.FetchU16();
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_S:
                Debug.Assert(reg < 4);
                argument             = reg + ARG_ES;
                argumentValue        = ARG_NONE;
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_GB:
                argument             = ARG_BYTE_REGISTER;
                argumentValue        = ARG_AL + reg;
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_GW:
                argument             = reg;
                argumentValue        = ARG_NONE;
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_OB:
            case ARG_OW:
                argument             = ARG_MEMORY;
                argumentValue        = fetcher.FetchU16();
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_A:
                argument = ARG_FAR_MEMORY;
                var address = fetcher.FetchU16();
                var segment = fetcher.FetchU16();
                argumentValue        = (int)(((uint)segment << 16) | address);
                argumentDisplacement = ARG_NONE;
                break;

            case ARG_EB:
            case ARG_EW:
            case ARG_M:
                switch (mod)
                {
                case 0:
                    if (rm == 6)
                    {
                        argument             = ARG_MEMORY;
                        argumentValue        = fetcher.FetchU16();
                        argumentDisplacement = ARG_NONE;
                    }
                    else
                    {
                        argument             = ARG_DEREFERENCE;
                        argumentValue        = rm;
                        argumentDisplacement = 0;
                    }
                    break;

                case 1:
                    argument             = ARG_DEREFERENCE;
                    argumentValue        = rm;
                    argumentDisplacement = (sbyte)fetcher.FetchU8();
                    break;

                case 2:
                    argument             = ARG_DEREFERENCE;
                    argumentValue        = rm;
                    argumentDisplacement = fetcher.FetchU16();
                    break;

                case 3:
                    Debug.Assert(argumentType != ARG_M);
                    if (argumentType == ARG_EB)
                    {
                        argument      = ARG_BYTE_REGISTER;
                        argumentValue = ARG_AL + rm;
                    }
                    else
                    {
                        argument      = rm;
                        argumentValue = ARG_NONE;
                    }
                    argumentDisplacement = ARG_NONE;
                    break;

                default:
                    throw new NotImplementedException();
                }
                break;

            case ARG_NONE:
                argument             = ARG_NONE;
                argumentValue        = ARG_NONE;
                argumentDisplacement = ARG_NONE;
                break;

            default:
                throw new NotImplementedException();
            }
        }
Пример #2
0
        public static Instruction Decode([NotNull] IInstructionFetcher fetcher)
        {
            Instruction instruction;

            var opcode = fetcher.FetchU8();

            instruction.Type          = opCodes[opcode].Type;
            instruction.SegmentPrefix = Cpu8086.Register.Invalid;
            instruction.OpcodePrefix  = 0;

            while (instruction.Type == InstructionType.Prefix)
            {
                switch (opcode)
                {
                case 0x26:
                    instruction.SegmentPrefix = Cpu8086.Register.ES;
                    break;

                case 0x2E:
                    instruction.SegmentPrefix = Cpu8086.Register.CS;
                    break;

                case 0x36:
                    instruction.SegmentPrefix = Cpu8086.Register.SS;
                    break;

                case 0x3E:
                    instruction.SegmentPrefix = Cpu8086.Register.DS;
                    break;

                case 0xF0:
                case 0xF2:
                case 0xF3:
                    instruction.OpcodePrefix = opcode;
                    break;

                default:
                    throw new NotImplementedException();
                }

                opcode           = fetcher.FetchU8();
                instruction.Type = opCodes[opcode].Type;
            }
            if (instruction.Type == InstructionType.EmulatorSpecial)
            {
                var opcode2 = fetcher.FetchU8();
                Debug.Assert(opcode2 == 0x0F);
            }
            Debug.Assert(instruction.Type != InstructionType.Invalid);

            var argument1Type = opCodes[opcode].Argument1Type;
            var argument2Type = opCodes[opcode].Argument2Type;

            instruction.Flag = opCodes[opcode].Flag;
            byte rm = 0xFF;

            if (instruction.Flag.Has(OpCodeFlag.HasRM))
            {
                rm = fetcher.FetchU8();
            }

            if (instruction.Type == InstructionType.Group)
            {
                instruction.Type = ConvertFromGroup(opcode, rm);
                Debug.Assert(instruction.Type != InstructionType.Invalid);
                var reg = (byte)((rm >> 3) & 7);
                if (opcode == 0xF6 && reg == 0)
                {
                    argument2Type = ARG_IB;
                }
                else if (opcode == 0xF7 && reg == 0)
                {
                    argument2Type = ARG_IW;
                }
                else if (opcode == 0xFF && (reg == 3 || reg == 5))
                {
                    argument1Type = ARG_M;
                }
            }

            ParseArgument(fetcher, instruction.Flag, out instruction.Argument1, out instruction.Argument1Value, out instruction.Argument1Displacement, argument1Type, rm);
            ParseArgument(fetcher, instruction.Flag, out instruction.Argument2, out instruction.Argument2Value, out instruction.Argument2Displacement, argument2Type, rm);

            return(instruction);
        }