public Rewriter(M68kArchitecture m68kArchitecture, EndianImageReader rdr, M68kState m68kState, IStorageBinder binder, IRewriterHost host) { this.arch = m68kArchitecture; this.state = m68kState; this.binder = binder; this.host = host; this.rdr = rdr; this.dasm = arch.CreateDisassemblerImpl(rdr).GetEnumerator(); this.instr = default !;
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; }
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; }
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; }