Ejemplo n.º 1
0
        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));
            }
        }
Ejemplo n.º 2
0
        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));
        }
Ejemplo n.º 3
0
        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));
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        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()));
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
        private void Push(Identifier reg)
        {
            var s = binder.EnsureRegister(arch.StackRegister);

            m.Assign(s, m.ISubS(s, 1));
            m.Assign(m.Mem8(s), reg);
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
        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();
        }
Ejemplo n.º 10
0
        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);
            }
        }
Ejemplo n.º 11
0
        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));
            }
        }
Ejemplo n.º 12
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.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);
        }
Ejemplo n.º 13
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.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);
        }
Ejemplo n.º 14
0
 private Expression Dec(Expression e)
 {
     return(m.ISubS(e, 1));
 }