private MemoryAccess RewriteMemoryOperand(MemoryOperand memop) { if (memop.Base != null) { Expression baseReg; if (memop.Base == Registers.pc) { baseReg = instr.Address + instr.Length; } else { baseReg = binder.EnsureRegister(memop.Base); } Expression ea = baseReg; if (memop.Index != null) { Expression idx = binder.EnsureRegister(memop.Index); if (idx.DataType.BitSize < ea.DataType.BitSize) { idx = m.Cast(PrimitiveType.UInt16, idx); } ea = m.IAdd(baseReg, idx); } else if (memop.PreIncrement) { m.Assign(ea, m.IAddS(ea, memop.Offset.Value)); } else if (memop.PostIncrement) { var tmp = binder.CreateTemporary(baseReg.DataType); m.Assign(tmp, ea); m.Assign(baseReg, m.IAddS(baseReg, memop.Offset.Value)); ea = tmp; } else { ea = m.IAdd(baseReg, (ushort)memop.Offset.Value); } if (memop.Indirect) { ea = m.Mem(PrimitiveType.Ptr16, ea); } return(m.Mem(memop.Width, ea)); } else { Debug.Assert(memop.Offset != null); return(m.Mem(memop.Width, Address.Ptr16((ushort)memop.Offset.Value))); } }
private Expression RewriteJmpSrc(MachineOperand op) { var memOp = op as MemoryOperand; if (memOp == null) { // PDP-11 always has a memory reference // for the destination of a transfer instruction. return(null); } var r = memOp.Register != null ? binder.EnsureRegister(memOp.Register) : null; var tmp = binder.CreateTemporary(op.Width); switch (memOp.Mode) { default: throw new AddressCorrelatedException( dasm.Current.Address, "Not implemented: addressing mode {0}.", memOp.Mode); case AddressMode.RegDef: return(r); case AddressMode.Absolute: return(Address.Ptr16(memOp.EffectiveAddress)); case AddressMode.AutoIncr: m.Assign(tmp, m.Mem(PrimitiveType.Ptr16, r)); m.Assign(r, m.IAdd(r, memOp.Width.Size)); break; case AddressMode.AutoIncrDef: m.Assign(tmp, m.Mem(op.Width, r)); m.Assign(r, m.IAdd(r, memOp.Width.Size)); break; case AddressMode.AutoDecr: m.Assign(r, m.ISub(r, memOp.Width.Size)); return(m.Mem(op.Width, r)); case AddressMode.AutoDecrDef: m.Assign(r, m.ISub(r, memOp.Width.Size)); m.Assign(tmp, m.Mem(op.Width, m.Mem(PrimitiveType.Ptr16, r))); return(tmp); case AddressMode.Indexed: if (memOp.Register == Registers.pc) { var offset = (short)memOp.EffectiveAddress; var addrBase = (long)instr.Address.ToLinear(); var addr = Address.Ptr16((ushort)(instr.Length + addrBase + offset)); return(addr); } else { return(m.Mem( this.dasm.Current.DataWidth, m.IAdd(r, Constant.Word16(memOp.EffectiveAddress)))); } case AddressMode.IndexedDef: if (memOp.Register == Registers.pc) { var offset = (short)memOp.EffectiveAddress; var addrBase = (long)instr.Address.ToLinear() + instr.Length; var addr = Constant.Word16((ushort)(addrBase + offset)); return(m.Mem( PrimitiveType.Word16, addr)); } else { return(m.Mem( PrimitiveType.Ptr16, m.IAdd(r, Constant.Word16(memOp.EffectiveAddress)))); } } return(tmp); /* * var immOp = op as ImmediateOperand; * if (immOp != null) * { * return immOp.Value; * } * var addrOp = op as AddressOperand; * if (addrOp != null) * { * return addrOp.Address; * } * throw new NotImplementedException(); */ }
} // the data width of the current instruction being rewritten. /// <summary> /// Rewrite operands being used as sources. /// </summary> /// <param name="operand"></param> /// <param name="addrInstr">Address of the current instruction</param> /// <returns></returns> public Expression RewriteSrc(MachineOperand operand, Address addrInstr, bool addressAsAddress = false) { Expression ea; Expression r; switch (operand) { case RegisterOperand reg: r = binder.EnsureRegister(reg.Register); if (DataWidth != null && DataWidth.Size != reg.Width.Size) { if (DataWidth.Domain == Domain.Real) { r = m.Cast(DataWidth, r); } else { r = m.Slice(DataWidth, r, 0); } } return(r); case M68kImmediateOperand imm: if (imm.Width.Domain == Domain.Real) { return(imm.Constant.CloneExpression()); } if (DataWidth != null && DataWidth.BitSize > imm.Width.BitSize) { return(Constant.Create(DataWidth, imm.Constant.ToInt64())); } else { return(Constant.Create(imm.Width, imm.Constant.ToUInt32())); } case MemoryOperand mem: return(RewriteMemoryAccess(mem, DataWidth, addrInstr)); case M68kAddressOperand addr: if (addressAsAddress) { return(addr.Address); } else { return(m.Mem(DataWidth, addr.Address)); } case PredecrementMemoryOperand pre: ea = binder.EnsureRegister(pre.Register); m.Assign(ea, m.ISubS(ea, DataWidth.Size)); return(m.Mem(DataWidth, ea)); case PostIncrementMemoryOperand post: r = binder.EnsureRegister(post.Register); var tmp = binder.CreateTemporary(DataWidth); m.Assign(tmp, m.Mem(DataWidth, r)); m.Assign(r, m.IAddS(r, DataWidth.Size)); return(tmp); case IndirectIndexedOperand indidx: ea = RewriteIndirectBaseRegister(indidx, addrInstr); Expression ix = binder.EnsureRegister(indidx.XRegister); if (indidx.XWidth.Size != 4) { ix = m.Cast(PrimitiveType.Int32, m.Cast(PrimitiveType.Int16, ix)); } if (indidx.Scale > 1) { ix = m.IMul(ix, Constant.Int32(indidx.Scale)); } return(m.Mem(DataWidth, m.IAdd(ea, ix))); case IndexedOperand indop: ea = Combine(indop.BaseDisplacement, indop.Base, addrInstr); if (indop.postindex) { ea = m.Mem32(ea); } if (indop.Index != null) { var idx = Combine(null, indop.Index, addrInstr); if (indop.index_reg_width.BitSize != 32) { idx = m.Cast(PrimitiveType.Word32, m.Cast(PrimitiveType.Int16, idx)); } if (indop.IndexScale > 1) { idx = m.IMul(idx, indop.IndexScale); } ea = Combine(ea, idx); } if (indop.preindex) { ea = m.Mem32(ea); } ea = Combine(ea, indop.OuterDisplacement); return(m.Mem(DataWidth, ea)); } throw new NotImplementedException("Unimplemented RewriteSrc for operand type " + operand.GetType().Name); }
private Expression SrcOp(MachineOperand op, Func <int, int> immediateFn = null) { var regOp = op as RegisterOperand; if (regOp != null) { var id = binder.EnsureRegister(regOp.Register); return(id); } var immOp = op as ImmediateOperand; if (immOp != null) { return(Constant.Word32(immediateFn(immOp.Value.ToInt32()))); } var addrOp = op as AddressOperand; if (addrOp != null) { return(addrOp.Address); } var mem = op as MemoryOperand; if (mem != null) { Identifier reg; switch (mem.mode) { default: throw new NotImplementedException(mem.mode.ToString()); case AddressingMode.Indirect: return(m.Mem(mem.Width, binder.EnsureRegister(mem.reg))); case AddressingMode.IndirectPreDecr: reg = binder.EnsureRegister(mem.reg); m.Assign(reg, m.ISubS(reg, mem.Width.Size)); return(m.Mem(mem.Width, reg)); case AddressingMode.IndirectPostIncr: var t = binder.CreateTemporary(mem.Width); reg = binder.EnsureRegister(mem.reg); m.Assign(t, m.Mem(mem.Width, reg)); m.Assign(reg, m.IAddS(reg, t.DataType.Size)); return(t); case AddressingMode.IndirectDisplacement: reg = binder.EnsureRegister(mem.reg); return(m.Mem( mem.Width, m.IAddS(reg, mem.disp))); case AddressingMode.IndexedIndirect: return(m.Mem(mem.Width, m.IAdd( binder.EnsureRegister(Registers.r0), binder.EnsureRegister(mem.reg)))); case AddressingMode.PcRelativeDisplacement: var addr = instr.Address.ToUInt32(); if (mem.Width.Size == 4) { addr &= ~3u; } addr += (uint)(mem.disp + 4); return(m.Mem(mem.Width, Address.Ptr32(addr))); } } throw new NotImplementedException(op.GetType().Name); }
private Expression RewriteSrcOp(int iOp, PrimitiveType width) { var op = this.instr.Operands[iOp]; switch (op) { case RegisterOperand regOp: var reg = binder.EnsureRegister(regOp.Register); if (reg == null) { return(null); } if (width.Size == 4) { return(reg); } else if (width.Size == 8) { var rHi = arch.GetRegister(1 + (int)reg.Storage.Domain); if (rHi == null) { return(null); } var regHi = binder.EnsureRegister(rHi); return(binder.EnsureSequence(width, regHi.Storage, reg.Storage)); } else if (width.Size == 16) { var regHi1 = binder.EnsureRegister(arch.GetRegister(1 + (int)reg.Storage.Domain)); var regHi2 = binder.EnsureRegister(arch.GetRegister(2 + (int)reg.Storage.Domain)); var regHi3 = binder.EnsureRegister(arch.GetRegister(3 + (int)reg.Storage.Domain)); var regLo = binder.EnsureSequence(PrimitiveType.Word64, regHi1.Storage, reg.Storage); var regHi = binder.EnsureSequence(PrimitiveType.Word64, regHi3.Storage, regHi2.Storage); return(binder.EnsureSequence(width, regHi.Storage, regLo.Storage)); } else { return(m.Cast(width, reg)); } case ImmediateOperand immOp: return(immOp.Value); case MemoryOperand memOp: Expression ea; if (memOp.Base != null) { reg = binder.EnsureRegister(memOp.Base); if (memOp.AutoDecrement) { m.Assign(reg, m.ISub(reg, width.Size)); } else if (memOp.AutoIncrement) { var tmp = binder.CreateTemporary(reg.DataType); m.Assign(tmp, reg); reg = tmp; } ea = reg; if (memOp.Offset != null) { ea = m.IAdd(ea, memOp.Offset); } if (memOp.Index != null) { Expression idx = binder.EnsureRegister(memOp.Index); if (width.Size != 1) { idx = m.IMul(idx, Constant.Int32(width.Size)); } ea = m.IAdd(ea, idx); } Expression load; if (memOp.Deferred) { load = m.Mem(width, m.Mem32(ea)); } else { load = m.Mem(width, ea); } if (memOp.AutoIncrement) { reg = binder.EnsureRegister(memOp.Base); int inc = (memOp.Deferred) ? 4 : width.Size; m.Assign(reg, m.IAdd(reg, inc)); } return(load); } else { ea = arch.MakeAddressFromConstant(memOp.Offset, false); Expression load; if (memOp.Deferred) { load = m.Mem(width, m.Mem32(ea)); } else { load = m.Mem(width, ea); } return(load); } case AddressOperand addrOp: return(addrOp.Address); } throw new NotImplementedException(op.GetType().Name); }
} // the data width of the current instruction being rewritten. /// <summary> /// Rewrite operands being used as sources. /// </summary> /// <param name="operand"></param> /// <param name="addrInstr">Address of the current instruction</param> /// <returns></returns> public Expression RewriteSrc(MachineOperand operand, Address addrInstr, bool addressAsAddress = false) { var reg = operand as RegisterOperand; if (reg != null) { Expression r = binder.EnsureRegister(reg.Register); if (DataWidth != null && DataWidth.Size != reg.Width.Size) { r = m.Cast(DataWidth, r); } return(r); } var imm = operand as M68kImmediateOperand; if (imm != null) { if (imm.Width.Domain == Domain.Real) { return(imm.Constant.CloneExpression()); } if (DataWidth != null && DataWidth.BitSize > imm.Width.BitSize) { return(Constant.Create(DataWidth, imm.Constant.ToInt64())); } else { return(Constant.Create(imm.Width, imm.Constant.ToUInt32())); } } var mem = operand as MemoryOperand; if (mem != null) { return(RewriteMemoryAccess(mem, DataWidth, addrInstr)); } var addr = operand as M68kAddressOperand; if (addr != null) { if (addressAsAddress) { return(addr.Address); } else { return(m.Mem(DataWidth, addr.Address)); } } var pre = operand as PredecrementMemoryOperand; if (pre != null) { var ea = binder.EnsureRegister(pre.Register); m.Assign(ea, m.ISub(ea, m.Int32(DataWidth.Size))); return(m.Mem(DataWidth, ea)); } var post = operand as PostIncrementMemoryOperand; if (post != null) { var r = binder.EnsureRegister(post.Register); var tmp = binder.CreateTemporary(DataWidth); m.Assign(tmp, m.Mem(DataWidth, r)); m.Assign(r, m.IAdd(r, m.Int32(DataWidth.Size))); return(tmp); } var indidx = operand as IndirectIndexedOperand; if (indidx != null) { Expression ea = RewriteIndirectBaseRegister(indidx, addrInstr); Expression ix = binder.EnsureRegister(indidx.XRegister); if (indidx.XWidth.Size != 4) { ix = m.Cast(PrimitiveType.Int32, m.Cast(PrimitiveType.Int16, ix)); } if (indidx.Scale > 1) { ix = m.IMul(ix, Constant.Int32(indidx.Scale)); } return(m.Mem(DataWidth, m.IAdd(ea, ix))); } var indop = operand as IndexedOperand; if (indop != null) { Expression ea = Combine(indop.Base, indop.base_reg); if (indop.postindex) { ea = m.Mem32(ea); } if (indop.index_reg != null) { var idx = Combine(null, indop.index_reg); if (indop.index_reg_width.BitSize != 32) { idx = m.Cast(PrimitiveType.Word32, m.Cast(PrimitiveType.Int16, idx)); } if (indop.index_scale > 1) { idx = m.IMul(idx, indop.index_scale); } ea = Combine(ea, idx); } if (indop.preindex) { ea = m.Mem32(ea); } ea = Combine(ea, indop.outer); return(m.Mem(DataWidth, ea)); } throw new NotImplementedException("Unimplemented RewriteSrc for operand type " + operand.GetType().Name); }