Пример #1
0
        private bool TryAddressRegisterIndirectWithIndex(ushort uInstr, PrimitiveType dataWidth, EndianImageReader rdr, out MachineOperand op)
        {
            if (!rdr.TryReadBeUInt16(out ushort extension))
            {
                op = null; return(false);
            }
            if (EXT_FULL(extension))
            {
                if (M68kDisassembler.EXT_EFFECTIVE_ZERO(extension))
                {
                    op = new M68kAddressOperand(Address.Ptr32(0));
                    return(true);
                }

                RegisterStorage base_reg        = null;
                RegisterStorage index_reg       = null;
                PrimitiveType   index_reg_width = null;
                int             index_scale     = 1;
                Constant        @base           = null;
                if (EXT_BASE_DISPLACEMENT_PRESENT(extension))
                {
                    @base = rdr.ReadBe(EXT_BASE_DISPLACEMENT_LONG(extension) ? PrimitiveType.Word32 : PrimitiveType.Int16);
                }

                Constant outer = null;
                if (EXT_OUTER_DISPLACEMENT_PRESENT(extension))
                {
                    outer = rdr.ReadBe(EXT_OUTER_DISPLACEMENT_LONG(extension) ? PrimitiveType.Word32 : PrimitiveType.Int16);
                }
                if (EXT_BASE_REGISTER_PRESENT(extension))
                {
                    base_reg = Registers.AddressRegister(uInstr & 7);
                }
                if (EXT_INDEX_REGISTER_PRESENT(extension))
                {
                    index_reg = EXT_INDEX_AR(extension)
                        ? Registers.AddressRegister((int)EXT_INDEX_REGISTER(extension))
                        : Registers.DataRegister((int)EXT_INDEX_REGISTER(extension));
                    index_reg_width = EXT_INDEX_LONG(extension) ? PrimitiveType.Word32 : PrimitiveType.Word16;
                    if (EXT_INDEX_SCALE(extension) != 0)
                    {
                        index_scale = 1 << EXT_INDEX_SCALE(extension);
                    }
                }
                bool preindex  = (extension & 7) > 0 && (extension & 7) < 4;
                bool postindex = (extension & 7) > 4;
                op = new IndexedOperand(dataWidth, @base, outer, base_reg, index_reg, index_reg_width, index_scale, preindex, postindex);
            }
            else
            {
                op = new IndirectIndexedOperand(
                    dataWidth,
                    EXT_8BIT_DISPLACEMENT(extension),
                    Registers.AddressRegister(uInstr & 7),
                    EXT_INDEX_AR(extension)
                        ? Registers.AddressRegister((int)EXT_INDEX_REGISTER(extension))
                        : Registers.DataRegister((int)EXT_INDEX_REGISTER(extension)),
                    EXT_INDEX_LONG(extension) ? PrimitiveType.Word32 : PrimitiveType.Int16,
                    1 << EXT_INDEX_SCALE(extension));
            }
            return(true);
        }
Пример #2
0
        private bool TryParseOperandInner(ushort uInstr, byte addressMode, byte operandBits, PrimitiveType dataWidth, EndianImageReader rdr, out MachineOperand op)
        {
            Constant offset;

            switch (addressMode)
            {
            case 0: // Data register direct.
                op = DataRegisterOperand(operandBits, 0);
                return(true);

            case 1: // Address register direct
                op = new RegisterOperand(AddressRegister(operandBits, 0));
                return(true);

            case 2:  // Address register indirect
                op = MemoryOperand.Indirect(dataWidth, AddressRegister(operandBits, 0));
                return(true);

            case 3:  // Address register indirect with postincrement.
                op = MemoryOperand.PostIncrement(dataWidth, AddressRegister(operandBits, 0));
                return(true);

            case 4:  // Address register indirect with predecrement.
                op = MemoryOperand.PreDecrement(dataWidth, AddressRegister(operandBits, 0));
                return(true);

            case 5: // Address register indirect with displacement.
                if (!rdr.TryReadBe(PrimitiveType.Int16, out offset))
                {
                    op = null;
                    return(false);
                }
                op = MemoryOperand.Indirect(dataWidth, AddressRegister(operandBits, 0), offset);
                return(true);

            case 6: // Address register indirect with index
                return(TryAddressRegisterIndirectWithIndex(uInstr, dataWidth, rdr, out op));

            case 7:
                switch (operandBits)
                {
                case 0: // Absolute short address
                    ushort usAddr;
                    if (!rdr.TryReadBeUInt16(out usAddr))
                    {
                        op = null; return(false);
                    }
                    op = new M68kAddressOperand(usAddr);
                    return(true);

                case 1: // Absolute long address
                    uint uAddr;
                    if (!rdr.TryReadBeUInt32(out uAddr))
                    {
                        op = null; return(false);
                    }
                    op = new M68kAddressOperand(uAddr);
                    return(true);

                case 2: // Program counter with displacement
                    var   off = rdr.Address - dasm.instr.Address;
                    short sOffset;
                    if (!rdr.TryReadBeInt16(out sOffset))
                    {
                        op = null; return(false);
                    }
                    off += sOffset;
                    op   = new MemoryOperand(dataWidth, Registers.pc, Constant.Int16((short)off));
                    return(true);

                case 3:
                    // Program counter with index
                    var    addrExt = rdr.Address;
                    ushort extension;
                    if (!rdr.TryReadBeUInt16(out extension))
                    {
                        op = null; return(false);
                    }

                    if (EXT_FULL(extension))
                    {
                        if (EXT_EFFECTIVE_ZERO(extension))
                        {
                            op = new M68kImmediateOperand(Constant.Word32(0));
                            return(true);
                        }
                        Constant @base = null;
                        Constant outer = null;
                        if (EXT_BASE_DISPLACEMENT_PRESENT(extension))
                        {
                            @base = EXT_BASE_DISPLACEMENT_LONG(extension)
                                ? rdr.ReadBe(PrimitiveType.Word32)
                                : rdr.ReadBe(PrimitiveType.Int16);
                        }
                        if (EXT_OUTER_DISPLACEMENT_PRESENT(extension))
                        {
                            outer = EXT_OUTER_DISPLACEMENT_LONG(extension)
                                ? rdr.ReadBe(PrimitiveType.Word32)
                                : rdr.ReadBe(PrimitiveType.Int16);
                        }
                        RegisterStorage base_reg = EXT_BASE_REGISTER_PRESENT(extension)
                            ? Registers.pc
                            : null;
                        RegisterStorage index_reg   = null;
                        PrimitiveType   index_width = null;
                        int             index_scale = 0;
                        if (EXT_INDEX_REGISTER_PRESENT(extension))
                        {
                            index_reg = EXT_INDEX_AR(extension)
                                ? Registers.AddressRegister((int)EXT_INDEX_REGISTER(extension))
                                : Registers.DataRegister((int)EXT_INDEX_REGISTER(extension));
                            index_width = EXT_INDEX_LONG(extension) ? PrimitiveType.Word32 : PrimitiveType.Int16;
                            index_scale = (EXT_INDEX_SCALE(extension) != 0)
                                ? 1 << EXT_INDEX_SCALE(extension)
                                : 0;
                        }
                        op = new IndexedOperand(dataWidth, @base, outer, base_reg, index_reg, index_width, index_scale,
                                                (extension & 7) > 0 && (extension & 7) < 4,
                                                (extension & 7) > 4);
                        return(true);
                    }
                    op = new IndirectIndexedOperand(
                        dataWidth,
                        EXT_8BIT_DISPLACEMENT(extension),
                        Registers.pc,
                        EXT_INDEX_AR(extension)
                            ? Registers.AddressRegister((int)EXT_INDEX_REGISTER(extension))
                            : Registers.DataRegister((int)EXT_INDEX_REGISTER(extension)),
                        EXT_INDEX_LONG(extension)
                            ? PrimitiveType.Word32
                            : PrimitiveType.Int16,
                        1 << EXT_INDEX_SCALE(extension));
                    return(true);

                case 4:
                    //  Immediate
                    if (dataWidth.Size == 1)        // don't want the instruction stream to get misaligned!
                    {
                        rdr.Offset += 1;
                    }
                    Constant coff;
                    if (!rdr.TryReadBe(dataWidth, out coff))
                    {
                        op = null; return(false);
                    }
                    op = new M68kImmediateOperand(coff);
                    return(true);

                default:
                    op = null;
                    return(false);
                }

            default:
                throw new NotImplementedException(string.Format("Address mode {0:X1} not implemented.", addressMode));
            }
        }