private MachineOperand AddressRegisterIndirectWithIndex(PrimitiveType dataWidth, ImageReader rdr) { ushort extension = rdr.ReadBeUInt16(); if (EXT_FULL(extension)) { if (M68kDisassembler.EXT_EFFECTIVE_ZERO(extension)) { return new M68kImmediateOperand(Constant.Zero(dataWidth)); } 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(opcode & 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; return new IndexedOperand(dataWidth, @base, outer, base_reg, index_reg, index_reg_width, index_scale, preindex, postindex); } else { return new IndirectIndexedOperand( EXT_8BIT_DISPLACEMENT(extension), Registers.AddressRegister(opcode & 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, EXT_INDEX_SCALE(extension)); } }
private MachineOperand ParseOperandInner(byte addressMode, byte operandBits, PrimitiveType dataWidth, ImageReader rdr) { Constant offset; switch (addressMode) { case 0: // Data register direct. return DataRegisterOperand(operandBits, 0); case 1: // Address register direct return new RegisterOperand(AddressRegister(operandBits, 0)); case 2: // Address register indirect return MemoryOperand.Indirect(dataWidth, AddressRegister(operandBits, 0)); case 3: // Address register indirect with postincrement. return MemoryOperand.PostIncrement(dataWidth, AddressRegister(operandBits, 0)); case 4: // Address register indirect with predecrement. return MemoryOperand.PreDecrement(dataWidth, AddressRegister(operandBits, 0)); case 5: // Address register indirect with displacement. offset = Constant.Int16(rdr.ReadBeInt16()); return MemoryOperand.Indirect(dataWidth, AddressRegister(operandBits, 0), offset); case 6: // Address register indirect with index return AddressRegisterIndirectWithIndex(dataWidth, rdr); case 7: switch (operandBits) { case 0: // Absolute short address return new M68kAddressOperand(rdr.ReadBeUInt16()); case 1: // Absolute long address return new M68kAddressOperand(rdr.ReadBeUInt32()); case 2: // Program counter with displacement var off = rdr.Address - dasm.instr.Address; off += rdr.ReadBeInt16(); return new MemoryOperand(dataWidth, Registers.pc, Constant.Int16((short) off)); case 3: // Program counter with index var addrExt = rdr.Address; ushort extension = rdr.ReadBeUInt16(); if (EXT_FULL(extension)) { if (EXT_EFFECTIVE_ZERO(extension)) { return new M68kImmediateOperand(Constant.Word32(0)); } 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; } return new IndexedOperand(dataWidth, @base, outer, base_reg, index_reg, index_width, index_scale, (extension & 7) > 0 && (extension & 7) < 4, (extension & 7) > 4); } return new IndirectIndexedOperand( 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)); case 4: // Immediate if (dataWidth.Size == 1) // don't want the instruction stream to get misaligned! rdr.ReadByte(); return new M68kImmediateOperand(rdr.ReadBe(dataWidth)); default: throw new NotImplementedException(string.Format("Address mode {0}:{1} not implemented.", addressMode, operandBits)); } default: throw new NotImplementedException(string.Format("Address mode {0:X1} not implemented.", addressMode)); } }
private static M68kImmediateOperand GetImmediate(ImageReader rdr, PrimitiveType type) { if (type.Size == 1) { rdr.ReadByte(); // skip a byte so we get the appropriate lsb byte and align the word stream. } return new M68kImmediateOperand(rdr.ReadBe(type)); }