/* * Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. * */ /* * Original code for this class taken from the Java HotSpot VM. * Modified for use with the Jakstab project. All modifications * Copyright 2007-2015 Johannes Kinder <jk@jakstab.org> */ package org.jakstab.asm.x86; import org.jakstab.asm.*; import org.jakstab.rtl.Context; public class X86Instruction extends AbstractInstruction implements Instruction, X86Opcodes, MemoryInstruction, Cloneable { final private int size; final private int prefixes; final private DataType dataType; //RTL dataType private Operand[] operands; final private int operandCount; private String description; public String getPrefixString() { StringBuffer buf = new StringBuffer(); if ((prefixes & PREFIX_REPZ) != 0) buf.append("repz "); if ((prefixes & PREFIX_REPNZ) != 0) buf.append("repnz "); if ((prefixes & PREFIX_LOCK) != 0) buf.append("lock "); return buf.toString(); } public boolean hasPrefixREPZ() { return (prefixes & PREFIX_REPZ) != 0; } public boolean hasPrefixREPNZ() { return (prefixes & PREFIX_REPNZ) != 0; } public boolean hasPrefixLOCK() { return (prefixes & PREFIX_LOCK) != 0; } public int getSize() { return size; } public String toString(long currentPc, SymbolFinder symFinder) { if (description == null) description = initDescription(currentPc, symFinder); return description; } @Override public int getOperandCount() { return operandCount; } @Override public Operand getOperand(int i) { return operands[i]; } public Operand getOperand1() { return operands[0]; } public Operand getOperand2() { return operands[1]; } public Operand getOperand3() { return operands[2]; } public DataType getDataType() { return dataType; } public boolean hasEsiBasedMemorySource() { return (getOperand2() instanceof X86MemoryOperand && ((X86MemoryOperand)getOperand2()).getBase().equals(X86Registers.ESI)); } public boolean hasEdiBasedMemoryTarget() { return (getOperand1() instanceof X86MemoryOperand && ((X86MemoryOperand)getOperand1()).getBase().equals(X86Registers.EDI)); } public X86Instruction(String name, Operand op1, Operand op2, Operand op3, DataType dataType, int size, int prefixes) { super(name); this.size = size; this.prefixes = prefixes; this.operands = new Operand[]{op1, op2, op3}; // Count non-null operands int operandCount = 3; for (int i=0; i < operands.length; i++) { if (operands[i] == null) { operandCount = i; break; } } this.operandCount = operandCount; this.dataType = dataType; // initialized when needed for the first time description = null; } public X86Instruction(String name, Operand op1, Operand op2, Operand op3, int size, int prefixes) { this(name, op1, op2, op3, DataType.UNKNOWN, size, prefixes); } public X86Instruction(String name, Operand op1, Operand op2, DataType dataType, int size, int prefixes) { this(name, op1, op2, (Operand)null, dataType, size, prefixes); } public X86Instruction(String name, Operand op1, Operand op2, int size, int prefixes) { this(name, op1, op2, (Operand)null, size, prefixes); } public X86Instruction(String name, Operand op1, int size, int prefixes) { this(name, op1, (Operand)null, (Operand)null, size, prefixes); } public X86Instruction(String name, int size, int prefixes) { this(name, (Operand)null, (Operand)null, (Operand)null, size, prefixes); } protected String initDescription(long currentPc, SymbolFinder symFinder) { StringBuffer buf = new StringBuffer(); buf.append(getPrefixString()); buf.append(getName()); buf.append(spaces); if (operands[2] != null) { //buf.append("("); //buf.append(operands[2].getClass().getSimpleName()); //buf.append(")"); buf.append(operands[2].toString(currentPc, symFinder)); buf.append(comma); } if (operands[1] != null) { //buf.append("("); //buf.append(operands[1].getClass().getSimpleName()); //buf.append(")"); buf.append(operands[1].toString(currentPc, symFinder)); buf.append(comma); } if(operands[0] != null) { //buf.append("("); //buf.append(operands[0].getClass().getSimpleName()); //buf.append(")"); buf.append(operands[0].toString(currentPc, symFinder)); } return buf.toString(); } protected static String comma = ", "; protected static String spaces = "\t"; @Override public Instruction evaluate(Context ctx) { boolean changed = false; Operand[] evaledOperands = new Operand[operands.length]; for (int i = 0; i < getOperandCount(); i++) { evaledOperands[i] = operands[i].evaluate(ctx); changed |= evaledOperands[i] != operands[i]; } if (!changed) return this; else { X86Instruction inst = null; try { inst = (X86Instruction) super.clone(); inst.operands = new Operand[inst.operands.length]; } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } System.arraycopy(evaledOperands, 0, inst.operands, 0, inst.operands.length); return inst; //return new X86Instruction(name, evaledOperands[0], evaledOperands[1], evaledOperands[2], size, prefixes); } } }