private bool TryPcRelative(ImageReader rdr, ushort opcode, out MachineOperand op)
        {
            var addr   = rdr.Address;
            int offset = opcode & 0xFF;

            if (offset == 0xFF)
            {
                if (!rdr.TryReadBeInt32(out offset))
                {
                    op = null;
                    return(false);
                }
            }
            else if (offset == 0x00)
            {
                short sOffset;
                if (!rdr.TryReadBeInt16(out sOffset))
                {
                    op = null;
                    return(false);
                }
                offset = sOffset;
            }
            else
            {
                offset = (sbyte)offset;
            }
            op = new M68kAddressOperand(addr + offset);
            return(true);
        }
Exemple #2
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);
        }
Exemple #3
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));
            }
        }
        /// <summary>
        /// Attempts to decode an operand.
        /// </summary>
        /// <param name="rdr"></param>
        /// <param name="args"></param>
        /// <param name="dataWidth"></param>
        /// <param name="op"></param>
        /// <returns>If true, either no more operands are needed, or an
        /// operand was fetched sucessfully. If false, the operand was
        /// invalid, either due to a bad encoding or because the reader read
        /// off the end of the memory area.
        /// </returns>
        public bool TryGetOperand(EndianImageReader rdr, string args, PrimitiveType dataWidth, out MachineOperand op)
        {
            if (i >= args.Length)
            {
                op = null; return(true);
            }
            for (; ;)
            {
                if (args[i] == ',')
                {
                    ++i;
                }
                Address addr;
                switch (args[i++])
                {
                case 'A':   // Address register A0-A7 encoded in in instrution
                    op = new RegisterOperand(AddressRegister(opcode, GetOpcodeOffset(args[i++])));
                    return(true);

                case 'c':   // CCR register
                    op = new RegisterOperand(Registers.ccr);
                    return(true);

                case 'D':   // Data register D0-D7 encoded in instruction
                    op = DataRegisterOperand(opcode, GetOpcodeOffset(args[i++]));
                    return(true);

                case 'E':   // Effective address (EA)
                    return(TryParseOperand(opcode, GetOpcodeOffset(args[i++]), dataWidth, rdr, out op));

                case 'e':   // Effective address with 3-bit halves swapped
                    return(TryParseSwappedOperand(opcode, GetOpcodeOffset(args[i++]), dataWidth, rdr, out op));

                case 'I':   // Immediate operand
                    return(TryGetImmediate(rdr, GetSizeType(0, args[i++], dataWidth), out op));

                case 'J':   // PC Relative jump
                    return(TryPcRelative(rdr, opcode, out op));

                case 'M':   // Register bitset
                    var size = GetSizeType(0, args[i++], dataWidth);
                    op = new RegisterSetOperand(rdr.ReadBeUInt16(), size);
                    return(true);

                case 'n':   // cache bitset
                    bitSet = rdr.ReadBeUInt16();
                    break;

                case 'm':   // Register bitset reversed
                    size = GetSizeType(0, args[i++], dataWidth);
                    op   = RegisterSetOperand.CreateReversed(bitSet, size);
                    return(true);

                case 'q':   // "Small" quick constant (3-bit part of the opcode)
                    op = GetQuickImmediate(GetOpcodeOffset(args[i++]), 0x07, 8, PrimitiveType.Byte);
                    return(true);

                case 'Q':   // "Large" quick constant (8-bit part of the opcode)
                    op = GetQuickImmediate(GetOpcodeOffset(args[i++]), 0xFF, 0, PrimitiveType.SByte);
                    return(true);

                case 'R': // relative
                    addr = rdr.Address;
                    int relative = 0;
                    switch (args[i++])
                    {
                    case 'w': relative = rdr.ReadBeInt16(); break;

                    case 'l': relative = rdr.ReadBeInt32(); break;

                    default: throw new NotImplementedException();
                    }
                    op = new M68kAddressOperand(addr + relative);
                    return(true);

                case 's':   // SR register
                    op = new RegisterOperand(Registers.sr);
                    return(true);

                case '+':   // Postincrement operator; following character specifies bit offset of the address register code.
                    op = new PostIncrementMemoryOperand(dataWidth, AddressRegister(opcode, GetOpcodeOffset(args[i++])));
                    return(true);

                case '-':   // Predecrement operator; following character specifies bit offset of the address register code.
                    op = new PredecrementMemoryOperand(dataWidth, AddressRegister(opcode, GetOpcodeOffset(args[i++])));
                    return(true);

                default: throw new FormatException(string.Format("Unknown argument type {0}.", args[--i]));
                }
            }
        }