/* * $Id$ * * Copyright (C) 2003-2016 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.assembler.x86; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.io.Writer; import java.util.Collection; import org.jnode.assembler.Label; import org.jnode.assembler.NativeStream; import org.jnode.assembler.ObjectResolver; import org.jnode.assembler.UnresolvedObjectRefException; import org.jnode.assembler.x86.X86Register.CRX; import org.jnode.assembler.x86.X86Register.GPR; import org.jnode.assembler.x86.X86Register.GPR32; import org.jnode.assembler.x86.X86Register.GPR64; import org.jnode.assembler.x86.X86Register.SR; import org.jnode.assembler.x86.X86Register.XMM; import org.jnode.util.NumberUtils; import org.jnode.vm.classmgr.VmType; import org.jnode.vm.x86.X86CpuID; /** * Debug version of AbstractX86Stream. * * @author Ewout Prangsma (epr@users.sourceforge.net) * @author Levente S\u00e1ntha (lsantha@users.sourceforge.net) */ public class X86TextAssembler extends X86Assembler implements X86Operation { class ObjectInfoImpl extends NativeStream.ObjectInfo { public void markEnd() { println(";\n; -- End of Object --\n;"); } } static class ObjectRefImpl extends NativeStream.ObjectRef { public ObjectRefImpl(Object object) { super(object); } public int getOffset() throws UnresolvedObjectRefException { return 0; } public boolean isResolved() { return true; } @Override public boolean isPublic() { //todo return false; } @Override public boolean isRelJump() { //todo return false; } @Override public void setPublic() { //todo } @Override public void setRelJump() { //todo } @Override public void setOffset(int offset) { //todo } public void addUnresolvedLink(int offset, int patchSize) { // TODO Auto-generated method stub } public void link(ObjectRef objectRef) throws UnresolvedObjectRefException { } } private static final String ccName(int jumpOpcode) { final String opc; switch (jumpOpcode) { case JA: opc = "a"; break; case JAE: opc = "ae"; break; case JB: opc = "b"; break; case JBE: opc = "be"; break; case JE: opc = "e"; break; case JNE: opc = "ne"; break; case JLE: opc = "le"; break; case JL: opc = "l"; break; case JGE: opc = "ge"; break; case JG: opc = "g"; break; default: throw new RuntimeException("Unknown jump opcode " + jumpOpcode); } return opc; } private static String getSSEOperationName(int operation) { switch (operation) { case SSE_ADD: return "ADDS"; case SSE_SUB: return "SUBS"; case SSE_MUL: return "MULS"; case SSE_DIV: return "DIVS"; default: throw new IllegalArgumentException("Unknown SSE operation " + operation); } } private final StringBuffer buf = new StringBuffer(); private final byte[] dummy = new byte[0]; private int idx = 0; final PrintWriter out; private final String stripPrefix; /** * Initialize this instance * * @param out */ public X86TextAssembler(Writer out, X86CpuID cpuId, Mode mode) { this(out, cpuId, mode, null); } /** * Initialize this instance * * @param out */ public X86TextAssembler(Writer out, X86CpuID cpuId, Mode mode, String stripPrefix) { super(cpuId, mode); this.out = new PrintWriter(out); this.stripPrefix = stripPrefix; } public int align(int value) { println("\talign " + value); return 0; } /** * Remove all data and references. */ public void clear() { buf.setLength(0); idx = 0; } private String disp(int v) { if (v > 0) { return "+" + v; } else if (v < 0) { return "" + v; } else { return ""; } } private String disp0(int v) { if (v > 0) { return "+" + v; } else if (v < 0) { return "" + v; } else { return "0"; } } private String size(int operandSize) { switch (operandSize) { case BITS8: return "byte"; case BITS16: return "word"; case BITS32: return "dword"; case BITS64: return "qword"; default: throw new IllegalArgumentException("Invalid operand size " + operandSize); } } /** * Flush the contents of the used stream. */ public void flush() throws IOException { out.print(buf.toString()); idx += buf.length(); buf.setLength(0); out.flush(); } public int get32(int offset) { return 0; } public int get8(int offset) { return 0; } public long getBaseAddr() { return 0; } public byte[] getBytes() { return dummy; } public int getLength() { return idx + buf.length(); } public ObjectRef getObjectRef(Object keyObj) { return new ObjectRefImpl(keyObj); } public Collection<? extends ObjectRef> getObjectRefs() { return null; } public ObjectResolver getResolver() { return null; } public Collection<?> getUnresolvedObjectRefs() { return null; } public boolean hasUnresolvedObjectRefs() { return false; } /** * Is logging enabled. This method will only return true on on debug like * implementations. * * @return boolean */ public boolean isLogEnabled() { return true; } public boolean isTextStream() { return true; } private String label(Object label) { String s = label.toString(); if (stripPrefix != null) { if (s.startsWith(stripPrefix)) { s = s.substring(stripPrefix.length()); } } return s; } /** * Write a log message. This method is only implemented on debug like * implementations. * * @param msg */ public void log(Object msg) { println(";\n; " + msg + "\n;"); } public int print(String msg) { final int rc = idx + buf.length(); buf.append(msg); return rc; } public int println(String msg) { final int rc = idx + buf.length(); buf.append(msg); buf.append('\n'); return rc; } public void set64(int offset, long v64) { } public void set32(int offset, int v32) { } public void set16(int offset, int v16) { } public void set8(int offset, int v8) { } public ObjectRef setObjectRef(Object label) { println(label(label) + ':'); return new ObjectRefImpl(label); } public void setResolver(ObjectResolver resolver) { } public ObjectInfo startObject(VmType<?> cls) { println(";\n; -- Start of object --\n;"); return new ObjectInfoImpl(); } /** * Remove count bytes from the end of the generated stream. * * @param count */ public void trim(int count) { buf.setLength(buf.length() - count); // println("\t; TRIM " + count + " bytes"); } public void write(byte[] data, int ofs, int len) { buf.append("\tdb "); for (int i = 0; i < len; i++) { if (i > 0) { buf.append(','); } buf.append(data[i]); } buf.append('\n'); } public void write16(int v16) { println("\tdw " + v16); } public void write32(int v32) { println("\tdd " + v32); } public void write64(long v64) { println("\tdq " + v64); } public void write8(int v8) { println("\tdb " + v8); } /** * Create a ADC dstReg, imm32 * * @param dstReg * @param imm32 */ public void writeADC(GPR dstReg, int imm32) { println("\tadc " + dstReg + ',' + imm32); } public void writeADC(int operandSize, GPR dstReg, int dstDisp, int imm32) { println("\tadc " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "]," + imm32); } public void writeADC(GPR dstReg, int dstDisp, GPR srcReg) { println("\tadc [" + dstReg + disp(dstDisp) + "]," + srcReg); } /** * Create a ADC dstReg, srcReg * * @param dstReg * @param srcReg */ public void writeADC(GPR dstReg, GPR srcReg) { println("\tadc " + dstReg + ',' + srcReg); } /** * Create a ADC dstReg, [srcReg+srcDisp] * * @param dstReg * @param srcReg * @param srcDisp */ public void writeADC(GPR dstReg, GPR srcReg, int srcDisp) { println("\tadc " + dstReg + ",[" + srcReg + disp(srcDisp) + ']'); } // LS /** * @param dstReg * @param imm32 */ public void writeADD(GPR dstReg, int imm32) { println("\tadd " + dstReg + ",0x" + NumberUtils.hex(imm32)); } public void writeADD(int operandSize, int dstDisp, int imm32) { println("\tadd " + size(operandSize) + '[' + disp0(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } /** * Create a ADD [dstReg+dstDisp], imm32 * * @param dstReg * @param dstDisp * @param imm32 */ public void writeADD(int operandSize, GPR dstReg, int dstDisp, int imm32) { println("\tadd " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeADD(int operandSize, SR dstReg, int dstDisp, int imm32) { println("\tadd " + size(operandSize) + '[' + dstReg + ":0x" + NumberUtils.hex(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeADD_MEM(X86Register.GPR reg, int memPtr32) { println("\tadd " + reg + ",[0x" + NumberUtils.hex(memPtr32) + ']'); } public void writeADD(GPR dstReg, int dstDisp, GPR srcReg) { println("\tadd [" + dstReg + disp(dstDisp) + "]," + srcReg); } public void writeADD(GPR dstReg, GPR srcReg) { println("\tadd " + dstReg + ',' + srcReg); } /** * Create a ADD dstReg, [srcReg+srcDisp] * * @param dstReg * @param srcReg * @param srcDisp */ public void writeADD(GPR dstReg, GPR srcReg, int srcDisp) { println("\tadd " + dstReg + ",[" + srcReg + disp(srcDisp) + ']'); } public void writeAND(GPR reg, int imm32) { println("\tand " + reg + ",0x" + NumberUtils.hex(imm32)); } public void writeAND(int operandSize, int dstDisp, int imm32) { println("\tand " + size(operandSize) + '[' + disp0(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } /** * @param dstReg * @param dstDisp * @param imm32 */ public void writeAND(int operandSize, GPR dstReg, int dstDisp, int imm32) { println("\tand " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeAND(GPR dstReg, int dstDisp, GPR srcReg) { println("\tand [" + dstReg + disp(dstDisp) + "]," + srcReg); } /** * @param operandSize * @param dstReg * @param dstDisp * @param imm32 */ public void writeAND(int operandSize, X86Register.SR dstReg, int dstDisp, int imm32) { println("\tand " + size(operandSize) + '[' + dstReg + ":0x" + NumberUtils.hex(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeAND(GPR dstReg, GPR srcReg) { println("\tand " + dstReg + ',' + srcReg); } /** * @param dstReg * @param srcReg * @param srcDisp */ public void writeAND(GPR dstReg, GPR srcReg, int srcDisp) { println("\tand " + dstReg + ",[" + srcReg + disp(srcDisp) + ']'); } public void writeArithSSEDOp(int operation, XMM dst, GPR src, int srcDisp) { final String op = getSSEOperationName(operation); println('\t' + op + 'D' + dst + ", qword [" + src + disp(srcDisp) + ']'); } public void writeArithSSEDOp(int operation, XMM dst, XMM src) { final String op = getSSEOperationName(operation); println('\t' + op + 'D' + dst + ", " + src); } public void writeArithSSESOp(int operation, XMM dst, GPR src, int srcDisp) { final String op = getSSEOperationName(operation); println('\t' + op + 'S' + dst + ", dword [" + src + disp(srcDisp) + ']'); } public void writeArithSSESOp(int operation, XMM dst, XMM src) { final String op = getSSEOperationName(operation); println('\t' + op + 'S' + dst + ", " + src); } public void writeBOUND(GPR lReg, GPR rReg, int rDisp) { println("\tbound " + lReg + ",[" + rReg + disp(rDisp) + ']'); } public void writeBreakPoint() { println("\tint 3"); } @Override public void writeBTS(GPR reg, int imm32) { println("\tbts " + reg + "," + imm32); } public void writeCALL(Label label) { println("\tcall " + label(label)); } /** * Create a call to address stored at the given offset in the given table * pointer. * * @param tablePtr * @param offset * @param rawAddress If true, tablePtr is a raw address */ public void writeCALL(Object tablePtr, int offset, boolean rawAddress) { println("\tcall [" + tablePtr + disp(offset) + ']'); } public void writeCALL(GPR reg) { println("\tcall " + reg); } /** * Create a call to address stored at the given [reg+offset]. * * @param reg * @param offset */ public void writeCALL(GPR reg, int offset) { println("\tcall [" + reg + disp(offset) + ']'); } /** * Create a call to address stored at the given [reg+offset]. * * @param reg * @param offset */ public void writeCALL_FAR(GPR reg, int offset) { println("\tcall far [" + reg + disp(offset) + ']'); } public void writeCALL(GPR regBase, GPR regIndex, int scale, int disp) { println("\tcall [" + regBase + '+' + regIndex + '*' + scale + disp(disp) + ']'); } public void writeCALL(GPR regIndex, int scale, int disp) { println("\tcall [" + regIndex + '*' + scale + disp(disp) + ']'); } public void writeCDQ(int operandSize) { testOperandSize(operandSize, BITS32 | BITS64); if (operandSize == BITS32) { println("\tcdq"); } else { if (!code64) { throw new InvalidOpcodeException(); } println("\tcqo"); } } /** * Create a cdqe. * Sign extend EAX to RAX. * Only valid in 64-bit mode. */ public void writeCDQE() throws InvalidOpcodeException { if (!code64) { throw new InvalidOpcodeException(); } println("\tcdqe"); } public void writeCLD() { println("\tcld"); } public void writeCLI() { println("\tcli"); } public void writeCLTS() { println("\tclts"); } /** * Create a CMOVcc dst,src * * @param ccOpcode * @param dst * @param src */ public void writeCMOVcc(int ccOpcode, GPR dst, GPR src) { println("\tCMOV" + ccName(ccOpcode) + ' ' + dst + ',' + src); } /** * Create a CMOVcc dst,[src+srcDisp] * * @param dst * @param src * @param srcDisp */ public void writeCMOVcc(int ccOpcode, GPR dst, GPR src, int srcDisp) { println("\tCMOV" + ccName(ccOpcode) + ' ' + dst + ",[" + src + disp(srcDisp) + ']'); } /** * Create a CMP [reg1+disp], reg2 * * @param reg1 * @param disp * @param reg2 */ public void writeCMP(GPR reg1, int disp, GPR reg2) { println("\tcmp [" + reg1 + disp(disp) + "]," + reg2); } public void writeCMP(GPR reg1, GPR reg2) { println("\tcmp " + reg1 + ',' + reg2); } /** * Create a CMP reg1, [reg2:disp] * * @param reg1 * @param reg2 * @param disp */ public void writeCMP(GPR reg1, SR reg2, int disp) { println("\tcmp " + reg1 + ",[" + reg2 + ":0x" + NumberUtils.hex(disp) + ']'); } /** * Create a CMP reg1, [reg2+disp] * * @param reg1 * @param reg2 * @param disp */ public void writeCMP(GPR reg1, GPR reg2, int disp) { println("\tcmp " + reg1 + ",[" + reg2 + disp(disp) + ']'); } public void writeCMP_Const(GPR reg, int imm32) { println("\tcmp " + reg + ",0x" + NumberUtils.hex(imm32)); } /** * Create a CMP [reg+disp], imm32 * * @param reg * @param disp * @param imm32 */ public void writeCMP_Const(int operandSize, GPR reg, int disp, int imm32) { println("\tcmp " + size(operandSize) + '[' + reg + disp(disp) + "],0x" + NumberUtils.hex(imm32)); } /** * Create a CMP [dstReg:dstDisp], imm32 * * @param operandSize * @param dstReg * @param dstDisp * @param imm32 */ public void writeCMP_Const(int operandSize, X86Register.SR dstReg, int dstDisp, int imm32) { println("\tcmp " + size(operandSize) + '[' + dstReg + ":0x" + NumberUtils.hex(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeCMP_EAX(int operandSize, int imm32) { testOperandSize(operandSize, BITS32 | BITS64); if (operandSize == BITS32) { println("\tcmp eax,0x" + NumberUtils.hex(imm32)); } else { println("\tcmp rax,0x" + NumberUtils.hex(imm32)); } } public void writeCMP_MEM(int operandSize, int memPtr, int imm32) { println("\tcmp " + size(operandSize) + '[' + memPtr + "],0x" + NumberUtils.hex(imm32)); } /** * Create a CMP reg,[memPtr] * * @param reg * @param memPtr */ public void writeCMP_MEM(GPR reg, int memPtr) { println("\tcmp " + reg + ", [" + memPtr + ']'); } public void writeCMPXCHG_EAX(GPR dstReg, int dstDisp, GPR srcReg, boolean lock) { println("\tcmpxchg [" + dstReg + disp(dstDisp) + "]," + srcReg); } public void writeCPUID() { println("\tcpuid"); } public void writeDEC(GPR dstReg) { println("\tdec " + dstReg); } public void writeDEC(int operandSize, GPR dstReg, int dstDisp) { println("\tdec " + size(operandSize) + '[' + dstReg + disp(dstDisp) + ']'); } public void writeDIV_EAX(GPR srcReg) { println("\tdiv " + srcReg); } public void writeEMMS() { println("\temms"); } public void writeFADD32(GPR srcReg, int srcDisp) { println("\tfadd dword [" + srcReg + disp(srcDisp) + ']'); } public void writeFADD64(GPR srcReg, int srcDisp) { println("\tfadd qword [" + srcReg + disp(srcDisp) + ']'); } public void writeFADDP(X86Register fpuReg) { println("\tfaddp " + fpuReg); } public void writeFCHS() { println("\tfchs"); } public void writeFDIV32(GPR srcReg, int srcDisp) { println("\tfdiv dword [" + srcReg + disp(srcDisp) + ']'); } public void writeFDIV64(GPR srcReg, int srcDisp) { println("\tfdiv qword [" + srcReg + disp(srcDisp) + ']'); } public void writeFDIVP(X86Register fpuReg) { println("\tfdivp " + fpuReg); } public void writeFFREE(X86Register fReg) { println("\tffree " + fReg); } public void writeFILD32(GPR dstReg, int dstDisp) { println("\tfild dword [" + dstReg + disp(dstDisp) + ']'); } public void writeFILD64(GPR dstReg, int dstDisp) { println("\tfild qword [" + dstReg + disp(dstDisp) + ']'); } public void writeFISTP32(GPR dstReg, int dstDisp) { println("\tfistp dword [" + dstReg + disp(dstDisp) + ']'); } public void writeFISTP64(GPR dstReg, int dstDisp) { println("\tfistp qword [" + dstReg + disp(dstDisp) + ']'); } public void writeFLD32(GPR srcReg, int srcDisp) { println("\tfld dword [" + srcReg + disp(srcDisp) + ']'); } public void writeFLD32(GPR srcBaseReg, GPR srcIndexReg, int srcScale, int srcDisp) { println("\tfld dword [" + srcBaseReg + '+' + srcIndexReg + '*' + srcScale + disp(srcDisp) + ']'); } public void writeFLD64(GPR srcReg, int srcDisp) { println("\tfld qword [" + srcReg + disp(srcDisp) + ']'); } public void writeFLD64(GPR srcBaseReg, GPR srcIndexReg, int srcScale, int srcDisp) { println("\tfld qword [" + srcBaseReg + '+' + srcIndexReg + '*' + srcScale + disp(srcDisp) + ']'); } public void writeFLDCW(GPR srcReg, int srcDisp) { println("\tfldcw word [" + srcReg + disp(srcDisp) + ']'); } public void writeFMUL32(GPR srcReg, int srcDisp) { println("\tfmul dword [" + srcReg + disp(srcDisp) + ']'); } public void writeFMUL64(GPR srcReg, int srcDisp) { println("\tfmul qword [" + srcReg + disp(srcDisp) + ']'); } public void writeFMULP(X86Register fpuReg) { println("\tfmulp " + fpuReg); } public void writeFNINIT() { println("\tfninit"); } public void writeFNSAVE(GPR srcReg, int srcDisp) { println("\tfnsave [" + srcReg + disp(srcDisp) + ']'); } public void writeFNSTSW_AX() { println("\tfnstsw ax"); } public void writeFPREM() { println("\tfprem"); } public void writeFRSTOR(GPR srcReg, int srcDisp) { println("\tfrstor [" + srcReg + disp(srcDisp) + ']'); } public void writeFSTCW(GPR srcReg, int srcDisp) { println("\tfstcw word [" + srcReg + disp(srcDisp) + ']'); } public void writeFSTP(X86Register fpuReg) { println("\tfstp " + fpuReg); } public void writeFSTP32(GPR dstReg, int dstDisp) { println("\tfstp dword [" + dstReg + disp(dstDisp) + ']'); } public void writeFSTP64(GPR dstReg, int dstDisp) { println("\tfstp qword [" + dstReg + disp(dstDisp) + ']'); } public void writeFSUB32(GPR srcReg, int srcDisp) { println("\tfsub32 dword [" + srcReg + disp(srcDisp) + ']'); } public void writeFSUB64(GPR srcReg, int srcDisp) { println("\tfsub64 qword [" + srcReg + disp(srcDisp) + ']'); } public void writeFSUBP(X86Register fpuReg) { println("\tfsubp " + fpuReg); } public void writeFUCOMPP() { println("\tfucompp"); } public void writeFXCH(X86Register fpuReg) { println("\tfxch " + fpuReg); } public void writeFXRSTOR(GPR srcReg, int srcDisp) { println("\tfxrstor [" + srcReg + disp(srcDisp) + ']'); } public void writeFXSAVE(GPR srcReg, int srcDisp) { println("\tfxsave [" + srcReg + disp(srcDisp) + ']'); } public void writeHLT() { println("\thlt"); } public void writeIDIV_EAX(GPR srcReg) { println("\tidiv " + srcReg); } public void writeIDIV_EAX(int operandSize, GPR srcReg, int srcDisp) { println("\tidiv " + size(operandSize) + '[' + srcReg + disp(srcDisp) + ']'); } public void writeIMUL(GPR dstReg, GPR srcReg) { println("\timul " + dstReg + ',' + srcReg); } /** * @param dstReg * @param srcReg * @param srcDisp */ public void writeIMUL(GPR dstReg, GPR srcReg, int srcDisp) { println("\timul " + dstReg + ",[" + srcReg + disp(srcDisp) + ']'); } /** * @param dstReg * @param srcReg * @param imm32 */ public void writeIMUL_3(GPR dstReg, GPR srcReg, int imm32) { println("\timul " + dstReg + ',' + srcReg + ",0x" + NumberUtils.hex(imm32)); } // LS /** * @param dstReg * @param srcReg * @param srcDisp * @param imm32 */ public void writeIMUL_3(GPR dstReg, GPR srcReg, int srcDisp, int imm32) { println("\timul " + dstReg + ",[" + srcReg + disp(srcDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeIMUL_EAX(GPR srcReg) { println("\timul " + srcReg); } public void writeIN(int operandSize) { if (operandSize == X86Constants.BITS8) { println("\tin " + X86Register.AL + ',' + X86Register.DX); } else if (operandSize == X86Constants.BITS16) { println("\tin " + X86Register.AX + ',' + X86Register.DX); } else if (operandSize == X86Constants.BITS32) { println("\tin " + X86Register.EAX + ',' + X86Register.DX); } else { throw new IllegalArgumentException("Invalid operand size for IN: " + operandSize); } } public void writeIN(int operandSize, int imm8) { if (operandSize == X86Constants.BITS8) { println("\tin " + X86Register.AL + ',' + imm8); } else if (operandSize == X86Constants.BITS16) { println("\tin " + X86Register.AX + ',' + imm8); } else if (operandSize == X86Constants.BITS32) { println("\tin " + X86Register.EAX + ',' + imm8); } else { throw new IllegalArgumentException("Invalid operand size for IN: " + operandSize); } } public void writeINC(GPR dstReg) { println("\tinc " + dstReg); } public void writeINC(int operandSize, X86Register.SR dstReg, int disp) { println("\tinc " + size(operandSize) + '[' + dstReg + ":0x" + NumberUtils.hex(disp) + ']'); } /** * Create a inc [reg32+disp] * * @param dstReg */ public void writeINC(int operandSize, GPR dstReg, int disp) { println("\tinc " + size(operandSize) + '[' + dstReg + disp(disp) + ']'); } public void writeINC(int operandSize, GPR dstReg, GPR dstIdxReg, int scale, int disp) { println("\tinc [" + dstReg + '+' + dstIdxReg + '*' + scale + disp(disp) + ']'); } /** * Create a inc [disp] * * @param dstDisp */ public void writeINC(int operandSize, int dstDisp) { println("\tinc " + size(operandSize) + '[' + dstDisp + ']'); } public void writeINT(int vector) { println("\tint 0x" + NumberUtils.hex(vector, 2)); } public void writeIRET() { println("\tiret"); } public void writeIRETQ() { println("\tiretq"); } public void writeJCC(Label label, int jumpOpcode) { println("\tj" + ccName(jumpOpcode) + ' ' + label(label)); } public void writeJECXZ(Label label) { println("\tjecxz " + label(label)); } public void writeJMP(Label label) { println("\tjmp " + label(label)); } /** * Create a absolute jump to address stored at the given offset in the given * table pointer. * * @param tablePtr * @param offset * @param rawAddress If true, tablePtr is a raw address */ public void writeJMP(Object tablePtr, int offset, boolean rawAddress) { if (tablePtr == null) tablePtr = "null"; // workaround for a peculiar NPE in StringBuffer println("\tjmp [ left out in: TextX86Stream.writeJMP(Object tablePtr, int offset, boolean rawAddress)]"); } /** * @param operandSize * @param seg * @param disp */ public void writeJMP(int operandSize, int seg, int disp) { println("\tjmp " + size(operandSize) + " 0x" + NumberUtils.hex(seg) + ":0x" + NumberUtils.hex(disp)); } /** * Create a absolute jump to address stored at the given offset (in * register) in the given table pointer. * * @param tablePtr * @param offsetReg */ public void writeJMP(Object tablePtr, GPR offsetReg) { println("\tjmp [" + tablePtr + '+' + offsetReg + ']'); } public void writeJMP(GPR reg32) { println("\tjmp " + reg32); } /** * Create a absolute jump to [reg32+disp] * * @param reg32 */ public final void writeJMP(GPR reg32, int disp) { println("\tjmp [" + reg32 + disp(disp) + ']'); } public void writeLDMXCSR(GPR srcReg, int disp) { println("\tldmxcsr dword [" + srcReg + disp(disp) + ']'); } public void writeLEA(GPR dstReg, GPR srcReg, int disp) { println("\tlea " + dstReg + ",[" + srcReg + disp(disp) + ']'); } public void writeLEA(X86Register.GPR dstReg, X86Register.GPR srcIdxReg, int scale, int disp) { if (scale == 1) println("\tlea " + dstReg + ",[" + srcIdxReg + disp(disp) + ']'); else println("\tlea " + dstReg + ",[" + srcIdxReg + '*' + scale + disp(disp) + ']'); } public void writeLGDT(int disp) { println("\tlgdt [" + disp0(disp) + ']'); } public void writeLIDT(int disp) { println("\tlidt [" + disp0(disp) + ']'); } public void writeLEA(GPR dstReg, GPR srcReg, GPR srcIdxReg, int scale, int disp) { if (scale == 1) println("\tlea " + dstReg + ",[" + srcReg + '+' + srcIdxReg + disp(disp) + ']'); else println("\tlea " + dstReg + ",[" + srcReg + '+' + srcIdxReg + '*' + scale + disp(disp) + ']'); } public void writeLMSW(GPR srcReg) { println("\tlmsw " + srcReg); } public void writeLODSD() { println("\tlodsd"); } public void writeLODSW() { println("\tlodsw"); } public void writeLOOP(Label label) throws UnresolvedObjectRefException { println("\tloop " + label(label)); } public void writeLTR(GPR srcReg) { println("\tltr " + srcReg); } public void writeMOV(int operandSize, GPR dstReg, int dstDisp, GPR srcReg) { println("\tmov " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "]," + srcReg); } /** * @param dstReg * @param dstDisp * @param srcReg */ public void writeMOV(X86Register.SR dstReg, int dstDisp, X86Register.GPR srcReg) { println("\tmov " + '[' + dstReg + ":0x" + NumberUtils.hex(dstDisp) + "]," + srcReg); } public void writeMOV(CRX dstReg, GPR srcReg) { println("\tmov " + dstReg + ',' + size(BITS32) + ' ' + srcReg); } public void writeMOV(GPR dstReg, CRX srcReg) { println("\tmov " + dstReg + ',' + size(BITS32) + ' ' + srcReg); } public void writeMOV(SR dstReg, GPR srcReg) { println("\tmov " + dstReg + ',' + size(BITS16) + ' ' + srcReg); } public void writeMOV(GPR dstReg, SR srcReg) { println("\tmov " + dstReg + ',' + size(BITS16) + ' ' + srcReg); } public void writeMOV(int operandSize, GPR dstReg, GPR srcReg) { println("\tmov " + dstReg + ',' + size(operandSize) + ' ' + srcReg); } public void writeMOV(int operandSize, GPR dstReg, GPR srcReg, int srcDisp) { println("\tmov " + dstReg + ',' + size(operandSize) + '[' + srcReg + disp(srcDisp) + ']'); } public void writeMOV(int operandSize, GPR dstReg, GPR dstIdxReg, int scale, int dstDisp, GPR srcReg) { println("\tmov " + size(operandSize) + '[' + dstReg + disp(dstDisp) + '+' + dstIdxReg + '*' + scale + "]," + srcReg); } public void writeMOV(int operandSize, GPR dstReg, GPR srcReg, GPR srcIdxReg, int scale, int srcDisp) { println("\tmov " + dstReg + ',' + size(operandSize) + '[' + srcReg + disp(srcDisp) + '+' + srcIdxReg + '*' + scale + ']'); } /** * Create a mov dstReg, [srcReg:srcDisp] * * @param dstReg * @param srcReg * @param srcDisp */ public void writeMOV(X86Register.GPR dstReg, X86Register.SR srcReg, int srcDisp) { println("\tmov " + dstReg + ",[" + srcReg + ":0x" + NumberUtils.hex(srcDisp) + ']'); } public void writeMOV(GPR dstReg, int srcDisp) { println("\tmov " + dstReg + ",[" + disp0(srcDisp) + ']'); } public void writeMOV(int dstDisp, X86Register.GPR srcReg) { println("\tmov [" + disp0(dstDisp) + "]," + srcReg); } public void writeMOV_Const(int operandSize, int dstDisp, int imm32) { println("\tmov " + size(operandSize) + '[' + disp0(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeMOV_Const(GPR dstReg, int imm32) { if (dstReg.getSize() == BITS32) { println("\tmov " + dstReg + ",0x" + NumberUtils.hex(imm32)); } else { println("\tmov " + dstReg + ",0x" + NumberUtils.hex((long) imm32)); } } public void writeMOV_Const(GPR dstReg, long imm64) { println("\tmov " + dstReg + ",0x" + NumberUtils.hex(imm64)); } /** * Create a mov [dstReg:dstDisp], <imm32> * * @param dstReg * @param dstDisp * @param imm32 */ public void writeMOV_Const(int operandSize, X86Register.SR dstReg, int dstDisp, int imm32) { println("\tmov " + size(operandSize) + '[' + dstReg + ":0x" + NumberUtils.hex(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } /** * Create a mov [destReg+destDisp], <imm32> * * @param dstReg * @param dstDisp * @param imm32 */ public void writeMOV_Const(int operandSize, GPR dstReg, int dstDisp, int imm32) { println("\tmov " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeMOV_Const(GPR dstReg, Object label) { println("\tmov " + dstReg + ',' + label); } /** * Create a mov [destReg+dstIdxReg*scale+destDisp], <imm32> * * @param dstReg * @param dstDisp * @param imm32 */ public void writeMOV_Const(int operandSize, GPR dstReg, GPR dstIdxReg, int scale, int dstDisp, int imm32) { println("\tmov " + size(operandSize) + '[' + dstReg + '+' + dstIdxReg + '*' + scale + disp(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeMOVD(int operandSize, X86Register.MMX mmx, X86Register.GPR reg, int disp) { println("\tmovd " + mmx + ',' + size(operandSize) + '[' + reg + disp(disp) + ']'); } public void writeMOVD(int operandSize, X86Register.GPR dstReg, int dstDisp, X86Register.MMX srcMmx) { println("\tmovd " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "]," + srcMmx); } public void writeMOVQ(X86Register.MMX dstMmx, X86Register.MMX srcMmx) { println("\tmovq " + dstMmx + ',' + srcMmx); } public void writeMOVQ(int operandSize, X86Register.MMX dstMmx, X86Register.GPR srcGpr, int srcDisp) { println("\tmovq " + dstMmx + ',' + size(operandSize) + '[' + srcGpr + disp(srcDisp) + ']'); } public void writeMOVQ(int operandSize, X86Register.MMX dstMmx, int srcDisp) { println("\tmovq " + dstMmx + ',' + size(operandSize) + '[' + disp0(srcDisp) + ']'); } public void writeMOVSB() { println("\tmovsb"); } public void writeMOVSD() { println("\tmovsd"); } public void writeMOVSD(GPR dst, int dstDisp, XMM src) { println("\tmovsd qword [" + dst + disp(dstDisp) + "]," + src); } public void writeMOVSD(XMM dst, GPR src, int srcDisp) { println("\tmovsd " + dst + ",qword [" + src + disp(srcDisp) + ']'); } public void writeMOVSD(XMM dst, XMM src) { println("\tmovsd " + dst + ',' + src); } public void writeMOVSS(GPR dst, int dstDisp, XMM src) { println("\tmovss dword [" + dst + disp(dstDisp) + "]," + src); } public void writeMOVSS(XMM dst, GPR src, int srcDisp) { println("\tmovss " + dst + ",dword [" + src + disp(srcDisp) + ']'); } public void writeMOVSS(XMM dst, XMM src) { println("\tmovss " + dst + ',' + src); } public void writeMOVSX(GPR dstReg, GPR srcReg, int srcSize) { println("\tmovsx " + dstReg + ',' + size(srcSize) + ' ' + srcReg); } public void writeMOVSX(GPR dstReg, GPR srcReg, int srcDisp, int srcSize) { println("\tmovsx " + dstReg + ',' + size(srcSize) + ' ' + '[' + srcReg + disp(srcDisp) + ']'); } /** * Create a movsxd dstReg, srcReg. Sign extends the srcReg to dstReg. Only * valid in 64-bit mode. * * @param dstReg * @param srcReg */ public void writeMOVSXD(GPR64 dstReg, GPR32 srcReg) throws InvalidOpcodeException { if (!code64) { throw new InvalidOpcodeException(); } println("\tmovsxd " + dstReg + ',' + srcReg); } public void writeMOVSW() { println("\tmovsw"); } public void writeMOVZX(GPR dstReg, GPR srcReg, int srcSize) { println("\tmovzx " + dstReg + ',' + size(srcSize) + ' ' + srcReg); } public void writeMOVZX(GPR dstReg, GPR srcReg, int srcDisp, int srcSize) { println("\tmovzx " + dstReg + ',' + size(srcSize) + ' ' + '[' + srcReg + disp(srcDisp) + ']'); } public void writeMUL_EAX(GPR srcReg) { println("\tmul " + srcReg); } public void writeNEG(GPR dstReg) { println("\tneg " + dstReg); } public void writeNEG(int operandSize, GPR dstReg, int dstDisp) { println("\tneg " + size(operandSize) + '[' + dstReg + disp(dstDisp) + ']'); } public void writeNOP() { println("\tnop"); } public void writeNOT(GPR dstReg) { println("\tnot " + dstReg); } public void writeNOT(int operandSize, GPR dstReg, int dstDisp) { println("\tnot " + size(operandSize) + '[' + dstReg + disp(dstDisp) + ']'); } // LS /** * @param dstReg * @param imm32 */ public void writeOR(GPR dstReg, int imm32) { println("\tor " + dstReg + ",0x" + NumberUtils.hex(imm32)); } /** * @param dstReg * @param dstDisp * @param imm32 */ public void writeOR(int operandSize, GPR dstReg, int dstDisp, int imm32) { println("\tor " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeOR(GPR dstReg, int dstDisp, GPR srcReg) { println("\tor [" + dstReg + disp(dstDisp) + "]," + srcReg); } /** * @param operandSize * @param dstReg * @param dstDisp * @param imm32 */ public void writeOR(int operandSize, X86Register.SR dstReg, int dstDisp, int imm32) { println("\tor " + size(operandSize) + '[' + dstReg + ":0x" + NumberUtils.hex(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } /** * @param operandSize * @param dstDisp * @param imm32 */ public void writeOR(int operandSize, int dstDisp, int imm32) { println("\tor " + size(operandSize) + '[' + disp0(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeOR(GPR dstReg, GPR srcReg) { println("\tor " + dstReg + ',' + srcReg); } /** * @param dstReg * @param srcReg * @param srcDisp */ public void writeOR(GPR dstReg, GPR srcReg, int srcDisp) { println("\tor " + dstReg + ",[" + srcReg + disp(srcDisp) + ']'); } public void writeOUT(int operandSize) { if (operandSize == X86Constants.BITS8) { println("\tout " + X86Register.DX + ',' + X86Register.AL); } else if (operandSize == X86Constants.BITS16) { println("\tout " + X86Register.DX + ',' + X86Register.AX); } else if (operandSize == X86Constants.BITS32) { println("\tout " + X86Register.DX + ',' + X86Register.EAX); } else { throw new IllegalArgumentException("Invalid operand size for OUT: " + operandSize); } } public void writeOUT(int operandSize, int imm8) { if (operandSize == X86Constants.BITS8) { println("\tout " + imm8 + ',' + X86Register.AL); } else if (operandSize == X86Constants.BITS16) { println("\tout " + imm8 + ',' + X86Register.AX); } else if (operandSize == X86Constants.BITS32) { println("\tout " + imm8 + ',' + X86Register.EAX); } else { throw new IllegalArgumentException("Invalid operand size for OUT: " + operandSize); } } public void writePACKUSWB(X86Register.MMX dstMmx, X86Register.MMX srcMmx) { println("\tpackuswb " + dstMmx + ',' + srcMmx); } public void writePADDW(X86Register.MMX dstMmx, X86Register.MMX srcMmx) { println("\tpaddw " + dstMmx + ',' + srcMmx); } public void writePAND(X86Register.MMX dstMmx, X86Register.MMX srcMmx) { println("\tpand " + dstMmx + ',' + srcMmx); } public void writePCMPGTW(X86Register.MMX dstMmx, X86Register.MMX srcMmx) { println("\tpcmpgtw " + dstMmx + ',' + srcMmx); } public void writePMULLW(X86Register.MMX dstMmx, X86Register.MMX srcMmx) { println("\tpmullw " + dstMmx + ',' + srcMmx); } public void writePOP(GPR dstReg) { println("\tpop " + dstReg); } public void writePOP(SR dstReg) { println("\tpop " + dstReg); } public void writePOP(GPR dstReg, int dstDisp) { println("\tpop [" + dstReg + disp(dstDisp) + ']'); } public void writePOPA() { println("\tpopa"); } public void writePOPF() { println("\tpopf"); } public void writePrefix(int prefix) { final String str; switch (prefix) { case FS_PREFIX: str = "fs"; break; case LOCK_PREFIX: str = "lock"; break; case REP_PREFIX: str = "rep"; break; default: throw new IllegalArgumentException("Unknown prefix " + prefix); } print("\t" + str); } public void writePSHUFW(X86Register.MMX dstMmx, X86Register.MMX srcMmx, int imm8) { println("\tpshufw " + dstMmx + ',' + srcMmx + ",0x" + NumberUtils.hex(imm8)); } public void writePSRLW(X86Register.MMX mmx, int imm8) { println("\tpsrlw " + mmx + ",0x" + NumberUtils.hex(imm8)); } public void writePSUBW(X86Register.MMX dstMmx, X86Register.MMX srcMmx) { println("\tpsubw " + dstMmx + ',' + srcMmx); } public void writePUNPCKLBW(X86Register.MMX dstMmx, X86Register.MMX srcMmx) { println("\tpunpcklbw " + dstMmx + ',' + srcMmx); } /** * @return The offset of the start of the instruction. */ public int writePUSH(int imm32) { return println("\tpush 0x" + NumberUtils.hex(imm32)); } /** * @return The offset of the start of the instruction. */ public int writePUSH(GPR srcReg) { return println("\tpush " + srcReg); } /** * @return The offset of the start of the instruction. */ public int writePUSH(SR srcReg) { return println("\tpush " + srcReg); } /** * @return The offset of the start of the instruction. */ public int writePUSH(GPR srcReg, int srcDisp) { return println("\tpush [" + srcReg + disp(srcDisp) + ']'); } /** * @return The offset of the start of the instruction. */ public int writePUSH(SR srcReg, int srcDisp) { return println("\tpush [" + srcReg + ':' + srcDisp + ']'); } /** * @return The offset of the start of the instruction. */ public int writePUSH(GPR srcBaseReg, GPR srcIndexReg, int srcScale, int srcDisp) { return println("\tpush [" + srcBaseReg + disp(srcDisp) + '+' + srcIndexReg + '*' + srcScale + ']'); } // PR /** * @return The offset of the start of the instruction. */ public int writePUSH_Const(Object objRef) { return println("\tpush " + objRef); } public void writePUSHA() { println("\tpusha"); } public void writePUSHF() { println("\tpushf"); } public void writePXOR(X86Register.MMX dstMmx, X86Register.MMX srcMmx) { println("\tpxor " + dstMmx + ',' + srcMmx); } public void writeRDTSC() { println("\trdtsc"); } /** * Create 32-bit offset relative to the current (after this offset) offset. * * @param label */ public void writeRelativeObjectRef(Label label) { println("\tdd relative " + label(label)); } public void writeRET() { println("\tret"); } public void writeRET(int imm16) { println("\tret " + imm16); } public void writeSAHF() { println("\tsahf"); } public void writeSAL(GPR dstReg, int imm8) { println("\tsal " + dstReg + ',' + imm8); } /** * @param srcReg * @param srcDisp * @param imm8 */ public void writeSAL(int operandSize, GPR srcReg, int srcDisp, int imm8) { println("\tsal " + size(operandSize) + '[' + srcReg + disp(srcDisp) + "]," + imm8); } public void writeSAL_CL(GPR dstReg) { println("\tsal " + dstReg + ",cl"); } /** * @param srcReg * @param srcDisp */ public void writeSAL_CL(int operandSize, GPR srcReg, int srcDisp) { println("\tsal " + size(operandSize) + '[' + srcReg + disp(srcDisp) + "],cl"); } public void writeSAR(GPR dstReg, int imm8) { println("\tsar " + dstReg + ',' + imm8); } /** * @param srcReg * @param srcDisp * @param imm8 */ public void writeSAR(int operandSize, GPR srcReg, int srcDisp, int imm8) { println("\tsar " + size(operandSize) + '[' + srcReg + disp(srcDisp) + "]," + imm8); } public void writeSAR_CL(GPR dstReg) { println("\tsar " + dstReg + ",cl"); } /** * @param srcReg * @param srcDisp */ public void writeSAR_CL(int operandSize, GPR srcReg, int srcDisp) { println("\tsar " + size(operandSize) + '[' + srcReg + disp(srcDisp) + "],cl"); } /** * Create a SBB dstReg, imm32 * * @param dstReg * @param imm32 */ public void writeSBB(GPR dstReg, int imm32) { println("\tsbb " + dstReg + ",0x" + NumberUtils.hex(imm32)); } public void writeSBB(int operandSize, GPR dstReg, int dstDisp, int imm32) { println("\tsbb " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeSBB(GPR dstReg, int dstDisp, GPR srcReg) { println("\tsbb [" + dstReg + disp(dstDisp) + "]," + srcReg); } public void writeSBB(GPR dstReg, GPR srcReg) { println("\tsbb " + dstReg + ',' + srcReg); } /** * @param dstReg * @param srcReg * @param srcDisp */ public void writeSBB(GPR dstReg, GPR srcReg, int srcDisp) { println("\tsbb " + dstReg + ",[" + srcReg + disp(srcDisp) + ']'); } /** * Create a SETcc dstReg * * @param dstReg * @param cc */ public void writeSETCC(GPR dstReg, int cc) { println("\tset" + ccName(cc) + ' ' + dstReg); } public void writeSHL(GPR dstReg, int imm8) { println("\tshl " + dstReg + ',' + imm8); } public void writeSHL(int operandSize, GPR dstReg, int dstDisp, int imm8) { println("\tshl " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "]," + imm8); } public void writeSHL_CL(GPR dstReg) { println("\tshl " + dstReg + ",cl"); } public void writeSHL_CL(int operandSize, GPR dstReg, int dstDisp) { println("\tshl " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "],CL"); } public void writeSHLD_CL(GPR dstReg, GPR srcReg) { println("\tshld " + dstReg + ',' + srcReg + ",cl"); } public void writeSHR(GPR dstReg, int imm8) { println("\tshr " + dstReg + ',' + imm8); } /** * @param srcReg * @param srcDisp * @param imm8 */ public void writeSHR(int operandSize, GPR srcReg, int srcDisp, int imm8) { println("\tshr " + size(operandSize) + '[' + srcReg + disp(srcDisp) + "]," + imm8); } public void writeSHR_CL(GPR dstReg) { println("\tshr " + dstReg + ",cl"); } /** * @param srcReg * @param srcDisp */ public void writeSHR_CL(int operandSize, GPR srcReg, int srcDisp) { println("\tshr " + size(operandSize) + '[' + srcReg + disp(srcDisp) + "],cl"); } public void writeSHRD_CL(GPR dstReg, GPR srcReg) { println("\tshrd " + dstReg + ',' + srcReg + ",cl"); } public void writeSTD() { println("\tstd"); } public void writeSTI() { println("\tsti"); } public void writeSTMXCSR(GPR srcReg, int disp) { println("\tstmxcsr dword [" + srcReg + disp(disp) + ']'); } public void writeSTOSB() { println("\tstosb"); } public void writeSTOSD() { println("\tstosd"); } public void writeSTOSQ() { println("\tstosq"); } public void writeSTOSW() { println("\tstosw"); } /** * Create a SUB reg, imm32 * * @param reg * @param imm32 */ public final void writeSUB(GPR reg, int imm32) { println("\tsub " + reg + ',' + imm32); } /** * @param dstDisp * @param srcReg */ public void writeSUB(int dstDisp, GPR srcReg) { println("\tsub [" + disp0(dstDisp) + "]," + srcReg); } /** * @param dstReg * @param dstDisp * @param imm32 */ public void writeSUB(int operandSize, GPR dstReg, int dstDisp, int imm32) { println("\tsub " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeSUB(GPR dstReg, int dstDisp, GPR srcReg) { println("\tsub [" + dstReg + disp(dstDisp) + "]," + srcReg); } public void writeSUB(GPR dstReg, GPR srcReg) { println("\tsub " + dstReg + ',' + srcReg); } /** * @param dstReg * @param srcReg * @param srcDisp */ public void writeSUB(GPR dstReg, GPR srcReg, int srcDisp) { println("\tsub " + dstReg + ", [" + srcReg + disp(srcDisp) + ']'); } public void writeTEST(GPR reg, int imm32) { println("\ttest " + reg + ",0x" + NumberUtils.hex(imm32)); } /** * Create a TEST [reg+disp], imm32 * * @param reg * @param disp * @param imm32 */ public void writeTEST(int operandSize, GPR reg, int disp, int imm32) { println("\ttest " + size(operandSize) + '[' + reg + disp(disp) + "],0x" + NumberUtils.hex(imm32)); } /** * @param operandSize * @param reg * @param disp * @param imm32 */ public void writeTEST(int operandSize, SR reg, int disp, int imm32) { println("\ttest " + size(operandSize) + '[' + reg + ":0x" + NumberUtils.hex(disp) + "],0x" + NumberUtils.hex(imm32)); } /** * Create a TEST reg1, reg2 * * @param reg1 * @param reg2 */ public void writeTEST(GPR reg1, GPR reg2) { println("\ttest " + reg1 + ',' + reg2); } public void writeTEST_AL(int value) { println("\ttest al," + value); } public void writeTEST_EAX(int operandSize, int value) { testOperandSize(operandSize, BITS32 | BITS64); if (operandSize == BITS32) { println("\ttest eax," + value); } else if (operandSize == BITS64) { println("\ttest rax," + value); } } public void writeTEST(int operandSize, int destDisp, int imm32) { println("\ttest " + size(operandSize) + '[' + disp0(destDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeTo(OutputStream os) throws IOException { } /** * @param dstDisp * @param srcReg */ public void writeXCHG(int dstDisp, X86Register.GPR srcReg) { println("\txchg [" + disp0(dstDisp) + "], " + srcReg); } public void writeXCHG(GPR dstReg, int dstDisp, GPR srcReg) { println("\txchg [" + dstReg + disp(dstDisp) + "], " + srcReg); } /** * @param dstReg * @param dstDisp * @param srcReg */ public void writeXCHG(X86Register.SR dstReg, int dstDisp, X86Register.GPR srcReg) { println("\txchg [" + dstReg + ":0x" + NumberUtils.hex(dstDisp) + "], " + srcReg); } public void writeXCHG(GPR dstReg, GPR srcReg) { println("\txchg " + dstReg + ", " + srcReg); } /** * @param dstReg * @param imm32 */ public void writeXOR(GPR dstReg, int imm32) { println("\txor " + dstReg + ",0x" + NumberUtils.hex(imm32)); } /** * @param dstReg * @param dstDisp * @param imm32 */ public void writeXOR(int operandSize, GPR dstReg, int dstDisp, int imm32) { println("\txor " + size(operandSize) + '[' + dstReg + disp(dstDisp) + "],0x" + NumberUtils.hex(imm32)); } public void writeXOR(GPR dstReg, int dstDisp, GPR srcReg) { println("\txor [" + dstReg + disp(dstDisp) + "]," + srcReg); } public void writeXOR(GPR dstReg, GPR srcReg) { println("\txor " + dstReg + ',' + srcReg); } /** * @param dstReg * @param srcReg * @param srcDisp */ public void writeXOR(GPR dstReg, GPR srcReg, int srcDisp) { println("\txor " + dstReg + ", [" + srcReg + disp(srcDisp) + ']'); } public void writeObjectRef(Object object) { } public void writeRDMSR() { println("\trdmsr"); } public void writeWRMSR() { println("\twrmsr"); } @Override public void setObjectRef(int offset, Object object) { //todo } @Override public int allocate(int size) { //todo return 0; } @Override public int getObjectRefsCount() { //todo return 0; } }