private void EmitLoad(Identifier dst, MemoryAccess src) { if (src.DataType.BitSize < dst.DataType.BitSize) { var tmp = binder.CreateTemporary(src.DataType); m.Assign(tmp, src); m.Assign(dst, m.Cast(dst.DataType, tmp)); } else { m.Assign(dst, src); } }
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 void RewriteLoad(MipsInstruction instr, PrimitiveType dt) { var src = Rewrite(instr.Operands[1]); var dst = Rewrite(instr.Operands[0]); src.DataType = dt; if (dst.DataType.Size != src.DataType.Size) { // If the source is smaller than the destination register, // perform a sign/zero extension/conversion. src = m.Cast(arch.WordWidth, src); } m.Assign(dst, src); }
private void RewriteLoad(MipsInstruction instr) { var opSrc = RewriteOperand(instr.op2); var opDst = RewriteOperand(instr.op1); emitter.Assign(opDst, emitter.Cast(arch.WordWidth, opSrc)); }
private void AssignToRegister(Identifier idDst, Expression src) { if (arch.WordWidth.BitSize == 64 && idDst.Storage.BitSize == 32) { var reg = (RegisterStorage)idDst.Storage; idDst = frame.EnsureRegister(Registers.Gp64BitRegisters[reg.Number]); src = m.Cast(PrimitiveType.UInt64, src); } m.Assign(idDst, src); }
private void RewriteSxt(string flags) { var src = RewriteOp(instr.Operands[0]); var tmp = binder.CreateTemporary(PrimitiveType.Byte); m.Assign(tmp, m.Slice(PrimitiveType.Byte, src, 0)); var dst = RewriteDst(instr.Operands[0], tmp, (a, b) => m.Cast(PrimitiveType.Int16, b)); EmitCc(dst, flags); }
private Expression RewriteSrc(MachineOperand op) { switch (op) { case RegisterOperand reg: return(binder.EnsureRegister(reg.Register)); case AddressOperand addr: return(addr.Address); case ImmediateOperand imm: return(imm.Value); case MemoryOperand mem: Expression ea; if (mem.Base != null) { ea = binder.EnsureRegister(mem.Base); if (mem.Index != null) { var idx = binder.EnsureRegister(mem.Index); ea = m.IAdd( ea, m.Cast(PrimitiveType.Int16, idx)); } else if (mem.Offset != null) { ea = m.IAdd( ea, m.Int16((sbyte)mem.Offset.ToByte())); } } else { ea = arch.MakeAddressFromConstant(mem.Offset, false); } var tmp = binder.CreateTemporary(mem.Width); m.Assign(tmp, m.Mem(mem.Width, ea)); return(tmp); } throw new NotImplementedException(op.GetType().Name); }
private Expression Operand(MachineOperand op) { switch (op) { case RegisterOperand rop: return(binder.EnsureRegister(rop.Register)); case ImmediateOperand imm: return(imm.Value); case MemoryOperand mem: Expression ea; if (mem.Address != null) { if (mem.Register != null) { ea = m.IAdd( mem.Address, m.Cast(PrimitiveType.UInt16, binder.EnsureRegister(mem.Register))); } else { ea = mem.Address; } } else { ea = RegisterPair(mem.Register); } return(m.Mem(mem.Width, ea)); case AddressOperand addr: return(addr.Address); default: throw new NotImplementedException(op.GetType().Name); } }
private void RewriteAddw() { var src = RewriteSrc(instr.Operands[1]); Func <Expression, Expression, Expression> fn; if (src.DataType.Size < instr.Operands[0].Width.Size) { if (src is Constant c) { fn = (a, b) => m.IAddS(a, c.ToInt32()); } else { fn = (a, b) => m.IAdd(a, m.Cast(PrimitiveType.Word16, b)); } } else { fn = m.IAdd; } var dst = RewriteDst(instr.Operands[0], src, fn); EmitCond(dst, CZ()); }
private void RewriteExt(H8Instruction instr, Domain domain) { var dstRange = new BitRange(0, instr.Size !.BitSize); var srcRange = new BitRange(0, instr.Size !.BitSize / 2); var dt = PrimitiveType.Create(domain, dstRange.Extent); var dst = (Identifier)OpSrc(instr.Operands[0]); var src = binder.EnsureRegister(arch.GetRegister( dst.Storage.Domain, srcRange) !); m.Assign(dst, m.Cast(dt, src)); EmitCond(Z, dst); m.Assign(binder.EnsureFlagGroup(N), Constant.False()); m.Assign(binder.EnsureFlagGroup(V), Constant.False()); }
private void AssignToRegister(Identifier idDst, Expression src) { if (arch.WordWidth.BitSize == 64 && idDst.Storage.BitSize == 32) { // Special case for X86-64: assignments to the 32-bit LSB of a // GP register clear the high bits of that register. We model // this zero-extending the register to 64 bits. We rely on later // stages of decompilation to clean this up. //$REVIEW: Arguably, this could be done better by clearing // the whole 64-bit register, then overwriting the bottom 32 bits. var reg = (RegisterStorage)idDst.Storage; idDst = binder.EnsureRegister(Registers.Gp64BitRegisters[reg.Number]); src = m.Cast(PrimitiveType.UInt64, src); } m.Assign(idDst, src); }
public IEnumerator <RtlInstructionCluster> GetEnumerator() { while (instrs.MoveNext()) { var instr = instrs.Current; this.rtlCluster = new RtlInstructionCluster(instr.Address, instr.Length); this.rtlCluster.Class = RtlClass.Linear; emitter = new RtlEmitter(rtlCluster.Instructions); Expression src; Expression dst; switch (instr.Opcode) { default: throw new AddressCorrelatedException( instr.Address, "Rewriting of PDP-11 instruction {0} not supported yet.", instr.Opcode); case Opcodes.clrb: dst = RewriteDst(instr.op1, emitter.Byte(0), s => s); SetFlags(dst, 0, FlagM.NF | FlagM.CF | FlagM.VF, FlagM.ZF); break; case Opcodes.mov: src = RewriteSrc(instr.op1); dst = RewriteDst(instr.op2, src, s => s); SetFlags(dst, FlagM.ZF | FlagM.NF, FlagM.VF, 0); break; case Opcodes.movb: src = RewriteSrc(instr.op1); dst = RewriteDst(instr.op2, src, s => emitter.Cast(PrimitiveType.Int16, s)); SetFlags(dst, FlagM.ZF | FlagM.NF, FlagM.VF, 0); break; case Opcodes.xor: src = RewriteSrc(instr.op1); dst = RewriteDst(instr.op2, src, (s, d) => emitter.Xor(d, s)); SetFlags(dst, FlagM.ZF | FlagM.NF, FlagM.CF | FlagM.VF, 0); break; } yield return(rtlCluster); } }
private void RewriteExt(PrimitiveType width) { var src = SrcOp(instr.Operands[0], null); var dst = DstOp(instr.Operands[1], src, (a, b) => m.Cast(width, b)); }
} // 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); }
private Expression RewriteSrcOp(int iOp, PrimitiveType width) { var op = dasm.Current.Operands[iOp]; var regOp = op as RegisterOperand; if (regOp != null) { var reg = frame.EnsureRegister(regOp.Register); if (width.Size == 4) { return(reg); } else if (width.Size == 8) { var regHi = frame.EnsureRegister(arch.GetRegister(1 + (int)reg.Storage.Domain)); return(frame.EnsureSequence(regHi.Storage, reg.Storage, width)); } else if (width.Size == 16) { var regHi1 = frame.EnsureRegister(arch.GetRegister(1 + (int)reg.Storage.Domain)); var regHi2 = frame.EnsureRegister(arch.GetRegister(2 + (int)reg.Storage.Domain)); var regHi3 = frame.EnsureRegister(arch.GetRegister(3 + (int)reg.Storage.Domain)); var regLo = frame.EnsureSequence(regHi1.Storage, reg.Storage, PrimitiveType.Word64); var regHi = frame.EnsureSequence(regHi3.Storage, regHi2.Storage, PrimitiveType.Word64); return(frame.EnsureSequence(regHi.Storage, regLo.Storage, width)); } else { return(emitter.Cast(width, reg)); } } var immOp = op as ImmediateOperand; if (immOp != null) { return(immOp.Value); } var memOp = op as MemoryOperand; if (memOp != null) { Expression ea; if (memOp.Base != null) { var reg = frame.EnsureRegister(memOp.Base); if (memOp.AutoDecrement) { emitter.Assign(reg, emitter.ISub(reg, width.Size)); } else if (memOp.AutoIncrement) { var tmp = frame.CreateTemporary(reg.DataType); emitter.Assign(tmp, reg); reg = tmp; } ea = reg; if (memOp.Offset != null) { ea = emitter.IAdd(ea, memOp.Offset); } if (memOp.Index != null) { Expression idx = frame.EnsureRegister(memOp.Index); if (width.Size != 1) { idx = emitter.IMul(idx, Constant.Int32(width.Size)); } ea = emitter.IAdd(ea, idx); } Expression load; if (memOp.Deferred) { load = emitter.Load(width, emitter.LoadDw(ea)); } else { load = emitter.Load(width, ea); } if (memOp.AutoIncrement) { if (memOp.AutoIncrement) { reg = frame.EnsureRegister(memOp.Base); int inc = (memOp.Deferred) ? 4 : width.Size; emitter.Assign(reg, emitter.IAdd(reg, inc)); } } return(load); } else { } } var addrOp = op as AddressOperand; if (addrOp != null) { return(addrOp.Address); } throw new NotImplementedException(op.GetType().Name); }
public IEnumerator <RtlInstructionCluster> GetEnumerator() { while (dasm.MoveNext()) { this.instr = dasm.Current; this.iclass = InstrClass.Linear; var instrs = new List <RtlInstruction>(); this.m = new RtlEmitter(instrs); switch (instr.Mnemonic) { default: host.Error( dasm.Current.Address, string.Format( "SuperH instruction {0} not supported yet.", dasm.Current.Mnemonic)); EmitUnitTest(); goto case Mnemonic.invalid; case Mnemonic.invalid: Invalid(); break; case Mnemonic.add: RewriteBinOp(m.IAdd, n => (sbyte)n); break; case Mnemonic.addc: RewriteAddcSubc(m.IAdd); break; case Mnemonic.addv: RewriteAddv(m.IAdd); break; case Mnemonic.and: RewriteBinOp(m.And, n => (byte)n); break; case Mnemonic.and_b: RewriteBinOp(m.And, n => (byte)n); break; case Mnemonic.bf: RewriteBranch(false, false); break; case Mnemonic.bf_s: RewriteBranch(false, true); break; case Mnemonic.bra: RewriteGoto(); break; case Mnemonic.braf: RewriteBraf(); break; case Mnemonic.brk: RewriteBrk(); break; case Mnemonic.bsr: RewriteBsr(); break; case Mnemonic.bsrf: RewriteBsrf(); break; case Mnemonic.bt: RewriteBranch(true, false); break; case Mnemonic.bt_s: RewriteBranch(true, true); break; case Mnemonic.clrmac: RewriteClr(Registers.mac); break; case Mnemonic.clrs: RewriteClrtSet(Registers.S, Constant.False()); break; case Mnemonic.clrt: RewriteClrtSet(Registers.T, Constant.False()); break; case Mnemonic.cmp_eq: RewriteCmp(m.Eq); break; case Mnemonic.cmp_ge: RewriteCmp(m.Ge); break; case Mnemonic.cmp_gt: RewriteCmp(m.Gt); break; case Mnemonic.cmp_hs: RewriteCmp(m.Uge); break; case Mnemonic.cmp_hi: RewriteCmp(m.Ugt); break; case Mnemonic.cmp_pl: RewriteCmp0(m.Gt0); break; case Mnemonic.cmp_pz: RewriteCmp0(m.Ge0); break; case Mnemonic.cmp_str: RewriteCmpStr(); break; case Mnemonic.div0s: RewriteDiv0s(); break; case Mnemonic.div0u: RewriteDiv0u(); break; case Mnemonic.div1: RewriteDiv1(); break; case Mnemonic.dmuls_l: RewriteDmul(m.SMul); break; case Mnemonic.dmulu_l: RewriteDmul(m.UMul); break; case Mnemonic.dt: RewriteDt(); break; case Mnemonic.exts_b: RewriteExt(PrimitiveType.SByte); break; case Mnemonic.exts_w: RewriteExt(PrimitiveType.Int16); break; case Mnemonic.extu_b: RewriteExt(PrimitiveType.Byte); break; case Mnemonic.extu_w: RewriteExt(PrimitiveType.UInt16); break; case Mnemonic.fabs: RewriteFabs(); break; case Mnemonic.fadd: RewriteBinOp(m.FAdd, null); break; case Mnemonic.fcmp_eq: RewriteCmp(m.FEq); break; case Mnemonic.fcmp_gt: RewriteCmp(m.FGt); break; case Mnemonic.fcnvds: RewriteUnary(d => m.Cast(PrimitiveType.Real32, d)); break; case Mnemonic.fcnvsd: RewriteUnary(d => m.Cast(PrimitiveType.Real64, d)); break; case Mnemonic.fdiv: RewriteBinOp(m.FDiv, null); break; case Mnemonic.fldi0: RewriteFldi(0.0F); break; case Mnemonic.fldi1: RewriteFldi(1.0F); break; case Mnemonic.flds: RewriteMov(); break; case Mnemonic.fmac: RewriteFmac(); break; case Mnemonic.fmov_d: RewriteMov(); break; case Mnemonic.fmov_s: RewriteMov(); break; case Mnemonic.jmp: RewriteJmp(); break; case Mnemonic.jsr: RewriteJsr(); break; case Mnemonic.lds: RewriteMov(); break; case Mnemonic.lds_l: RewriteMov(); break; case Mnemonic.mac_l: RewriteMac(PrimitiveType.Int64); break; case Mnemonic.mac_w: RewriteMac(PrimitiveType.Int32); break; case Mnemonic.mov: RewriteMov(); break; case Mnemonic.mova: RewriteMova(); break; case Mnemonic.mov_b: RewriteMov(); break; case Mnemonic.mov_w: RewriteMov(); break; case Mnemonic.mov_l: RewriteMov(); break; case Mnemonic.movt: RewriteMovt(); break; case Mnemonic.mul_l: RewriteMul_l(); break; case Mnemonic.muls_w: RewriteMul_w(PrimitiveType.Int16, m.SMul); break; case Mnemonic.mulu_w: RewriteMul_w(PrimitiveType.UInt16, m.UMul); break; case Mnemonic.neg: RewriteUnary(m.Neg); break; case Mnemonic.negc: RewriteNegc(); break; case Mnemonic.not: RewriteUnary(m.Comp); break; case Mnemonic.nop: m.Nop(); break; case Mnemonic.ocbi: RewriteOcbi(); break; case Mnemonic.or: RewriteBinOp(m.Or, u => (byte)u); break; case Mnemonic.rotcl: RewriteRotc(PseudoProcedure.RolC); break; case Mnemonic.rotcr: RewriteRotc(PseudoProcedure.RorC); break; case Mnemonic.rotl: RewriteRot(PseudoProcedure.Rol); break; case Mnemonic.rotr: RewriteRot(PseudoProcedure.Ror); break; case Mnemonic.rts: RewriteRts(); break; case Mnemonic.sett: RewriteClrtSet(Registers.T, Constant.True()); break; case Mnemonic.shad: RewriteShd(m.Shl, m.Sar); break; case Mnemonic.shar: RewriteShift(m.Sar, 1); break; case Mnemonic.shld: RewriteShd(m.Shl, m.Shr); break; case Mnemonic.shll: RewriteShift(m.Shl, 1); break; case Mnemonic.shll2: RewriteShift(m.Shl, 2); break; case Mnemonic.shll8: RewriteShift(m.Shl, 8); break; case Mnemonic.shll16: RewriteShift(m.Shl, 16); break; case Mnemonic.shlr: RewriteShift(m.Shr, 1); break; case Mnemonic.shlr2: RewriteShift(m.Shr, 2); break; case Mnemonic.shlr8: RewriteShift(m.Shr, 8); break; case Mnemonic.shlr16: RewriteShift(m.Shr, 16); break; case Mnemonic.stc: RewriteMov(); break; case Mnemonic.sts: RewriteMov(); break; case Mnemonic.sts_l: RewriteMov(); break; case Mnemonic.sub: RewriteBinOp(m.ISub, null); break; case Mnemonic.subc: RewriteAddcSubc(m.ISub); break; case Mnemonic.swap_w: RewriteSwapW(); break; case Mnemonic.tst: RewriteTst(); break; case Mnemonic.xor: RewriteBinOp(m.Xor, n => (byte)n); break; case Mnemonic.xtrct: RewriteXtrct(); break; } yield return(m.MakeCluster(instr.Address, instr.Length, this.iclass)); } }
private void RewriteOp( Storage rDst, Func <Func <Expression, Expression, Expression>, Expression, Expression, MemoryOperand, Expression> memFn, Func <Expression, Expression, Expression> bin, Action <Expression> genFlags) { Expression dst = rDst != null?binder.EnsureIdentifier(rDst) : null; Expression tmp; switch (instr.Operands[0]) { case RegisterOperand reg: tmp = binder.EnsureRegister(reg.Register); m.Assign(tmp, bin(dst, tmp)); break; case ImmediateOperand imm: m.Assign(dst, bin(dst, imm.Value)); tmp = dst; break; case MemoryOperand mem: Expression ea; Expression idx; switch (mem.AccessMode) { case MemoryOperand.Mode.AccumulatorOffset: ea = binder.EnsureRegister(mem.Base); idx = binder.EnsureRegister(mem.Index); if (idx.DataType.BitSize < ea.DataType.BitSize) { idx = m.Cast(PrimitiveType.Int16, idx); } ea = m.IAdd(ea, idx); tmp = memFn(bin, dst, ea, mem); break; case MemoryOperand.Mode.ConstantOffset: if (mem.Base == null) { ea = Address.Ptr16((ushort)mem.Offset); } else if (mem.Base == Registers.PCR) { ea = instr.Address + (instr.Length + mem.Offset); } else { ea = binder.EnsureRegister(mem.Base); ea = m.AddSubSignedInt(ea, mem.Offset); } tmp = memFn(bin, dst, ea, mem); break; case MemoryOperand.Mode.Direct: ea = m.IAdd(binder.EnsureRegister(Registers.DP), Constant.Word16((byte)mem.Offset)); tmp = memFn(bin, dst, ea, mem); break; case MemoryOperand.Mode.PostInc1: ea = binder.EnsureRegister(mem.Base); tmp = memFn(bin, dst, ea, mem); m.Assign(ea, m.IAddS(ea, 1)); break; case MemoryOperand.Mode.PostInc2: ea = binder.EnsureRegister(mem.Base); tmp = memFn(bin, dst, ea, mem); m.Assign(ea, m.IAddS(ea, 2)); break; case MemoryOperand.Mode.PreDec1: ea = binder.EnsureRegister(mem.Base); m.Assign(ea, m.ISubS(ea, 1)); tmp = memFn(bin, dst, ea, mem); break; case MemoryOperand.Mode.PreDec2: ea = binder.EnsureRegister(mem.Base); m.Assign(ea, m.ISubS(ea, 2)); tmp = memFn(bin, dst, ea, mem); break; default: throw new NotImplementedException($"Unimplemented access mode {mem.AccessMode.ToString()}"); } break; default: throw new NotImplementedException($"Unimplemented operand type {instr.Operands[0].GetType().Name}"); } genFlags(tmp); }
} // 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.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 void RewriteMovx() { var src = Operand(1); m.Assign(Reg(0), m.Cast(PrimitiveType.Word32, src)); }
public HExpr Cast(BaseType type, HExpr a) { return(MapToHandle(m.Cast(Interop.DataTypes[type], GetExpression(a)))); }
private void RewriteExt(PrimitiveType width) { var src = SrcOp(instr.op1, null); var dst = DstOp(instr.op2, src, (a, b) => m.Cast(width, b)); }
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); }
public IEnumerator <RtlInstructionCluster> GetEnumerator() { while (dasm.MoveNext()) { this.instr = dasm.Current; var instrs = new List <RtlInstruction>(); this.m = new RtlEmitter(instrs); switch (instr.Opcode) { case Opcode.invalid: default: Invalid(); break; case Opcode.add: RewriteBinOp(m.IAdd, n => (sbyte)n); break; case Opcode.addc: RewriteAddcSubc(m.IAdd); break; case Opcode.addv: RewriteAddv(m.IAdd); break; case Opcode.and: RewriteBinOp(m.And, n => (byte)n); break; case Opcode.and_b: RewriteBinOp(m.And, n => (byte)n); break; case Opcode.bf: RewriteBranch(false, false); break; case Opcode.bf_s: RewriteBranch(false, true); break; case Opcode.bra: RewriteGoto(); break; case Opcode.braf: RewriteBraf(); break; case Opcode.brk: RewriteBrk(); break; case Opcode.bsr: RewriteBsr(); break; case Opcode.bsrf: RewriteBsrf(); break; case Opcode.bt: RewriteBranch(true, false); break; case Opcode.bt_s: RewriteBranch(true, true); break; case Opcode.clrmac: RewriteClr(Registers.mac); break; case Opcode.clrt: RewriteClrtSetT(Constant.False()); break; case Opcode.cmp_eq: RewriteCmp(m.Eq); break; case Opcode.cmp_ge: RewriteCmp(m.Ge); break; case Opcode.cmp_gt: RewriteCmp(m.Gt); break; case Opcode.cmp_hs: RewriteCmp(m.Uge); break; case Opcode.cmp_hi: RewriteCmp(m.Ugt); break; case Opcode.cmp_pl: RewriteCmp0(m.Gt0); break; case Opcode.cmp_pz: RewriteCmp0(m.Ge0); break; case Opcode.div0s: RewriteDiv0s(); break; case Opcode.div0u: RewriteDiv0u(); break; case Opcode.div1: RewriteDiv1(); break; case Opcode.dmuls_l: RewriteDmul(m.SMul); break; case Opcode.dmulu_l: RewriteDmul(m.UMul); break; case Opcode.dt: RewriteDt(); break; case Opcode.exts_b: RewriteExt(PrimitiveType.SByte); break; case Opcode.exts_w: RewriteExt(PrimitiveType.Int16); break; case Opcode.extu_b: RewriteExt(PrimitiveType.Byte); break; case Opcode.extu_w: RewriteExt(PrimitiveType.UInt16); break; case Opcode.fabs: RewriteFabs(); break; case Opcode.fadd: RewriteBinOp(m.FAdd, null); break; case Opcode.fcmp_eq: RewriteCmp(m.FEq); break; case Opcode.fcmp_gt: RewriteCmp(m.FGt); break; case Opcode.fcnvds: RewriteUnary(d => m.Cast(PrimitiveType.Real32, d)); break; case Opcode.fcnvsd: RewriteUnary(d => m.Cast(PrimitiveType.Real64, d)); break; case Opcode.fdiv: RewriteBinOp(m.FDiv, null); break; case Opcode.fldi0: RewriteFldi(0.0F); break; case Opcode.fldi1: RewriteFldi(1.0F); break; case Opcode.flds: RewriteMov(); break; case Opcode.jmp: RewriteJmp(); break; case Opcode.jsr: RewriteJsr(); break; case Opcode.lds_l: RewriteMov(); break; case Opcode.mov: RewriteMov(); break; case Opcode.mova: RewriteMova(); break; case Opcode.mov_b: RewriteMov(); break; case Opcode.mov_w: RewriteMov(); break; case Opcode.mov_l: RewriteMov(); break; case Opcode.movt: RewriteMovt(); break; case Opcode.mul_l: RewriteMul_l(); break; case Opcode.muls_w: RewriteMul_w(PrimitiveType.Int16, m.SMul); break; case Opcode.mulu_w: RewriteMul_w(PrimitiveType.UInt16, m.UMul); break; case Opcode.neg: RewriteUnary(m.Neg); break; case Opcode.negc: RewriteNegc(); break; case Opcode.not: RewriteUnary(m.Comp); break; case Opcode.nop: this.rtlc = RtlClass.Linear; m.Nop(); break; case Opcode.or: RewriteBinOp(m.Or, u => (byte)u); break; case Opcode.rotcl: RewriteRotc(PseudoProcedure.RolC); break; case Opcode.rotcr: RewriteRotc(PseudoProcedure.RorC); break; case Opcode.rotl: RewriteRot(PseudoProcedure.Rol); break; case Opcode.rotr: RewriteRot(PseudoProcedure.Ror); break; case Opcode.rts: RewriteRts(); break; case Opcode.sett: RewriteClrtSetT(Constant.True()); break; case Opcode.shad: RewriteShd(m.Shl, m.Sar); break; case Opcode.shar: RewriteShift(m.Sar, 1); break; case Opcode.shld: RewriteShd(m.Shl, m.Shr); break; case Opcode.shll: RewriteShift(m.Shl, 1); break; case Opcode.shll2: RewriteShift(m.Shl, 2); break; case Opcode.shll8: RewriteShift(m.Shl, 8); break; case Opcode.shll16: RewriteShift(m.Shl, 16); break; case Opcode.shlr: RewriteShift(m.Shr, 1); break; case Opcode.shlr2: RewriteShift(m.Shr, 2); break; case Opcode.shlr8: RewriteShift(m.Shr, 8); break; case Opcode.shlr16: RewriteShift(m.Shr, 16); break; case Opcode.sts: RewriteMov(); break; case Opcode.sts_l: RewriteMov(); break; case Opcode.sub: RewriteBinOp(m.ISub, null); break; case Opcode.subc: RewriteAddcSubc(m.ISub); break; case Opcode.swap_w: RewriteSwapW(); break; case Opcode.tst: RewriteTst(); break; case Opcode.xor: RewriteBinOp(m.Xor, n => (byte)n); break; case Opcode.xtrct: RewriteXtrct(); break; } var rtlc = new RtlInstructionCluster(instr.Address, instr.Length, instrs.ToArray()) { Class = this.rtlc, }; yield return(rtlc); } }