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); }
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)); } }