/*
* $Id$
*
* Copyright (C) 2003-2015 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.vm.x86.compiler.l2;
import static org.jnode.vm.compiler.ir.AddressingMode.CONSTANT;
import static org.jnode.vm.compiler.ir.AddressingMode.REGISTER;
import static org.jnode.vm.compiler.ir.AddressingMode.STACK;
import static org.jnode.vm.compiler.ir.AddressingMode.TOPS;
import static org.jnode.vm.x86.compiler.X86CompilerConstants.INTSIZE;
import org.jnode.assembler.Label;
import org.jnode.assembler.x86.X86Assembler;
import org.jnode.assembler.x86.X86Constants;
import org.jnode.assembler.x86.X86Register;
import org.jnode.assembler.x86.X86Register.GPR;
import org.jnode.bootlog.BootLogInstance;
import org.jnode.vm.JvmType;
import org.jnode.vm.classmgr.ObjectLayout;
import org.jnode.vm.classmgr.Signature;
import org.jnode.vm.classmgr.TIBLayout;
import org.jnode.vm.classmgr.VmArray;
import org.jnode.vm.classmgr.VmClassType;
import org.jnode.vm.classmgr.VmConstClass;
import org.jnode.vm.classmgr.VmConstFieldRef;
import org.jnode.vm.classmgr.VmConstMethodRef;
import org.jnode.vm.classmgr.VmField;
import org.jnode.vm.classmgr.VmInstanceField;
import org.jnode.vm.classmgr.VmInstanceMethod;
import org.jnode.vm.classmgr.VmMethod;
import org.jnode.vm.classmgr.VmSharedStaticsEntry;
import org.jnode.vm.classmgr.VmStaticField;
import org.jnode.vm.classmgr.VmStaticMethod;
import org.jnode.vm.classmgr.VmType;
import org.jnode.vm.compiler.CompileError;
import org.jnode.vm.compiler.ir.AddressingMode;
import org.jnode.vm.compiler.ir.CodeGenerator;
import org.jnode.vm.compiler.ir.Constant;
import org.jnode.vm.compiler.ir.IRBasicBlock;
import org.jnode.vm.compiler.ir.IntConstant;
import org.jnode.vm.compiler.ir.LongConstant;
import org.jnode.vm.compiler.ir.Operand;
import org.jnode.vm.compiler.ir.RegisterLocation;
import org.jnode.vm.compiler.ir.RegisterPool;
import org.jnode.vm.compiler.ir.StackLocation;
import org.jnode.vm.compiler.ir.Variable;
import org.jnode.vm.compiler.ir.quad.ArrayAssignQuad;
import org.jnode.vm.compiler.ir.quad.ArrayLengthAssignQuad;
import org.jnode.vm.compiler.ir.quad.ArrayStoreQuad;
import org.jnode.vm.compiler.ir.quad.BinaryOperation;
import org.jnode.vm.compiler.ir.quad.BinaryQuad;
import org.jnode.vm.compiler.ir.quad.BranchCondition;
import org.jnode.vm.compiler.ir.quad.CheckcastQuad;
import org.jnode.vm.compiler.ir.quad.ConditionalBranchQuad;
import org.jnode.vm.compiler.ir.quad.ConstantClassAssignQuad;
import org.jnode.vm.compiler.ir.quad.ConstantRefAssignQuad;
import org.jnode.vm.compiler.ir.quad.ConstantStringAssignQuad;
import org.jnode.vm.compiler.ir.quad.InstanceofAssignQuad;
import org.jnode.vm.compiler.ir.quad.InterfaceCallAssignQuad;
import org.jnode.vm.compiler.ir.quad.InterfaceCallQuad;
import org.jnode.vm.compiler.ir.quad.LookupswitchQuad;
import org.jnode.vm.compiler.ir.quad.MonitorenterQuad;
import org.jnode.vm.compiler.ir.quad.MonitorexitQuad;
import org.jnode.vm.compiler.ir.quad.NewAssignQuad;
import org.jnode.vm.compiler.ir.quad.NewMultiArrayAssignQuad;
import org.jnode.vm.compiler.ir.quad.NewObjectArrayAssignQuad;
import org.jnode.vm.compiler.ir.quad.NewPrimitiveArrayAssignQuad;
import org.jnode.vm.compiler.ir.quad.Quad;
import org.jnode.vm.compiler.ir.quad.RefAssignQuad;
import org.jnode.vm.compiler.ir.quad.RefStoreQuad;
import org.jnode.vm.compiler.ir.quad.SpecialCallAssignQuad;
import org.jnode.vm.compiler.ir.quad.SpecialCallQuad;
import org.jnode.vm.compiler.ir.quad.StaticCallAssignQuad;
import org.jnode.vm.compiler.ir.quad.StaticCallQuad;
import org.jnode.vm.compiler.ir.quad.StaticRefAssignQuad;
import org.jnode.vm.compiler.ir.quad.StaticRefStoreQuad;
import org.jnode.vm.compiler.ir.quad.TableswitchQuad;
import org.jnode.vm.compiler.ir.quad.ThrowQuad;
import org.jnode.vm.compiler.ir.quad.UnaryOperation;
import org.jnode.vm.compiler.ir.quad.UnaryQuad;
import org.jnode.vm.compiler.ir.quad.UnconditionalBranchQuad;
import org.jnode.vm.compiler.ir.quad.VarReturnQuad;
import org.jnode.vm.compiler.ir.quad.VariableRefAssignQuad;
import org.jnode.vm.compiler.ir.quad.VirtualCallAssignQuad;
import org.jnode.vm.compiler.ir.quad.VirtualCallQuad;
import org.jnode.vm.compiler.ir.quad.VoidReturnQuad;
import org.jnode.vm.facade.TypeSizeInfo;
import org.jnode.vm.facade.VmUtils;
import org.jnode.vm.x86.compiler.X86CompilerHelper;
import org.jnode.vm.x86.compiler.X86IMTCompiler32;
import org.jnode.vm.x86.compiler.X86JumpTable;
/**
* @author Madhu Siddalingaiah
* @author Levente S\u00e1ntha
*/
public class GenericX86CodeGenerator<T extends X86Register> extends CodeGenerator<T> implements
X86Constants {
private static final GPR SR1 = X86Register.EAX;
// private static final Register SR2 = Register.EBX;
// private static final Register SR3 = Register.ECX;
// private static final Register SR4 = Register.EDX;
public static final int BYTESIZE = X86Constants.BITS8;
public static final int WORDSIZE = X86Constants.BITS16;
protected final VmMethod currentMethod;
protected final X86StackFrame stackFrame;
protected final TypeSizeInfo typeSizeInfo;
protected Variable<T>[] spilledVariables;
protected X86Assembler os;
protected int startOffset;
private int displacement = -4;
private String labelPrefix;
private String instrLabelPrefix;
private Label[] addressLabels;
private final RegisterPool<T> registerPool;
/**
* Initialize this instance
*/
public GenericX86CodeGenerator(X86Assembler x86Stream, RegisterPool<T> pool, int lenght, TypeSizeInfo typeSizeInfo,
X86StackFrame stackFrame, VmMethod method) {
CodeGenerator.setCodeGenerator(this);
this.registerPool = pool;
this.os = x86Stream;
labelPrefix = stackFrame.getHelper().genLabel("").toString();
instrLabelPrefix = labelPrefix + "_bci_";
addressLabels = new Label[lenght];
this.typeSizeInfo = typeSizeInfo;
this.stackFrame = stackFrame;
this.currentMethod = method;
}
public final Label getInstrLabel(int address) {
Label l = addressLabels[address];
if (l == null) {
l = new Label(instrLabelPrefix + address);
addressLabels[address] = l;
}
return l;
}
public RegisterPool<T> getRegisterPool() {
return registerPool;
}
public boolean supports3AddrOps() {
return false;
}
// public void setArgumentVariables(Variable<T>[] vars, int nArgs) {
// displacement = 0;
// for (int i = 0; i < nArgs; i += 1) {
// // TODO this might not be right, check with Ewout
// displacement = vars[i].getIndex() * 4;
// vars[i].setLocation(new StackLocation<T>(displacement));
// }
// // not sure how big the last arg is...
// displacement += 8;
// }
// public void setSpilledVariables(Variable<T>[] variables) {
// this.spilledVariables = variables;
// int n = spilledVariables.length;
// for (int i = 0; i < n; i += 1) {
// StackLocation<T> loc = (StackLocation<T>) spilledVariables[i]
// .getLocation();
// loc.setDisplacement(displacement);
// switch (spilledVariables[i].getType()) {
// case Operand.BYTE:
// case Operand.CHAR:
// case Operand.SHORT:
// case Operand.INT:
// case Operand.FLOAT:
// case Operand.REFERENCE:
// displacement -= 4;
// break;
// case Operand.LONG:
// case Operand.DOUBLE:
// displacement -= 8;
// break;
// }
// }
// }
public void setSpilledVariables(Variable[] variables) {
this.spilledVariables = variables;
int n = spilledVariables.length;
int noArgs = currentMethod.getNoArguments();
for (int i = 0; i < n; i += 1) {
Variable<X86Register> var = (Variable<X86Register>) spilledVariables[i];
StackLocation loc = (StackLocation) var.getLocation();
loc.setDisplacement(stackFrame.getEbpOffset(typeSizeInfo, noArgs + i));
}
}
// public void emitHeader() {
// os.writePUSH(X86Register.EBP);
// // os.writePUSH(context.getMagic());
// // os.writePUSH(0); // PC, which is only used in interpreted methods
// /** EAX MUST contain the VmMethod structure upon entry of the method */
// // os.writePUSH(Register.EAX);
// os.writeMOV(X86Constants.BITS32, X86Register.EBP, X86Register.ESP);
// }
@Override
public void emitHeader() {
this.startOffset = stackFrame.emitHeader();
}
public void generateCodeFor(ConditionalBranchQuad<T> quad) {
throw new IllegalArgumentException("Unknown operation");
}
public void generateCodeFor(ConstantRefAssignQuad<T> quad) {
checkLabel(quad.getAddress());
Variable<T> lhs = quad.getLHS();
if (lhs.getAddressingMode() == REGISTER) {
T reg1 = ((RegisterLocation<T>) lhs.getLocation()).getRegister();
IntConstant<T> rhs = (IntConstant<T>) quad.getRHS();
os.writeMOV_Const((GPR) reg1, rhs.getValue());
} else if (lhs.getAddressingMode() == STACK) {
IntConstant<T> rhs = (IntConstant<T>) quad.getRHS();
int disp1 = ((StackLocation<T>) lhs.getLocation()).getDisplacement();
// TODO os.writeMOV_Const(X86Register.EBP, disp1, rhs.getValue());
} else {
throw new IllegalArgumentException("Unknown operation");
}
}
private int prev_addr = 0;
public void checkLabel(int address) {
for (int i = prev_addr + 1; i <= address; i++) {
Label l = addressLabels[i];
if (l == null) {
l = getInstrLabel(i);
}
os.setObjectRef(l);
}
prev_addr = address;
}
public void generateCodeFor(UnconditionalBranchQuad<T> quad) {
checkLabel(quad.getAddress());
if (quad.getTargetAddress() < quad.getAddress()) {
stackFrame.getHelper().writeYieldPoint(getInstrLabel(quad.getAddress()));
}
os.writeJMP(getInstrLabel(quad.getTargetAddress()));
}
public void generateCodeFor(VariableRefAssignQuad<T> quad) {
checkLabel(quad.getAddress());
Variable<T> lhs = quad.getLHS();
if (lhs.getAddressingMode() == REGISTER) {
T reg1 = ((RegisterLocation<T>) lhs.getLocation()).getRegister();
Operand<T> rhs = quad.getRHS();
AddressingMode mode = rhs.getAddressingMode();
if (mode == CONSTANT) {
os.writeMOV_Const((GPR) reg1, ((IntConstant<T>) rhs).getValue());
} else if (mode == REGISTER) {
T reg2 = ((RegisterLocation<T>) ((Variable<T>) rhs).getLocation()).getRegister();
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
} else if (mode == STACK) {
int disp2 = ((StackLocation<T>) ((Variable<T>) rhs).getLocation()).getDisplacement();
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
} else if (mode == TOPS) {
os.writePOP((GPR) reg1);
} else {
throw new IllegalArgumentException();
}
} else if (lhs.getAddressingMode() == STACK) {
int disp1 = ((StackLocation<T>) lhs.getLocation()).getDisplacement();
Operand<T> rhs = quad.getRHS();
AddressingMode mode = rhs.getAddressingMode();
if (mode == CONSTANT) {
//todo investigate lhs.getType() based checks
// if (lhs.getType() == Operand.INT) {
// os.writeMOV_Const(X86Constants.BITS32, X86Register.EBP, disp1, ((IntConstant<T>) rhs).getValue());
// } else if (lhs.getType() == Operand.LONG) {
// long value = ((LongConstant<T>) rhs).getValue();
// final int v_lsb = (int) (value & 0xFFFFFFFFL);
// final int v_msb = (int) ((value >>> 32) & 0xFFFFFFFFL);
// os.writeMOV_Const(BITS32, X86Register.EBP, disp1 - stackFrame.getHelper().SLOTSIZE, v_lsb);
// os.writeMOV_Const(BITS32, X86Register.EBP, disp1, v_msb);
// } else {
// throw new IllegalArgumentException("Type: " + lhs.getType());
// }
if (rhs instanceof IntConstant) {
os.writeMOV_Const(X86Constants.BITS32, X86Register.EBP, disp1, ((IntConstant<T>) rhs).getValue());
} else if (rhs instanceof LongConstant) {
long value = ((LongConstant<T>) rhs).getValue();
final int v_lsb = (int) (value & 0xFFFFFFFFL);
final int v_msb = (int) ((value >>> 32) & 0xFFFFFFFFL);
os.writeMOV_Const(BITS32, X86Register.EBP, disp1 - stackFrame.getHelper().SLOTSIZE, v_lsb);
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, v_msb);
} else {
throw new IllegalArgumentException("Type: " + lhs.getType());
}
} else if (mode == REGISTER) {
T reg2 = ((RegisterLocation<T>) ((Variable<T>) rhs).getLocation()).getRegister();
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
} else if (mode == STACK) {
//todo optimize it
int disp2 = ((StackLocation) ((Variable) rhs).getLocation()).getDisplacement();
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
} else if (mode == TOPS) {
os.writePOP(X86Register.EBP, disp1);
} else {
throw new IllegalArgumentException();
}
}
}
public void generateCodeFor(VarReturnQuad<T> quad) {
checkLabel(quad.getAddress());
Operand<T> op = quad.getOperand();
if (op.getAddressingMode() == CONSTANT) {
if (op instanceof IntConstant) {
IntConstant<T> iconst = (IntConstant<T>) op;
os.writeMOV_Const(X86Register.EAX, iconst.getValue());
} else if (op instanceof LongConstant) {
LongConstant<T> lconst = (LongConstant<T>) op;
long value = lconst.getValue();
if (value != 0) {
final int lsbv = (int) (value & 0xFFFFFFFFL);
final int msbv = (int) ((value >>> 32) & 0xFFFFFFFFL);
os.writeMOV_Const(X86Register.EAX, lsbv);
os.writeMOV_Const(X86Register.EDX, msbv);
} else {
os.writeXOR(X86Register.EAX, X86Register.EAX);
os.writeXOR(X86Register.EDX, X86Register.EDX);
}
} else {
throw new IllegalArgumentException();
}
} else if (op.getAddressingMode() == REGISTER) {
GPR src = (GPR) ((RegisterLocation<T>) ((Variable<T>) op).getLocation()).getRegister();
if (!src.equals(X86Register.EAX)) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, src);
}
} else if (op.getAddressingMode() == STACK) {
if (op.getType() != Operand.LONG && op.getType() != Operand.DOUBLE) {
StackLocation<T> stackLoc = (StackLocation<T>) ((Variable<T>) op).getLocation();
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, stackLoc.getDisplacement());
} else if (op.getType() == Operand.LONG) {
int disp1 = ((StackLocation<T>) ((Variable<T>) op).getLocation()).getDisplacement();
int disp2 = disp1 - stackFrame.getHelper().SLOTSIZE;
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeMOV(X86Constants.BITS32, X86Register.EDX, X86Register.EBP, disp1);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
stackFrame.emitReturn();
}
public void generateCodeFor(VoidReturnQuad<T> quad) {
checkLabel(quad.getAddress());
// TODO: hack for testing
// os.writeMOV(X86Constants.BITS32, X86Register.ESP, X86Register.EBP);
// os.writePOP(X86Register.EBP);
// os.writeRET();
stackFrame.emitReturn();
}
public void generateCodeFor(UnaryQuad<T> quad, Object lhsReg, UnaryOperation operation,
Constant<T> con) {
throw new IllegalArgumentException("Constants should be folded");
}
public void generateCodeFor(UnaryQuad<T> quad, Object lhsReg, UnaryOperation operation, Object rhsReg) {
checkLabel(quad.getAddress());
switch (operation) {
case I2L:
throw new IllegalArgumentException("Unknown operation: " + operation);
case I2F:
os.writePUSH((GPR) rhsReg);
os.writeFILD32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) lhsReg);
break;
case I2D:
case L2I:
case L2F:
case L2D:
throw new IllegalArgumentException("Unknown operation: " + operation);
case F2I:
os.writePUSH((GPR) rhsReg);
os.writeFLD32(X86Register.ESP, 0);
os.writeFISTP32(X86Register.ESP, 0);
os.writePOP((GPR) lhsReg);
break;
case F2L:
case F2D:
case D2I:
case D2L:
case D2F:
throw new IllegalArgumentException("Unknown operation: " + operation);
case I2B: {
GPR lhsGpr = (GPR) lhsReg;
if (lhsGpr.isSuitableForBits8()) {
os.writeMOVSX(lhsGpr, (GPR) rhsReg, BYTESIZE);
} else {
os.writeMOVSX(SR1, lhsGpr, BYTESIZE);
os.writeMOV(X86Constants.BITS32, lhsGpr, SR1);
}
break;
}
case I2C:
os.writeMOVZX((GPR) lhsReg, (GPR) rhsReg, WORDSIZE);
break;
case I2S:
os.writeMOVSX((GPR) lhsReg, (GPR) rhsReg, WORDSIZE);
break;
case INEG:
if (lhsReg != rhsReg) {
os.writeMOV(X86Constants.BITS32, (GPR) lhsReg, (GPR) rhsReg);
}
os.writeNEG((GPR) lhsReg);
break;
case LNEG:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FNEG:
os.writePUSH((GPR) rhsReg);
os.writeFLD32(X86Register.ESP, 0);
os.writeFCHS();
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) lhsReg);
break;
case DNEG:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateCodeFor(UnaryQuad<T> quad, Object lhsReg, UnaryOperation operation,
int rhsDisp) {
checkLabel(quad.getAddress());
switch (operation) {
case I2L:
throw new IllegalArgumentException("Unknown operation: " + operation);
case I2F:
os.writePUSH(X86Register.EBP, rhsDisp);
os.writeFILD32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) lhsReg);
break;
case L2I:
os.writeMOV(BITS32, (GPR) lhsReg, X86Register.EBP, rhsDisp - stackFrame.getHelper().SLOTSIZE);
break;
case I2D:
case L2F:
case L2D:
throw new IllegalArgumentException("Unknown operation: " + operation);
case F2I:
os.writePUSH(X86Register.EBP, rhsDisp);
os.writeFLD32(X86Register.ESP, 0);
os.writeFISTP32(X86Register.ESP, 0);
os.writePOP((GPR) lhsReg);
break;
case F2L:
case F2D:
case D2I:
case D2L:
case D2F:
throw new IllegalArgumentException("Unknown operation: " + operation);
case I2B: {
GPR lhsGpr = (GPR) lhsReg;
if (lhsGpr.isSuitableForBits8()) {
os.writeMOVSX(lhsGpr, SR1, rhsDisp, BYTESIZE);
} else {
os.writeMOVSX(SR1, X86Register.EBP, rhsDisp, BYTESIZE);
os.writeMOV(X86Constants.BITS32, lhsGpr, SR1);
}
break;
}
case I2C:
os.writeMOVZX((GPR) lhsReg, X86Register.EBP, rhsDisp, WORDSIZE);
break;
case I2S:
os.writeMOVSX((GPR) lhsReg, X86Register.EBP, rhsDisp, WORDSIZE);
break;
case INEG:
os.writeMOV(X86Constants.BITS32, (GPR) lhsReg, X86Register.EBP, rhsDisp);
os.writeNEG((GPR) lhsReg);
break;
case LNEG:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FNEG:
os.writePUSH(X86Register.EBP, rhsDisp);
os.writeFLD32(X86Register.ESP, 0);
os.writeFCHS();
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) lhsReg);
break;
case DNEG:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateCodeFor(UnaryQuad<T> quad, int lhsDisp, UnaryOperation operation,
Object rhsReg) {
checkLabel(quad.getAddress());
switch (operation) {
case I2L:
os.writePUSH(X86Register.EAX);
os.writePUSH(X86Register.EDX);
os.writeMOV(BITS32, X86Register.EAX, (GPR) rhsReg);
os.writeCDQ(BITS32);
os.writeMOV(BITS32, X86Register.EBP, lhsDisp, X86Register.EDX);
os.writeMOV(BITS32, X86Register.EBP, lhsDisp - stackFrame.getHelper().SLOTSIZE, X86Register.EAX);
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EAX);
break;
case I2F:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, lhsDisp, (GPR) rhsReg);
os.writeFILD32(X86Register.EBP, lhsDisp);
os.writeFSTP32(X86Register.EBP, lhsDisp);
break;
case I2D:
case L2I:
case L2F:
case L2D:
case F2I:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, lhsDisp, (GPR) rhsReg);
os.writeFLD32(X86Register.EBP, lhsDisp);
os.writeFISTP32(X86Register.EBP, lhsDisp);
break;
case F2L:
case F2D:
case D2I:
case D2L:
case D2F:
throw new IllegalArgumentException("Unknown operation: " + operation);
case I2B:
os.writePUSH(SR1);
os.writeMOVSX(SR1, (GPR) rhsReg, BYTESIZE);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, lhsDisp, SR1);
os.writePOP(SR1);
break;
case I2C:
os.writePUSH(SR1);
os.writeMOVZX(SR1, (GPR) rhsReg, WORDSIZE);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, lhsDisp, SR1);
os.writePOP(SR1);
break;
case I2S:
os.writePUSH(SR1);
os.writeMOVSX(SR1, (GPR) rhsReg, WORDSIZE);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, lhsDisp, SR1);
os.writePOP(SR1);
break;
case INEG:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, lhsDisp, (GPR) rhsReg);
os.writeNEG(BITS32, X86Register.EBP, lhsDisp);
break;
case LNEG:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FNEG:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, lhsDisp, (GPR) rhsReg);
os.writeFLD32(X86Register.EBP, lhsDisp);
os.writeFCHS();
os.writeFSTP32(X86Register.EBP, lhsDisp);
break;
case DNEG:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateCodeFor(UnaryQuad<T> quad, int lhsDisp, UnaryOperation operation,
int rhsDisp) {
checkLabel(quad.getAddress());
switch (operation) {
case I2L:
os.writePUSH(X86Register.EAX);
os.writePUSH(X86Register.EDX);
os.writeMOV(BITS32, X86Register.EAX, X86Register.EBP, rhsDisp);
os.writeCDQ(BITS32);
os.writeMOV(BITS32, X86Register.EBP, lhsDisp, X86Register.EDX);
os.writeMOV(BITS32, X86Register.EBP, lhsDisp - stackFrame.getHelper().SLOTSIZE, X86Register.EAX);
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EAX);
break;
case I2F:
os.writeFILD32(X86Register.EBP, rhsDisp);
os.writeFSTP32(X86Register.EBP, lhsDisp);
break;
case I2D:
throw new IllegalArgumentException("Unknown operation: " + operation);
case L2I:
os.writeMOV(BITS32, SR1, X86Register.EBP, rhsDisp - stackFrame.getHelper().SLOTSIZE);
os.writeMOV(BITS32, X86Register.EBP, lhsDisp, SR1);
break;
case L2F:
case L2D:
throw new IllegalArgumentException("Unknown operation: " + operation);
case F2I:
os.writeFLD32(X86Register.EBP, rhsDisp);
os.writeFISTP32(X86Register.EBP, lhsDisp);
break;
case F2L:
case F2D:
case D2I:
case D2L:
case D2F:
throw new IllegalArgumentException("Unknown operation: " + operation);
case I2B:
os.writePUSH(SR1);
os.writeMOVSX(SR1, X86Register.EBP, rhsDisp, BYTESIZE);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, lhsDisp, SR1);
os.writePOP(SR1);
break;
case I2C:
os.writePUSH(SR1);
os.writeMOVZX(SR1, X86Register.EBP, rhsDisp, WORDSIZE);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, lhsDisp, SR1);
os.writePOP(SR1);
break;
case I2S:
os.writePUSH(SR1);
os.writeMOVSX(SR1, X86Register.EBP, rhsDisp, WORDSIZE);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, lhsDisp, SR1);
os.writePOP(SR1);
break;
case INEG:
if (rhsDisp != lhsDisp) {
os.writePUSH(X86Register.EBP, rhsDisp);
os.writePOP(X86Register.EBP, lhsDisp);
}
os.writeNEG(BITS32, X86Register.EBP, lhsDisp);
break;
case LNEG:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FNEG:
os.writeFLD32(X86Register.EBP, rhsDisp);
os.writeFCHS();
os.writeFSTP32(X86Register.EBP, lhsDisp);
break;
case DNEG:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateCodeFor(UnaryQuad<T> quad, int lhsDisp, UnaryOperation operation,
Constant<T> con) {
throw new IllegalArgumentException("Constants should be folded");
}
public void generateBinaryOP(T reg1, Constant<T> c2,
BinaryOperation operation, Constant<T> c3) {
throw new IllegalArgumentException("Constants should be folded");
}
public void generateBinaryOP(T reg1, Constant<T> c2,
BinaryOperation operation, T reg3) {
IntConstant<T> iconst2 = (IntConstant<T>) c2;
switch (operation) {
case IADD:
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writeADD((GPR) reg1, (GPR) reg3);
break;
case IAND:
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writeAND((GPR) reg1, (GPR) reg3);
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV_Const(X86Register.EAX, iconst2.getValue());
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
if (reg1 == X86Register.EAX) {
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else if (reg1 == X86Register.EDX) {
os.writeMOV(X86Constants.BITS32, X86Register.EDX, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case IMUL:
os.writeIMUL_3((GPR) reg1, (GPR) reg3, iconst2.getValue());
break;
case IOR:
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writeOR((GPR) reg1, (GPR) reg3);
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV_Const(X86Register.EAX, iconst2.getValue());
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
if (reg1 == X86Register.EDX) {
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else if (reg1 == X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EDX);
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case ISHL: // needs CL
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSAL_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAL_CL((GPR) reg1);
}
break;
case ISHR: // needs CL
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSAL_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAR_CL((GPR) reg1);
}
break;
case ISUB:
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writeSUB((GPR) reg1, (GPR) reg3);
break;
case IUSHR:
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSAL_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
} else {
os.writeSHR_CL((GPR) reg1);
}
break;
case IXOR:
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writeXOR((GPR) reg1, (GPR) reg3);
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writePUSH(iconst2.getValue());
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV(X86Constants.BITS32, X86Register.ESP, 0, (GPR) reg3);
os.writeFADD32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FDIV:
os.writePUSH(iconst2.getValue());
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV(X86Constants.BITS32, X86Register.ESP, 0, (GPR) reg3);
os.writeFDIV32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FMUL:
os.writePUSH(iconst2.getValue());
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV(X86Constants.BITS32, X86Register.ESP, 0, (GPR) reg3);
os.writeFMUL32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FREM:
os.writePUSH((GPR) reg3);
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV_Const(BITS32, X86Register.ESP, 0, iconst2.getValue());
os.writeFLD32(X86Register.ESP, 0);
os.writeFPREM();
os.writeFSTP32(X86Register.ESP, 0);
os.writeFFREE(X86Register.ST0);
os.writePOP((GPR) reg1);
break;
case FSUB:
os.writePUSH(iconst2.getValue());
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV(X86Constants.BITS32, X86Register.ESP, 0, (GPR) reg3);
os.writeFSUB32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(T reg1, Constant<T> c2,
BinaryOperation operation, int disp3) {
IntConstant<T> iconst2 = (IntConstant<T>) c2;
switch (operation) {
case IADD:
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writeADD((GPR) reg1, X86Register.EBP, disp3);
break;
case IAND:
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writeAND((GPR) reg1, X86Register.EBP, disp3);
break;
case IDIV: // not supported
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV_Const(X86Register.EAX, iconst2.getValue());
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
if (reg1 == X86Register.EAX) {
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else if (reg1 == X86Register.EDX) {
os.writeMOV(X86Constants.BITS32, X86Register.EDX, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case IMUL:
os.writeIMUL_3((GPR) reg1, X86Register.EBP, disp3, iconst2.getValue());
break;
case IOR:
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writeOR((GPR) reg1, X86Register.EBP, disp3);
break;
case IREM:
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV_Const(X86Register.EAX, iconst2.getValue());
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
if (reg1 == X86Register.EDX) {
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else if (reg1 == X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EDX);
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case ISHL: // not supported
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAL_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
break;
case ISHR: // not supported
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAR_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
break;
case ISUB:
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writeSUB((GPR) reg1, X86Register.EBP, disp3);
break;
case IUSHR: // not supported
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSHR_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
break;
case IXOR:
os.writeMOV_Const((GPR) reg1, iconst2.getValue());
os.writeXOR((GPR) reg1, X86Register.EBP, disp3);
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writePUSH(iconst2.getValue());
os.writeFLD32(X86Register.ESP, 0);
os.writeFADD32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FDIV:
os.writePUSH(iconst2.getValue());
os.writeFLD32(X86Register.ESP, 0);
os.writeFDIV32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FMUL:
os.writePUSH(iconst2.getValue());
os.writeFLD32(X86Register.ESP, 0);
os.writeFMUL32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FREM:
os.writePUSH(iconst2.getValue());
os.writeFLD32(X86Register.EBP, disp3);
os.writeFLD32(X86Register.ESP, 0);
os.writeFPREM();
os.writeFSTP32(X86Register.ESP, 0);
os.writeFFREE(X86Register.ST0);
os.writePOP((GPR) reg1);
break;
case FSUB:
os.writePUSH(iconst2.getValue());
os.writeFLD32(X86Register.ESP, 0);
os.writeFSUB32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(T reg1, T reg2,
BinaryOperation operation, Constant<T> c3) {
IntConstant<T> iconst3 = (IntConstant<T>) c3;
switch (operation) {
case IADD:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeADD((GPR) reg1, iconst3.getValue());
break;
case IAND:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeAND((GPR) reg1, iconst3.getValue());
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writePUSH(iconst3.getValue());
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
os.writePOP(X86Register.EDX);
if (reg1 == X86Register.EAX) {
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else if (reg1 == X86Register.EDX) {
os.writeMOV(X86Constants.BITS32, X86Register.EDX, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case IMUL:
os.writeIMUL_3((GPR) reg1, (GPR) reg2, iconst3.getValue());
break;
case IOR:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeOR((GPR) reg1, iconst3.getValue());
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writePUSH(iconst3.getValue());
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
os.writePOP(X86Register.EAX);
if (reg1 == X86Register.EDX) {
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else if (reg1 == X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EDX);
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case ISHL: // needs CL
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeSAL((GPR) reg1, iconst3.getValue());
break;
case ISHR: // needs CL
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeSAR((GPR) reg1, iconst3.getValue());
break;
case ISUB:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeSUB((GPR) reg1, iconst3.getValue());
break;
case IUSHR: // needs CL
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeSHR((GPR) reg1, iconst3.getValue());
break;
case IXOR:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeXOR((GPR) reg1, iconst3.getValue());
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV_Const(BITS32, X86Register.ESP, 0, iconst3.getValue());
os.writeFADD32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FDIV:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV_Const(BITS32, X86Register.ESP, 0, iconst3.getValue());
os.writeFDIV32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FMUL:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV_Const(BITS32, X86Register.ESP, 0, iconst3.getValue());
os.writeFMUL32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FREM:
os.writePUSH(iconst3.getValue());
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV(X86Constants.BITS32, X86Register.ESP, 0, (GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeFPREM();
os.writeFSTP32(X86Register.ESP, 0);
os.writeFFREE(X86Register.ST0);
os.writePOP((GPR) reg1);
break;
case FSUB:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV_Const(BITS32, X86Register.ESP, 0, iconst3.getValue());
os.writeFSUB32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(T reg1, T reg2,
BinaryOperation operation, T reg3) {
switch (operation) {
case IADD:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeADD((GPR) reg1, (GPR) reg3);
break;
case IAND:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeAND((GPR) reg1, (GPR) reg3);
break;
case IDIV:
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
if (reg1 == X86Register.EAX) {
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else if (reg1 == X86Register.EDX) {
os.writeMOV(X86Constants.BITS32, X86Register.EDX, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case IMUL:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeIMUL((GPR) reg1, (GPR) reg3);
break;
case IOR:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeOR((GPR) reg1, (GPR) reg3);
break;
case IREM: // needs EAX, EDX //TODO verify
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
if (reg1 == X86Register.EDX) {
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else if (reg1 == X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EDX);
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case ISHL: // needs CL
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSAL_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAL_CL((GPR) reg1);
}
break;
case ISHR: // needs CL
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSAR_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAL_CL((GPR) reg1);
}
break;
case ISUB:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeSUB((GPR) reg1, (GPR) reg3);
break;
case IUSHR: // needs CL
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSHR_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAL_CL((GPR) reg1);
}
break;
case IXOR:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeXOR((GPR) reg1, (GPR) reg3);
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV(X86Constants.BITS32, X86Register.ESP, 0, (GPR) reg3);
os.writeFADD32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FDIV:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV(X86Constants.BITS32, X86Register.ESP, 0, (GPR) reg3);
os.writeFDIV32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FMUL:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV(X86Constants.BITS32, X86Register.ESP, 0, (GPR) reg3);
os.writeFMUL32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FREM:
os.writePUSH((GPR) reg3);
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV(X86Constants.BITS32, X86Register.ESP, 0, (GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeFPREM();
os.writeFSTP32(X86Register.ESP, 0);
os.writeFFREE(X86Register.ST0);
os.writePOP((GPR) reg1);
break;
case FSUB:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeMOV(X86Constants.BITS32, X86Register.ESP, 0, (GPR) reg3);
os.writeFSUB32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(T reg1, T reg2,
BinaryOperation operation, int disp3) {
switch (operation) {
case IADD:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeADD((GPR) reg1, X86Register.EBP, disp3);
break;
case IAND:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeAND((GPR) reg1, X86Register.EBP, disp3);
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
if (reg1 == X86Register.EAX) {
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else if (reg1 == X86Register.EDX) {
os.writeMOV(X86Constants.BITS32, X86Register.EDX, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case IMUL:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeIMUL((GPR) reg1, X86Register.EBP, disp3);
break;
case IOR:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeOR((GPR) reg1, X86Register.EBP, disp3);
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
if (reg1 == X86Register.EDX) {
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else if (reg1 == X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EDX);
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case ISHL: // needs CL
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAL_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
break;
case ISHR: // needs CL
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAR_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
break;
case ISUB:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeSUB((GPR) reg1, X86Register.EBP, disp3);
break;
case IUSHR: // needs CL
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSHR_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
break;
case IXOR:
if (reg1 != reg2) {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, (GPR) reg2);
}
os.writeXOR((GPR) reg1, X86Register.EBP, disp3);
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeFADD32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FDIV:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeFDIV32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FMUL:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeFMUL32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FREM:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.EBP, disp3);
os.writeFLD32(X86Register.ESP, 0);
os.writeFPREM();
os.writeFSTP32(X86Register.ESP, 0);
os.writeFFREE(X86Register.ST0);
os.writePOP((GPR) reg1);
break;
case FSUB:
os.writePUSH((GPR) reg2);
os.writeFLD32(X86Register.ESP, 0);
os.writeFSUB32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(BinaryQuad<T> quad, T reg1, int disp2,
BinaryOperation operation, Constant<T> c3) {
switch (operation) {
case IADD:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeADD((GPR) reg1, ((IntConstant<T>) c3).getValue());
break;
case IAND:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeAND((GPR) reg1, ((IntConstant<T>) c3).getValue());
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writePUSH(((IntConstant<T>) c3).getValue());
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
os.writePOP(X86Register.EDX);
if (reg1 == X86Register.EAX) {
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else if (reg1 == X86Register.EDX) {
os.writeMOV(X86Constants.BITS32, X86Register.EDX, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case IMUL:
os.writeIMUL_3((GPR) reg1, X86Register.EBP, disp2, ((IntConstant<T>) c3).getValue());
break;
case IOR:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeOR((GPR) reg1, ((IntConstant<T>) c3).getValue());
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writePUSH(((IntConstant<T>) c3).getValue());
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
os.writePOP(X86Register.EAX);
if (reg1 == X86Register.EDX) {
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else if (reg1 == X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EDX);
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case ISHL: // needs CL
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeSAL((GPR) reg1, ((IntConstant<T>) c3).getValue());
break;
case ISHR: // needs CL
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeSAR((GPR) reg1, ((IntConstant<T>) c3).getValue());
break;
case ISUB:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeSUB((GPR) reg1, ((IntConstant<T>) c3).getValue());
break;
case IUSHR: // needs CL
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeSHR((GPR) reg1, ((IntConstant<T>) c3).getValue());
break;
case IXOR:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeXOR((GPR) reg1, ((IntConstant<T>) c3).getValue());
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writePUSH(((IntConstant<T>) c3).getValue());
os.writeFLD32(X86Register.EBP, disp2);
os.writeFADD32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FDIV:
os.writePUSH(((IntConstant<T>) c3).getValue());
os.writeFLD32(X86Register.EBP, disp2);
os.writeFDIV32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FMUL:
os.writePUSH(((IntConstant<T>) c3).getValue());
os.writeFLD32(X86Register.EBP, disp2);
os.writeFMUL32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FREM:
os.writePUSH(((IntConstant<T>) c3).getValue());
os.writeFLD32(X86Register.ESP, 0);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFPREM();
os.writeFSTP32(X86Register.ESP, 0);
os.writeFFREE(X86Register.ST0);
os.writePOP((GPR) reg1);
break;
case FSUB:
os.writePUSH(((IntConstant<T>) c3).getValue());
os.writeFLD32(X86Register.EBP, disp2);
os.writeFSUB32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case LCMP: {
final Label curInstrLabel = getInstrLabel(quad.getAddress());
final Label ltLabel = new Label(curInstrLabel + "lt");
final Label endLabel = new Label(curInstrLabel + "end");
GPR gpr1 = (GPR) reg1;
// Calculate
if (os.isCode32()) {
long value = ((LongConstant<T>) c3).getValue();
final int v_lsb = (int) (value & 0xFFFFFFFFL);
final int v_msb = (int) ((value >>> 32) & 0xFFFFFFFFL);
int disp2lsb = disp2 - stackFrame.getHelper().SLOTSIZE;
int disp2msb = disp2;
os.writeXOR(gpr1, gpr1);
os.writeSUB(BITS32, X86Register.EBP, disp2lsb, v_lsb);
os.writeSBB(BITS32, X86Register.EBP, disp2msb, v_msb);
os.writeJCC(ltLabel, X86Constants.JL); // JL
os.writeMOV(BITS32, SR1, X86Register.EBP, disp2lsb);
os.writeOR(SR1, X86Register.EBP, disp2msb);
}
// else {
// final GPR64 v2r = v2.getRegister(eContext);
// final GPR64 v1r = v1.getRegister(eContext);
// os.writeCMP(v1r, v2r);
// os.writeJCC(ltLabel, X86Constants.JL); // JL
// }
os.writeJCC(endLabel, X86Constants.JZ); // value1 == value2
/** GT */
os.writeINC(gpr1);
os.writeJMP(endLabel);
/** LT */
os.setObjectRef(ltLabel);
os.writeDEC(gpr1);
os.setObjectRef(endLabel);
break;
}
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(T reg1, int disp2,
BinaryOperation operation, T reg3) {
switch (operation) {
case IADD:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeADD((GPR) reg1, (GPR) reg3);
break;
case IAND:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeAND((GPR) reg1, (GPR) reg3);
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
if (reg1 == X86Register.EAX) {
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else if (reg1 == X86Register.EDX) {
os.writeMOV(X86Constants.BITS32, X86Register.EDX, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case IMUL:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeIMUL((GPR) reg1, (GPR) reg3);
break;
case IOR:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeOR((GPR) reg1, (GPR) reg3);
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
if (reg1 == X86Register.EDX) {
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else if (reg1 == X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EDX);
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case ISHL: // needs CL
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSHR_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAL_CL((GPR) reg1);
}
break;
case ISHR: // needs CL
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSHR_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAR_CL((GPR) reg1);
}
break;
case ISUB:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeSUB((GPR) reg1, (GPR) reg3);
break;
case IUSHR: // needs CL
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSHR_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
} else {
os.writeSHR_CL((GPR) reg1);
}
break;
case IXOR:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeXOR((GPR) reg1, (GPR) reg3);
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writePUSH((GPR) reg3);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFADD32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FDIV:
os.writePUSH((GPR) reg3);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFDIV32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FMUL:
os.writePUSH((GPR) reg3);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFMUL32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FREM:
os.writePUSH((GPR) reg3);
os.writeFLD32(X86Register.ESP, 0);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFPREM();
os.writeFSTP32(X86Register.ESP, 0);
os.writeFFREE(X86Register.ST0);
os.writePOP((GPR) reg1);
break;
case FSUB:
os.writePUSH((GPR) reg3);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFSUB32(X86Register.ESP, 0);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(T reg1, int disp2,
BinaryOperation operation, int disp3) {
switch (operation) {
case IADD:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeADD((GPR) reg1, X86Register.EBP, disp3);
break;
case IAND:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeAND((GPR) reg1, X86Register.EBP, disp3);
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
if (reg1 == X86Register.EAX) {
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else if (reg1 == X86Register.EDX) {
os.writeMOV(X86Constants.BITS32, X86Register.EDX, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case IMUL:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeIMUL((GPR) reg1, X86Register.EBP, disp3);
break;
case IOR: // not supported
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeOR((GPR) reg1, X86Register.EBP, disp3);
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
if (reg1 == X86Register.EDX) {
os.writePOP(X86Register.EAX);
os.writeADD(X86Register.ESP, 4);
} else if (reg1 == X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EDX);
os.writePOP(X86Register.EDX);
os.writePOP(X86Register.EDX);
} else {
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
}
break;
case ISHL: // needs CL
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAL_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
break;
case ISHR: // needs CL
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAR_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
break;
case ISUB:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeSUB((GPR) reg1, X86Register.EBP, disp3);
break;
case IUSHR: // needs CL
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSHR_CL((GPR) reg1);
os.writePOP(X86Register.ECX);
break;
case IXOR:
os.writeMOV(X86Constants.BITS32, (GPR) reg1, X86Register.EBP, disp2);
os.writeXOR((GPR) reg1, X86Register.EBP, disp3);
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writeFLD32(X86Register.EBP, disp2);
os.writeFADD32(X86Register.EBP, disp3);
os.writePUSH((GPR) reg1);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FDIV:
os.writeFLD32(X86Register.EBP, disp2);
os.writeFDIV32(X86Register.EBP, disp3);
os.writePUSH((GPR) reg1);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FMUL:
os.writeFLD32(X86Register.EBP, disp2);
os.writeFMUL32(X86Register.EBP, disp3);
os.writePUSH((GPR) reg1);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case FREM:
os.writeFLD32(X86Register.EBP, disp3);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFPREM();
os.writePUSH((GPR) reg1);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
os.writeFFREE(X86Register.ST0);
break;
case FSUB:
os.writeFLD32(X86Register.EBP, disp2);
os.writeFSUB32(X86Register.EBP, disp3);
os.writePUSH((GPR) reg1);
os.writeFSTP32(X86Register.ESP, 0);
os.writePOP((GPR) reg1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
// / WE should not get to this method
public void generateBinaryOP(int disp1, Constant<T> c2,
BinaryOperation operation, Constant<T> c3) {
throw new IllegalArgumentException("Constants should be folded");
}
public void generateBinaryOP(int disp1, Constant<T> c2,
BinaryOperation operation, T reg3) {
IntConstant<T> iconst2 = (IntConstant<T>) c2;
switch (operation) {
case IADD:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeADD(X86Register.EBP, disp1, (GPR) reg3);
break;
case IAND:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeAND(X86Register.EBP, disp1, (GPR) reg3);
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV_Const(X86Register.EAX, iconst2.getValue());
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case IMUL:
os.writePUSH((GPR) reg3);
os.writeIMUL_3((GPR) reg3, (GPR) reg3, iconst2.getValue());
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writePOP((GPR) reg3);
break;
case IOR:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeOR(X86Register.EBP, disp1, (GPR) reg3);
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV_Const(X86Register.EAX, iconst2.getValue());
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case ISHL: // needs CL
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSAL_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAL_CL(BITS32, X86Register.EBP, disp1);
}
break;
case ISHR: // needs CL
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSAR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAR_CL(BITS32, X86Register.EBP, disp1);
}
break;
case ISUB:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeSUB(X86Register.EBP, disp1, (GPR) reg3);
break;
case IUSHR: // needs CL
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSHR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
} else {
os.writeSHR_CL(BITS32, X86Register.EBP, disp1);
}
break;
case IXOR: // not supported
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeXOR(X86Register.EBP, disp1, (GPR) reg3);
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFADD32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FDIV:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFDIV32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FMUL:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFMUL32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FREM:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeFLD32(X86Register.EBP, disp1);
os.writeFPREM();
os.writeFSTP32(X86Register.EBP, disp1);
os.writeFFREE(X86Register.ST0);
break;
case FSUB:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFSUB32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(int disp1, Constant<T> c2,
BinaryOperation operation, int disp3) {
IntConstant<T> iconst2 = (IntConstant<T>) c2;
switch (operation) {
case IADD:
os.writePUSH(SR1);
os.writeMOV_Const(SR1, iconst2.getValue());
os.writeADD(SR1, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case IAND:
os.writePUSH(SR1);
os.writeMOV_Const(SR1, iconst2.getValue());
os.writeAND(SR1, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case IDIV:
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV_Const(X86Register.EAX, iconst2.getValue());
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case IMUL:
os.writePUSH(SR1);
os.writeIMUL_3(SR1, X86Register.EBP, disp3, iconst2.getValue());
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case IOR:
os.writePUSH(SR1);
os.writeMOV_Const(SR1, iconst2.getValue());
os.writeOR(SR1, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case IREM:
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV_Const(X86Register.EAX, iconst2.getValue());
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case ISHL:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAL_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
break;
case ISHR:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
break;
case ISUB:
os.writePUSH(SR1);
os.writeMOV_Const(SR1, iconst2.getValue());
os.writeSUB(SR1, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case IUSHR:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSHR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
break;
case IXOR:
os.writePUSH(SR1);
os.writeMOV_Const(SR1, iconst2.getValue());
os.writeXOR(SR1, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeFLD32(X86Register.EBP, disp1);
os.writeFADD32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FDIV:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeFLD32(X86Register.EBP, disp1);
os.writeFDIV32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FMUL:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeFLD32(X86Register.EBP, disp1);
os.writeFMUL32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FREM:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeFSUB32(X86Register.EBP, disp3);
os.writeFLD32(X86Register.EBP, disp1);
os.writeFPREM();
os.writeFSTP32(X86Register.EBP, disp1);
os.writeFFREE(X86Register.ST0);
break;
case FSUB:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst2.getValue());
os.writeFLD32(X86Register.EBP, disp1);
os.writeFSUB32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(int disp1, T reg2,
BinaryOperation operation, Constant<T> c3) {
IntConstant<T> iconst3 = (IntConstant<T>) c3;
switch (operation) {
case IADD:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeADD(BITS32, X86Register.EBP, disp1, iconst3.getValue());
break;
case IAND:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeAND(BITS32, X86Register.EBP, disp1, iconst3.getValue());
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writePUSH(iconst3.getValue());
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
os.writePOP(X86Register.EDX);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case IMUL:
os.writePUSH((GPR) reg2);
os.writeIMUL_3((GPR) reg2, (GPR) reg2, iconst3.getValue());
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writePOP((GPR) reg2);
break;
case IOR:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeOR(BITS32, X86Register.EBP, disp1, iconst3.getValue());
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writePUSH(iconst3.getValue());
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
os.writePOP(X86Register.EAX);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case ISHL: // needs CL
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeSAL(BITS32, X86Register.EBP, disp1, iconst3.getValue());
break;
case ISHR: // needs CL
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeSAR(BITS32, X86Register.EBP, disp1, iconst3.getValue());
break;
case ISUB:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeSUB(BITS32, X86Register.EBP, disp1, iconst3.getValue());
break;
case IUSHR: // needs CL
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeSHR(BITS32, X86Register.EBP, disp1, iconst3.getValue());
break;
case IXOR:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeXOR(BITS32, X86Register.EBP, disp1, iconst3.getValue());
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst3.getValue());
os.writeFADD32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FDIV:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst3.getValue());
os.writeFDIV32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FMUL:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst3.getValue());
os.writeFMUL32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FREM:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst3.getValue());
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeFPREM();
os.writeFSTP32(X86Register.EBP, disp1);
os.writeFFREE(X86Register.ST0);
break;
case FSUB:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, iconst3.getValue());
os.writeFSUB32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(int disp1, T reg2,
BinaryOperation operation, T reg3) {
switch (operation) {
case IADD:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeADD(X86Register.EBP, disp1, (GPR) reg3);
break;
case IAND:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeAND(X86Register.EBP, disp1, (GPR) reg3);
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case IMUL:
os.writePUSH((GPR) reg2);
os.writeIMUL((GPR) reg2, (GPR) reg3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writePOP((GPR) reg2);
break;
case IOR:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeOR(X86Register.EBP, disp1, (GPR) reg3);
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case ISHL: // needs CL
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSAL_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAL_CL(BITS32, X86Register.EBP, disp1);
}
break;
case ISHR: // needs CL
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSAR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAR_CL(BITS32, X86Register.EBP, disp1);
}
break;
case ISUB:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeSUB(X86Register.EBP, disp1, (GPR) reg3);
break;
case IUSHR: // needs CL
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSHR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
} else {
os.writeSHR_CL(BITS32, X86Register.EBP, disp1);
}
break;
case IXOR:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeXOR(X86Register.EBP, disp1, (GPR) reg3);
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFADD32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FDIV:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFDIV32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FMUL:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFMUL32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FREM:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeFPREM();
os.writeFSTP32(X86Register.EBP, disp1);
os.writeFFREE(X86Register.ST0);
break;
case FSUB:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFSUB32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(int disp1, T reg2, BinaryOperation operation, int disp3) {
switch (operation) {
case IADD:
os.writePUSH((GPR) reg2);
os.writeADD((GPR) reg2, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writePOP((GPR) reg2);
break;
case IAND:
os.writePUSH((GPR) reg2);
os.writeAND((GPR) reg2, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writePOP((GPR) reg2);
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case IMUL:
os.writePUSH((GPR) reg2);
os.writeIMUL((GPR) reg2, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writePOP((GPR) reg2);
break;
case IOR:
os.writePUSH((GPR) reg2);
os.writeOR((GPR) reg2, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writePOP((GPR) reg2);
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
if (reg2 != X86Register.EAX) {
os.writeMOV(X86Constants.BITS32, X86Register.EAX, (GPR) reg2);
}
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case ISHL: // needs CL
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAL_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
break;
case ISHR: // needs CL
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
break;
case ISUB:
os.writePUSH((GPR) reg2);
os.writeSUB((GPR) reg2, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writePOP((GPR) reg2);
break;
case IUSHR: // needs CL
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSHR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
break;
case IXOR:
os.writePUSH((GPR) reg2);
os.writeXOR((GPR) reg2, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writePOP((GPR) reg2);
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeFADD32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FDIV:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeFDIV32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FMUL:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeFMUL32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FREM:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp3);
os.writeFLD32(X86Register.EBP, disp1);
os.writeFPREM();
os.writeFSTP32(X86Register.EBP, disp1);
os.writeFFREE(X86Register.ST0);
break;
case FSUB:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg2);
os.writeFLD32(X86Register.EBP, disp1);
os.writeFSUB32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(BinaryQuad<T> quad, int disp1, int disp2, BinaryOperation operation, Constant<T> c3) {
switch (operation) {
case IADD: // not supported due to the move bellow
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeADD(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
break;
case IAND:
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeAND(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writePUSH(((IntConstant<T>) c3).getValue());
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
os.writePOP(X86Register.EDX);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case IMUL:
os.writePUSH(SR1);
os.writeIMUL_3(SR1, X86Register.EBP, disp2, ((IntConstant<T>) c3).getValue());
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case IOR:
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeOR(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writePUSH(((IntConstant<T>) c3).getValue());
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
os.writePOP(X86Register.EAX);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case ISHL: // needs CL
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeSAL(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
break;
case ISHR: // needs CL
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeSAR(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
break;
case ISUB: // not supported
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeSUB(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
break;
case IUSHR: // needs CL
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeSHR(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
break;
case IXOR: // not supported
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeXOR(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
os.writeFLD32(X86Register.EBP, disp2);
os.writeFADD32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FDIV:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
os.writeFLD32(X86Register.EBP, disp2);
os.writeFDIV32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FMUL:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
os.writeFLD32(X86Register.EBP, disp2);
os.writeFMUL32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FREM:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
os.writeFLD32(X86Register.EBP, disp1);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFPREM();
os.writeFSTP32(X86Register.EBP, disp1);
os.writeFFREE(X86Register.ST0);
break;
case FSUB:
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c3).getValue());
os.writeFLD32(X86Register.EBP, disp2);
os.writeFSUB32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case LCMP: {
final Label curInstrLabel = getInstrLabel(quad.getAddress());
final Label ltLabel = new Label(curInstrLabel + "lt");
final Label endLabel = new Label(curInstrLabel + "end");
// Calculate
if (os.isCode32()) {
long value = ((LongConstant<T>) c3).getValue();
final int v_lsb = (int) (value & 0xFFFFFFFFL);
final int v_msb = (int) ((value >>> 32) & 0xFFFFFFFFL);
int disp2lsb = disp2 - stackFrame.getHelper().SLOTSIZE;
int disp2msb = disp2;
os.writeSUB(BITS32, X86Register.EBP, disp2lsb, v_lsb);
os.writeSBB(BITS32, X86Register.EBP, disp2msb, v_msb);
os.writeJCC(ltLabel, X86Constants.JL); // JL
os.writeMOV(BITS32, SR1, X86Register.EBP, disp2lsb);
os.writeOR(SR1, X86Register.EBP, disp2msb);
}
// else {
// final GPR64 v2r = v2.getRegister(eContext);
// final GPR64 v1r = v1.getRegister(eContext);
// os.writeCMP(v1r, v2r);
// os.writeJCC(ltLabel, X86Constants.JL); // JL
// }
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, 0);
os.writeJCC(endLabel, X86Constants.JZ); // value1 == value2
/** GT */
os.writeINC(BITS32, X86Register.EBP, disp1);
os.writeJMP(endLabel);
/** LT */
os.setObjectRef(ltLabel);
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, -1);
os.setObjectRef(endLabel);
break;
}
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(int disp1, int disp2,
BinaryOperation operation, T reg3) {
switch (operation) {
case IADD:
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeADD(X86Register.EBP, disp1, (GPR) reg3);
break;
case IAND:
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeAND(X86Register.EBP, disp1, (GPR) reg3);
break;
case IDIV: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case IMUL:
os.writePUSH((GPR) reg3);
os.writeIMUL((GPR) reg3, X86Register.EBP, disp2);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writePOP((GPR) reg3);
break;
case IOR:
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeOR(X86Register.EBP, disp1, (GPR) reg3);
break;
case IREM: // needs EAX
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
if (reg3 == X86Register.EAX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 0);
} else if (reg3 == X86Register.EDX) {
os.writeIDIV_EAX(BITS32, X86Register.ESP, 4);
} else {
os.writeIDIV_EAX((GPR) reg3);
}
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case ISHL: // needs CL
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSAL_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAL_CL(BITS32, X86Register.EBP, disp1);
}
break;
case ISHR: // needs CL
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSAR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
} else {
os.writeSAR_CL(BITS32, X86Register.EBP, disp1);
}
break;
case ISUB:
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeSUB(X86Register.EBP, disp1, (GPR) reg3);
break;
case IUSHR: // needs CL
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
if (reg3 != X86Register.ECX) {
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, (GPR) reg3);
os.writeSHR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
} else {
os.writeSHR_CL(BITS32, X86Register.EBP, disp1);
}
break;
case IXOR:
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writeXOR(GPR.EBP, disp1, (GPR) reg3);
break;
case DADD:
case DDIV:
case DMUL:
case DREM:
case DSUB:
throw new IllegalArgumentException("Unknown operation: " + operation);
case FADD:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFADD32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FDIV:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFDIV32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FMUL:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFMUL32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FREM:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFLD32(X86Register.EBP, disp1);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFPREM();
os.writeFSTP32(X86Register.EBP, disp1);
os.writeFFREE(X86Register.ST0);
break;
case FSUB:
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, (GPR) reg3);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFSUB32(X86Register.EBP, disp1);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case LADD:
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
case LSUB:
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
public void generateBinaryOP(BinaryQuad<T> quad, int disp1, int disp2, BinaryOperation operation, int disp3) {
switch (operation) {
case IADD:
os.writePUSH(SR1);
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP, disp2);
os.writeADD(SR1, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case IAND:
os.writePUSH(SR1);
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP, disp2);
os.writeAND(SR1, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case IDIV:
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EAX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case IMUL:
os.writePUSH(SR1);
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP, disp2);
os.writeIMUL(SR1, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case IOR:
os.writePUSH(SR1);
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP, disp2);
os.writeOR(SR1, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case IREM:
os.writePUSH(X86Register.EDX);
os.writePUSH(X86Register.EAX);
os.writeMOV(X86Constants.BITS32, X86Register.EAX, X86Register.EBP, disp2);
os.writeCDQ(BITS32);
os.writeIDIV_EAX(BITS32, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, X86Register.EDX);
os.writePOP(X86Register.EAX);
os.writePOP(X86Register.EDX);
break;
case ISHL:
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAL_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
break;
case ISHR:
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSAR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
break;
case ISUB:
os.writePUSH(SR1);
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP, disp2);
os.writeSUB(SR1, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case IUSHR:
if (disp1 != disp2) {
os.writePUSH(X86Register.EBP, disp2);
os.writePOP(X86Register.EBP, disp1);
}
os.writePUSH(X86Register.ECX);
os.writeMOV(X86Constants.BITS32, X86Register.ECX, X86Register.EBP, disp3);
os.writeSHR_CL(BITS32, X86Register.EBP, disp1);
os.writePOP(X86Register.ECX);
break;
case IXOR:
os.writePUSH(SR1);
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP, disp2);
os.writeXOR(SR1, X86Register.EBP, disp3);
os.writeMOV(X86Constants.BITS32, X86Register.EBP, disp1, SR1);
os.writePOP(SR1);
break;
case DADD:
os.writeFLD64(X86Register.EBP, disp2);
os.writeFADD64(X86Register.EBP, disp3);
os.writeFSTP64(X86Register.EBP, disp1);
break;
case DDIV:
os.writeFLD64(X86Register.EBP, disp2);
os.writeFDIV64(X86Register.EBP, disp3);
os.writeFSTP64(X86Register.EBP, disp1);
break;
case DMUL:
os.writeFLD64(X86Register.EBP, disp2);
os.writeFMUL64(X86Register.EBP, disp3);
os.writeFSTP64(X86Register.EBP, disp1);
break;
case DREM:
os.writeFLD64(X86Register.EBP, disp3);
os.writeFLD64(X86Register.EBP, disp2);
os.writeFPREM();
os.writeFSTP64(X86Register.EBP, disp1);
os.writeFFREE(X86Register.ST0);
break;
case DSUB:
os.writeFLD64(X86Register.EBP, disp2);
os.writeFSUB64(X86Register.EBP, disp3);
os.writeFSTP64(X86Register.EBP, disp1);
break;
case FADD:
os.writeFLD32(X86Register.EBP, disp2);
os.writeFADD32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FDIV:
os.writeFLD32(X86Register.EBP, disp2);
os.writeFDIV32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FMUL:
os.writeFLD32(X86Register.EBP, disp2);
os.writeFMUL32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case FREM:
os.writeFLD32(X86Register.EBP, disp3);
os.writeFLD32(X86Register.EBP, disp2);
os.writeFPREM();
os.writeFSTP32(X86Register.EBP, disp1);
os.writeFFREE(X86Register.ST0);
break;
case FSUB:
os.writeFLD32(X86Register.EBP, disp2);
os.writeFSUB32(X86Register.EBP, disp3);
os.writeFSTP32(X86Register.EBP, disp1);
break;
case LCMP: {
final Label curInstrLabel = getInstrLabel(quad.getAddress());
final Label ltLabel = new Label(curInstrLabel + "lt");
final Label endLabel = new Label(curInstrLabel + "end");
// Calculate
if (os.isCode32()) {
int disp3lsb = disp3 - stackFrame.getHelper().SLOTSIZE;
int disp3msb = disp3;
int disp2lsb = disp2 - stackFrame.getHelper().SLOTSIZE;
int disp2msb = disp2;
os.writeMOV(BITS32, SR1, X86Register.EBP, disp2lsb);
os.writeSUB(SR1, X86Register.EBP, disp3lsb);
os.writeMOV(BITS32, X86Register.EBP, disp2lsb, SR1);
os.writeMOV(BITS32, SR1, X86Register.EBP, disp2msb);
os.writeSBB(SR1, X86Register.EBP, disp3msb);
os.writeJCC(ltLabel, X86Constants.JL); // JL
os.writeOR(X86Register.EBP, disp2lsb, SR1);
}
// else {
// final GPR64 v2r = v2.getRegister(eContext);
// final GPR64 v1r = v1.getRegister(eContext);
// os.writeCMP(v1r, v2r);
// os.writeJCC(ltLabel, X86Constants.JL); // JL
// }
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, 0);
os.writeJCC(endLabel, X86Constants.JZ); // value1 == value2
/** GT */
os.writeINC(BITS32, X86Register.EBP, disp1);
os.writeJMP(endLabel);
/** LT */
os.setObjectRef(ltLabel);
os.writeMOV_Const(BITS32, X86Register.EBP, disp1, -1);
os.setObjectRef(endLabel);
break;
}
case LADD: {
int disp3lsb = disp3 - stackFrame.getHelper().SLOTSIZE;
int disp3msb = disp3;
int disp2lsb = disp2 - stackFrame.getHelper().SLOTSIZE;
int disp2msb = disp2;
int disp1lsb = disp2 - stackFrame.getHelper().SLOTSIZE;
int disp1msb = disp2;
os.writeMOV(BITS32, SR1, X86Register.EBP, disp2lsb);
os.writeADD(SR1, X86Register.EBP, disp3lsb);
os.writeMOV(BITS32, X86Register.EBP, disp1lsb, SR1);
os.writeMOV(BITS32, SR1, X86Register.EBP, disp2msb);
os.writeADC(SR1, X86Register.EBP, disp3msb);
os.writeMOV(BITS32, X86Register.EBP, disp1msb, SR1);
break;
}
case LAND:
case LDIV:
case LMUL:
case LOR:
case LREM:
case LSHL:
case LSHR:
throw new IllegalArgumentException("Unknown operation: " + operation);
case LSUB:
int disp3lsb = disp3 - stackFrame.getHelper().SLOTSIZE;
int disp3msb = disp3;
int disp2lsb = disp2 - stackFrame.getHelper().SLOTSIZE;
int disp2msb = disp2;
int disp1lsb = disp2 - stackFrame.getHelper().SLOTSIZE;
int disp1msb = disp2;
os.writeMOV(BITS32, SR1, X86Register.EBP, disp2lsb);
os.writeSUB(SR1, X86Register.EBP, disp3lsb);
os.writeMOV(BITS32, X86Register.EBP, disp1lsb, SR1);
os.writeMOV(BITS32, SR1, X86Register.EBP, disp2msb);
os.writeSBB(SR1, X86Register.EBP, disp3msb);
os.writeMOV(BITS32, X86Register.EBP, disp1msb, SR1);
break;
case LUSHR:
case LXOR:
default:
throw new IllegalArgumentException("Unknown operation: " + operation);
}
}
/** ******** BRANCHES ************************************** */
public void generateCodeFor(ConditionalBranchQuad<T> quad, BranchCondition condition, Object reg) {
checkLabel(quad.getAddress());
yieldPoint(quad);
os.writeTEST((GPR) reg, (GPR) reg);
generateJumpForUnaryCondition(quad, condition);
}
public void generateCodeFor(ConditionalBranchQuad<T> quad, BranchCondition condition, int disp) {
checkLabel(quad.getAddress());
yieldPoint(quad);
os.writeCMP_Const(BITS32, X86Register.EBP, disp, 0);
generateJumpForUnaryCondition(quad, condition);
}
private void generateJumpForUnaryCondition(ConditionalBranchQuad<T> quad, BranchCondition condition) {
switch (condition) {
case IFEQ:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JE);
break;
case IFNE:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JNE);
break;
case IFGT:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JG);
break;
case IFGE:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JGE);
break;
case IFLT:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JL);
break;
case IFLE:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JLE);
break;
case IFNULL:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JE);
break;
case IFNONNULL:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JNE);
break;
default:
throw new IllegalArgumentException("Unknown condition " + condition);
}
}
public void generateCodeFor(ConditionalBranchQuad<T> quad, BranchCondition condition, Constant<T> cons) {
checkLabel(quad.getAddress());
yieldPoint(quad);
os.writeMOV_Const(SR1, ((IntConstant) cons).getValue());
os.writeCMP_Const(SR1, 0);
generateJumpForUnaryCondition(quad, condition);
}
public void generateCodeFor(ConditionalBranchQuad<T> quad, Constant<T> c1, BranchCondition condition,
Constant<T> c2) {
checkLabel(quad.getAddress());
yieldPoint(quad);
os.writeMOV_Const(SR1, ((IntConstant) c1).getValue());
os.writeCMP_Const(SR1, ((IntConstant) c2).getValue());
generateJumpForBinaryCondition(quad, condition);
}
public void generateCodeFor(ConditionalBranchQuad<T> quad, Constant<T> c1, BranchCondition condition, int disp2) {
checkLabel(quad.getAddress());
yieldPoint(quad);
os.writeMOV_Const(SR1, ((IntConstant) c1).getValue());
os.writeCMP(SR1, X86Register.EBP, disp2);
generateJumpForBinaryCondition(quad, condition);
}
public void generateCodeFor(ConditionalBranchQuad<T> quad, Constant<T> c1, BranchCondition condition, Object reg2) {
checkLabel(quad.getAddress());
yieldPoint(quad);
os.writeMOV_Const(SR1, ((IntConstant) c1).getValue());
os.writeCMP(SR1, (GPR) reg2);
generateJumpForBinaryCondition(quad, condition);
}
public void generateCodeFor(ConditionalBranchQuad<T> quad, int disp1, BranchCondition condition, Constant<T> c2) {
checkLabel(quad.getAddress());
os.writeCMP_Const(BITS32, X86Register.EBP, disp1, ((IntConstant<T>) c2).getValue());
generateJumpForBinaryCondition(quad, condition);
}
public void generateCodeFor(ConditionalBranchQuad<T> quad, int disp1, BranchCondition condition, int disp2) {
checkLabel(quad.getAddress());
yieldPoint(quad);
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP, disp1);
os.writeCMP(SR1, X86Register.EBP, disp2);
generateJumpForBinaryCondition(quad, condition);
}
public void generateCodeFor(ConditionalBranchQuad<T> quad, int disp1, BranchCondition condition, Object reg2) {
checkLabel(quad.getAddress());
os.writeCMP(X86Register.EBP, disp1, (GPR) reg2);
generateJumpForBinaryCondition(quad, condition);
}
public void generateCodeFor(ConditionalBranchQuad<T> quad, Object reg1, BranchCondition condition, Constant<T> c2) {
checkLabel(quad.getAddress());
os.writeCMP_Const((GPR) reg1, ((IntConstant<T>) c2).getValue());
generateJumpForBinaryCondition(quad, condition);
}
public void generateCodeFor(ConditionalBranchQuad<T> quad, Object reg1, BranchCondition condition, int disp2) {
checkLabel(quad.getAddress());
yieldPoint(quad);
os.writeCMP((GPR) reg1, X86Register.EBP, disp2);
generateJumpForBinaryCondition(quad, condition);
}
public void generateCodeFor(ConditionalBranchQuad<T> quad, Object reg1, BranchCondition condition, Object reg2) {
checkLabel(quad.getAddress());
yieldPoint(quad);
os.writeCMP((GPR) reg1, (GPR) reg2);
generateJumpForBinaryCondition(quad, condition);
}
private void generateJumpForBinaryCondition(ConditionalBranchQuad<T> quad, BranchCondition condition) {
switch (condition) {
case IF_ICMPEQ:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JE);
break;
case IF_ICMPNE:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JNE);
break;
case IF_ICMPGT:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JG);
break;
case IF_ICMPGE:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JGE);
break;
case IF_ICMPLT:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JL);
break;
case IF_ICMPLE:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JLE);
break;
case IF_ACMPEQ:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JE);
break;
case IF_ACMPNE:
os.writeJCC(getInstrLabel(quad.getTargetAddress()), X86Constants.JNE);
break;
default:
throw new IllegalArgumentException("Unknown condition " + condition);
}
}
public void endMethod() {
stackFrame.emitTrailer(typeSizeInfo, currentMethod.getBytecode().getNoLocals());
}
public synchronized void startMethod(VmMethod method) {
// this.maxLocals = method.getBytecode().getNoLocals();
// this.loader = method.getDeclaringClass().getLoader();
//// helper.reset();
//// helper.setMethod(method);
// // this.startOffset = os.getLength();
//
// this.startOffset = stackFrame.emitHeader();
}
private void yieldPoint(ConditionalBranchQuad<T> quad) {
if (quad.getTargetAddress() < quad.getAddress()) {
stackFrame.getHelper().writeYieldPoint(getInstrLabel(quad.getAddress()));
}
}
@Override
public void generateCodeFor(NewPrimitiveArrayAssignQuad<T> quad) {
// Setup a call to SoftByteCodes.allocArray
X86CompilerHelper helper = stackFrame.getHelper();
helper.writePushStaticsEntry(getInstrLabel(quad.getAddress()),
helper.getMethod().getDeclaringClass()); /* currentClass */
os.writePUSH(quad.getType()); /* type */
Operand size = quad.getSize();
/* count */
if (size.getAddressingMode() == CONSTANT) {
os.writePUSH(((IntConstant) size).getValue());
} else if (size.getAddressingMode() == REGISTER) {
os.writePUSH((GPR) ((RegisterLocation) ((Variable) size).getLocation()).getRegister());
} else if (size.getAddressingMode() == STACK) {
os.writePUSH(X86Register.EBP,
((StackLocation) ((Variable) size).getLocation()).getDisplacement());
} else {
throw new IllegalArgumentException();
}
helper.invokeJavaMethod(stackFrame.getEntryPoints().getAllocPrimitiveArrayMethod());
Variable lhs = quad.getLHS();
if (lhs.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, (GPR) ((RegisterLocation) lhs.getLocation()).getRegister(), X86Register.EAX);
} else if (lhs.getAddressingMode() == STACK) {
os.writeMOV(BITS32, X86Register.EBP,
((StackLocation) lhs.getLocation()).getDisplacement(), X86Register.EAX);
} else {
throw new IllegalArgumentException();
}
}
@Override
public void generateCodeFor(NewObjectArrayAssignQuad<T> quad) {
VmConstClass clazz = quad.getComponentType();
Label label = getInstrLabel(quad.getAddress());
writeResolveAndLoadClassToReg(clazz, SR1, label);
os.writePUSH(SR1);
Operand sizeOp = quad.getSize();
if (sizeOp.getAddressingMode() == CONSTANT) {
os.writePUSH(((IntConstant) sizeOp).getValue());
} else if (sizeOp.getAddressingMode() == REGISTER) {
os.writePUSH((GPR) ((RegisterLocation) ((Variable) sizeOp).getLocation()).getRegister());
} else if (sizeOp.getAddressingMode() == STACK) {
os.writePUSH(X86Register.EBP, ((StackLocation) ((Variable) sizeOp).getLocation()).getDisplacement());
} else {
throw new IllegalArgumentException();
}
stackFrame.getHelper().invokeJavaMethod(stackFrame.getEntryPoints().getAnewarrayMethod());
Variable lhs = quad.getLHS();
if (lhs.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, (GPR) ((RegisterLocation) lhs.getLocation()).getRegister(), X86Register.EAX);
} else if (lhs.getAddressingMode() == STACK) {
os.writeMOV(BITS32, X86Register.EBP, ((StackLocation) lhs.getLocation()).getDisplacement(),
X86Register.EAX);
} else {
throw new IllegalArgumentException();
}
}
@Override
public void generateCodeFor(NewMultiArrayAssignQuad<T> quad) {
// Create the dimensions array
Operand[] sizes = quad.getSizes();
Label label = getInstrLabel(quad.getAddress());
X86CompilerHelper helper = stackFrame.getHelper();
helper.writePushStaticsEntry(label, currentMethod.getDeclaringClass()); /* currentClass */
os.writePUSH(10); /* type=int */
os.writePUSH(sizes.length); /* elements */
helper.invokeJavaMethod(stackFrame.getEntryPoints().getAllocPrimitiveArrayMethod());
final GPR dimsr = SR1;
if (SR1 != X86Register.EAX) {
os.writeMOV(BITS32, SR1, X86Register.EAX);
}
// Dimension array is now in dimsr
// Pop all dimensions (note the reverse order that allocMultiArray
// expects)
final int slotSize = stackFrame.getHelper().SLOTSIZE;
int arrayDataOffset = VmArray.DATA_OFFSET * slotSize;
for (int i = 0; i < sizes.length; i++) {
final int ofs = arrayDataOffset + (i * 4);
Operand size = sizes[i];
if (size.getAddressingMode() == CONSTANT) {
os.writeMOV_Const(BITS32, dimsr, ofs, ((IntConstant) size).getValue());
} else if (size.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, dimsr, ofs,
(GPR) ((RegisterLocation) ((Variable) size).getLocation()).getRegister());
} else if (size.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
os.writeMOV(BITS32, sr2, X86Register.EBP,
((StackLocation) ((Variable) size).getLocation()).getDisplacement());
os.writeMOV(BITS32, dimsr, ofs, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
}
os.writePUSH(dimsr);
VmConstClass clazz = quad.getComponentType();
// Resolve the array class
writeResolveAndLoadClassToReg(clazz, dimsr, label);
// Now call the multianewarrayhelper
os.writeXCHG(X86Register.ESP, 0, dimsr);
os.writePUSH(dimsr); // dimensions[]
helper.invokeJavaMethod(stackFrame.getEntryPoints().getAllocMultiArrayMethod());
Variable lhs = quad.getLHS();
if (lhs.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, (GPR) ((RegisterLocation) lhs.getLocation()).getRegister(), X86Register.EAX);
} else if (lhs.getAddressingMode() == STACK) {
os.writeMOV(BITS32, X86Register.EBP, ((StackLocation) lhs.getLocation()).getDisplacement(),
X86Register.EAX);
} else {
throw new IllegalArgumentException();
}
}
@Override
public void generateCodeFor(ArrayLengthAssignQuad quad) {
Variable lhs = quad.getLHS();
final int slotSize = stackFrame.getHelper().SLOTSIZE;
int arrayLengthOffset = VmArray.LENGTH_OFFSET * slotSize;
if (lhs.getAddressingMode() == REGISTER) {
GPR dstReg = (GPR) ((RegisterLocation) lhs.getLocation()).getRegister();
Variable ref = quad.getRef();
if (ref.getAddressingMode() == REGISTER) {
os.writeMOV(INTSIZE, dstReg, (GPR) ((RegisterLocation) ref.getLocation()).getRegister(),
arrayLengthOffset);
} else if (ref.getAddressingMode() == STACK) {
os.writeMOV(BITS32, SR1, X86Register.EBP, ((StackLocation) ref.getLocation()).getDisplacement());
os.writeMOV(INTSIZE, dstReg, SR1, arrayLengthOffset);
} else {
throw new IllegalArgumentException();
}
} else if (lhs.getAddressingMode() == STACK) {
Variable ref = quad.getRef();
if (ref.getAddressingMode() == REGISTER) {
os.writeMOV(INTSIZE, SR1, (GPR) ((RegisterLocation) ref.getLocation()).getRegister(),
arrayLengthOffset);
} else if (ref.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writeMOV(BITS32, sr2, X86Register.EBP, ((StackLocation) ref.getLocation()).getDisplacement());
os.writeMOV(INTSIZE, SR1, sr2, arrayLengthOffset);
} else {
throw new IllegalArgumentException();
}
os.writeMOV(BITS32, X86Register.EBP, ((StackLocation) lhs.getLocation()).getDisplacement(), SR1);
} else {
throw new IllegalArgumentException();
}
}
@Override
public void generateCodeFor(ArrayAssignQuad quad) {
checkLabel(quad.getAddress());
Variable lhs = quad.getLHS();
Variable ref = quad.getRef();
Operand ind = quad.getInd();
checkBounds(ref, ind, quad.getAddress());
final int slotSize = stackFrame.getHelper().SLOTSIZE;
int arrayDataOffset = VmArray.DATA_OFFSET * slotSize;
// Load data
// if (idx.isConstant()) {
// final int offset = idx.getValue() * scale;
// os.writeMOV(valSize, resultr, refr, offset + arrayDataOffset);
// } else {
int scale = 4;
if (quad.getInd().getAddressingMode() == CONSTANT) {
IntConstant indr = (IntConstant) ind;
GPR resultr = (GPR) ((RegisterLocation) lhs.getLocation()).getRegister();
// if (os.isCode64()) {
// final GPR64 idxr64 = (GPR64) eContext.getGPRPool().getRegisterInSameGroup(idxr, JvmType.LONG);
// os.writeMOVSXD(idxr64, (GPR32) idxr);
// idxr = idxr64;
// }
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOV(BITS32, resultr, refr, indr.getValue() * scale + arrayDataOffset);
} else if (ref.getAddressingMode() == STACK) {
os.writeMOV(BITS32, SR1, X86Register.EBP, ((StackLocation) ref.getLocation()).getDisplacement());
os.writeMOV(BITS32, resultr, SR1, indr.getValue() * scale + arrayDataOffset);
} else {
throw new IllegalArgumentException();
}
} else if (quad.getInd().getAddressingMode() == REGISTER) {
GPR indr = (GPR) ((RegisterLocation) ((Variable) ind).getLocation()).getRegister();
if (lhs.getAddressingMode() == REGISTER) {
GPR resultr = (GPR) ((RegisterLocation) lhs.getLocation()).getRegister();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOV(BITS32, resultr, refr, indr, scale, arrayDataOffset);
} else if (ref.getAddressingMode() == STACK) {
os.writeMOV(BITS32, SR1, X86Register.EBP, ((StackLocation) ref.getLocation()).getDisplacement());
os.writeMOV(BITS32, resultr, SR1, indr, scale, arrayDataOffset);
} else {
throw new IllegalArgumentException();
}
} else if (lhs.getAddressingMode() == STACK) {
int rdisp = ((StackLocation) lhs.getLocation()).getDisplacement();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOV(BITS32, SR1, refr, indr, scale, arrayDataOffset);
os.writeMOV(BITS32, X86Register.EBP, rdisp, SR1);
} else if (ref.getAddressingMode() == STACK) {
os.writeMOV(BITS32, SR1, X86Register.EBP, ((StackLocation) ref.getLocation()).getDisplacement());
os.writePUSH(SR1, indr, scale, arrayDataOffset);
os.writePOP(X86Register.EBP, rdisp);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
// if (os.isCode64()) {
// final GPR64 idxr64 = (GPR64) eContext.getGPRPool().getRegisterInSameGroup(idxr, JvmType.LONG);
// os.writeMOVSXD(idxr64, (GPR32) idxr);
// idxr = idxr64;
// }
//os.writeMOV(BITS32, resultr, refr, indr, scale, arrayDataOffset);
} else if (quad.getInd().getAddressingMode() == STACK) {
int indDisp = ((StackLocation) ((Variable) ind).getLocation()).getDisplacement();
if (lhs.getAddressingMode() == REGISTER) {
GPR resultr = (GPR) ((RegisterLocation) lhs.getLocation()).getRegister();
if (ref.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, SR1, X86Register.EBP, indDisp);
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOV(BITS32, resultr, refr, SR1, scale, arrayDataOffset);
} else if (ref.getAddressingMode() == STACK) {
os.writeMOV(BITS32, SR1, X86Register.EBP, ((StackLocation) ref.getLocation()).getDisplacement());
GPR sr2 = (resultr == X86Register.EDX) ? X86Register.EBX : X86Register.EDX;
os.writePUSH(sr2);
os.writeMOV(BITS32, sr2, X86Register.EBP, indDisp);
os.writeMOV(BITS32, resultr, SR1, sr2, scale, arrayDataOffset);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else if (lhs.getAddressingMode() == STACK) {
int rdisp = ((StackLocation) lhs.getLocation()).getDisplacement();
if (ref.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, SR1, X86Register.EBP, indDisp);
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writePUSH(refr, SR1, scale, arrayDataOffset);
os.writePOP(X86Register.EBP, rdisp);
} else if (ref.getAddressingMode() == STACK) {
os.writeMOV(BITS32, SR1, X86Register.EBP, ((StackLocation) ref.getLocation()).getDisplacement());
GPR sr2 = (SR1 == X86Register.EDX) ? X86Register.EBX : X86Register.EDX;
os.writePUSH(sr2);
os.writeMOV(BITS32, sr2, X86Register.EBP, indDisp);
os.writePUSH(SR1, sr2, scale, arrayDataOffset);
os.writePOP(X86Register.EBP, rdisp);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
// if (os.isCode64()) {
// final GPR64 idxr64 = (GPR64) eContext.getGPRPool().getRegisterInSameGroup(idxr, JvmType.LONG);
// os.writeMOVSXD(idxr64, (GPR32) idxr);
// idxr = idxr64;
// }
//os.writeMOV(BITS32, resultr, refr, indr, scale, arrayDataOffset);
} else {
throw new IllegalArgumentException();
}
}
@Override
public void generateCodeFor(ArrayStoreQuad quad) {
checkLabel(quad.getAddress());
Variable ref = quad.getRef();
Operand ind = quad.getInd();
Operand rhs = quad.getRHS();
checkBounds(ref, ind, quad.getAddress());
final int slotSize = stackFrame.getHelper().SLOTSIZE;
int arrayDataOffset = VmArray.DATA_OFFSET * slotSize;
// Load data
// if (idx.isConstant()) {
// final int offset = idx.getValue() * scale;
// os.writeMOV(valSize, resultr, refr, offset + arrayDataOffset);
// } else {
int scale = 4;
// Verify
//todo spec issue: add type compatibility check (elemType <- valueType), throw ArrayStoreException
if (ref.getAddressingMode() == REGISTER) {
GPR dstReg = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
if (ind.getAddressingMode() == CONSTANT) {
final int offset = ((IntConstant) ind).getValue() * scale;
if (rhs.getAddressingMode() == CONSTANT) {
os.writeMOV_Const(BITS32, dstReg, offset + arrayDataOffset, ((IntConstant) rhs).getValue());
} else if (rhs.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, dstReg, offset + arrayDataOffset,
(GPR) ((RegisterLocation) ((Variable) rhs).getLocation()).getRegister());
} else if (rhs.getAddressingMode() == STACK) {
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP,
((StackLocation) ((Variable) rhs).getLocation()).getDisplacement());
os.writeMOV(BITS32, dstReg, offset + arrayDataOffset, SR1);
} else {
throw new IllegalArgumentException();
}
} else if (ind.getAddressingMode() == REGISTER) {
GPR idxReg = (GPR) ((RegisterLocation) ((Variable) ind).getLocation()).getRegister();
if (rhs.getAddressingMode() == CONSTANT) {
os.writeMOV_Const(BITS32, dstReg, idxReg, scale, arrayDataOffset, ((IntConstant) rhs).getValue());
} else if (rhs.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, dstReg, idxReg, scale, arrayDataOffset,
(GPR) ((RegisterLocation) ((Variable) rhs).getLocation()).getRegister());
} else if (rhs.getAddressingMode() == STACK) {
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP,
((StackLocation) ((Variable) rhs).getLocation()).getDisplacement());
os.writeMOV(BITS32, dstReg, idxReg, scale, arrayDataOffset, SR1);
} else {
throw new IllegalArgumentException();
}
} else if (ind.getAddressingMode() == STACK) {
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP,
((StackLocation) ((Variable) ind).getLocation()).getDisplacement());
if (rhs.getAddressingMode() == CONSTANT) {
os.writeMOV_Const(BITS32, dstReg, SR1, scale, arrayDataOffset, ((IntConstant) rhs).getValue());
} else if (rhs.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, dstReg, SR1, scale, arrayDataOffset,
(GPR) ((RegisterLocation) ((Variable) rhs).getLocation()).getRegister());
} else if (rhs.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
os.writeMOV(BITS32, sr2, X86Register.EBP,
((StackLocation) ((Variable) rhs).getLocation()).getDisplacement());
os.writeMOV(BITS32, dstReg, SR1, scale, arrayDataOffset, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
} else if (ref.getAddressingMode() == STACK) {
os.writeMOV(BITS32, SR1, X86Register.EBP, ((StackLocation) ref.getLocation()).getDisplacement());
if (ind.getAddressingMode() == CONSTANT) {
final int offset = ((IntConstant) ind).getValue() * scale;
if (rhs.getAddressingMode() == CONSTANT) {
os.writeMOV_Const(BITS32, SR1, offset + arrayDataOffset, ((IntConstant) rhs).getValue());
} else if (rhs.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, SR1, offset + arrayDataOffset,
(GPR) ((RegisterLocation) ((Variable) rhs).getLocation()).getRegister());
} else if (rhs.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
os.writeMOV(BITS32, sr2, X86Register.EBP,
((StackLocation) ((Variable) rhs).getLocation()).getDisplacement());
os.writeMOV(BITS32, SR1, offset + arrayDataOffset, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else if (ind.getAddressingMode() == REGISTER) {
GPR idxReg = (GPR) ((RegisterLocation) ((Variable) ind).getLocation()).getRegister();
if (rhs.getAddressingMode() == CONSTANT) {
os.writeMOV_Const(BITS32, SR1, idxReg, scale, arrayDataOffset, ((IntConstant) rhs).getValue());
} else if (rhs.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, SR1, idxReg, scale, arrayDataOffset,
(GPR) ((RegisterLocation) ((Variable) rhs).getLocation()).getRegister());
} else if (rhs.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
os.writeMOV(BITS32, sr2, X86Register.EBP,
((StackLocation) ((Variable) rhs).getLocation()).getDisplacement());
os.writeMOV(BITS32, SR1, idxReg, scale, arrayDataOffset, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else if (ind.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
os.writeMOV(BITS32, sr2, X86Register.EBP,
((StackLocation) ((Variable) ind).getLocation()).getDisplacement());
if (rhs.getAddressingMode() == CONSTANT) {
os.writeMOV_Const(BITS32, SR1, sr2, scale, arrayDataOffset, ((IntConstant) rhs).getValue());
} else if (rhs.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, SR1, sr2, scale, arrayDataOffset,
(GPR) ((RegisterLocation) ((Variable) rhs).getLocation()).getRegister());
} else if (rhs.getAddressingMode() == STACK) {
GPR sr3;
if (SR1 != X86Register.ECX) {
if (sr2 != X86Register.ECX) {
sr3 = X86Register.ECX;
} else if (SR1 != X86Register.EDX) {
sr3 = X86Register.EDX;
} else {
sr3 = X86Register.EAX;
}
} else {
sr3 = sr2 == X86Register.EDX ? X86Register.EBX : X86Register.EDX;
}
os.writePUSH(sr3);
os.writeMOV(BITS32, sr3, X86Register.EBP,
((StackLocation) ((Variable) rhs).getLocation()).getDisplacement());
os.writeMOV(BITS32, SR1, sr2, scale, arrayDataOffset, sr3);
os.writePOP(sr3);
} else {
throw new IllegalArgumentException();
}
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
}
private final void checkBounds(Variable ref, Operand index, int address) {
// counters.getCounter("checkbounds").inc();
final Label curInstrLabel = getInstrLabel(address);
final Label test = new Label(curInstrLabel + "$$cbtest");
final Label failed = new Label(curInstrLabel + "$$cbfailed");
// assertCondition(ref.isGPR(), "ref must be in a register");
// final GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeJMP(test);
os.setObjectRef(failed);
// Call SoftByteCodes.throwArrayOutOfBounds
if (ref.getAddressingMode() == REGISTER) {
os.writePUSH((GPR) ((RegisterLocation) ref.getLocation()).getRegister());
} else if (ref.getAddressingMode() == STACK) {
os.writePUSH(X86Register.EBP, ((StackLocation) ref.getLocation()).getDisplacement());
} else {
throw new IllegalArgumentException();
}
// if (index.isConstant()) {
// os.writePUSH(index.getValue());
// } else {
if (index.getAddressingMode() == CONSTANT) {
os.writePUSH(((IntConstant) index).getValue());
} else if (index.getAddressingMode() == REGISTER) {
os.writePUSH((GPR) ((RegisterLocation) ((Variable) index).getLocation()).getRegister());
} else if (index.getAddressingMode() == STACK) {
os.writePUSH(X86Register.EBP, ((StackLocation) ((Variable) index).getLocation()).getDisplacement());
} else {
throw new IllegalArgumentException();
}
// }
// invokeJavaMethod(context.getThrowArrayOutOfBounds());
stackFrame.getHelper().invokeJavaMethod(stackFrame.getEntryPoints().getThrowArrayOutOfBounds());
final int slotSize = stackFrame.getHelper().SLOTSIZE;
int arrayLengthOffset = VmArray.LENGTH_OFFSET * slotSize;
// CMP length, index
os.setObjectRef(test);
// if (index.isConstant()) {
// os
// .writeCMP_Const(BITS32, refr, arrayLengthOffset, index
// .getValue());
// } else {
if (index.getAddressingMode() == CONSTANT) {
if (ref.getAddressingMode() == REGISTER) {
os.writeCMP_Const(X86Constants.BITS32, (GPR) ((RegisterLocation) ref.getLocation()).getRegister(),
arrayLengthOffset, ((IntConstant) index).getValue());
} else if (ref.getAddressingMode() == STACK) {
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP,
((StackLocation) ref.getLocation()).getDisplacement());
os.writeCMP_Const(X86Constants.BITS32, SR1, arrayLengthOffset, ((IntConstant) index).getValue());
} else {
throw new IllegalArgumentException();
}
} else if (index.getAddressingMode() == REGISTER) {
if (ref.getAddressingMode() == REGISTER) {
os.writeCMP((GPR) ((RegisterLocation) ref.getLocation()).getRegister(),
arrayLengthOffset, (GPR) ((RegisterLocation) ((Variable) index).getLocation()).getRegister());
} else if (ref.getAddressingMode() == STACK) {
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP,
((StackLocation) ref.getLocation()).getDisplacement());
os.writeCMP(SR1, arrayLengthOffset,
(GPR) ((RegisterLocation) ((Variable) index).getLocation()).getRegister());
} else {
throw new IllegalArgumentException();
}
} else if (index.getAddressingMode() == STACK) {
if (ref.getAddressingMode() == REGISTER) {
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP,
((StackLocation) ((Variable) index).getLocation()).getDisplacement());
os.writeCMP((GPR) ((RegisterLocation) ref.getLocation()).getRegister(), arrayLengthOffset, SR1);
} else if (ref.getAddressingMode() == STACK) {
os.writeMOV(X86Constants.BITS32, SR1, X86Register.EBP,
((StackLocation) ref.getLocation()).getDisplacement());
os.writeADD(SR1, arrayLengthOffset);
os.writeCMP(SR1, X86Register.EBP, ((StackLocation) ((Variable) index).getLocation()).getDisplacement());
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
// }
os.writeJCC(failed, X86Constants.JNA);
}
@Override
public void generateCodeFor(ConstantClassAssignQuad<T> quad) {
VmConstClass clazz = quad.getConstClass();
// Resolve the class
Label label = getInstrLabel(quad.getAddress());
writeResolveAndLoadClassToReg(clazz, SR1, label);
// Call SoftByteCodes#getClassForVmType
os.writePUSH(SR1);
stackFrame.getHelper().invokeJavaMethod(stackFrame.getEntryPoints().getGetClassForVmTypeMethod());
Variable lhs = quad.getLHS();
if (lhs.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, (GPR) ((RegisterLocation) lhs.getLocation()).getRegister(), X86Register.EAX);
} else if (lhs.getAddressingMode() == STACK) {
os.writeMOV(BITS32, X86Register.EBP, ((StackLocation) lhs.getLocation()).getDisplacement(),
X86Register.EAX);
} else {
throw new IllegalArgumentException();
}
}
@Override
public void generateCodeFor(ConstantStringAssignQuad<T> quad) {
//todo
// throw new UnsupportedOperationException();
}
@Override
public void generateCodeFor(CheckcastQuad<T> quad) {
//todo
// throw new UnsupportedOperationException();
}
@Override
public void generateCodeFor(InstanceofAssignQuad<T> quad) {
VmConstClass clazz = quad.getConstClass();
Operand ref = quad.getRef();
Variable lhs = quad.getLHS();
Label currentLabel = getInstrLabel(quad.getAddress());
// Resolve the classRef
clazz.resolve(currentMethod.getDeclaringClass().getLoader());
// Prepare
// final X86RegisterPool pool = eContext.getGPRPool();
final VmType<?> resolvedType = clazz.getResolvedVmClass();
if (resolvedType.isInterface() || resolvedType.isArray()) {
if (ref.getAddressingMode() == REGISTER) {
//todo
throw new IllegalArgumentException();
} else if (ref.getAddressingMode() == STACK) {
//todo
throw new IllegalArgumentException();
} else {
throw new IllegalArgumentException();
}
// // It is an interface, do it the hard way
//
// // Load reference
// final RefItem ref = vstack.popRef();
// ref.load(eContext);
// final GPR refr = ref.getRegister();
//
// // Allocate tmp registers
// final GPR classr = (GPR) L1AHelper.requestRegister(eContext,
// JvmType.REFERENCE, false);
// final GPR cntr = (GPR) L1AHelper.requestRegister(eContext,
// JvmType.INT, false);
// final GPR tmpr = (GPR) L1AHelper.requestRegister(eContext,
// JvmType.REFERENCE, false);
// final Label curInstrLabel = currentLabel;
//
// /* Objectref is already on the stack */
// writeResolveAndLoadClassToReg(classRef, classr);
// stackFrame.getHelper().writeClassInitialize(curInstrLabel, classr, tmpr, resolvedType);
//
// final Label trueLabel = new Label(curInstrLabel + "io-true");
// final Label endLabel = new Label(curInstrLabel + "io-end");
//
// /* Is instanceof? */
// instanceOf(refr, classr, tmpr, cntr, trueLabel, false, currentLabel);
//
// final IntItem result = (IntItem) L1AHelper.requestWordRegister(eContext, JvmType.INT, false);
// final GPR resultr = result.getRegister();
//
// /* Not instanceof */
// // TODO: use setcc instead of jumps
// os.writeXOR(resultr, resultr);
// os.writeJMP(endLabel);
//
// os.setObjectRef(trueLabel);
// os.writeMOV_Const(resultr, 1);
//
// // Push result
// os.setObjectRef(endLabel);
// ref.release(eContext);
//
// vstack.push(result);
//
// // Release
// pool.release(classr);
// pool.release(tmpr);
// pool.release(cntr);
} else {
// It is a class, do the fast way
// if (ref.getAddressingMode() == REGISTER) {
// GPR refr = (GPR) ((RegisterLocation) ((Variable) ref).getLocation()).getRegister();
// if (lhs.getAddressingMode() == REGISTER) {
// GPR resultr = (GPR) ((RegisterLocation) lhs.getLocation()).getRegister();
// instanceOfClass(refr, (VmClassType<?>) clazz.getResolvedVmClass(),
// SR1, resultr, null, false, currentLabel);
// } else if (lhs.getAddressingMode() == STACK) {
// //todo
// throw new IllegalArgumentException();
// } else {
// throw new IllegalArgumentException();
// }
// } else if (ref.getAddressingMode() == STACK) {
// if (lhs.getAddressingMode() == REGISTER) {
// //todo
// throw new IllegalArgumentException();
// } else if (lhs.getAddressingMode() == STACK) {
// //todo
// throw new IllegalArgumentException();
// } else {
// throw new IllegalArgumentException();
// }
// } else {
// throw new IllegalArgumentException();
// }
}
}
/**
* Emit the core of the instanceof code.
*
* @param objectr Register containing the object reference
* @param trueLabel Where to jump for a true result. A false result will continue
* directly after this method Register ECX must be free and it
* destroyed.
*/
private void instanceOfClass(GPR objectr, VmClassType<?> type, GPR tmpr,
GPR resultr, Label trueLabel, boolean skipNullTest, Label currentLabel) {
final int depth = type.getSuperClassDepth();
X86CompilerHelper helper = stackFrame.getHelper();
final int staticsOfs = helper.getSharedStaticsOffset(type);
final Label curInstrLabel = currentLabel;
final Label notInstanceOfLabel = new Label(curInstrLabel
+ "notInstanceOf");
if (!type.isAlwaysInitialized()) {
if (os.isCode32()) {
helper.writeGetStaticsEntry(curInstrLabel, tmpr, type);
}
// else {
// helper.writeGetStaticsEntry64(curInstrLabel, (GPR64) tmpr, (VmSharedStaticsEntry) type);
// }
helper.writeClassInitialize(curInstrLabel, tmpr, tmpr, type);
}
// Clear result (means !instanceof)
if (resultr != null) {
os.writeXOR(resultr, resultr);
}
// Test objectr == null
if (!skipNullTest) {
// Is objectr null?
os.writeTEST(objectr, objectr);
os.writeJCC(notInstanceOfLabel, X86Constants.JZ);
}
final int slotSize = helper.SLOTSIZE;
final int asize = helper.ADDRSIZE;
final int tibOffset = ObjectLayout.TIB_SLOT * slotSize;
final int arrayLengthOffset = VmArray.LENGTH_OFFSET * slotSize;
final int arrayDataOffset = VmArray.DATA_OFFSET * slotSize;
// TIB -> tmp
os.writeMOV(asize, tmpr, objectr, tibOffset);
// SuperClassesArray -> tmp
os.writeMOV(asize, tmpr, tmpr, arrayDataOffset
+ (TIBLayout.SUPERCLASSES_INDEX * slotSize));
// Length of superclassarray must be >= depth
os.writeCMP_Const(BITS32, tmpr, arrayLengthOffset, depth);
os.writeJCC(notInstanceOfLabel, X86Constants.JNA);
// Get superClassesArray[depth] -> objectr
os.writeMOV(asize, tmpr, tmpr, arrayDataOffset + (depth * slotSize));
// Compare objectr with classtype
os.writeCMP(helper.STATICS, staticsOfs, tmpr);
if (resultr != null) {
os.writeSETCC(resultr, X86Constants.JE);
} else {
// Conditional forward jump is assumed not to be taken.
// Therefor will the JCC followed by a JMP be faster.
os.writeJCC(notInstanceOfLabel, X86Constants.JNE);
os.writeJMP(trueLabel);
}
os.setObjectRef(notInstanceOfLabel);
}
/**
* Emit the core of the instanceof code.
*
* @param objectr Register containing the object reference
* @param typer Register containing the type reference
* @param trueLabel Where to jump for a true result. A false result will continue
* directly after this method Register ECX must be free and it
* destroyed.
*/
private void instanceOf(GPR objectr, GPR typer, GPR tmpr, GPR cntr,
Label trueLabel, boolean skipNullTest, Label currentLabel) {
final Label curInstrLabel = currentLabel;
final Label loopLabel = new Label(curInstrLabel + "loop");
final Label notInstanceOfLabel = new Label(curInstrLabel
+ "notInstanceOf");
X86CompilerHelper helper = stackFrame.getHelper();
if (VmUtils.verifyAssertions()) {
VmUtils._assert(objectr.getSize() == helper.ADDRSIZE, "objectr size");
VmUtils._assert(typer.getSize() == helper.ADDRSIZE, "typer size");
VmUtils._assert(tmpr.getSize() == helper.ADDRSIZE, "tmpr size");
VmUtils._assert(cntr.getSize() == BITS32, "cntr size");
}
if (!skipNullTest) {
/* Is objectref null? */
os.writeTEST(objectr, objectr);
os.writeJCC(notInstanceOfLabel, X86Constants.JZ);
}
final int slotSize = helper.SLOTSIZE;
final int asize = helper.ADDRSIZE;
final int tibOffset = ObjectLayout.TIB_SLOT * slotSize;
final int arrayLengthOffset = VmArray.LENGTH_OFFSET * slotSize;
final int arrayDataOffset = VmArray.DATA_OFFSET * slotSize;
// TIB -> tmp
os.writeMOV(asize, tmpr, objectr, tibOffset);
// SuperClassesArray -> tmp
os.writeMOV(asize, tmpr, tmpr, arrayDataOffset
+ (TIBLayout.SUPERCLASSES_INDEX * slotSize));
// SuperClassesArray.length -> cntr
os.writeMOV(BITS32, cntr, tmpr, arrayLengthOffset);
// &superClassesArray[cnt-1] -> tmpr
// if (os.isCode64()) {
// // the MOV to cntr already zero-extends it, so no extension needed.
// cntr = L1AHelper.get64BitReg(eContext, cntr);
// }
os.writeLEA(tmpr, tmpr, cntr, slotSize, arrayDataOffset - slotSize);
os.setObjectRef(loopLabel);
// cmp superClassesArray[index],type
os.writeCMP(tmpr, 0, typer);
// Is equal?
os.writeJCC(trueLabel, X86Constants.JE);
// index--
os.writeLEA(tmpr, tmpr, -slotSize);
// cnt--
os.writeDEC(cntr);
// if (cnt == 0)
os.writeJCC(notInstanceOfLabel, X86Constants.JZ);
// Goto loop
os.writeJMP(loopLabel);
// Not instanceof
os.setObjectRef(notInstanceOfLabel);
}
@Override
public void generateCodeFor(LookupswitchQuad<T> quad) {
checkLabel(quad.getAddress());
int[] matchValues = quad.getMatchValues();
final int n = matchValues.length;
final GPR keyr;
Operand key = quad.getKey();
if (key.getAddressingMode() == CONSTANT) {
//todo optimize it
os.writeMOV_Const(SR1, ((IntConstant) key).getValue());
keyr = SR1;
} else if (key.getAddressingMode() == REGISTER) {
keyr = (GPR) ((RegisterLocation) ((Variable) key).getLocation()).getRegister();
} else if (key.getAddressingMode() == STACK) {
int displacement1 = ((StackLocation) ((Variable) key).getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, displacement1);
keyr = SR1;
} else {
throw new IllegalArgumentException();
}
IRBasicBlock[] blocks = quad.getTargetBlocks();
for (int i = 0; i < n; i++) {
os.writeCMP_Const(keyr, matchValues[i]);
os.writeJCC(getInstrLabel(blocks[i].getStartPC()), X86Constants.JE); // JE
}
os.writeJMP(getInstrLabel(blocks[n].getStartPC()));
}
@Override
public void generateCodeFor(TableswitchQuad<T> quad) {
// IMPROVE: check Jaos implementation
Operand val = quad.getValue();
IRBasicBlock[] blocks = quad.getTargetBlocks();
int lowValue = quad.getLowValue();
int highValue = quad.getHighValue();
int defAddress = quad.getDefaultAddress();
X86CompilerHelper helper = stackFrame.getHelper();
final int n = blocks.length;
if ((n > 4) && os.isCode32()) {
// Optimized version. Needs some overhead, so only useful for
// larger tables.
//counters.getCounter("tableswitch-opt").inc();
final Label curInstrLabel = getInstrLabel(quad.getAddress());
final Label l1 = new Label(curInstrLabel + "$$l1");
final Label l2 = new Label(curInstrLabel + "$$l2");
final int l12distance = os.isCode32() ? 12 : 23;
final int l1Ofs;
if (val.getAddressingMode() == CONSTANT) {
//todo optimize it more
int value = ((IntConstant) val).getValue();
final GPR tmp = SR1;
value -= lowValue;
// If outsite low-high range, jump to default
if (value >= n) {
os.writeJMP(helper.getInstrLabel(defAddress));
}
// Get absolute address of l1 into S0. (do not use
// stackMgr.writePOP!)
os.writeCALL(l1);
os.setObjectRef(l1);
l1Ofs = os.getLength();
os.writePOP(tmp);
// Calculate absolute address of jumptable entry into S1
os.writeLEA(tmp, tmp, value * helper.ADDRSIZE + l12distance);
// Calculate absolute address of jump target
os.writeADD(tmp, tmp, 0);
os.writeLEA(tmp, tmp, 4); // Compensate for writeRelativeObject
// difference
// Jump to the calculated address
os.writeJMP(tmp);
} else if (val.getAddressingMode() == REGISTER) {
GPR valr = (GPR) ((RegisterLocation) ((Variable) val).getLocation()).getRegister();
final GPR tmp = SR1;
if (lowValue != 0) {
os.writeSUB(valr, lowValue);
}
// If outsite low-high range, jump to default
os.writeCMP_Const(valr, n);
os.writeJCC(helper.getInstrLabel(defAddress), X86Constants.JAE);
// Get absolute address of l1 into S0. (do not use
// stackMgr.writePOP!)
os.writeCALL(l1);
os.setObjectRef(l1);
l1Ofs = os.getLength();
os.writePOP(tmp);
// Calculate absolute address of jumptable entry into S1
os.writeLEA(tmp, tmp, valr, helper.ADDRSIZE, l12distance);
// Calculate absolute address of jump target
os.writeADD(tmp, tmp, 0);
os.writeLEA(tmp, tmp, 4); // Compensate for writeRelativeObject
// difference
// Jump to the calculated address
os.writeJMP(tmp);
} else if (val.getAddressingMode() == STACK) {
int vald = ((StackLocation) ((Variable) val).getLocation()).getDisplacement();
final GPR tmp = SR1;
if (lowValue != 0) {
os.writeSUB(BITS32, X86Register.EBP, vald, lowValue);
}
// If outsite low-high range, jump to default
os.writeCMP_Const(BITS32, X86Register.EBP, vald, n);
os.writeJCC(helper.getInstrLabel(defAddress), X86Constants.JAE);
// Get absolute address of l1 into S0. (do not use
// stackMgr.writePOP!)
os.writeCALL(l1);
os.setObjectRef(l1);
l1Ofs = os.getLength();
os.writePOP(tmp);
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
os.writeMOV(BITS32, sr2, X86Register.EBP, vald);
// Calculate absolute address of jumptable entry into S1
os.writeLEA(tmp, tmp, sr2, helper.ADDRSIZE, l12distance);
os.writePOP(sr2);
// Calculate absolute address of jump target
os.writeADD(tmp, tmp, 0);
os.writeLEA(tmp, tmp, 4); // Compensate for writeRelativeObject
// difference
// Jump to the calculated address
os.writeJMP(tmp);
} else {
throw new IllegalArgumentException();
}
// Emit offsets relative to where they are emitted
os.setObjectRef(l2);
final int l2Ofs = os.getLength();
if ((l2Ofs - l1Ofs) != l12distance) {
if (!os.isTextStream()) {
throw new CompileError("l12distance must be "
+ (l2Ofs - l1Ofs));
}
}
for (int i = 0; i < n; i++) {
os.writeRelativeObjectRef(getInstrLabel(blocks[i].getStartPC()));
}
// L1AHelper.releaseRegister(eContext, tmp);
} else {
// Space wasting, but simple implementation
// counters.getCounter("tableswitch-nonopt").inc();
GPR valr;
if (val.getAddressingMode() == CONSTANT) {
//todo optimize it
os.writeMOV_Const(SR1, ((IntConstant) val).getValue());
valr = SR1;
} else if (val.getAddressingMode() == REGISTER) {
valr = (GPR) ((RegisterLocation) ((Variable) val).getLocation()).getRegister();
} else if (val.getAddressingMode() == STACK) {
int displacement1 = ((StackLocation) ((Variable) val).getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, displacement1);
valr = SR1;
} else {
throw new IllegalArgumentException();
}
for (int i = 0; i < n; i++) {
os.writeCMP_Const(valr, lowValue + i);
os.writeJCC(getInstrLabel(blocks[i].getStartPC()), X86Constants.JE); // JE
}
os.writeJMP(getInstrLabel(defAddress));
}
// val.release(eContext);
}
@Override
public void generateCodeFor(MonitorenterQuad<T> quad) {
Operand op = quad.getOperand();
if (op.getAddressingMode() == REGISTER) {
os.writePUSH((GPR) ((RegisterLocation) ((Variable) op).getLocation()).getRegister());
} else if (op.getAddressingMode() == STACK) {
os.writePUSH(X86Register.EBP, ((StackLocation) ((Variable) op).getLocation()).getDisplacement());
} else {
throw new IllegalArgumentException();
}
stackFrame.getHelper().invokeJavaMethod(stackFrame.getEntryPoints().getMonitorEnterMethod());
}
@Override
public void generateCodeFor(MonitorexitQuad<T> quad) {
Operand op = quad.getOperand();
if (op.getAddressingMode() == REGISTER) {
os.writePUSH((GPR) ((RegisterLocation) ((Variable) op).getLocation()).getRegister());
} else if (op.getAddressingMode() == STACK) {
os.writePUSH(X86Register.EBP, ((StackLocation) ((Variable) op).getLocation()).getDisplacement());
} else {
throw new IllegalArgumentException();
}
stackFrame.getHelper().invokeJavaMethod(stackFrame.getEntryPoints().getMonitorExitMethod());
}
@Override
public void generateCodeFor(NewAssignQuad<T> quad) {
VmConstClass clazz = quad.getType();
Label label = getInstrLabel(quad.getAddress());
writeResolveAndLoadClassToReg(clazz, SR1, label);
/* Setup a call to SoftByteCodes.allocObject */
os.writePUSH(SR1); /* vmClass */
os.writePUSH(-1); /* Size */
stackFrame.getHelper().invokeJavaMethod(stackFrame.getEntryPoints().getAllocObjectMethod());
Variable lhs = quad.getLHS();
if (lhs.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, (GPR) ((RegisterLocation) lhs.getLocation()).getRegister(), X86Register.EAX);
} else if (lhs.getAddressingMode() == STACK) {
os.writeMOV(BITS32, X86Register.EBP, ((StackLocation) lhs.getLocation()).getDisplacement(),
X86Register.EAX);
} else {
throw new IllegalArgumentException();
}
}
@Override
public void generateCodeFor(ThrowQuad<T> quad) {
// Exception must be in EAX
Operand op = quad.getOperand();
if (op.getAddressingMode() == REGISTER) {
GPR reg = (GPR) ((RegisterLocation) ((Variable) op).getLocation()).getRegister();
if (reg != X86Register.EAX) {
os.writeMOV(BITS32, X86Register.EAX, reg);
}
} else if (op.getAddressingMode() == STACK) {
os.writeMOV(BITS32, X86Register.EAX, X86Register.EBP,
((StackLocation) ((Variable) op).getLocation()).getDisplacement());
} else {
throw new IllegalArgumentException();
}
// Jump
stackFrame.getHelper().writeJumpTableCALL(X86JumpTable.VM_ATHROW_IDX);
}
/**
* Write code to resolve the given constant class (if needed) and load the
* resolved class (VmType instance) into the given register.
*
* @param classRef
* @param label
*/
private void writeResolveAndLoadClassToReg(VmConstClass classRef, GPR dst, Label label) {
// Resolve the class
classRef.resolve(currentMethod.getDeclaringClass().getLoader());
final VmType type = classRef.getResolvedVmClass();
// Load the class from the statics table
X86CompilerHelper helper = stackFrame.getHelper();
if (os.isCode32()) {
helper.writeGetStaticsEntry(label, dst, type);
} else {
helper.writeGetStaticsEntry64(label, (X86Register.GPR64) dst, (VmSharedStaticsEntry) type);
}
}
@Override
public void generateCodeFor(StaticRefAssignQuad<T> quad) {
checkLabel(quad.getAddress());
VmConstFieldRef fieldRef = quad.getRHS().getFiledRef();
final Label curInstrLabel = getInstrLabel(quad.getAddress());
fieldRef.resolve(currentMethod.getDeclaringClass().getLoader());
final int type = JvmType.SignatureToType(fieldRef.getSignature());
final VmStaticField sf = (VmStaticField) fieldRef.getResolvedVmField();
// Initialize if needed
// if (!sf.getDeclaringClass().isAlwaysInitialized()) {
// writeInitializeClass(fieldRef);
// }
// Get static field object
// if (JvmType.isFloat(type)) {
// final boolean is32bit = !fieldRef.isWide();
// if (sf.isShared()) {
// stackFrame.getHelper().writeGetStaticsEntryToFPU(curInstrLabel, (VmSharedStaticsEntry) sf, is32bit);
// } else {
// final GPR tmp = (GPR) L1AHelper.requestRegister(eContext,
// JvmType.REFERENCE, false);
// helper.writeGetStaticsEntryToFPU(curInstrLabel,
// (VmIsolatedStaticsEntry) sf, is32bit, tmp);
// L1AHelper.releaseRegister(eContext, tmp);
// }
// final Item result = ifac.createFPUStack(type);
// pushFloat(result);
// vstack.push(result);
// } else
if (!fieldRef.isWide()) {
//final WordItem result = L1AHelper.requestWordRegister(eContext, type, false);
Variable<T> lhs = quad.getLHS();
//final GPR resultr = lhs result.getRegister();
if (os.isCode32() || (type != JvmType.REFERENCE)) {
if (sf.isShared()) {
if (lhs.getAddressingMode() == REGISTER) {
stackFrame.getHelper().writeGetStaticsEntry(curInstrLabel,
(GPR) ((RegisterLocation) lhs.getLocation()).getRegister(), sf);
} else {
//todo
}
} else {
if (lhs.getAddressingMode() == REGISTER) {
//todo ESI ??
GPR tmp = GPR.ESI;
stackFrame.getHelper().writeGetStaticsEntry(curInstrLabel,
(GPR) ((RegisterLocation) lhs.getLocation()).getRegister(), sf, tmp);
} else {
//todo
}
}
}
// else {
// if (sf.isShared()) {
// stackFrame.getHelper().writeGetStaticsEntry64(curInstrLabel, (GPR64) resultr,
// (VmSharedStaticsEntry) sf);
// } else {
// stackFrame.getHelper().writeGetStaticsEntry64(curInstrLabel, (GPR64) resultr,
// (VmIsolatedStaticsEntry) sf);
// }
// }
}
// else {
// final DoubleWordItem result = L1AHelper.requestDoubleWordRegisters(
// eContext, type);
// if (os.isCode32()) {
// final GPR lsb = result.getLsbRegister(eContext);
// final GPR msb = result.getMsbRegister(eContext);
// if (sf.isShared()) {
// helper.writeGetStaticsEntry64(curInstrLabel, lsb, msb, (VmSharedStaticsEntry) sf);
// } else {
// helper.writeGetStaticsEntry64(curInstrLabel, lsb, msb, (VmIsolatedStaticsEntry) sf);
// }
// } else {
// final GPR64 reg = result.getRegister(eContext);
// if (sf.isShared()) {
// helper.writeGetStaticsEntry64(curInstrLabel, reg, (VmSharedStaticsEntry) sf);
// } else {
// helper.writeGetStaticsEntry64(curInstrLabel, reg, (VmIsolatedStaticsEntry) sf);
// }
// }
// vstack.push(result);
// }
}
public void generateCodeFor(StaticRefStoreQuad<T> quad) {
checkLabel(quad.getAddress());
final Label curInstrLabel = getInstrLabel(quad.getAddress());
VmConstFieldRef fieldRef = quad.getField().getFiledRef();
fieldRef.resolve(currentMethod.getDeclaringClass().getLoader());
final int type = JvmType.SignatureToType(fieldRef.getSignature());
final VmStaticField sf = (VmStaticField) fieldRef.getResolvedVmField();
if (!fieldRef.isWide()) {
if (os.isCode32() || (type != JvmType.REFERENCE)) {
if (sf.isShared()) {
if (quad.getOperand().getAddressingMode() == REGISTER) {
stackFrame.getHelper().writePutStaticsEntry(curInstrLabel,
(GPR) ((RegisterLocation) ((Variable) quad.getOperand()).getLocation()).getRegister(), sf);
} else {
//todo
}
} else {
if (quad.getOperand().getAddressingMode() == REGISTER) {
//todo ESI ??
GPR tmp = GPR.ESI;
stackFrame.getHelper().writePutStaticsEntry(curInstrLabel,
(GPR) ((RegisterLocation) ((Variable) quad.getOperand()).getLocation()).getRegister(),
sf, tmp);
} else {
//todo
}
}
}
// else {
// if (sf.isShared()) {
// helper.writePutStaticsEntry64(curInstrLabel, (GPR64) valr, sf);
// } else {
// final GPR tmp = (GPR) L1AHelper.requestRegister(eContext, JvmType.REFERENCE, false);
// helper.writePutStaticsEntry64(curInstrLabel, (GPR64) valr, sf, tmp);
// L1AHelper.releaseRegister(eContext, tmp);
// }
// }
// if (!sf.isPrimitive() && helper.needsWriteBarrier()) {
// final GPR tmp = (GPR) L1AHelper.requestRegister(eContext, JvmType.INT, false);
// helper.writePutstaticWriteBarrier(sf, valr, tmp);
// L1AHelper.releaseRegister(eContext, tmp);
// }
}
// else {
// final DoubleWordItem dval = (DoubleWordItem) val;
// if (os.isCode32()) {
// if (sf.isShared()) {
// helper.writePutStaticsEntry64(curInstrLabel, dval.getLsbRegister(eContext), dval
// .getMsbRegister(eContext), sf);
// } else {
// final GPR tmp = (GPR) L1AHelper.requestRegister(eContext, JvmType.REFERENCE, false);
// helper.writePutStaticsEntry64(curInstrLabel, dval.getLsbRegister(eContext),
// dval.getMsbRegister(eContext), sf, tmp);
// L1AHelper.releaseRegister(eContext, tmp);
// }
// } else {
// if (sf.isShared()) {
// helper.writePutStaticsEntry64(curInstrLabel, dval.getRegister(eContext), sf);
// } else {
// final GPR tmp = (GPR) L1AHelper.requestRegister(eContext, JvmType.REFERENCE, false);
// helper.writePutStaticsEntry64(curInstrLabel, dval.getRegister(eContext), sf, tmp);
// L1AHelper.releaseRegister(eContext, tmp);
// }
// }
// }
}
@Override
public void generateCodeFor(RefAssignQuad<T> quad) {
VmConstFieldRef fieldRef = quad.getFieldRef();
fieldRef.resolve(currentMethod.getDeclaringClass().getLoader());
final VmField field = fieldRef.getResolvedVmField();
if (field.isStatic()) {
throw new IncompatibleClassChangeError(
"getfield called on static field " + fieldRef.getName());
}
final VmInstanceField inf = (VmInstanceField) field;
final int fieldOffset = inf.getOffset();
final int type = JvmType.SignatureToType(fieldRef.getSignature());
final boolean isfloat = JvmType.isFloat(type);
Variable dest = quad.getLHS();
Variable ref = (Variable) quad.getRef();
// get field
if (!fieldRef.isWide()) {
if (isfloat) {
//todo
throw new IllegalArgumentException();
// result = ifac.createFPUStack(JvmType.FLOAT);
// os.writeFLD32(refr, fieldOffset);
// pushFloat(result);
} else {
final char fieldType = field.getSignature().charAt(0);
//todo check 8bits support for registers
switch (fieldType) {
case 'Z': { // boolean
if (dest.getAddressingMode() == REGISTER) {
GPR destr = (GPR) ((RegisterLocation) dest.getLocation()).getRegister();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOVZX(destr, refr, fieldOffset, BITS8);
} else if (ref.getAddressingMode() == STACK) {
int disp = ((StackLocation) ref.getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOVZX(destr, SR1, fieldOffset, BITS8);
} else {
throw new IllegalArgumentException();
}
} else if (dest.getAddressingMode() == STACK) {
int destd = ((StackLocation) dest.getLocation()).getDisplacement();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOVZX(SR1, refr, fieldOffset, BITS8);
os.writeMOV(BITS32, X86Register.EBP, destd, SR1);
} else if (ref.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
int disp = ((StackLocation) ref.getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOVZX(sr2, SR1, fieldOffset, BITS8);
os.writeMOV(BITS32, X86Register.EBP, destd, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
break;
}
case 'B': { // byte
if (dest.getAddressingMode() == REGISTER) {
GPR destr = (GPR) ((RegisterLocation) dest.getLocation()).getRegister();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOVSX(destr, refr, fieldOffset, BITS8);
} else if (ref.getAddressingMode() == STACK) {
int disp = ((StackLocation) ref.getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOVSX(destr, SR1, fieldOffset, BITS8);
} else {
throw new IllegalArgumentException();
}
} else if (dest.getAddressingMode() == STACK) {
int destd = ((StackLocation) dest.getLocation()).getDisplacement();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOVSX(SR1, refr, fieldOffset, BITS8);
os.writeMOV(BITS32, X86Register.EBP, destd, SR1);
} else if (ref.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
int disp = ((StackLocation) ref.getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOVSX(sr2, SR1, fieldOffset, BITS8);
os.writeMOV(BITS32, X86Register.EBP, destd, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
break;
}
case 'C': { // char
if (dest.getAddressingMode() == REGISTER) {
GPR destr = (GPR) ((RegisterLocation) dest.getLocation()).getRegister();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOVZX(destr, refr, fieldOffset, BITS16);
} else if (ref.getAddressingMode() == STACK) {
int disp = ((StackLocation) ref.getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOVZX(destr, SR1, fieldOffset, BITS16);
} else {
throw new IllegalArgumentException();
}
} else if (dest.getAddressingMode() == STACK) {
int destd = ((StackLocation) dest.getLocation()).getDisplacement();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOVZX(SR1, refr, fieldOffset, BITS16);
os.writeMOV(BITS32, X86Register.EBP, destd, SR1);
} else if (ref.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
int disp = ((StackLocation) ref.getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOVZX(sr2, SR1, fieldOffset, BITS16);
os.writeMOV(BITS32, X86Register.EBP, destd, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
break;
}
case 'S': { // short
if (dest.getAddressingMode() == REGISTER) {
GPR destr = (GPR) ((RegisterLocation) dest.getLocation()).getRegister();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOVSX(destr, refr, fieldOffset, BITS16);
} else if (ref.getAddressingMode() == STACK) {
int disp = ((StackLocation) ref.getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOVSX(destr, SR1, fieldOffset, BITS16);
} else {
throw new IllegalArgumentException();
}
} else if (dest.getAddressingMode() == STACK) {
int destd = ((StackLocation) dest.getLocation()).getDisplacement();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOVSX(SR1, refr, fieldOffset, BITS16);
os.writeMOV(BITS32, X86Register.EBP, destd, SR1);
} else if (ref.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
int disp = ((StackLocation) ref.getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOVSX(sr2, SR1, fieldOffset, BITS16);
os.writeMOV(BITS32, X86Register.EBP, destd, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
break;
}
case 'I': // int
case 'L': // Object
case '[': { // array
if (dest.getAddressingMode() == REGISTER) {
GPR destr = (GPR) ((RegisterLocation) dest.getLocation()).getRegister();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOV(BITS32, destr, refr, fieldOffset);
} else if (ref.getAddressingMode() == STACK) {
int disp = ((StackLocation) ref.getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOV(BITS32, destr, SR1, fieldOffset);
} else {
throw new IllegalArgumentException();
}
} else if (dest.getAddressingMode() == STACK) {
int destd = ((StackLocation) dest.getLocation()).getDisplacement();
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ref.getLocation()).getRegister();
os.writeMOV(BITS32, SR1, refr, fieldOffset);
os.writeMOV(BITS32, X86Register.EBP, destd, SR1);
} else if (ref.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
int disp = ((StackLocation) ref.getLocation()).getDisplacement();
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOV(BITS32, sr2, SR1, fieldOffset);
os.writeMOV(BITS32, X86Register.EBP, destd, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
break;
}
default:
throw new IllegalArgumentException("Unknown fieldType " + fieldType);
}
}
} else {
// if (isfloat) {
// result = ifac.createFPUStack(JvmType.DOUBLE);
// os.writeFLD64(refr, fieldOffset);
// pushFloat(result);
// } else {
// final DoubleWordItem idw = L1AHelper
// .requestDoubleWordRegisters(eContext, type);
// if (os.isCode32()) {
// final GPR lsb = idw.getLsbRegister(eContext);
// final GPR msb = idw.getMsbRegister(eContext);
// os.writeMOV(BITS32, lsb, refr, fieldOffset + LSB);
// os.writeMOV(BITS32, msb, refr, fieldOffset + MSB);
// } else {
// final GPR64 reg = idw.getRegister(eContext);
// os.writeMOV(BITS64, reg, refr, fieldOffset);
// }
// result = idw;
// }
//todo
throw new IllegalArgumentException();
}
}
@Override
public void generateCodeFor(RefStoreQuad<T> quad) {
VmConstFieldRef fieldRef = quad.getFieldRef();
fieldRef.resolve(currentMethod.getDeclaringClass().getLoader());
final VmField field = fieldRef.getResolvedVmField();
if (field.isStatic()) {
throw new IncompatibleClassChangeError(
"getfield called on static field " + fieldRef.getName());
}
final VmInstanceField inf = (VmInstanceField) field;
final int offset = inf.getOffset();
final boolean wide = fieldRef.isWide();
// Get operands
// final Item val = vstack.pop();
// assertCondition(val.getCategory() == ((wide) ? 2 : 1),
// "category mismatch");
Operand ref = quad.getRef();
Operand val = quad.getValue();
if (!wide) {
final char fieldType = field.getSignature().charAt(0);
// Store field
switch (fieldType) {
case 'Z': // boolean
case 'B': // byte
//todo 8bits support wval.loadToBITS8GPR(eContext);
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ((Variable) ref).getLocation()).getRegister();
if (val.getAddressingMode() == CONSTANT) {
os.writeMOV_Const(BITS8, refr, offset, ((IntConstant) val).getValue());
} else if (val.getAddressingMode() == REGISTER) {
os.writeMOV(BITS8, refr, offset,
(GPR) ((RegisterLocation) ((Variable) val).getLocation()).getRegister());
} else if (val.getAddressingMode() == STACK) {
os.writeMOV(BITS32, SR1, X86Register.EBP,
((StackLocation) ((Variable) val).getLocation()).getDisplacement());
os.writeMOV(BITS8, refr, offset, SR1);
} else {
throw new IllegalArgumentException();
}
} else if (ref.getAddressingMode() == STACK) {
int disp = ((StackLocation) ((Variable) ref).getLocation()).getDisplacement();
if (val.getAddressingMode() == CONSTANT) {
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOV_Const(BITS8, SR1, offset, ((IntConstant) val).getValue());
} else if (val.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOV(BITS8, SR1, offset,
(GPR) ((RegisterLocation) ((Variable) val).getLocation()).getRegister());
} else if (val.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOV(BITS32, sr2, X86Register.EBP,
((StackLocation) ((Variable) val).getLocation()).getDisplacement());
os.writeMOV(BITS8, SR1, offset, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
break;
case 'C': // char
case 'S': // short
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ((Variable) ref).getLocation()).getRegister();
if (val.getAddressingMode() == CONSTANT) {
os.writeMOV_Const(BITS16, refr, offset, ((IntConstant) val).getValue());
} else if (val.getAddressingMode() == REGISTER) {
os.writeMOV(BITS16, refr, offset,
(GPR) ((RegisterLocation) ((Variable) val).getLocation()).getRegister());
} else if (val.getAddressingMode() == STACK) {
os.writeMOV(BITS32, SR1, X86Register.EBP,
((StackLocation) ((Variable) val).getLocation()).getDisplacement());
os.writeMOV(BITS16, refr, offset, SR1);
} else {
throw new IllegalArgumentException();
}
} else if (ref.getAddressingMode() == STACK) {
int disp = ((StackLocation) ((Variable) ref).getLocation()).getDisplacement();
if (val.getAddressingMode() == CONSTANT) {
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOV_Const(BITS16, SR1, offset, ((IntConstant) val).getValue());
} else if (val.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOV(BITS16, SR1, offset,
(GPR) ((RegisterLocation) ((Variable) val).getLocation()).getRegister());
} else if (val.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOV(BITS32, sr2, X86Register.EBP,
((StackLocation) ((Variable) val).getLocation()).getDisplacement());
os.writeMOV(BITS16, SR1, offset, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
break;
case 'F': // float
case 'I': // int
case 'L': // Object
case '[': // array
if (ref.getAddressingMode() == REGISTER) {
GPR refr = (GPR) ((RegisterLocation) ((Variable) ref).getLocation()).getRegister();
if (val.getAddressingMode() == CONSTANT) {
os.writeMOV_Const(BITS32, refr, offset, ((IntConstant) val).getValue());
} else if (val.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, refr, offset,
(GPR) ((RegisterLocation) ((Variable) val).getLocation()).getRegister());
} else if (val.getAddressingMode() == STACK) {
os.writeMOV(BITS32, SR1, X86Register.EBP,
((StackLocation) ((Variable) val).getLocation()).getDisplacement());
os.writeMOV(BITS32, refr, offset, SR1);
} else {
throw new IllegalArgumentException();
}
} else if (ref.getAddressingMode() == STACK) {
int disp = ((StackLocation) ((Variable) ref).getLocation()).getDisplacement();
if (val.getAddressingMode() == CONSTANT) {
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOV_Const(BITS32, SR1, offset, ((IntConstant) val).getValue());
} else if (val.getAddressingMode() == REGISTER) {
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOV(BITS32, SR1, offset,
(GPR) ((RegisterLocation) ((Variable) val).getLocation()).getRegister());
} else if (val.getAddressingMode() == STACK) {
GPR sr2 = SR1 == X86Register.EAX ? X86Register.EBX : X86Register.EAX;
os.writePUSH(sr2);
os.writeMOV(BITS32, SR1, X86Register.EBP, disp);
os.writeMOV(BITS32, sr2, X86Register.EBP,
((StackLocation) ((Variable) val).getLocation()).getDisplacement());
os.writeMOV(BITS32, SR1, offset, sr2);
os.writePOP(sr2);
} else {
throw new IllegalArgumentException();
}
} else {
throw new IllegalArgumentException();
}
break;
default:
throw new IllegalArgumentException("Unknown fieldType: " + fieldType);
}
// Writebarrier
// if (!inf.isPrimitive() && helper.needsWriteBarrier()) {
// final GPR tmp = (GPR) L1AHelper.requestRegister(eContext,
// JvmType.REFERENCE, false);
// helper.writePutfieldWriteBarrier(inf, refr, valr, tmp);
// L1AHelper.releaseRegister(eContext, tmp);
// }
} else {
// final DoubleWordItem dval = (DoubleWordItem) val;
// if (os.isCode32()) {
// os.writeMOV(BITS32, refr, offset + MSB, dval
// .getMsbRegister(eContext));
// os.writeMOV(BITS32, refr, offset + LSB, dval
// .getLsbRegister(eContext));
// } else {
// os.writeMOV(BITS64, refr, offset, dval.getRegister(eContext));
// }
throw new IllegalArgumentException();
}
}
@Override
public void generateCodeFor(SpecialCallAssignQuad quad) {
VmConstMethodRef methodRef = quad.getMethodRef();
methodRef.resolve(currentMethod.getDeclaringClass().getLoader());
try {
final VmMethod sm = methodRef.getResolvedVmMethod();
//dropParameters(sm, true);
writeParameters(quad);
// Call the methods code from the statics table
stackFrame.getHelper().invokeJavaMethod(sm);
// Result is already on the stack.
} catch (ClassCastException ex) {
BootLogInstance.get().error(methodRef.getResolvedVmMethod().getClass().getName() + '#' +
methodRef.getName());
throw ex;
}
Variable lhs = quad.getLHS();
if (lhs.getAddressingMode() == REGISTER) {
GPR reg = (GPR) ((RegisterLocation) lhs.getLocation()).getRegister();
if (reg != GPR.EAX) {
os.writeMOV(X86Constants.BITS32, reg, GPR.EAX);
}
} else if (lhs.getAddressingMode() == STACK) {
int disp = ((StackLocation) lhs.getLocation()).getDisplacement();
os.writeMOV(X86Constants.BITS32, GPR.ESP, disp, GPR.EAX);
}
}
@Override
public void generateCodeFor(SpecialCallQuad quad) {
VmConstMethodRef methodRef = quad.getMethodRef();
methodRef.resolve(currentMethod.getDeclaringClass().getLoader());
try {
final VmMethod sm = methodRef.getResolvedVmMethod();
//dropParameters(sm, true);
writeParameters(quad);
// Call the methods code from the statics table
stackFrame.getHelper().invokeJavaMethod(sm);
// Result is already on the stack.
} catch (ClassCastException ex) {
// BootLogInstance.get().error(methodRef.getResolvedVmMethod().getClass().getName() + '#' +
// methodRef.getName());
throw ex;
}
}
@Override
public void generateCodeFor(VirtualCallAssignQuad quad) {
checkLabel(quad.getAddress());
VmConstMethodRef methodRef = quad.getMethodRef();
methodRef.resolve(currentMethod.getDeclaringClass().getLoader());
final VmMethod mts = methodRef.getResolvedVmMethod();
if (mts.isStatic()) {
throw new IncompatibleClassChangeError(
"Static method in invokevirtual");
}
final VmInstanceMethod method = (VmInstanceMethod) mts;
final VmType<?> declClass = method.getDeclaringClass();
if (declClass.isMagicType()) {
// magicHelper.emitMagic(eContext, method, false, this, currentMethod);
} else {
// TODO: port to ORP style (http://orp.sourceforge.net/)
// vstack.push(eContext);
writeParameters(quad);
// dropParameters(mts, true);
if (method.isFinal() || method.isPrivate() || declClass.isFinal()) {
// Do a fast invocation
// counters.getCounter("virtual-final").inc();
// Call the methods native code from the statics table
stackFrame.getHelper().invokeJavaMethod(method);
// Result is already on the stack.
} else {
// Do a virtual method table invocation
// counters.getCounter("virtual-vmt").inc();
final int tibIndex = method.getTibOffset();
final int argSlotCount = Signature.getArgSlotCount(typeSizeInfo, methodRef
.getSignature());
final int slotSize = stackFrame.getHelper().SLOTSIZE;
final int asize = stackFrame.getHelper().ADDRSIZE;
int arrayDataOffset = VmArray.DATA_OFFSET * slotSize;
int tibOffset = ObjectLayout.TIB_SLOT * slotSize;
/* Get objectref -> EAX */
os.writeMOV(asize, stackFrame.getHelper().AAX, stackFrame.getHelper().SP, argSlotCount * slotSize);
/* Get VMT of objectref -> EAX */
os.writeMOV(asize, stackFrame.getHelper().AAX, stackFrame.getHelper().AAX, tibOffset);
/* Get entry in VMT -> EAX */
os.writeMOV(asize, stackFrame.getHelper().AAX, stackFrame.getHelper().AAX,
arrayDataOffset + (tibIndex * slotSize));
/* Now invoke the method */
os.writeCALL(stackFrame.getHelper().AAX,
stackFrame.getEntryPoints().getVmMethodNativeCodeField().getOffset());
// stackFrame.getHelper().pushReturnValue(methodRef.getSignature());
// Result is already on the stack.
}
}
Variable lhs = quad.getLHS();
if (lhs.getAddressingMode() == REGISTER) {
GPR reg = (GPR) ((RegisterLocation) lhs.getLocation()).getRegister();
if (reg != GPR.EAX) {
os.writeMOV(X86Constants.BITS32, reg, GPR.EAX);
}
} else if (lhs.getAddressingMode() == STACK) {
int disp = ((StackLocation) lhs.getLocation()).getDisplacement();
os.writeMOV(X86Constants.BITS32, GPR.ESP, disp, GPR.EAX);
}
}
@Override
public void generateCodeFor(VirtualCallQuad quad) {
checkLabel(quad.getAddress());
VmConstMethodRef methodRef = quad.getMethodRef();
methodRef.resolve(currentMethod.getDeclaringClass().getLoader());
final VmMethod mts = methodRef.getResolvedVmMethod();
if (mts.isStatic()) {
throw new IncompatibleClassChangeError(
"Static method in invokevirtual");
}
final VmInstanceMethod method = (VmInstanceMethod) mts;
final VmType<?> declClass = method.getDeclaringClass();
if (declClass.isMagicType()) {
// magicHelper.emitMagic(eContext, method, false, this, currentMethod);
} else {
// TODO: port to ORP style (http://orp.sourceforge.net/)
// vstack.push(eContext);
writeParameters(quad);
// dropParameters(mts, true);
if (method.isFinal() || method.isPrivate() || declClass.isFinal()) {
// Do a fast invocation
// counters.getCounter("virtual-final").inc();
// Call the methods native code from the statics table
stackFrame.getHelper().invokeJavaMethod(method);
// Result is already on the stack.
} else {
// Do a virtual method table invocation
// counters.getCounter("virtual-vmt").inc();
final int tibIndex = method.getTibOffset();
final int argSlotCount = Signature.getArgSlotCount(typeSizeInfo, methodRef
.getSignature());
final int slotSize = stackFrame.getHelper().SLOTSIZE;
final int asize = stackFrame.getHelper().ADDRSIZE;
int arrayDataOffset = VmArray.DATA_OFFSET * slotSize;
int tibOffset = ObjectLayout.TIB_SLOT * slotSize;
/* Get objectref -> EAX */
os.writeMOV(asize, stackFrame.getHelper().AAX, stackFrame.getHelper().SP, argSlotCount * slotSize);
/* Get VMT of objectref -> EAX */
os.writeMOV(asize, stackFrame.getHelper().AAX, stackFrame.getHelper().AAX, tibOffset);
/* Get entry in VMT -> EAX */
os.writeMOV(asize, stackFrame.getHelper().AAX, stackFrame.getHelper().AAX,
arrayDataOffset + (tibIndex * slotSize));
/* Now invoke the method */
os.writeCALL(stackFrame.getHelper().AAX,
stackFrame.getEntryPoints().getVmMethodNativeCodeField().getOffset());
// stackFrame.getHelper().pushReturnValue(methodRef.getSignature());
// Result is already on the stack.
}
}
}
@Override
public void generateCodeFor(StaticCallAssignQuad<T> quad) {
checkLabel(quad.getAddress());
VmConstMethodRef methodRef = quad.getMethodRef();
methodRef.resolve(currentMethod.getDeclaringClass().getLoader());
final VmStaticMethod method = (VmStaticMethod) methodRef.getResolvedVmMethod();
if (method.getDeclaringClass().isMagicType()) {
//todo magicHelper.emitMagic(eContext, method, true, this, currentMethod);
} else {
writeParameters(quad);
//todo handle return types
final int offset = stackFrame.getHelper().getSharedStaticsOffset(method);
os.writeCALL(stackFrame.getHelper().STATICS, offset);
Variable lhs = quad.getLHS();
if (lhs.getAddressingMode() == REGISTER) {
GPR reg = (GPR) ((RegisterLocation) lhs.getLocation()).getRegister();
if (reg != GPR.EAX) {
os.writeMOV(X86Constants.BITS32, reg, GPR.EAX);
}
} else if (lhs.getAddressingMode() == STACK) {
int disp = ((StackLocation) lhs.getLocation()).getDisplacement();
os.writeMOV(X86Constants.BITS32, GPR.ESP, disp, GPR.EAX);
}
}
}
@Override
public void generateCodeFor(StaticCallQuad<T> quad) {
checkLabel(quad.getAddress());
VmConstMethodRef methodRef = quad.getMethodRef();
methodRef.resolve(currentMethod.getDeclaringClass().getLoader());
final VmStaticMethod method = (VmStaticMethod) methodRef.getResolvedVmMethod();
if (method.getDeclaringClass().isMagicType()) {
//todo magicHelper.emitMagic(eContext, method, true, this, currentMethod);
} else {
writeParameters(quad);
final int offset = stackFrame.getHelper().getSharedStaticsOffset(method);
os.writeCALL(stackFrame.getHelper().STATICS, offset);
}
}
@Override
public void generateCodeFor(InterfaceCallAssignQuad quad) {
VmConstMethodRef methodRef = quad.getMethodRef();
methodRef.resolve(currentMethod.getDeclaringClass().getLoader());
final VmMethod method = methodRef.getResolvedVmMethod();
final int argSlotCount = quad.getReferencedOps().length - 1;
writeParameters(quad);
// Get objectref -> EAX
X86CompilerHelper helper = stackFrame.getHelper();
os.writeMOV(helper.ADDRSIZE, helper.AAX, helper.SP, argSlotCount * helper.SLOTSIZE);
X86IMTCompiler32.emitInvokeInterface(os, method);
Variable lhs = quad.getLHS();
if (lhs.getAddressingMode() == REGISTER) {
GPR reg = (GPR) ((RegisterLocation) lhs.getLocation()).getRegister();
if (reg != GPR.EAX) {
os.writeMOV(X86Constants.BITS32, reg, GPR.EAX);
}
} else if (lhs.getAddressingMode() == STACK) {
int disp = ((StackLocation) lhs.getLocation()).getDisplacement();
os.writeMOV(X86Constants.BITS32, GPR.ESP, disp, GPR.EAX);
}
}
@Override
public void generateCodeFor(InterfaceCallQuad quad) {
VmConstMethodRef methodRef = quad.getMethodRef();
// Resolve the method
methodRef.resolve(currentMethod.getDeclaringClass().getLoader());
final VmMethod method = methodRef.getResolvedVmMethod();
final int argSlotCount = quad.getReferencedOps().length - 1;
// remove parameters from vstack
writeParameters(quad);
// Get objectref -> EAX
X86CompilerHelper helper = stackFrame.getHelper();
os.writeMOV(helper.ADDRSIZE, helper.AAX, helper.SP, argSlotCount * helper.SLOTSIZE);
// Write the actual invokeinterface
// if (os.isCode32()) {
X86IMTCompiler32.emitInvokeInterface(os, method);
// } else {
// X86IMTCompiler64.emitInvokeInterface(os, method);
// }
// Test the stack alignment
//stackFrame.writeStackAlignmentTest(getInstrLabel(quad.getAddress()));
}
private void writeParameters(Quad quad) {
Operand<T>[] referencedOps = quad.getReferencedOps();
for (int i = 0; i < referencedOps.length; i++) {
Operand operand = referencedOps[i];
if (operand.getAddressingMode() == CONSTANT) {
//todo handle other types
int c = ((IntConstant) operand).getValue();
os.writePUSH(c);
} else if (operand.getAddressingMode() == REGISTER) {
GPR reg = (GPR) ((RegisterLocation) ((Variable) operand).getLocation()).getRegister();
os.writePUSH(reg);
} else if (operand.getAddressingMode() == STACK) {
int disp = ((StackLocation) ((Variable) operand).getLocation()).getDisplacement();
os.writePUSH(GPR.EBP, disp);
if (operand.getType() == Operand.LONG) {
os.writePUSH(GPR.EBP, disp - stackFrame.getHelper().SLOTSIZE);
}
} else {
throw new IllegalArgumentException();
}
}
}
}