Beispiel #1
0
        private Expression RewriteDst(MachineOperand op, Expression src, Func <Expression, Expression, Expression> fn)
        {
            var reg = op as RegisterOperand;

            if (reg != null)
            {
                var id = binder.EnsureRegister(reg.Register);
                m.Assign(id, fn(id, src));
                return(id);
            }
            if (op is AddressOperand addr)
            {
                return(addr.Address);
            }
            if (op is MemoryOperand mem)
            {
                Expression ea;
                if (mem.Base != null)
                {
                    ea = binder.EnsureRegister(mem.Base);
                }
                else
                {
                    ea = arch.MakeAddressFromConstant(mem.Offset, false);
                }
                if (mem.Increment < 0)
                {
                    m.Assign(ea, m.ISub(ea, mem.Width.Size));
                }
                var load = m.Mem(mem.Width, ea);
                var tmp  = binder.CreateTemporary(ea.DataType);
                m.Assign(tmp, fn(load, src));
                m.Assign(m.Mem(mem.Width, ea), tmp);
                if (mem.Increment > 0)
                {
                    m.Assign(ea, m.IAdd(ea, mem.Width.Size));
                }
                return(tmp);
            }
            throw new NotImplementedException(op.GetType().Name);
        }
Beispiel #2
0
 private Expression Dec(Expression e)
 {
     return(m.ISub(e, 1));
 }
Beispiel #3
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.Slice(width, reg, 0));
                }

            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)
                    {
                        if (memOp.Offset.DataType.BitSize < ea.DataType.BitSize)
                        {
                            ea = m.IAddS(ea, memOp.Offset.ToInt32());
                        }
                        else
                        {
                            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:
                //$BUG: enabling the commented code causes huge regressions in the
                // unzip subject.

                /*if (addrOp.Width.BitSize > width.BitSize)
                 * {
                 *  var c = addrOp.Address.ToUInt32();
                 *  return Constant.Create(width, c);
                 * }
                 * else*/
            {
                return(addrOp.Address);
            }
            }
            throw new NotImplementedException(op.GetType().Name);
        }
Beispiel #4
0
        public IEnumerator <RtlInstructionCluster> GetEnumerator()
        {
            while (instrs.MoveNext())
            {
                if (!instrs.Current.TryGetInternal(out this.instr))
                {
                    continue;
                    throw new AddressCorrelatedException(
                              instrs.Current.Address,
                              "Invalid opcode cannot be rewritten to IR.");
                }
                this.ops       = instr.ArchitectureDetail.Operands;
                this.ric       = new RtlInstructionCluster(instrs.Current.Address, instr.Bytes.Length);
                this.ric.Class = RtlClass.Linear;
                this.emitter   = new RtlEmitter(ric.Instructions);
                switch (instr.Id)
                {
                default:
                    throw new AddressCorrelatedException(
                              instrs.Current.Address,
                              "Rewriting ARM Thumb opcode '{0}' ({1}) is not supported yet.",
                              instr.Mnemonic, instr.Id);

                case ArmInstruction.ADD: RewriteBinop((a, b) => emitter.IAdd(a, b)); break;

                case ArmInstruction.ADDW: RewriteAddw(); break;

                case ArmInstruction.ADR: RewriteAdr(); break;

                case ArmInstruction.AND: RewriteAnd(); break;

                case ArmInstruction.ASR: RewriteShift(emitter.Sar); break;

                case ArmInstruction.B: RewriteB(); break;

                case ArmInstruction.BIC: RewriteBic(); break;

                case ArmInstruction.BL: RewriteBl(); break;

                case ArmInstruction.BLX: RewriteBlx(); break;

                case ArmInstruction.BX: RewriteBx(); break;

                case ArmInstruction.CBZ: RewriteCbnz(emitter.Eq0); break;

                case ArmInstruction.CBNZ: RewriteCbnz(emitter.Ne0); break;

                case ArmInstruction.CMP: RewriteCmp(); break;

                case ArmInstruction.DMB: RewriteDmb(); break;

                case ArmInstruction.EOR: RewriteEor(); break;

                case ArmInstruction.IT: RewriteIt(); continue;  // Don't emit anything yet.;

                case ArmInstruction.LDR: RewriteLdr(PrimitiveType.Word32, PrimitiveType.Word32); break;

                case ArmInstruction.LDRB: RewriteLdr(PrimitiveType.UInt32, PrimitiveType.Byte); break;

                case ArmInstruction.LDRSB: RewriteLdr(PrimitiveType.Int32, PrimitiveType.SByte); break;

                case ArmInstruction.LDREX: RewriteLdrex(); break;

                case ArmInstruction.LDRH: RewriteLdr(PrimitiveType.UInt32, PrimitiveType.Word16); break;

                case ArmInstruction.LSL: RewriteShift(emitter.Shl); break;

                case ArmInstruction.LSR: RewriteShift(emitter.Shr); break;

                case ArmInstruction.MOV: RewriteMov(); break;

                case ArmInstruction.MOVT: RewriteMovt(); break;

                case ArmInstruction.MOVW: RewriteMovw(); break;

                case ArmInstruction.MRC: RewriteMrc(); break;

                case ArmInstruction.MVN: RewriteMvn(); break;

                case ArmInstruction.POP: RewritePop(); break;

                case ArmInstruction.PUSH: RewritePush(); break;

                case ArmInstruction.RSB: RewriteRsb(); break;

                case ArmInstruction.STM: RewriteStm(); break;

                case ArmInstruction.STR: RewriteStr(PrimitiveType.Word32); break;

                case ArmInstruction.STRH: RewriteStr(PrimitiveType.Word16); break;

                case ArmInstruction.STRB: RewriteStr(PrimitiveType.Byte); break;

                case ArmInstruction.STREX: RewriteStrex(); break;

                case ArmInstruction.SUB: RewriteBinop((a, b) => emitter.ISub(a, b)); break;

                case ArmInstruction.SUBW: RewriteSubw(); break;

                case ArmInstruction.TRAP: RewriteTrap(); break;

                case ArmInstruction.TST: RewriteTst(); break;

                case ArmInstruction.UDF: RewriteUdf(); break;

                case ArmInstruction.UXTH: RewriteUxth(); break;
                }
                itState = (itState << 1) & 0x0F;
                if (itState == 0)
                {
                    itStateCondition = ArmCodeCondition.AL;
                }
                yield return(ric);
            }
        }
Beispiel #5
0
        private void RewriteBlockInstruction(Func <Expression, Expression, Expression> incdec, bool repeat)
        {
            var bc = binder.EnsureRegister(Registers.bc);
            var de = binder.EnsureRegister(Registers.de);
            var hl = binder.EnsureRegister(Registers.hl);
            var V  = FlagGroup(FlagM.PF);

            m.Assign(m.Mem8(de), m.Mem8(hl));
            m.Assign(hl, incdec(hl, Constant.Int16(1)));
            m.Assign(de, incdec(de, Constant.Int16(1)));
            m.Assign(bc, m.ISub(bc, 1));
            if (repeat)
            {
                m.BranchInMiddleOfInstruction(m.Ne0(bc), dasm.Current.Address, InstrClass.Transfer);
            }
            m.Assign(V, m.Const(PrimitiveType.Bool, 0));
        }
Beispiel #6
0
        public IEnumerator <RtlInstructionCluster> GetEnumerator()
        {
            while (dasm.MoveNext())
            {
                this.instr = dasm.Current;
                var rtls = new List <RtlInstruction>();
                m           = new RtlEmitter(rtls);
                this.iclass = instr.InstructionClass;
                switch (instr.Mnemonic)
                {
                default:
                    host.Error(instr.Address, $"WE32100 instruction '{instr}' is not supported yet.");
                    EmitUnitTest();
                    goto case Mnemonic.invalid;

                case Mnemonic.invalid:
                    m.Invalid(); iclass = InstrClass.Invalid; break;

                case Mnemonic.addb2: RewriteArithmetic2(m.IAdd, PrimitiveType.Byte); break;

                case Mnemonic.addh2: RewriteArithmetic2(m.IAdd, PrimitiveType.Word16); break;

                case Mnemonic.addw2: RewriteArithmetic2(m.IAdd, PrimitiveType.Word32); break;

                case Mnemonic.addb3: RewriteArithmetic3(m.IAdd, PrimitiveType.Byte); break;

                case Mnemonic.addh3: RewriteArithmetic3(m.IAdd, PrimitiveType.Word16); break;

                case Mnemonic.addw3: RewriteArithmetic3(m.IAdd, PrimitiveType.Word32); break;

                case Mnemonic.andb2: RewriteLogical2(m.And, PrimitiveType.Byte); break;

                case Mnemonic.andh2: RewriteLogical2(m.And, PrimitiveType.Word16); break;

                case Mnemonic.andw2: RewriteLogical2(m.And, PrimitiveType.Word32); break;

                case Mnemonic.andb3: RewriteLogical3(m.And, PrimitiveType.Byte); break;

                case Mnemonic.andh3: RewriteLogical3(m.And, PrimitiveType.Word16); break;

                case Mnemonic.andw3: RewriteLogical3(m.And, PrimitiveType.Word32); break;

                case Mnemonic.dech: RewriteUnary(e => m.ISub(e, 1), PrimitiveType.Word16, NZVC); break;

                case Mnemonic.movb: RewriteMov(PrimitiveType.Byte); break;

                case Mnemonic.subb2: RewriteArithmetic2(m.ISub, PrimitiveType.Byte); break;

                case Mnemonic.subh2: RewriteArithmetic2(m.ISub, PrimitiveType.Word16); break;

                case Mnemonic.subw2: RewriteArithmetic2(m.ISub, PrimitiveType.Word32); break;

                case Mnemonic.xorb2: RewriteLogical2(m.Xor, PrimitiveType.Byte); break;

                case Mnemonic.xorh2: RewriteLogical2(m.Xor, PrimitiveType.Word16); break;

                case Mnemonic.xorw2: RewriteLogical2(m.Xor, PrimitiveType.Word32); break;
                }
                yield return(m.MakeCluster(instr.Address, instr.Length, iclass));
            }
        }
Beispiel #7
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);
        }
Beispiel #8
0
        private void RewriteCp_b()
        {
            var op1 = m.Slice(PrimitiveType.Byte, RewriteOp(0), 0);
            var op2 = m.Slice(PrimitiveType.Byte, RewriteOp(1), 0);
            var grf = binder.EnsureFlagGroup(VNZC);

            m.Assign(grf, m.Cond(m.ISub(op1, op2)));
        }
Beispiel #9
0
        private Expression?RewriteApplication(ApplicationOperand app)
        {
            var ops = app.Operands.Select(o => OperandSrc(o) !).ToArray();
            var dt  = app.Width;

            switch (app.Mnemonic)
            {
            case Mnemonic.add: return(m.IAdd(ops[0], ops[1]));

            case Mnemonic.addasl: return(RewriteAddAsl(ops[0], ops[1], ops[2]));

            case Mnemonic.allocframe: RewriteAllocFrame(app.Operands[0]); return(null);

            case Mnemonic.and: return(m.And(ops[0], ops[1]));

            case Mnemonic.asl: return(m.Shl(ops[0], ops[1]));

            case Mnemonic.aslh: return(m.Shl(ops[0], 16));

            case Mnemonic.asr: return(m.Sar(ops[0], ops[1]));

            case Mnemonic.asrh: return(m.Sar(ops[0], 16));

            case Mnemonic.cmp__eq: return(m.Eq(ops[0], ops[1]));

            case Mnemonic.cmp__gt: return(m.Gt(ops[0], ops[1]));

            case Mnemonic.cmp__gtu: return(m.Ugt(ops[0], ops[1]));

            case Mnemonic.cmpb__eq: return(RewriteCmp(PrimitiveType.Byte, m.Eq, ops[0], ops[1]));

            case Mnemonic.cmpb__gt: return(RewriteCmp(PrimitiveType.Byte, m.Gt, ops[0], ops[1]));

            case Mnemonic.cmpb__gtu: return(RewriteCmp(PrimitiveType.Byte, m.Ugt, ops[0], ops[1]));

            case Mnemonic.cmph__eq: return(RewriteCmp(PrimitiveType.Word16, m.Eq, ops[0], ops[1]));

            case Mnemonic.cmph__gt: return(RewriteCmp(PrimitiveType.Word16, m.Gt, ops[0], ops[1]));

            case Mnemonic.cmph__gtu: return(RewriteCmp(PrimitiveType.Word16, m.Ugt, ops[0], ops[1]));

            case Mnemonic.dfcmp__eq: return(m.FEq(ops[0], ops[1]));

            case Mnemonic.dfcmp__ge: return(m.FGe(ops[0], ops[1]));

            case Mnemonic.dfcmp__uo: return(host.Intrinsic("isunordered", false, PrimitiveType.Bool, ops[0], ops[1]));

            case Mnemonic.combine: return(RewriteCombine(ops[0], ops[1]));

            case Mnemonic.convert_d2df: return(m.Convert(ops[0], PrimitiveType.Int64, PrimitiveType.Real64));

            case Mnemonic.convert_df2sf: return(m.Convert(ops[0], PrimitiveType.Real64, PrimitiveType.Real32));

            case Mnemonic.convert_sf2df: return(m.Convert(ops[0], PrimitiveType.Real32, PrimitiveType.Real64));

            case Mnemonic.EQ: return(m.Eq(ops[0], ops[1]));

            case Mnemonic.extract: return(RewriteExtract(Domain.SignedInt, ops[0], app.Operands));

            case Mnemonic.extractu: return(RewriteExtract(Domain.UnsignedInt, ops[0], app.Operands));

            case Mnemonic.loop0: RewriteLoop(0, ops); return(null);

            case Mnemonic.loop1: RewriteLoop(1, ops); return(null);

            case Mnemonic.lsl: return(m.Shl(ops[0], ops[1]));

            case Mnemonic.lsr: return(m.Shr(ops[0], ops[1]));

            case Mnemonic.mpy: return(RewriteMpy(ops[0], ops[1]));

            case Mnemonic.mpyi: return(RewriteMpyi(ops[0], ops[1]));

            case Mnemonic.mpyu: return(RewriteMpyu(app.Width, ops[0], ops[1]));

            case Mnemonic.mux: return(m.Conditional(ops[1].DataType, ops[0], ops[1], ops[2]));

            case Mnemonic.NE: return(m.Ne(ops[0], ops[1]));

            case Mnemonic.neg: return(m.Neg(ops[0]));

            case Mnemonic.not: return(m.Not(ops[0]));

            case Mnemonic.or: return(m.Or(ops[0], ops[1]));

            case Mnemonic.sub: return(m.ISub(ops[0], ops[1]));

            case Mnemonic.sxtb: return(RewriteExt(ops[0], PrimitiveType.SByte, PrimitiveType.Int32));

            case Mnemonic.sxth: return(RewriteExt(ops[0], PrimitiveType.Int16, PrimitiveType.Int32));

            case Mnemonic.xor: return(m.Xor(ops[0], ops[1]));

            case Mnemonic.zxtb: return(RewriteExt(ops[0], PrimitiveType.Byte, PrimitiveType.UInt32));

            case Mnemonic.zxth: return(RewriteExt(ops[0], PrimitiveType.UInt16, PrimitiveType.UInt32));

            case Mnemonic.abs: dt = PrimitiveType.Int32; goto intrinsicFunc;

            case Mnemonic.max: dt = PrimitiveType.Int32; goto intrinsicFunc;

            case Mnemonic.maxu: dt = PrimitiveType.UInt32; goto intrinsicFunc;

            case Mnemonic.min: dt = PrimitiveType.Int32; goto intrinsicFunc;

            case Mnemonic.minu: dt = PrimitiveType.UInt32; goto intrinsicFunc;

            case Mnemonic.all8:
            case Mnemonic.any8:
            case Mnemonic.bitsclr:
            case Mnemonic.bitsplit:
            case Mnemonic.bitsset:
            case Mnemonic.ciad:
            case Mnemonic.cl0:
            case Mnemonic.cl1:
            case Mnemonic.clb:
            case Mnemonic.clrbit:
            case Mnemonic.crswap:
            case Mnemonic.cswi:
            case Mnemonic.ct0:
            case Mnemonic.dfclass:
            case Mnemonic.fastcorner9:
            case Mnemonic.insert:   //$BUG: like DPB?
            case Mnemonic.memw_locked:
            case Mnemonic.setbit:
            case Mnemonic.start:
            case Mnemonic.stop:
            case Mnemonic.tlbw:
            case Mnemonic.tlbp:
            case Mnemonic.trap0:
            case Mnemonic.trap1:
            case Mnemonic.togglebit:
            case Mnemonic.tstbit:
intrinsicFunc:
                return(RewriteIntrinsic(app.Mnemonic.ToString(), true, dt, ops));

            case Mnemonic.dccleana:
            case Mnemonic.dccleaninva:
            case Mnemonic.dcfetch:
            case Mnemonic.dcinva:
            case Mnemonic.dczeroa:
                return(RewriteIntrinsic(app.Mnemonic.ToString(), true, VoidType.Instance, ops));

            case Mnemonic.vavgh: return(RewriteVectorIntrinsic(app.Mnemonic, false, PrimitiveType.Word16, ops));

            case Mnemonic.vcmpb__eq: return(RewriteVectorIntrinsic(app.Mnemonic, false, PrimitiveType.Byte, ops));

            case Mnemonic.vmux: return(RewriteVectorIntrinsic(app.Mnemonic, false, PrimitiveType.Byte, ops));

            case Mnemonic.vsplatb: return(RewriteVectorIntrinsic(app.Mnemonic, false, PrimitiveType.Byte, ops));

            case Mnemonic.vsubh: return(RewriteVectorIntrinsic(app.Mnemonic, false, PrimitiveType.Int16, ops));
            }
            throw new ArgumentException($"Hexagon rewriter for {app.Mnemonic} not implemented yet.", app.Mnemonic.ToString());
        }
Beispiel #10
0
        private Expression Operand(MachineOperand op)
        {
            var rop = op as RegisterOperand;

            if (rop != null)
            {
                return(frame.EnsureRegister(rop.Register));
            }
            var immOp = op as ImmediateOperand;

            if (immOp != null)
            {
                return(immOp.Value);
            }
            var shOp = op as ShiftOperand;

            if (shOp != null)
            {
                var r  = Operand(shOp.Operand);
                var sh = Operand(shOp.Shift);
                switch (shOp.Opcode)
                {
                case Opcode.lsl: return(emitter.Shl(r, sh));

                case Opcode.lsr: return(emitter.Shr(r, sh));

                case Opcode.asr: return(emitter.Sar(r, sh));

                case Opcode.ror: return(host.PseudoProcedure(PseudoProcedure.Ror, PrimitiveType.Word32, r, sh));

                default: throw new NotSupportedException(string.Format("Unsupported shift operation {0}.", shOp.Opcode));
                }
            }
            var memOp = op as ArmMemoryOperand;

            if (memOp != null)
            {
                Expression baseReg = frame.EnsureRegister(memOp.Base);
                Expression ea      = baseReg;
                if (memOp.Base.Number == 0x0F)  // PC-relative address
                {
                    var imm = memOp.Offset as ArmImmediateOperand;
                    if (imm != null)
                    {
                        if (memOp.Writeback)
                        {
                            throw new NotImplementedException();
                        }
                        var dst = (uint)((int)instr.Address.ToUInt32() + imm.Value.ToInt32()) + 8u;

                        return(emitter.Load(memOp.Width, Address.Ptr32(dst)));
                    }
                }
                if (memOp.Offset != null && memOp.Preindexed)
                {
                    var offset = Operand(memOp.Offset);
                    ea = memOp.Subtract
                        ? emitter.ISub(ea, offset)
                        : emitter.IAdd(ea, offset);
                }
                if (memOp.Preindexed && memOp.Writeback)
                {
                    emitter.Assign(baseReg, ea);
                    ea = baseReg;
                }
                return(emitter.Load(memOp.Width, ea));
            }
            throw new NotSupportedException(string.Format("Unsupported operand {0}.", op));
        }
Beispiel #11
0
        public IEnumerator <RtlInstructionCluster> GetEnumerator()
        {
            while (dasm.MoveNext())
            {
                di      = dasm.Current;
                ric     = new RtlInstructionCluster(di.Address, di.Length);
                emitter = new RtlEmitter(ric.Instructions);
                orw     = new OperandRewriter(arch, this.emitter, this.frame, di.dataWidth);
                switch (di.code)
                {
                case Opcode.add: RewriteBinOp((s, d) => emitter.IAdd(d, s), FlagM.CVZNX); break;

                case Opcode.adda: RewriteBinOp((s, d) => emitter.IAdd(d, s)); break;

                case Opcode.addi: RewriteArithmetic((s, d) => emitter.IAdd(d, s)); break;

                case Opcode.addq: RewriteAddSubq((s, d) => emitter.IAdd(d, s)); break;

                case Opcode.addx: RewriteAddSubx(Operator.IAdd); break;

                case Opcode.and: RewriteLogical((s, d) => emitter.And(d, s)); break;

                case Opcode.andi: RewriteLogical((s, d) => emitter.And(d, s)); break;

                case Opcode.asl: RewriteArithmetic((s, d) => emitter.Shl(d, s)); break;

                case Opcode.asr: RewriteShift((s, d) => emitter.Sar(d, s)); break;

/*
 *
 * Mnemonic Condition Encoding Test
 * T* True 0000 1
 * F* False 0001 0
 * HI High 0010 C L Z
 * LS Low or Same 0011 C V Z
 * VC Overflow Clear 1000 V
 * VS Overflow Set 1001 V
 */
                case Opcode.bclr: RewriteBclrBset("__bclr"); break;

                case Opcode.bcc: RewriteBcc(ConditionCode.UGE, FlagM.CF); break;

                case Opcode.bcs: RewriteBcc(ConditionCode.ULT, FlagM.CF); break;

                case Opcode.beq: RewriteBcc(ConditionCode.EQ, FlagM.ZF); break;

                case Opcode.bge: RewriteBcc(ConditionCode.GE, FlagM.NF | FlagM.VF); break;

                case Opcode.bgt: RewriteBcc(ConditionCode.GT, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Opcode.bhi: RewriteBcc(ConditionCode.UGT, FlagM.CF | FlagM.ZF); break;

                case Opcode.ble: RewriteBcc(ConditionCode.LE, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Opcode.blt: RewriteBcc(ConditionCode.LT, FlagM.CF | FlagM.ZF); break;

                case Opcode.bls: RewriteBcc(ConditionCode.ULE, FlagM.VF | FlagM.ZF); break;

                case Opcode.bmi: RewriteBcc(ConditionCode.LT, FlagM.NF); break;

                case Opcode.bne: RewriteBcc(ConditionCode.NE, FlagM.ZF); break;

                case Opcode.bpl: RewriteBcc(ConditionCode.GT, FlagM.NF); break;

                case Opcode.bchg: RewriteBchg(); break;

                case Opcode.bra: RewriteBra(); break;

                case Opcode.bset: RewriteBclrBset("__bset"); break;

                case Opcode.bsr: RewriteBsr(); break;

                case Opcode.btst: RewriteBtst(); break;

                case Opcode.clr: RewriteClr(); break;

                case Opcode.cmp: RewriteCmp(); break;

                case Opcode.cmpa: RewriteCmp(); break;

                case Opcode.cmpi: RewriteCmp(); break;

                case Opcode.dble: RewriteDbcc(ConditionCode.GT, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Opcode.dbhi: RewriteDbcc(ConditionCode.ULE, FlagM.CF | FlagM.ZF); break;

                case Opcode.dbra: RewriteDbcc(ConditionCode.None, 0); break;

                case Opcode.divu: RewriteDiv(Operator.UDiv); break;

                case Opcode.eor: RewriteLogical((s, d) => emitter.Xor(d, s)); break;

                case Opcode.eori: RewriteLogical((s, d) => emitter.Xor(d, s)); break;

                case Opcode.exg: RewriteExg(); break;

                case Opcode.ext: RewriteExt(); break;

                case Opcode.extb: RewriteExtb(); break;

                case Opcode.illegal: if (!RewriteIllegal())
                    {
                        goto default;
                    }
                    break;

                case Opcode.jmp: RewriteJmp(); break;

                case Opcode.jsr: RewriteJsr(); break;

                case Opcode.lea: RewriteLea(); break;

                case Opcode.link: RewriteLink(); break;

                case Opcode.lsl: RewriteShift((s, d) => emitter.Shl(d, s)); break;

                case Opcode.lsr: RewriteShift((s, d) => emitter.Shr(d, s)); break;

                case Opcode.move: RewriteMove(true); break;

                case Opcode.movea: RewriteMove(false); break;

                case Opcode.moveq: RewriteMoveq(); break;

                case Opcode.movem: RewriteMovem(); break;

                case Opcode.muls: RewriteMul((s, d) => emitter.SMul(d, s)); break;

                case Opcode.mulu: RewriteMul((s, d) => emitter.UMul(d, s)); break;

                case Opcode.neg: RewriteUnary(s => emitter.Neg(s), AllConditions); break;

                case Opcode.negx: RewriteUnary(RewriteNegx, AllConditions); break;

                case Opcode.nop: continue;

                case Opcode.not: RewriteUnary(s => emitter.Comp(s), LogicalConditions); break;

                case Opcode.or: RewriteLogical((s, d) => emitter.Or(d, s)); break;

                case Opcode.ori: RewriteLogical((s, d) => emitter.Or(d, s)); break;

                case Opcode.pea: RewritePea(); break;

                case Opcode.rol: RewriteRotation(PseudoProcedure.Rol); break;

                case Opcode.ror: RewriteRotation(PseudoProcedure.Ror);  break;

                case Opcode.roxl: RewriteRotationX(PseudoProcedure.RolC);  break;

                case Opcode.roxr: RewriteRotationX(PseudoProcedure.RorC);  break;

                case Opcode.rts: emitter.Return(4, 0); break;

                case Opcode.scc: RewriteScc(ConditionCode.UGE, FlagM.CF); break;

                case Opcode.scs: RewriteScc(ConditionCode.ULT, FlagM.CF); break;

                case Opcode.seq: RewriteScc(ConditionCode.EQ, FlagM.ZF); break;

                case Opcode.sge: RewriteScc(ConditionCode.GE, FlagM.NF | FlagM.VF); break;

                case Opcode.sgt: RewriteScc(ConditionCode.GT, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Opcode.shi: RewriteScc(ConditionCode.UGT, FlagM.CF | FlagM.ZF); break;

                case Opcode.sle: RewriteScc(ConditionCode.LE, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Opcode.slt: RewriteScc(ConditionCode.LT, FlagM.CF | FlagM.ZF); break;

                case Opcode.sls: RewriteScc(ConditionCode.ULE, FlagM.VF | FlagM.ZF); break;

                case Opcode.smi: RewriteScc(ConditionCode.LT, FlagM.NF); break;

                case Opcode.sne: RewriteScc(ConditionCode.NE, FlagM.ZF); break;

                case Opcode.spl: RewriteScc(ConditionCode.GT, FlagM.NF); break;

                case Opcode.st: orw.RewriteMoveDst(di.op1, di.Address, PrimitiveType.Bool, Constant.True()); break;

                case Opcode.sf: orw.RewriteMoveDst(di.op1, di.Address, PrimitiveType.Bool, Constant.False()); break;

                case Opcode.sub: RewriteArithmetic((s, d) => emitter.ISub(d, s)); break;

                case Opcode.suba: RewriteArithmetic((s, d) => emitter.ISub(d, s)); break;

                case Opcode.subi: RewriteArithmetic((s, d) => emitter.ISub(d, s)); break;

                case Opcode.subq: RewriteAddSubq((s, d) => emitter.ISub(d, s)); break;

                case Opcode.subx: RewriteArithmetic((s, d) => emitter.ISub(emitter.ISub(d, s), frame.EnsureFlagGroup((uint)FlagM.XF, "X", PrimitiveType.Bool))); break;

                case Opcode.swap: RewriteSwap(); break;

                case Opcode.tst: RewriteTst(); break;

                case Opcode.unlk: RewriteUnlk(); break;

                default:
                    throw new AddressCorrelatedException(
                              di.Address,
                              "Rewriting M68k opcode '{0}' is not supported yet.",
                              di.code);
                }
                yield return(ric);
            }
            yield break;
        }
Beispiel #12
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(regHi.Storage, reg.Storage, width));
                }
                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(regHi1.Storage, reg.Storage, PrimitiveType.Word64);
                    var regHi = binder.EnsureSequence(regHi3.Storage, regHi2.Storage, PrimitiveType.Word64);
                    return(binder.EnsureSequence(regHi.Storage, regLo.Storage, width));
                }
                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)
                    {
                        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
                {
                }
                break;

            case AddressOperand addrOp:
                return(addrOp.Address);
            }
            throw new NotImplementedException(op.GetType().Name);
        }
Beispiel #13
0
        private Expression Sbc(Expression a, Expression b)
        {
            var C = binder.EnsureFlagGroup(arch.GetFlagGroup(Registers.CC, (uint)FlagM.C));

            return(m.ISub(m.ISub(a, b), C));
        }
Beispiel #14
0
        private Expression DstOp(MachineOperand op, Expression src, Func <Expression, Expression> fn)
        {
            var regOp = op as RegisterOperand;

            if (regOp != null)
            {
                var id = binder.EnsureRegister(regOp.Register);
                m.Assign(id, fn(src));
                return(id);
            }
            var mem = op as MemoryOperand;

            if (mem != null)
            {
                Identifier r0;
                Identifier gbr;
                Identifier reg;
                var        tmp = binder.CreateTemporary(op.Width);
                switch (mem.mode)
                {
                case AddressingMode.Indirect:
                    reg = binder.EnsureRegister(mem.reg);
                    m.Assign(
                        m.Mem(mem.Width, reg),
                        fn(src));
                    return(null);

                case AddressingMode.IndirectDisplacement:
                    reg = binder.EnsureRegister(mem.reg);
                    m.Assign(
                        m.Mem(mem.Width, m.IAdd(reg, Constant.Int32(mem.disp))),
                        fn(src));
                    return(null);

                case AddressingMode.IndirectPreDecr:
                    reg = binder.EnsureRegister(mem.reg);
                    m.Assign(reg, m.ISub(reg, Constant.Int32(mem.Width.Size)));
                    m.Assign(
                        m.Mem(tmp.DataType, reg),
                        fn(src));
                    return(null);

                case AddressingMode.IndexedIndirect:
                    m.Assign(
                        m.Mem(mem.Width, m.IAdd(
                                  binder.EnsureRegister(Registers.r0),
                                  binder.EnsureRegister(mem.reg))),
                        fn(src));
                    return(null);

                case AddressingMode.GbrIndexedIndirect:
                    r0  = binder.EnsureRegister(Registers.r0);
                    gbr = binder.EnsureRegister(Registers.gbr);
                    m.Assign(tmp, m.Mem(tmp.DataType, m.IAdd(r0, gbr)));
                    m.Assign(
                        m.Mem(tmp.DataType, m.IAdd(r0, gbr)),
                        fn(src));
                    return(tmp);

                default: throw new NotImplementedException(mem.mode.ToString());
                }
            }
            throw new NotImplementedException(op.GetType().Name);
        }
Beispiel #15
0
 public HExpr ISub(HExpr a, HExpr b)
 {
     return(MapToHandle(m.ISub(GetExpression(a), GetExpression(b))));
 }
Beispiel #16
0
        public IEnumerator <RtlInstructionCluster> GetEnumerator()
        {
            while (dasm.MoveNext())
            {
                di = dasm.Current;
                var addr = di.Address;
                var len  = di.Length;
                rtlInstructions = new List <RtlInstruction>();
                rtlc            = RtlClass.Linear;
                m   = new RtlEmitter(rtlInstructions);
                orw = new OperandRewriter(arch, this.m, this.binder, di.dataWidth);
                switch (di.code)
                {
                default:
                    host.Warn(
                        di.Address,
                        "Rewriting M68k opcode '{0}' is not supported yet.",
                        di.code);
                    m.Invalid();
                    break;

                case Opcode.illegal: RewriteIllegal(); break;

                case Opcode.add: RewriteBinOp((s, d) => m.IAdd(d, s), FlagM.CVZNX); break;

                case Opcode.adda: RewriteBinOp((s, d) => m.IAdd(d, s)); break;

                case Opcode.addi: RewriteArithmetic((s, d) => m.IAdd(d, s)); break;

                case Opcode.addq: RewriteAddSubq((s, d) => m.IAdd(d, s)); break;

                case Opcode.addx: RewriteAddSubx(m.IAdd); break;

                case Opcode.and: RewriteLogical((s, d) => m.And(d, s)); break;

                case Opcode.andi: RewriteLogical((s, d) => m.And(d, s)); break;

                case Opcode.asl: RewriteArithmetic((s, d) => m.Shl(d, s)); break;

                case Opcode.asr: RewriteShift((s, d) => m.Sar(d, s)); break;

/*
 *
 * Mnemonic Condition Encoding Test
 * T* True 0000 1
 * F* False 0001 0
 * HI High 0010 C L Z
 * LS Low or Same 0011 C V Z
 * VC Overflow Clear 1000 V
 * VS Overflow Set 1001 V
 */
                case Opcode.bclr: RewriteBclrBset("__bclr"); break;

                case Opcode.bcc: RewriteBcc(ConditionCode.UGE, FlagM.CF); break;

                case Opcode.bcs: RewriteBcc(ConditionCode.ULT, FlagM.CF); break;

                case Opcode.beq: RewriteBcc(ConditionCode.EQ, FlagM.ZF); break;

                case Opcode.bge: RewriteBcc(ConditionCode.GE, FlagM.NF | FlagM.VF); break;

                case Opcode.bgt: RewriteBcc(ConditionCode.GT, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Opcode.bhi: RewriteBcc(ConditionCode.UGT, FlagM.CF | FlagM.ZF); break;

                case Opcode.ble: RewriteBcc(ConditionCode.LE, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Opcode.blt: RewriteBcc(ConditionCode.LT, FlagM.CF | FlagM.ZF); break;

                case Opcode.bls: RewriteBcc(ConditionCode.ULE, FlagM.VF | FlagM.ZF); break;

                case Opcode.bmi: RewriteBcc(ConditionCode.LT, FlagM.NF); break;

                case Opcode.bne: RewriteBcc(ConditionCode.NE, FlagM.ZF); break;

                case Opcode.bpl: RewriteBcc(ConditionCode.GT, FlagM.NF); break;

                case Opcode.bvs: RewriteBcc(ConditionCode.OV, FlagM.VF); break;

                case Opcode.bchg: RewriteBchg(); break;

                case Opcode.bra: RewriteBra(); break;

                case Opcode.bset: RewriteBclrBset("__bset"); break;

                case Opcode.bsr: RewriteBsr(); break;

                case Opcode.btst: RewriteBtst(); break;

                case Opcode.cas: RewriteCas(); break;

                case Opcode.clr: RewriteClr(); break;

                case Opcode.chk: RewriteChk(); break;

                case Opcode.chk2: RewriteChk2(); break;

                case Opcode.cmp: RewriteCmp(); break;

                case Opcode.cmp2: RewriteCmp2(); break;

                case Opcode.cmpa: RewriteCmp(); break;

                case Opcode.cmpi: RewriteCmp(); break;

                case Opcode.cmpm: RewriteCmp(); break;

                case Opcode.dbeq: RewriteDbcc(ConditionCode.EQ, FlagM.ZF); break;

                case Opcode.dble: RewriteDbcc(ConditionCode.GT, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Opcode.dbhi: RewriteDbcc(ConditionCode.ULE, FlagM.CF | FlagM.ZF); break;

                case Opcode.dbne: RewriteDbcc(ConditionCode.NE, FlagM.ZF); break;

                case Opcode.dbra: RewriteDbcc(ConditionCode.None, 0); break;

                case Opcode.divs: RewriteDiv(m.SDiv, PrimitiveType.Int16); break;

                case Opcode.divsl: RewriteDiv(m.SDiv, PrimitiveType.Int32); break;

                case Opcode.divu: RewriteDiv(m.UDiv, PrimitiveType.UInt16); break;

                case Opcode.eor: RewriteLogical((s, d) => m.Xor(d, s)); break;

                case Opcode.eori: RewriteLogical((s, d) => m.Xor(d, s)); break;

                case Opcode.exg: RewriteExg(); break;

                case Opcode.ext: RewriteExt(); break;

                case Opcode.extb: RewriteExtb(); break;

                case Opcode.fadd: RewriteFBinOp((s, d) => m.FAdd(d, s)); break;

                //$REVIEW: the following don't respect NaN, but NaN typically doesn't exist in HLLs.
                case Opcode.fbf: m.Nop(); break;

                case Opcode.fbnge: RewriteFbcc(ConditionCode.LT); break;

                case Opcode.fbnlt: RewriteFbcc(ConditionCode.GE); break;

                case Opcode.fbnle: RewriteFbcc(ConditionCode.GT); break;

                case Opcode.fbogl: RewriteFbcc(ConditionCode.NE); break;

                case Opcode.fbult: RewriteFbcc(ConditionCode.LT); break;

                case Opcode.fbun: RewriteFbcc(ConditionCode.IS_NAN); break;

                case Opcode.fcmp: RewriteFcmp(); break;

                case Opcode.fdiv: RewriteFBinOp((s, d) => m.FDiv(d, s)); break;

                case Opcode.fmove: RewriteFmove(); break;

                case Opcode.fmovecr: RewriteFmovecr(); break;

                case Opcode.fmovem: RewriteMovem(i => arch.GetRegister(i + Registers.fp0.Number)); break;

                case Opcode.fmul: RewriteFBinOp((s, d) => m.FMul(d, s)); break;

                case Opcode.fneg: RewriteFUnaryOp(m.Neg); break;

                case Opcode.fsub: RewriteFBinOp((s, d) => m.FSub(d, s)); break;

                case Opcode.jmp: RewriteJmp(); break;

                case Opcode.jsr: RewriteJsr(); break;

                case Opcode.lea: RewriteLea(); break;

                case Opcode.link: RewriteLink(); break;

                case Opcode.lsl: RewriteShift((s, d) => m.Shl(d, s)); break;

                case Opcode.lsr: RewriteShift((s, d) => m.Shr(d, s)); break;

                case Opcode.move: RewriteMove(true); break;

                case Opcode.movea: RewriteMove(false); break;

                case Opcode.movep: RewriteMovep(); break;

                case Opcode.moveq: RewriteMoveq(); break;

                case Opcode.movem: RewriteMovem(arch.GetRegister); break;

                case Opcode.muls: RewriteMul((s, d) => m.SMul(d, s)); break;

                case Opcode.mulu: RewriteMul((s, d) => m.UMul(d, s)); break;

                case Opcode.neg: RewriteUnary(s => m.Neg(s), AllConditions); break;

                case Opcode.negx: RewriteUnary(RewriteNegx, AllConditions); break;

                case Opcode.nop: m.Nop(); break;

                case Opcode.not: RewriteUnary(s => m.Comp(s), LogicalConditions); break;

                case Opcode.or: RewriteLogical((s, d) => m.Or(d, s)); break;

                case Opcode.ori: RewriteLogical((s, d) => m.Or(d, s)); break;

                case Opcode.pea: RewritePea(); break;

                case Opcode.rol: RewriteRotation(PseudoProcedure.Rol); break;

                case Opcode.ror: RewriteRotation(PseudoProcedure.Ror);  break;

                case Opcode.roxl: RewriteRotationX(PseudoProcedure.RolC);  break;

                case Opcode.roxr: RewriteRotationX(PseudoProcedure.RorC);  break;

                case Opcode.rts: RewriteRts(); break;

                case Opcode.scc: RewriteScc(ConditionCode.UGE, FlagM.CF); break;

                case Opcode.scs: RewriteScc(ConditionCode.ULT, FlagM.CF); break;

                case Opcode.seq: RewriteScc(ConditionCode.EQ, FlagM.ZF); break;

                case Opcode.sge: RewriteScc(ConditionCode.GE, FlagM.NF | FlagM.VF); break;

                case Opcode.sgt: RewriteScc(ConditionCode.GT, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Opcode.shi: RewriteScc(ConditionCode.UGT, FlagM.CF | FlagM.ZF); break;

                case Opcode.sle: RewriteScc(ConditionCode.LE, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Opcode.slt: RewriteScc(ConditionCode.LT, FlagM.CF | FlagM.ZF); break;

                case Opcode.sls: RewriteScc(ConditionCode.ULE, FlagM.VF | FlagM.ZF); break;

                case Opcode.smi: RewriteScc(ConditionCode.LT, FlagM.NF); break;

                case Opcode.sne: RewriteScc(ConditionCode.NE, FlagM.ZF); break;

                case Opcode.spl: RewriteScc(ConditionCode.GT, FlagM.NF); break;

                case Opcode.st: orw.RewriteMoveDst(di.op1, di.Address, PrimitiveType.Bool, Constant.True()); break;

                case Opcode.sf: orw.RewriteMoveDst(di.op1, di.Address, PrimitiveType.Bool, Constant.False()); break;

                case Opcode.stop: RewriteStop(); break;

                case Opcode.sub: RewriteArithmetic((s, d) => m.ISub(d, s)); break;

                case Opcode.suba: RewriteArithmetic((s, d) => m.ISub(d, s)); break;

                case Opcode.subi: RewriteArithmetic((s, d) => m.ISub(d, s)); break;

                case Opcode.subq: RewriteAddSubq((s, d) => m.ISub(d, s)); break;

                case Opcode.subx: RewriteArithmetic((s, d) => m.ISub(m.ISub(d, s), binder.EnsureFlagGroup(Registers.ccr, (uint)FlagM.XF, "X", PrimitiveType.Bool))); break;

                case Opcode.swap: RewriteSwap(); break;

                case Opcode.trap: RewriteTrap(); break;

                case Opcode.tst: RewriteTst(); break;

                case Opcode.unlk: RewriteUnlk(); break;
                }
                yield return(new RtlInstructionCluster(
                                 addr,
                                 len,
                                 rtlInstructions.ToArray())
                {
                    Class = rtlc
                });
            }
            yield break;
        }
Beispiel #17
0
        private void RewriteBlockInstruction(Func <Expression, Expression, Expression> incdec, bool repeat)
        {
            var bc = frame.EnsureRegister(Registers.bc);
            var de = frame.EnsureRegister(Registers.de);
            var hl = frame.EnsureRegister(Registers.hl);
            var V  = FlagGroup(FlagM.PF);

            emitter.Assign(emitter.LoadB(de), emitter.LoadB(hl));
            emitter.Assign(hl, incdec(hl, Constant.Int16(1)));
            emitter.Assign(de, incdec(de, Constant.Int16(1)));
            emitter.Assign(bc, emitter.ISub(bc, 1));
            if (repeat)
            {
                emitter.BranchInMiddleOfInstruction(emitter.Ne0(bc), dasm.Current.Address, RtlClass.Transfer);
            }
            emitter.Assign(V, emitter.Const(PrimitiveType.Bool, 0));
        }
Beispiel #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>
        /// <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);
        }
Beispiel #19
0
        public IEnumerator <RtlInstructionCluster> GetEnumerator()
        {
            while (dasm.MoveNext())
            {
                instr = dasm.Current;
                var addr = instr.Address;
                var len  = instr.Length;
                rtlInstructions = new List <RtlInstruction>();
                rtlc            = instr.InstructionClass;
                m   = new RtlEmitter(rtlInstructions);
                orw = new OperandRewriter(arch, this.m, this.binder, instr.dataWidth);
                switch (instr.Mnemonic)
                {
                default:
                    host.Warn(
                        instr.Address,
                        "M68k instruction '{0}' is not supported yet.",
                        instr.Mnemonic);
                    m.Invalid();
                    break;

                case Mnemonic.illegal: RewriteIllegal(); break;

                case Mnemonic.abcd: RewriteAbcd(); break;

                case Mnemonic.add: RewriteBinOp((s, d) => m.IAdd(d, s), FlagM.CVZNX); break;

                case Mnemonic.adda: RewriteBinOp((s, d) => m.IAdd(d, s)); break;

                case Mnemonic.addi: RewriteArithmetic((s, d) => m.IAdd(d, s)); break;

                case Mnemonic.addq: RewriteAddSubq((s, d) => m.IAdd(d, s)); break;

                case Mnemonic.addx: RewriteAddSubx(m.IAdd); break;

                case Mnemonic.and: RewriteLogical((s, d) => m.And(d, s)); break;

                case Mnemonic.andi: RewriteLogical((s, d) => m.And(d, s)); break;

                case Mnemonic.asl: RewriteArithmetic((s, d) => m.Shl(d, s)); break;

                case Mnemonic.asr: RewriteShift((s, d) => m.Sar(d, s)); break;

/*
 *
 * Mnemonic Condition Encoding Test
 * T* True 0000 1
 * F* False 0001 0
 * HI High 0010 C L Z
 * LS Low or Same 0011 C V Z
 * VC Overflow Clear 1000 V
 * VS Overflow Set 1001 V
 */
                case Mnemonic.bclr: RewriteBclrBset("__bclr"); break;

                case Mnemonic.bcc: RewriteBcc(ConditionCode.UGE, FlagM.CF); break;

                case Mnemonic.bcs: RewriteBcc(ConditionCode.ULT, FlagM.CF); break;

                case Mnemonic.beq: RewriteBcc(ConditionCode.EQ, FlagM.ZF); break;

                case Mnemonic.bge: RewriteBcc(ConditionCode.GE, FlagM.NF | FlagM.VF); break;

                case Mnemonic.bgt: RewriteBcc(ConditionCode.GT, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Mnemonic.bhi: RewriteBcc(ConditionCode.UGT, FlagM.CF | FlagM.ZF); break;

                case Mnemonic.ble: RewriteBcc(ConditionCode.LE, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Mnemonic.bls: RewriteBcc(ConditionCode.ULE, FlagM.CF | FlagM.ZF); break;

                case Mnemonic.blt: RewriteBcc(ConditionCode.LT, FlagM.NF | FlagM.VF); break;

                case Mnemonic.bmi: RewriteBcc(ConditionCode.LT, FlagM.NF); break;

                case Mnemonic.bne: RewriteBcc(ConditionCode.NE, FlagM.ZF); break;

                case Mnemonic.bpl: RewriteBcc(ConditionCode.GT, FlagM.NF); break;

                case Mnemonic.bvc: RewriteBcc(ConditionCode.NO, FlagM.VF); break;

                case Mnemonic.bvs: RewriteBcc(ConditionCode.OV, FlagM.VF); break;

                case Mnemonic.bchg: RewriteBchg(); break;

                case Mnemonic.bkpt: RewriteBkpt(); break;

                case Mnemonic.bra: RewriteBra(); break;

                case Mnemonic.bset: RewriteBclrBset("__bset"); break;

                case Mnemonic.bsr: RewriteBsr(); break;

                case Mnemonic.btst: RewriteBtst(); break;

                case Mnemonic.callm: RewriteCallm(); break;

                case Mnemonic.cas: RewriteCas(); break;

                case Mnemonic.clr: RewriteClr(); break;

                case Mnemonic.chk: RewriteChk(); break;

                case Mnemonic.chk2: RewriteChk2(); break;

                case Mnemonic.cmp: RewriteCmp(); break;

                case Mnemonic.cmp2: RewriteCmp2(); break;

                case Mnemonic.cmpa: RewriteCmp(); break;

                case Mnemonic.cmpi: RewriteCmp(); break;

                case Mnemonic.cmpm: RewriteCmp(); break;

                case Mnemonic.dbcc: RewriteDbcc(ConditionCode.UGE, FlagM.CF); break;

                case Mnemonic.dbcs: RewriteDbcc(ConditionCode.ULT, FlagM.CF); break;

                case Mnemonic.dbeq: RewriteDbcc(ConditionCode.EQ, FlagM.ZF); break;

                case Mnemonic.dbge: RewriteDbcc(ConditionCode.GE, FlagM.NF | FlagM.VF); break;

                case Mnemonic.dbgt: RewriteDbcc(ConditionCode.GE, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Mnemonic.dbhi: RewriteDbcc(ConditionCode.UGT, FlagM.CF | FlagM.ZF); break;

                case Mnemonic.dble: RewriteDbcc(ConditionCode.GT, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Mnemonic.dbls: RewriteDbcc(ConditionCode.ULE, FlagM.CF | FlagM.ZF); break;

                case Mnemonic.dblt: RewriteDbcc(ConditionCode.LT, FlagM.NF | FlagM.VF); break;

                case Mnemonic.dbmi: RewriteDbcc(ConditionCode.LT, FlagM.NF); break;

                case Mnemonic.dbne: RewriteDbcc(ConditionCode.NE, FlagM.ZF); break;

                case Mnemonic.dbpl: RewriteDbcc(ConditionCode.GT, FlagM.NF); break;

                case Mnemonic.dbt: RewriteDbcc(ConditionCode.ALWAYS, 0); break;

                case Mnemonic.dbra: RewriteDbcc(ConditionCode.None, 0); break;

                case Mnemonic.divs: RewriteDiv(m.SDiv, PrimitiveType.Int16); break;

                case Mnemonic.divsl: RewriteDiv(m.SDiv, PrimitiveType.Int32); break;

                case Mnemonic.divu: RewriteDiv(m.UDiv, PrimitiveType.UInt16); break;

                case Mnemonic.divul: RewriteDiv(m.UDiv, PrimitiveType.UInt32); break;

                case Mnemonic.eor: RewriteLogical((s, d) => m.Xor(d, s)); break;

                case Mnemonic.eori: RewriteLogical((s, d) => m.Xor(d, s)); break;

                case Mnemonic.exg: RewriteExg(); break;

                case Mnemonic.ext: RewriteExt(); break;

                case Mnemonic.extb: RewriteExtb(); break;

                case Mnemonic.fadd: RewriteFBinOp((s, d) => m.FAdd(d, s)); break;

                //$REVIEW: the following don't respect NaN, but NaN typically doesn't exist in HLLs.
                case Mnemonic.fbf: m.Nop(); break;

                case Mnemonic.fblt: RewriteFbcc(ConditionCode.LT); break;

                case Mnemonic.fbgl: RewriteFbcc(ConditionCode.NE); break;

                case Mnemonic.fbgt: RewriteFbcc(ConditionCode.GT); break;

                case Mnemonic.fbgle: RewriteFbcc(ConditionCode.NE); break;    //$BUG: should be !is_nan

                case Mnemonic.fbne: RewriteFbcc(ConditionCode.NE); break;

                case Mnemonic.fbnge: RewriteFbcc(ConditionCode.LT); break;

                case Mnemonic.fbngl: RewriteFbcc(ConditionCode.EQ); break;

                case Mnemonic.fbngle: RewriteFbcc(ConditionCode.EQ); break;   //$BUG: should be is_nan

                case Mnemonic.fbnlt: RewriteFbcc(ConditionCode.GE); break;

                case Mnemonic.fbnle: RewriteFbcc(ConditionCode.GT); break;

                case Mnemonic.fbogl: RewriteFbcc(ConditionCode.NE); break;

                case Mnemonic.fbole: RewriteFbcc(ConditionCode.LE); break;

                case Mnemonic.fbolt: RewriteFbcc(ConditionCode.LT); break;

                case Mnemonic.fbogt: RewriteFbcc(ConditionCode.GT); break;

                case Mnemonic.fbor: RewriteFbcc(ConditionCode.EQ); break;     //$REVIEW: is this correct?

                case Mnemonic.fbseq: RewriteFbcc(ConditionCode.EQ); break;

                case Mnemonic.fbsf: RewriteFbcc(ConditionCode.NEVER); break;

                case Mnemonic.fbsne: RewriteFbcc(ConditionCode.NE); break;

                case Mnemonic.fbst: RewriteFbcc(ConditionCode.ALWAYS); break;

                case Mnemonic.fbuge: RewriteFbcc(ConditionCode.GE); break;

                case Mnemonic.fbugt: RewriteFbcc(ConditionCode.GT); break;

                case Mnemonic.fbult: RewriteFbcc(ConditionCode.LT); break;

                case Mnemonic.fbun: RewriteFbcc(ConditionCode.IS_NAN); break;

                case Mnemonic.fasin: RewriteFasin(); break;

                case Mnemonic.fintrz: RewriteFintrz(); break;

                case Mnemonic.fcmp: RewriteFcmp(); break;

                case Mnemonic.fdiv: RewriteFBinOp((s, d) => m.FDiv(d, s)); break;

                case Mnemonic.fmove: RewriteFmove(); break;

                case Mnemonic.fmovecr: RewriteFmovecr(); break;

                case Mnemonic.fmovem: RewriteMovem(i => Registers.GetRegister(i + Registers.fp0.Number)); break;

                case Mnemonic.fmul: RewriteFBinOp((s, d) => m.FMul(d, s)); break;

                case Mnemonic.fneg: RewriteFUnaryOp(m.Neg); break;

                case Mnemonic.fsqrt: RewriteFsqrt(); break;

                case Mnemonic.fsub: RewriteFBinOp((s, d) => m.FSub(d, s)); break;

                case Mnemonic.ftan: RewriteFtan(); break;

                case Mnemonic.jmp: RewriteJmp(); break;

                case Mnemonic.jsr: RewriteJsr(); break;

                case Mnemonic.lea: RewriteLea(); break;

                case Mnemonic.link: RewriteLink(); break;

                case Mnemonic.lsl: RewriteShift((s, d) => m.Shl(d, s)); break;

                case Mnemonic.lsr: RewriteShift((s, d) => m.Shr(d, s)); break;

                case Mnemonic.move: RewriteMove(true); break;

                case Mnemonic.move16: RewriteMove16(); break;

                case Mnemonic.movea: RewriteMove(false); break;

                case Mnemonic.movep: RewriteMovep(); break;

                case Mnemonic.moveq: RewriteMoveq(); break;

                case Mnemonic.moves: RewriteMoves(); break;

                case Mnemonic.movem: RewriteMovem(Registers.GetRegister); break;

                case Mnemonic.muls: RewriteMul((s, d) => m.SMul(d, s)); break;

                case Mnemonic.mulu: RewriteMul((s, d) => m.UMul(d, s)); break;

                case Mnemonic.nbcd: RewriteNbcd(); break;

                case Mnemonic.neg: RewriteUnary(s => m.Neg(s), AllConditions); break;

                case Mnemonic.negx: RewriteUnary(RewriteNegx, AllConditions); break;

                case Mnemonic.nop: m.Nop(); break;

                case Mnemonic.not: RewriteUnary(s => m.Comp(s), LogicalConditions); break;

                case Mnemonic.or: RewriteLogical((s, d) => m.Or(d, s)); break;

                case Mnemonic.ori: RewriteLogical((s, d) => m.Or(d, s)); break;

                case Mnemonic.pack: RewritePack(); break;

                case Mnemonic.pea: RewritePea(); break;

                case Mnemonic.pflushr: RewritePflushr(); break;

                case Mnemonic.ptest: RewritePtest(); break;

                case Mnemonic.rol: RewriteRotation(PseudoProcedure.Rol); break;

                case Mnemonic.ror: RewriteRotation(PseudoProcedure.Ror);  break;

                case Mnemonic.roxl: RewriteRotationX(PseudoProcedure.RolC);  break;

                case Mnemonic.roxr: RewriteRotationX(PseudoProcedure.RorC);  break;

                case Mnemonic.rtd: RewriteRtd(); break;

                case Mnemonic.rte: RewriteRte(); break;

                case Mnemonic.rtm: RewriteRtm(); break;

                case Mnemonic.rts: RewriteRts(); break;

                case Mnemonic.sbcd: RewriteSbcd(); break;

                case Mnemonic.scc: RewriteScc(ConditionCode.UGE, FlagM.CF); break;

                case Mnemonic.scs: RewriteScc(ConditionCode.ULT, FlagM.CF); break;

                case Mnemonic.seq: RewriteScc(ConditionCode.EQ, FlagM.ZF); break;

                case Mnemonic.sge: RewriteScc(ConditionCode.GE, FlagM.NF | FlagM.VF); break;

                case Mnemonic.sgt: RewriteScc(ConditionCode.GT, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Mnemonic.shi: RewriteScc(ConditionCode.UGT, FlagM.CF | FlagM.ZF); break;

                case Mnemonic.sle: RewriteScc(ConditionCode.LE, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Mnemonic.sls: RewriteScc(ConditionCode.ULE, FlagM.CF | FlagM.ZF); break;

                case Mnemonic.slt: RewriteScc(ConditionCode.LT, FlagM.NF | FlagM.ZF); break;

                case Mnemonic.smi: RewriteScc(ConditionCode.LT, FlagM.NF); break;

                case Mnemonic.sne: RewriteScc(ConditionCode.NE, FlagM.ZF); break;

                case Mnemonic.spl: RewriteScc(ConditionCode.GT, FlagM.NF); break;

                case Mnemonic.svc: RewriteScc(ConditionCode.NO, FlagM.VF); break;

                case Mnemonic.svs: RewriteScc(ConditionCode.OV, FlagM.VF); break;

                case Mnemonic.st: orw.RewriteMoveDst(instr.Operands[0], instr.Address, PrimitiveType.Bool, Constant.True()); break;

                case Mnemonic.sf: orw.RewriteMoveDst(instr.Operands[0], instr.Address, PrimitiveType.Bool, Constant.False()); break;

                case Mnemonic.stop: RewriteStop(); break;

                case Mnemonic.sub: RewriteArithmetic((s, d) => m.ISub(d, s)); break;

                case Mnemonic.suba: RewriteBinOp((s, d) => m.ISub(d, s)); break;

                case Mnemonic.subi: RewriteArithmetic((s, d) => m.ISub(d, s)); break;

                case Mnemonic.subq: RewriteAddSubq((s, d) => m.ISub(d, s)); break;

                case Mnemonic.subx: RewriteArithmetic((s, d) => m.ISub(m.ISub(d, s), binder.EnsureFlagGroup(Registers.ccr, (uint)FlagM.XF, "X", PrimitiveType.Bool))); break;

                case Mnemonic.swap: RewriteSwap(); break;

                case Mnemonic.trap: RewriteTrap(); break;

                case Mnemonic.trapcc: RewriteTrapCc(ConditionCode.UGE, FlagM.CF); break;

                case Mnemonic.trapcs: RewriteTrapCc(ConditionCode.ULT, FlagM.CF); break;

                case Mnemonic.trapeq: RewriteTrapCc(ConditionCode.EQ, FlagM.ZF); break;

                case Mnemonic.trapf: RewriteTrapCc(ConditionCode.NEVER, 0); break;

                case Mnemonic.trapge: RewriteTrapCc(ConditionCode.GE, FlagM.NF | FlagM.VF); break;

                case Mnemonic.trapgt: RewriteTrapCc(ConditionCode.GT, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Mnemonic.traphi: RewriteTrapCc(ConditionCode.UGT, FlagM.CF | FlagM.ZF); break;

                case Mnemonic.traple: RewriteTrapCc(ConditionCode.LE, FlagM.NF | FlagM.VF | FlagM.ZF); break;

                case Mnemonic.traplt: RewriteTrapCc(ConditionCode.LT, FlagM.CF | FlagM.VF); break;

                case Mnemonic.trapls: RewriteTrapCc(ConditionCode.ULE, FlagM.VF | FlagM.ZF); break;

                case Mnemonic.trapmi: RewriteTrapCc(ConditionCode.LT, FlagM.NF); break;

                case Mnemonic.trapne: RewriteTrapCc(ConditionCode.NE, FlagM.ZF); break;

                case Mnemonic.trappl: RewriteTrapCc(ConditionCode.GT, FlagM.NF); break;

                case Mnemonic.trapvc: RewriteTrapCc(ConditionCode.NO, FlagM.VF); break;

                case Mnemonic.trapvs: RewriteTrapCc(ConditionCode.OV, FlagM.VF); break;

                case Mnemonic.tas: RewriteTas(); break;

                case Mnemonic.tst: RewriteTst(); break;

                case Mnemonic.unlk: RewriteUnlk(); break;

                case Mnemonic.unpk: RewriteUnpk(); break;
                }
                yield return(new RtlInstructionCluster(
                                 addr,
                                 len,
                                 rtlInstructions.ToArray())
                {
                    Class = rtlc
                });
            }
            yield break;
        }
Beispiel #20
0
        private Expression RewriteJmpSrc(MachineOperand op)
        {
            var memOp = op as MemoryOperand;

            if (memOp == null)
            {
                throw new AddressCorrelatedException(
                          instrs.Current.Address,
                          "Invalid addressing mode for transfer functions.",
                          memOp.Mode);
            }
            var r   = frame.EnsureRegister(memOp.Register);
            var tmp = frame.CreateTemporary(op.Width);

            switch (memOp.Mode)
            {
            default:
                throw new AddressCorrelatedException(
                          instrs.Current.Address,
                          "Not implemented: addressing mode {0}.",
                          memOp.Mode);

            case AddressMode.RegDef:
                return(r);

            case AddressMode.Absolute:
                return(Address.Ptr16(memOp.EffectiveAddress));

            case AddressMode.AutoIncr:
                m.Assign(tmp, m.Load(op.Width, m.Load(PrimitiveType.Ptr16, r)));
                m.Assign(r, m.IAdd(r, memOp.Width.Size));
                break;

            case AddressMode.AutoIncrDef:
                m.Assign(tmp, m.Load(op.Width, r));
                m.Assign(r, m.IAdd(r, memOp.Width.Size));
                break;

            case AddressMode.AutoDecr:
                m.Assign(r, m.ISub(r, memOp.Width.Size));
                return(m.Load(op.Width, r));

            case AddressMode.AutoDecrDef:
                m.Assign(r, m.ISub(r, memOp.Width.Size));
                m.Assign(tmp, m.Load(op.Width, m.Load(PrimitiveType.Ptr16, r)));
                return(tmp);

            case AddressMode.Indexed:
                if (memOp.Register == Registers.pc)
                {
                    var offset   = (short)memOp.EffectiveAddress;
                    var addrBase = (long)rtlCluster.Address.ToLinear();
                    var addr     = Address.Ptr16((ushort)(2 + addrBase + offset));
                    return(addr);
                }
                else
                {
                    return(m.Load(
                               this.instrs.Current.DataWidth,
                               m.IAdd(r, Constant.Word16(memOp.EffectiveAddress))));
                }

            case AddressMode.IndexedDef:
                if (memOp.Register == Registers.pc)
                {
                    var offset   = (short)memOp.EffectiveAddress;
                    var addrBase = (long)rtlCluster.Address.ToLinear() + rtlCluster.Length;
                    var addr     = Constant.Word16((ushort)(addrBase + offset));
                    return(m.Load(
                               PrimitiveType.Word16,
                               addr));
                }
                else
                {
                    return(m.Load(
                               PrimitiveType.Ptr16,
                               m.IAdd(r, Constant.Word16(memOp.EffectiveAddress))));
                }
            }
            return(tmp);

            /*
             *  var immOp = op as ImmediateOperand;
             *  if (immOp != null)
             *  {
             *      return immOp.Value;
             *  }
             *  var addrOp = op as AddressOperand;
             *  if (addrOp != null)
             *  {
             *      return addrOp.Address;
             *  }
             *  throw new NotImplementedException();
             */
        }
Beispiel #21
0
        private Expression RewriteJmpSrc(MachineOperand op)
        {
            var memOp = op as MemoryOperand;

            if (memOp == null)
            {
                // PDP-11 always has a memory reference
                // for the destination of a transfer instruction.
                return(null);
            }
            var r = memOp.Register != null
                ? binder.EnsureRegister(memOp.Register)
                : null;

            var tmp = binder.CreateTemporary(op.Width);

            switch (memOp.Mode)
            {
            default:
                throw new AddressCorrelatedException(
                          dasm.Current.Address,
                          "Not implemented: addressing mode {0}.",
                          memOp.Mode);

            case AddressMode.RegDef:
                return(r);

            case AddressMode.Absolute:
                return(Address.Ptr16(memOp.EffectiveAddress));

            case AddressMode.AutoIncr:
                m.Assign(tmp, m.Mem(PrimitiveType.Ptr16, r));
                m.Assign(r, m.IAdd(r, memOp.Width.Size));
                break;

            case AddressMode.AutoIncrDef:
                m.Assign(tmp, m.Mem(op.Width, r));
                m.Assign(r, m.IAdd(r, memOp.Width.Size));
                break;

            case AddressMode.AutoDecr:
                m.Assign(r, m.ISub(r, memOp.Width.Size));
                return(m.Mem(op.Width, r));

            case AddressMode.AutoDecrDef:
                m.Assign(r, m.ISub(r, memOp.Width.Size));
                m.Assign(tmp, m.Mem(op.Width, m.Mem(PrimitiveType.Ptr16, r)));
                return(tmp);

            case AddressMode.Indexed:
                if (memOp.Register == Registers.pc)
                {
                    var offset   = (short)memOp.EffectiveAddress;
                    var addrBase = (long)instr.Address.ToLinear();
                    var addr     = Address.Ptr16((ushort)(instr.Length + addrBase + offset));
                    return(addr);
                }
                else
                {
                    return(m.Mem(
                               this.dasm.Current.DataWidth,
                               m.IAdd(r, Constant.Word16(memOp.EffectiveAddress))));
                }

            case AddressMode.IndexedDef:
                if (memOp.Register == Registers.pc)
                {
                    var offset   = (short)memOp.EffectiveAddress;
                    var addrBase = (long)instr.Address.ToLinear() + instr.Length;
                    var addr     = Constant.Word16((ushort)(addrBase + offset));
                    return(m.Mem(
                               PrimitiveType.Word16,
                               addr));
                }
                else
                {
                    return(m.Mem(
                               PrimitiveType.Ptr16,
                               m.IAdd(r, Constant.Word16(memOp.EffectiveAddress))));
                }
            }
            return(tmp);

            /*
             *  var immOp = op as ImmediateOperand;
             *  if (immOp != null)
             *  {
             *      return immOp.Value;
             *  }
             *  var addrOp = op as AddressOperand;
             *  if (addrOp != null)
             *  {
             *      return addrOp.Address;
             *  }
             *  throw new NotImplementedException();
             */
        }
Beispiel #22
0
        private Expression RewriteCondition(Expression left, Expression right)
        {
            Expression e;

            switch (instr.Condition.Type)
            {
            case ConditionType.Tr: e = Constant.True(); break;

            case ConditionType.Never:
            case ConditionType.Never64:
                e = Constant.False(); break;

            case ConditionType.Eq:
            case ConditionType.Eq64:
                e = m.Eq(left, right); break;

            case ConditionType.Ne:
            case ConditionType.Ne64:
                e = m.Ne(left, right); break;

            case ConditionType.Lt:
            case ConditionType.Lt64:
                e = m.Lt(left, right); break;

            case ConditionType.Le:
            case ConditionType.Le64:
                e = m.Le(left, right); break;

            case ConditionType.Ge:
            case ConditionType.Ge64:
                e = m.Ge(left, right); break;

            case ConditionType.Gt:
            case ConditionType.Gt64:
                e = m.Gt(left, right); break;

            case ConditionType.Ult:
            case ConditionType.Ult64:
                e = m.Ult(left, right); break;

            case ConditionType.Ule:
            case ConditionType.Ule64:
                e = m.Ule(left, right); break;

            case ConditionType.Uge:
            case ConditionType.Uge64:
                e = m.Uge(left, right); break;

            case ConditionType.Ugt:
            case ConditionType.Ugt64:
                e = m.Ugt(left, right); break;

            case ConditionType.Uv:
            case ConditionType.Uv64:
                e = m.Test(ConditionCode.NO, m.USub(left, right)); break;

            case ConditionType.Sv:
            case ConditionType.Sv64:
                e = m.Test(ConditionCode.NO, m.ISub(left, right)); break;

            case ConditionType.Nuv:
            case ConditionType.Nuv64:
                e = m.Test(ConditionCode.OV, m.USub(left, right)); break;

            case ConditionType.Nsv:
            case ConditionType.Nsv64:
                e = m.Test(ConditionCode.OV, m.ISub(left, right)); break;

            case ConditionType.Even:
            case ConditionType.Even64:
                e = m.Eq0(m.And(left, 1)); break;

            case ConditionType.Odd:
            case ConditionType.Odd64:
                e = m.Ne0(m.And(left, 1)); break;

            case ConditionType.Vnz:
            case ConditionType.Vnz64:
                e = m.And(m.Eq(left, right), m.Test(ConditionCode.NO, m.ISub(left, right))); break;

            case ConditionType.Znv:
            case ConditionType.Znv64:
                e = m.And(m.Ne(left, right), m.Test(ConditionCode.OV, m.ISub(left, right))); break;

            default:
                throw new NotImplementedException(instr.Condition.ToString());
            }
            return(e);
        }