public override SparcInstruction Decode(uint wInstr, SparcDisassembler dasm) { uint i = ((wInstr >> 25) & 0xF) + offset; SparcInstruction instr = branchOps[i].Decode(wInstr, dasm); instr.InstructionClass |= ((wInstr & (1u << 29)) != 0) ? InstrClass.Annul : 0; return(instr); }
public SparcRewriter(SparcArchitecture arch, IEnumerator <SparcInstruction> instrs, SparcProcessorState state, IStorageBinder binder, IRewriterHost host) { this.arch = arch; this.binder = binder; this.host = host; this.dasm = new LookaheadEnumerator <SparcInstruction>(instrs); this.instrCur = null !; this.m = null !; this.rdr = null !; }
public SparcRewriter(SparcArchitecture arch, EndianImageReader rdr, SparcProcessorState state, IStorageBinder binder, IRewriterHost host) { this.arch = arch; this.binder = binder; this.host = host; this.rdr = rdr; this.dasm = new LookaheadEnumerator <SparcInstruction>(CreateDisassemblyStream(rdr)); this.instrCur = null !; this.m = null !; }
public override SparcInstruction Decode(SparcDisassembler dasm, uint wInstr) { uint i = ((wInstr >> 25) & 0xF) + offset; SparcInstruction instr = branchOps[i].Decode(dasm, wInstr); if ((wInstr & (1u << 29)) != 0) { instr.Annul = true; } return(instr); }
public IEnumerator <RtlInstructionCluster> GetEnumerator() { while (dasm.MoveNext()) { instrCur = dasm.Current; var addr = instrCur.Address; var rtlInstructions = new List <RtlInstruction>(); rtlc = InstrClass.Linear; m = new RtlEmitter(rtlInstructions); switch (instrCur.Mnemonic) { default: EmitUnitTest(); host.Warn( instrCur.Address, "SPARC instruction '{0}' is not supported yet.", instrCur.Mnemonic); goto case Mnemonic.illegal; case Mnemonic.illegal: rtlc = InstrClass.Invalid; m.Invalid(); break; case Mnemonic.add: RewriteAlu(m.IAdd, false); break; case Mnemonic.addcc: RewriteAluCc(m.IAdd, false); break; case Mnemonic.addx: RewriteAddxSubx(m.IAdd, false); break; case Mnemonic.addxcc: RewriteAddxSubx(m.IAdd, true); break; case Mnemonic.and: RewriteAlu(m.And, false); break; case Mnemonic.andcc: RewriteAluCc(m.And, false); break; case Mnemonic.andn: RewriteAlu(m.And, true); break; case Mnemonic.ba: RewriteBranch(Constant.True()); break; case Mnemonic.bn: RewriteBranch(Constant.False()); break; case Mnemonic.bne: RewriteBranch(m.Test(ConditionCode.NE, Grf(FlagM.ZF))); break; case Mnemonic.be: RewriteBranch(m.Test(ConditionCode.EQ, Grf(FlagM.ZF))); break; case Mnemonic.bg: RewriteBranch(m.Test(ConditionCode.GT, Grf(FlagM.ZF | FlagM.NF | FlagM.VF))); break; case Mnemonic.bge: RewriteBranch(m.Test(ConditionCode.GE, Grf(FlagM.NF | FlagM.VF))); break; case Mnemonic.bgu: RewriteBranch(m.Test(ConditionCode.UGE, Grf(FlagM.CF | FlagM.ZF))); break; case Mnemonic.bl: RewriteBranch(m.Test(ConditionCode.LT, Grf(FlagM.ZF | FlagM.NF | FlagM.VF))); break; case Mnemonic.ble: RewriteBranch(m.Test(ConditionCode.LE, Grf(FlagM.ZF | FlagM.NF | FlagM.VF))); break; case Mnemonic.bleu: RewriteBranch(m.Test(ConditionCode.ULE, Grf(FlagM.CF | FlagM.ZF))); break; case Mnemonic.bcc: RewriteBranch(m.Test(ConditionCode.UGE, Grf(FlagM.CF))); break; case Mnemonic.bcs: RewriteBranch(m.Test(ConditionCode.ULT, Grf(FlagM.CF))); break; case Mnemonic.bneg: RewriteBranch(m.Test(ConditionCode.LT, Grf(FlagM.NF))); break; case Mnemonic.bpos: RewriteBranch(m.Test(ConditionCode.GE, Grf(FlagM.NF))); break; // Z //case Opcode.bgu not (C or Z) //case Opcode.bleu (C or Z) //case Opcode.bcc not C //case Opcode.bcs C //case Opcode.bpos not N //case Opcode.bneg N //case Opcode.bvc not V //case Opcode.bvs V case Mnemonic.call: RewriteCall(); break; case Mnemonic.fabss: RewriteFabss(); break; case Mnemonic.fadds: RewriteFadds(); break; case Mnemonic.fbne: RewriteBranch(m.Test(ConditionCode.NE, Grf(FlagM.LF | FlagM.GF))); break; case Mnemonic.fba: RewriteBranch(Constant.True()); break; case Mnemonic.fbn: RewriteBranch(Constant.False()); break; case Mnemonic.fbu: RewriteBranch(m.Test(ConditionCode.NE, Grf(FlagM.UF))); break; case Mnemonic.fbg: RewriteBranch(m.Test(ConditionCode.GT, Grf(FlagM.GF))); break; case Mnemonic.fbug: RewriteBranch(m.Test(ConditionCode.GT, Grf(FlagM.GF | FlagM.UF))); break; //case Opcode.fbug : on Unordered or Greater G or U //case Opcode.fbl : on Less L case Mnemonic.fbul: RewriteBranch(m.Test(ConditionCode.LT, Grf(FlagM.GF | FlagM.UF))); break; //case Opcode.fbul : on Unordered or Less L or U //case Opcode.fblg : on Less or Greater L or G //case Opcode.fbne : on Not Equal L or G or U //case Opcode.fbe : on Equal E case Mnemonic.fbue: RewriteBranch(m.Test(ConditionCode.EQ, Grf(FlagM.EF | FlagM.UF))); break; case Mnemonic.fbuge: RewriteBranch(m.Test(ConditionCode.GE, Grf(FlagM.EF | FlagM.GF | FlagM.UF))); break; //case Opcode.fble : on Less or Equal E or L //case Opcode.fbule : on Unordered or Less or Equal E or L or U case Mnemonic.fbule: RewriteBranch(m.Test(ConditionCode.LE, Grf(FlagM.EF | FlagM.LF | FlagM.UF))); break; case Mnemonic.fbge: RewriteBranch(m.Test(ConditionCode.GE, Grf(FlagM.EF | FlagM.GF))); break; // case Opcode.FBO : on Ordered E or L or G case Mnemonic.fcmpes: RewriteFcmpes(); break; case Mnemonic.fcmpd: RewriteFcmpd(); break; case Mnemonic.fcmpq: RewriteFcmpq(); break; case Mnemonic.fcmps: RewriteFcmps(); break; case Mnemonic.fdivd: RewriteFdivs(); break; case Mnemonic.fdivs: RewriteFdivd(); break; case Mnemonic.fdtos: RewriteFdtos(); break; case Mnemonic.fitod: RewriteFitod(); break; case Mnemonic.fitoq: RewriteFitoq(); break; case Mnemonic.fitos: RewriteFitos(); break; case Mnemonic.fmovs: RewriteFmovs(); break; case Mnemonic.fmuls: RewriteFmuls(); break; case Mnemonic.fnegs: RewriteFmovs(); break; case Mnemonic.fstod: RewriteFstod(); break; case Mnemonic.fsubs: RewriteFsubs(); break; case Mnemonic.jmpl: RewriteJmpl(); break; case Mnemonic.ld: RewriteLoad(PrimitiveType.Word32); break; case Mnemonic.lddf: RewriteLoad(PrimitiveType.Real64); break; case Mnemonic.ldf: RewriteLoad(PrimitiveType.Real32); break; case Mnemonic.ldd: RewriteLoad(PrimitiveType.Word64); break; case Mnemonic.ldsb: RewriteLoad(PrimitiveType.SByte); break; case Mnemonic.ldsh: RewriteLoad(PrimitiveType.Int16); break; case Mnemonic.ldstub: RewriteLdstub(); break; case Mnemonic.ldub: RewriteLoad(PrimitiveType.Byte); break; case Mnemonic.lduh: RewriteLoad(PrimitiveType.Word16); break; case Mnemonic.ldfsr: RewriteLoad(PrimitiveType.Word32); break; case Mnemonic.mulscc: RewriteMulscc(); break; case Mnemonic.or: RewriteAlu(m.Or, false); break; case Mnemonic.orcc: RewriteAluCc(m.Or, false); break; case Mnemonic.restore: RewriteRestore(); break; case Mnemonic.rett: RewriteRett(); break; case Mnemonic.save: RewriteSave(); break; case Mnemonic.sethi: RewriteSethi(); break; case Mnemonic.sdiv: RewriteAlu(m.SDiv, false); break; case Mnemonic.sdivcc: RewriteAlu(m.SDiv, false); break; case Mnemonic.sll: RewriteAlu(m.Shl, false); break; case Mnemonic.smul: RewriteAlu(m.SMul, false); break; case Mnemonic.smulcc: RewriteAluCc(m.SMul, false); break; case Mnemonic.sra: RewriteAlu(m.Sar, false); break; case Mnemonic.srl: RewriteAlu(m.Shr, false); break; case Mnemonic.st: RewriteStore(PrimitiveType.Word32); break; case Mnemonic.stb: RewriteStore(PrimitiveType.Byte); break; case Mnemonic.std: RewriteStore(PrimitiveType.Word64); break; case Mnemonic.stdf: RewriteStore(PrimitiveType.Real64); break; case Mnemonic.stf: RewriteStore(PrimitiveType.Real32); break; case Mnemonic.sth: RewriteStore(PrimitiveType.Word16); break; case Mnemonic.stfsr: RewriteStore(PrimitiveType.Word32); break; case Mnemonic.sub: RewriteAlu(m.ISub, false); break; case Mnemonic.subcc: RewriteAluCc(m.ISub, false); break; case Mnemonic.subx: RewriteAddxSubx(m.ISub, false); break; case Mnemonic.subxcc: RewriteAddxSubx(m.ISub, true); break; case Mnemonic.ta: RewriteTrap(Constant.True()); break; case Mnemonic.tn: RewriteTrap(Constant.False()); break; case Mnemonic.tne: RewriteTrap(m.Test(ConditionCode.NE, Grf(FlagM.ZF))); break; case Mnemonic.te: RewriteTrap(m.Test(ConditionCode.EQ, Grf(FlagM.ZF))); break; case Mnemonic.udiv: RewriteAlu(m.UDiv, false); break; case Mnemonic.udivcc: RewriteAluCc(m.UDiv, false); break; case Mnemonic.umul: RewriteAlu(m.UMul, false); break; case Mnemonic.umulcc: RewriteAluCc(m.UMul, false); break; case Mnemonic.unimp: m.Invalid(); break; case Mnemonic.xor: RewriteAlu(m.Xor, false); break; case Mnemonic.xorcc: RewriteAlu(m.Xor, true); break; case Mnemonic.xnor: RewriteAlu(XNor, false); break; case Mnemonic.xnorcc: RewriteAlu(XNor, true); break; } yield return(new RtlInstructionCluster(addr, 4, rtlInstructions.ToArray()) { Class = rtlc }); } }
public IEnumerator <RtlInstructionCluster> GetEnumerator() { while (dasm.MoveNext()) { instrCur = dasm.Current; ric = new RtlInstructionCluster(instrCur.Address, 4); ric.Class = RtlClass.Linear; emitter = new RtlEmitter(ric.Instructions); switch (instrCur.Opcode) { default: throw new AddressCorrelatedException( instrCur.Address, "Rewriting SPARC opcode '{0}' is not supported yet.", instrCur.Opcode); case Opcode.add: RewriteAlu(Operator.IAdd); break; case Opcode.addcc: RewriteAluCc(Operator.IAdd); break; case Opcode.and: RewriteAlu(Operator.And); break; case Opcode.andcc: RewriteAluCc(Operator.And); break; case Opcode.ba: RewriteBranch(Constant.True()); break; case Opcode.bn: RewriteBranch(Constant.False()); break; case Opcode.bne: RewriteBranch(emitter.Test(ConditionCode.NE, Grf(FlagM.ZF))); break; case Opcode.be: RewriteBranch(emitter.Test(ConditionCode.EQ, Grf(FlagM.ZF))); break; // Z //case Opcode.bg not (Z or (N xor V)) //case Opcode.ble Z or (N xor V) //case Opcode.bge not (N xor V) //case Opcode.bl N xor V //case Opcode.bgu not (C or Z) //case Opcode.bleu (C or Z) //case Opcode.bcc not C //case Opcode.bcs C //case Opcode.bpos not N //case Opcode.bneg N //case Opcode.bvc not V //case Opcode.bvs V case Opcode.call: RewriteCall(); break; case Opcode.fbne: RewriteBranch(emitter.Test(ConditionCode.NE, Grf(FlagM.LF | FlagM.GF))); break; case Opcode.fba: RewriteBranch(Constant.True()); break; case Opcode.fbn: RewriteBranch(Constant.False()); break; //case Opcode.fbu : on Unordered U //case Opcode.fbg : RewriteBranch(emitter.Test(ConditionCode.GT, Grf(FlagM.GF))); break; //case Opcode.fbug : on Unordered or Greater G or U //case Opcode.fbl : on Less L //case Opcode.fbul : on Unordered or Less L or U //case Opcode.fblg : on Less or Greater L or G //case Opcode.fbne : on Not Equal L or G or U //case Opcode.fbe : on Equal E //case Opcode.fbue : on Unordered or Equal E or U //case Opcode.fbge : on Greater or Equal E or G //case Opcode.fbuge : on Unordered or Greater or Equal E or G or U //case Opcode.fble : on Less or Equal E or L //case Opcode.fbule : on Unordered or Less or Equal E or L or U // case Opcode.FBO : on Ordered E or L or G case Opcode.fitod: RewriteFitod(); break; case Opcode.fitoq: RewriteFitoq(); break; case Opcode.fitos: RewriteFitos(); break; case Opcode.jmpl: RewriteJmpl(); break; case Opcode.ldsb: RewriteLoad(PrimitiveType.SByte); break; case Opcode.mulscc: RewriteMulscc(); break; case Opcode.or: RewriteAlu(Operator.Or); break; case Opcode.orcc: RewriteAluCc(Operator.Or); break; case Opcode.rett: RewriteRett(); break; case Opcode.sethi: RewriteSethi(); break; case Opcode.sdiv: RewriteAlu(Operator.SDiv); break; case Opcode.sdivcc: RewriteAlu(Operator.SDiv); break; case Opcode.sll: RewriteAlu(Operator.Shl); break; case Opcode.smul: RewriteAlu(Operator.SMul); break; case Opcode.smulcc: RewriteAlu(Operator.SMul); break; case Opcode.sth: RewriteStore(PrimitiveType.Word16); break; case Opcode.ta: RewriteTrap(Constant.True()); break; case Opcode.tn: RewriteTrap(Constant.False()); break; case Opcode.tne: RewriteTrap(emitter.Test(ConditionCode.NE, Grf(FlagM.ZF))); break; case Opcode.te: RewriteTrap(emitter.Test(ConditionCode.EQ, Grf(FlagM.ZF))); break; case Opcode.udiv: RewriteAlu(Operator.UDiv); break; case Opcode.udivcc: RewriteAluCc(Operator.UDiv); break; case Opcode.umul: RewriteAlu(Operator.UMul); break; case Opcode.umulcc: RewriteAluCc(Operator.UMul); break; } yield return(ric); } }
public IEnumerator <RtlInstructionCluster> GetEnumerator() { while (dasm.MoveNext()) { instrCur = dasm.Current; ric = new RtlInstructionCluster(instrCur.Address, 4); ric.Class = RtlClass.Linear; emitter = new RtlEmitter(ric.Instructions); switch (instrCur.Opcode) { default: throw new AddressCorrelatedException( instrCur.Address, "Rewriting SPARC opcode '{0}' is not supported yet.", instrCur.Opcode); case Opcode.add: RewriteAlu(emitter.IAdd, false); break; case Opcode.addcc: RewriteAluCc(emitter.IAdd, false); break; case Opcode.addx: RewriteAddxSubx(emitter.IAdd, false); break; case Opcode.addxcc: RewriteAddxSubx(emitter.IAdd, true); break; case Opcode.and: RewriteAlu(emitter.And, false); break; case Opcode.andcc: RewriteAluCc(emitter.And, false); break; case Opcode.andn: RewriteAlu(emitter.And, true); break; case Opcode.ba: RewriteBranch(Constant.True()); break; case Opcode.bn: RewriteBranch(Constant.False()); break; case Opcode.bne: RewriteBranch(emitter.Test(ConditionCode.NE, Grf(FlagM.ZF))); break; case Opcode.be: RewriteBranch(emitter.Test(ConditionCode.EQ, Grf(FlagM.ZF))); break; case Opcode.bg: RewriteBranch(emitter.Test(ConditionCode.GT, Grf(FlagM.ZF | FlagM.NF | FlagM.VF))); break; case Opcode.bge: RewriteBranch(emitter.Test(ConditionCode.GE, Grf(FlagM.NF | FlagM.VF))); break; case Opcode.bgu: RewriteBranch(emitter.Test(ConditionCode.UGE, Grf(FlagM.CF | FlagM.ZF))); break; case Opcode.bl: RewriteBranch(emitter.Test(ConditionCode.LT, Grf(FlagM.ZF | FlagM.NF | FlagM.VF))); break; case Opcode.ble: RewriteBranch(emitter.Test(ConditionCode.LE, Grf(FlagM.ZF | FlagM.NF | FlagM.VF))); break; case Opcode.bleu: RewriteBranch(emitter.Test(ConditionCode.ULE, Grf(FlagM.CF | FlagM.ZF))); break; case Opcode.bcc: RewriteBranch(emitter.Test(ConditionCode.UGE, Grf(FlagM.CF))); break; case Opcode.bcs: RewriteBranch(emitter.Test(ConditionCode.ULT, Grf(FlagM.CF))); break; case Opcode.bneg: RewriteBranch(emitter.Test(ConditionCode.LT, Grf(FlagM.NF))); break; case Opcode.bpos: RewriteBranch(emitter.Test(ConditionCode.GE, Grf(FlagM.NF))); break; // Z //case Opcode.bgu not (C or Z) //case Opcode.bleu (C or Z) //case Opcode.bcc not C //case Opcode.bcs C //case Opcode.bpos not N //case Opcode.bneg N //case Opcode.bvc not V //case Opcode.bvs V case Opcode.call: RewriteCall(); break; case Opcode.fabss: RewriteFabss(); break; case Opcode.fadds: RewriteFadds(); break; case Opcode.fbne: RewriteBranch(emitter.Test(ConditionCode.NE, Grf(FlagM.LF | FlagM.GF))); break; case Opcode.fba: RewriteBranch(Constant.True()); break; case Opcode.fbn: RewriteBranch(Constant.False()); break; case Opcode.fbu: RewriteBranch(emitter.Test(ConditionCode.NE, Grf(FlagM.UF))); break; case Opcode.fbg: RewriteBranch(emitter.Test(ConditionCode.GT, Grf(FlagM.GF))); break; case Opcode.fbug: RewriteBranch(emitter.Test(ConditionCode.GT, Grf(FlagM.GF | FlagM.UF))); break; //case Opcode.fbug : on Unordered or Greater G or U //case Opcode.fbl : on Less L case Opcode.fbul: RewriteBranch(emitter.Test(ConditionCode.LT, Grf(FlagM.GF | FlagM.UF))); break; //case Opcode.fbul : on Unordered or Less L or U //case Opcode.fblg : on Less or Greater L or G //case Opcode.fbne : on Not Equal L or G or U //case Opcode.fbe : on Equal E //case Opcode.fbue : on Unordered or Equal E or U //case Opcode.fbge : on Greater or Equal E or G //case Opcode.fbuge : on Unordered or Greater or Equal E or G or U case Opcode.fbuge: RewriteBranch(emitter.Test(ConditionCode.GE, Grf(FlagM.EF | FlagM.GF | FlagM.UF))); break; //case Opcode.fble : on Less or Equal E or L //case Opcode.fbule : on Unordered or Less or Equal E or L or U case Opcode.fbule: RewriteBranch(emitter.Test(ConditionCode.LE, Grf(FlagM.EF | FlagM.LF | FlagM.UF))); break; // case Opcode.FBO : on Ordered E or L or G case Opcode.fcmpes: RewriteFcmpes(); break; case Opcode.fdivs: RewriteFdivs(); break; case Opcode.fitod: RewriteFitod(); break; case Opcode.fitoq: RewriteFitoq(); break; case Opcode.fitos: RewriteFitos(); break; case Opcode.fmovs: RewriteFmovs(); break; case Opcode.fmuls: RewriteFmuls(); break; case Opcode.fnegs: RewriteFmovs(); break; case Opcode.fsubs: RewriteFsubs(); break; case Opcode.jmpl: RewriteJmpl(); break; case Opcode.ld: RewriteLoad(PrimitiveType.Word32); break; case Opcode.lddf: RewriteDLoad(PrimitiveType.Real64); break; case Opcode.ldf: RewriteLoad(PrimitiveType.Real32); break; case Opcode.ldd: RewriteLoad(PrimitiveType.Word64); break; case Opcode.ldsb: RewriteLoad(PrimitiveType.SByte); break; case Opcode.ldsh: RewriteLoad(PrimitiveType.Int16); break; case Opcode.ldub: RewriteLoad(PrimitiveType.Byte); break; case Opcode.lduh: RewriteLoad(PrimitiveType.Word16); break; case Opcode.mulscc: RewriteMulscc(); break; case Opcode.or: RewriteAlu(emitter.Or, false); break; case Opcode.orcc: RewriteAluCc(emitter.Or, false); break; case Opcode.restore: RewriteRestore(); break; case Opcode.rett: RewriteRett(); break; case Opcode.save: RewriteSave(); break; case Opcode.sethi: RewriteSethi(); break; case Opcode.sdiv: RewriteAlu(emitter.SDiv, false); break; case Opcode.sdivcc: RewriteAlu(emitter.SDiv, false); break; case Opcode.sll: RewriteAlu(emitter.Shl, false); break; case Opcode.smul: RewriteAlu(emitter.SMul, false); break; case Opcode.smulcc: RewriteAluCc(emitter.SMul, false); break; case Opcode.sra: RewriteAlu(emitter.Sar, false); break; case Opcode.srl: RewriteAlu(emitter.Shr, false); break; case Opcode.st: RewriteStore(PrimitiveType.Word32); break; case Opcode.stb: RewriteStore(PrimitiveType.Byte); break; case Opcode.std: RewriteStore(PrimitiveType.Word64); break; case Opcode.stf: RewriteStore(PrimitiveType.Real32); break; case Opcode.sth: RewriteStore(PrimitiveType.Word16); break; case Opcode.sub: RewriteAlu(emitter.ISub, false); break; case Opcode.subcc: RewriteAluCc(emitter.ISub, false); break; case Opcode.subx: RewriteAddxSubx(emitter.ISub, false); break; case Opcode.subxcc: RewriteAddxSubx(emitter.ISub, true); break; case Opcode.ta: RewriteTrap(Constant.True()); break; case Opcode.tn: RewriteTrap(Constant.False()); break; case Opcode.tne: RewriteTrap(emitter.Test(ConditionCode.NE, Grf(FlagM.ZF))); break; case Opcode.te: RewriteTrap(emitter.Test(ConditionCode.EQ, Grf(FlagM.ZF))); break; case Opcode.udiv: RewriteAlu(emitter.UDiv, false); break; case Opcode.udivcc: RewriteAluCc(emitter.UDiv, false); break; case Opcode.umul: RewriteAlu(emitter.UMul, false); break; case Opcode.umulcc: RewriteAluCc(emitter.UMul, false); break; case Opcode.unimp: emitter.Invalid(); break; case Opcode.xor: RewriteAlu(emitter.Xor, false); break; } yield return(ric); } }
private SparcInstruction Instr(Opcode opcode, params object[] ops) { var instr = new SparcInstruction { Opcode = opcode }; if (ops.Length > 0) { instr.Op1 = Op(ops[0]); if (ops.Length > 1) { instr.Op2 = Op(ops[1]); if (ops.Length > 2) { instr.Op3 = Op(ops[2]); } } } return instr; }