private void RewriteMem(int iOp, Expression src, Action <Expression, Expression> write, Expression?seg) { var op = instr.Operands[iOp]; var mop = (MemoryOperand)op; var baseReg = binder.EnsureRegister(mop.Base !); Expression ea = baseReg; if (mop.PreDecrement) { m.Assign(baseReg, m.ISubS(baseReg, 1)); } else if (mop.Displacement != 0) { ea = m.IAddS(ea, mop.Displacement); } Expression val; if (seg != null) { val = m.SegMem(mop.Width, seg, ea); } else { val = m.Mem(mop.Width, ea); } write(val, src); if (mop.PostIncrement) { m.Assign(baseReg, m.IAddS(baseReg, 1)); } }
private Expression Mem(MemoryOperand mem) { Expression ea; if (mem.Base != null) { var baseReg = binder.EnsureRegister(mem.Base); ea = baseReg; if (mem.Predecrement) { m.Assign(baseReg, m.ISubS(baseReg, mem.Width.Size)); } if (mem.Offset != 0) { ea = m.IAdd(ea, mem.Offset); } if (mem.Postincrement) { m.Assign(baseReg, m.IAddS(baseReg, mem.Width.Size)); } } else { ea = Address.Ptr16((ushort)mem.Offset); } return(m.Mem(mem.Width, ea)); }
private void Push(RegisterStorage stackRegister, RegisterStorage reg) { var sp = binder.EnsureRegister(stackRegister); m.Assign(sp, m.ISubS(sp, reg.DataType.Size)); m.Assign(m.Mem(reg.DataType, sp), binder.EnsureRegister(reg)); }
private Expression SrcOp(MachineOperand op, Func <int, int>?immediateFn = null) { switch (op) { case RegisterOperand regOp: var id = binder.EnsureRegister(regOp.Register); return(id); case ImmediateOperand immOp: return(Constant.Word32(immediateFn !(immOp.Value.ToInt32()))); case AddressOperand addrOp: return(addrOp.Address); case MemoryOperand mem: 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 void RewriteAllocFrame(MachineOperand opImm) { var ea = binder.CreateTemporary(PrimitiveType.Ptr32); m.Assign(ea, m.ISubS(binder.EnsureRegister(Registers.sp), 8)); m.Assign(m.Mem32(ea), binder.EnsureRegister(Registers.fp)); m.Assign(m.Mem32(m.IAddS(ea, 4)), binder.EnsureRegister(Registers.lr)); m.Assign(binder.EnsureRegister(Registers.fp), ea); m.Assign(binder.EnsureRegister(Registers.sp), m.ISubS(ea, ((ImmediateOperand)opImm).Value.ToInt32())); }
private void RewritePush() { var sp = binder.EnsureRegister(Registers.sp); m.Assign(sp, m.ISubS(sp, 2)); var src = RewriteSrc(instr.Operands[0]); if (src.DataType.BitSize < 16) { src = m.Cast(PrimitiveType.Word16, src); } m.Assign(m.Mem16(sp), src); }
private void Push(Identifier reg) { var s = binder.EnsureRegister(arch.StackRegister); m.Assign(s, m.ISubS(s, 1)); m.Assign(m.Mem8(s), reg); }
private void RewritePsh(RegisterStorage reg) { var val = binder.EnsureRegister(reg); var sp = binder.EnsureRegister(Registers.sp); m.Assign(sp, m.ISubS(sp, (short)val.DataType.Size)); m.Assign(m.Mem(val.DataType, sp), val); }
private Expression OpSrc(MachineOperand op) { switch (op) { case RegisterOperand reg: return(binder.EnsureRegister(reg.Register)); case ImmediateOperand imm: return(imm.Value); case MemoryOperand mem: Expression ea; if (mem.Base != null) { var regBase = binder.EnsureRegister(mem.Base); if (mem.PostIncrement) { ea = binder.CreateTemporary(regBase.DataType); m.Assign(ea, regBase); } else if (mem.PreDecrement) { m.Assign(regBase, m.ISubS(regBase, mem.Width.Size)); ea = regBase; } else { ea = m.AddSubSignedInt(regBase, mem.Offset); } } else { ea = Address.Ptr16((ushort)mem.Offset); } return(m.Mem(mem.Width ?? (DataType)VoidType.Instance, ea)); } throw new NotImplementedException(); }
private void RewriteCp(Func <Expression, Expression, Expression> incDec, bool repeat) { var addr = dasm.Current.Address; var a = binder.EnsureRegister(Registers.a); var bc = binder.EnsureRegister(Registers.bc); var hl = binder.EnsureRegister(Registers.hl); var z = FlagGroup(FlagM.ZF); m.Assign(z, m.Cond(m.ISub(a, m.Mem8(hl)))); m.Assign(hl, incDec(hl, m.Int16(1))); m.Assign(bc, m.ISubS(bc, 1)); if (repeat) { m.BranchInMiddleOfInstruction(m.Eq0(bc), addr + dasm.Current.Length, InstrClass.ConditionalTransfer); m.Branch(m.Test(ConditionCode.NE, z), addr, InstrClass.ConditionalTransfer); } }
public IEnumerator <RtlInstructionCluster> GetEnumerator() { while (dasm.MoveNext()) { this.instr = dasm.Current; var instrs = new List <RtlInstruction>(); this.m = new RtlEmitter(instrs); this.iclass = dasm.Current.InstructionClass; switch (instr.Mnemonic) { case Mnemonic.invalid: m.Invalid(); break; case Mnemonic.brk: case Mnemonic.cmps: case Mnemonic.movs: case Mnemonic.retb: case Mnemonic.stop: default: EmitUnitTest(); this.iclass = InstrClass.Invalid; m.Invalid(); break; case Mnemonic.add: RewriteAdd(); break; case Mnemonic.addc: RewriteAddcSubc(m.IAdd); break; case Mnemonic.addw: RewriteAddw(); break; case Mnemonic.and: RewriteLogical(m.And); break; case Mnemonic.and1: RewriteLogical1(m.And); break; case Mnemonic.bc: RewriteBranch(ConditionCode.ULT, C()); break; case Mnemonic.bf: RewriteBf(); break; case Mnemonic.bh: RewriteBranch(ConditionCode.UGT, CZ()); break; case Mnemonic.bnc: RewriteBranch(ConditionCode.UGE, C()); break; case Mnemonic.bnh: RewriteBranch(ConditionCode.ULE, CZ()); break; case Mnemonic.bnz: RewriteBranch(ConditionCode.NE, Z()); break; case Mnemonic.br: RewriteBr(); break; case Mnemonic.bt: RewriteBt(); break; case Mnemonic.btclr: RewriteBtclr(); break; case Mnemonic.bz: RewriteBranch(ConditionCode.EQ, Z()); break; case Mnemonic.call: RewriteCall(); break; case Mnemonic.callt: RewriteCall(); break; case Mnemonic.clr1: RewriteClr1(); break; case Mnemonic.clrb: RewriteClr(PrimitiveType.Byte); break; case Mnemonic.clrw: RewriteClr(PrimitiveType.Word16); break; case Mnemonic.cmp: RewriteCmp(); break; case Mnemonic.cmp0: RewriteCmp0(); break; case Mnemonic.cmpw: RewriteCmp(); break; case Mnemonic.dec: RewriteIncDec((a, b) => m.ISubS(a, 1)); break; case Mnemonic.decw: RewriteIncwDecw((a, b) => m.ISubS(a, 1)); break; case Mnemonic.halt: RewriteHalt(); break; case Mnemonic.inc: RewriteIncDec((a, b) => m.IAddS(a, 1)); break; case Mnemonic.incw: RewriteIncwDecw((a, b) => m.IAddS(a, 1)); break; case Mnemonic.mov: RewriteMov(); break; case Mnemonic.mov1: RewriteMov1(); break; case Mnemonic.movw: RewriteMov(); break; case Mnemonic.mulu: RewriteMulu(); break; case Mnemonic.oneb: RewriteOne(PrimitiveType.Byte); break; case Mnemonic.onew: RewriteOne(PrimitiveType.Word16); break; case Mnemonic.or: RewriteLogical(m.Or); break; case Mnemonic.or1: RewriteLogical1(m.Or); break; case Mnemonic.nop: m.Nop(); break; case Mnemonic.not1: RewriteNot1(); break; case Mnemonic.pop: RewritePop(); break; case Mnemonic.push: RewritePush(); break; case Mnemonic.ret: RewriteRet(); break; case Mnemonic.reti: RewriteRet(); break; case Mnemonic.rol: RewriteRotate(PseudoProcedure.Rol); break; case Mnemonic.rolc: RewriteRotateC(PseudoProcedure.RolC); break; case Mnemonic.rolwc: RewriteRotateC(PseudoProcedure.RolC); break; case Mnemonic.ror: RewriteRotate(PseudoProcedure.Ror); break; case Mnemonic.rorc: RewriteRotate(PseudoProcedure.RorC); break; case Mnemonic.sar: RewriteShift(m.Sar); break; case Mnemonic.sarw: RewriteShiftw(m.Sar); break; case Mnemonic.sel: RewriteSel(); break; case Mnemonic.set1: RewriteSet1(); break; case Mnemonic.shl: RewriteShift(m.Shl); break; case Mnemonic.shlw: RewriteShiftw(m.Shl); break; case Mnemonic.shr: RewriteShift(m.Shr); break; case Mnemonic.shrw: RewriteShiftw(m.Shr); break; case Mnemonic.skc: RewriteSkip(ConditionCode.ULT, C()); break; case Mnemonic.skh: RewriteSkip(ConditionCode.UGT, CZ()); break; case Mnemonic.sknc: RewriteSkip(ConditionCode.UGE, C()); break; case Mnemonic.sknh: RewriteSkip(ConditionCode.ULE, CZ()); break; case Mnemonic.sknz: RewriteSkip(ConditionCode.NE, Z()); break; case Mnemonic.skz: RewriteSkip(ConditionCode.EQ, Z()); break; case Mnemonic.sub: RewriteSub(); break; case Mnemonic.subc: RewriteAddcSubc(m.ISub); break; case Mnemonic.subw: RewriteSubw(); break; case Mnemonic.xch: RewriteXch(); break; case Mnemonic.xchw: RewriteXch(); break; case Mnemonic.xor: RewriteLogical(m.Xor); break; case Mnemonic.xor1: RewriteLogical1(m.Xor); break; } yield return(m.MakeCluster(instr.Address, instr.Length, iclass)); } }
} // 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> 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.Convert(r, r.DataType, DataWidth); } else { r = m.Slice(DataWidth, r, 0); } } return(r); case M68kImmediateOperand imm: if (imm.Width.IsReal) { 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.Slice(PrimitiveType.Int16, ix, 0); ix = m.Convert(ix, PrimitiveType.Int16, PrimitiveType.Int32); } 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.Convert(m.Slice(PrimitiveType.Int16, idx, 0), PrimitiveType.Int16, PrimitiveType.Int32); } 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); }
} // 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.ISubS(ea, 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.IAddS(r, 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); }
private Expression Dec(Expression e) { return(m.ISubS(e, 1)); }