Пример #1
0
 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);
     }
 }
Пример #2
0
 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)));
     }
 }
Пример #3
0
        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);
        }
Пример #4
0
        private void RewriteLoad(MipsInstruction instr)
        {
            var opSrc = RewriteOperand(instr.op2);
            var opDst = RewriteOperand(instr.op1);

            emitter.Assign(opDst, emitter.Cast(arch.WordWidth, opSrc));
        }
Пример #5
0
 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);
 }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
            }
        }
Пример #9
0
        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());
        }
Пример #10
0
        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());
        }
Пример #11
0
 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);
 }
Пример #12
0
        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);
            }
        }
Пример #13
0
 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));
 }
Пример #14
0
        }                                                // 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);
        }
Пример #15
0
        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);
        }
Пример #16
0
        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));
            }
        }
Пример #17
0
        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);
        }
Пример #18
0
        }                                                // 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);
        }
Пример #19
0
        private void RewriteMovx()
        {
            var src = Operand(1);

            m.Assign(Reg(0), m.Cast(PrimitiveType.Word32, src));
        }
Пример #20
0
 public HExpr Cast(BaseType type, HExpr a)
 {
     return(MapToHandle(m.Cast(Interop.DataTypes[type], GetExpression(a))));
 }
Пример #21
0
 private void RewriteExt(PrimitiveType width)
 {
     var src = SrcOp(instr.op1, null);
     var dst = DstOp(instr.op2, src, (a, b) => m.Cast(width, b));
 }
Пример #22
0
        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);
        }
Пример #23
0
        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);
            }
        }