From: <cap...@us...> - 2007-06-11 16:00:26
|
Revision: 130 http://svn.sourceforge.net/pearcolator/?rev=130&view=rev Author: captain5050 Date: 2007-06-11 09:00:28 -0700 (Mon, 11 Jun 2007) Log Message: ----------- Fixes to get us building against the Jikes RVM SVN head again Modified Paths: -------------- ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java rvmroot.patch src/org/binarytranslator/vmInterface/DynamicCodeRunner.java Modified: ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java =================================================================== --- ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java 2007-06-11 15:48:25 UTC (rev 129) +++ ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java 2007-06-11 16:00:28 UTC (rev 130) @@ -1,10 +1,14 @@ /* - * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net). - * The Jikes RVM project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php + * This file is part of the Jikes RVM project (http://jikesrvm.org). * - * (C) Copyright IBM Corp. 2001 + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.ia32; @@ -15,7 +19,6 @@ import org.jikesrvm.compilers.opt.OPT_DefUse; import org.jikesrvm.compilers.opt.OPT_OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.Binary; -import org.jikesrvm.compilers.opt.ir.BinaryAcc; import org.jikesrvm.compilers.opt.ir.CacheOp; import org.jikesrvm.compilers.opt.ir.Call; import org.jikesrvm.compilers.opt.ir.CondMove; @@ -26,11 +29,13 @@ import org.jikesrvm.compilers.opt.ir.MIR_Call; import org.jikesrvm.compilers.opt.ir.MIR_Compare; import org.jikesrvm.compilers.opt.ir.MIR_CompareExchange; +import org.jikesrvm.compilers.opt.ir.MIR_CompareExchange8B; import org.jikesrvm.compilers.opt.ir.MIR_CondBranch; import org.jikesrvm.compilers.opt.ir.MIR_CondMove; import org.jikesrvm.compilers.opt.ir.MIR_ConvertDW2QW; import org.jikesrvm.compilers.opt.ir.MIR_Divide; import org.jikesrvm.compilers.opt.ir.MIR_DoubleShift; +import org.jikesrvm.compilers.opt.ir.MIR_Lea; import org.jikesrvm.compilers.opt.ir.MIR_LowTableSwitch; import org.jikesrvm.compilers.opt.ir.MIR_Move; import org.jikesrvm.compilers.opt.ir.MIR_Multiply; @@ -63,6 +68,9 @@ import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_CMPL; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_CMPL; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GUARD_MOVE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SHL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SHR; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_USHR; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_ADC; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_ADD; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_AND; @@ -92,8 +100,12 @@ import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_IDIV; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_IMUL2; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_JCC; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_LEA; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_LOCK_CMPXCHG; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_LOCK_CMPXCHG8B; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MOV; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MOVSD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MOVSS; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MOVSX__B; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MOVZX__B; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MUL; @@ -116,7 +128,6 @@ import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_XOR; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IR_PROLOGUE; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.MIR_LOWTABLESWITCH; - import org.jikesrvm.compilers.opt.ir.OPT_Register; import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperandEnumeration; @@ -166,6 +177,95 @@ } /** + * Create the MIR instruction given by operator from the Binary LIR operands + * @param operator the MIR operator + * @param s the instruction being replaced + * @param result the destination register/memory + * @param val1 the first operand + * @param val2 the second operand + */ + protected void EMIT_Commutative(OPT_Operator operator, OPT_Instruction s, OPT_Operand result, OPT_Operand val1, OPT_Operand val2) { + if(VM.VerifyAssertions) VM._assert(result.isRegister() || result.isMemory()); + // Swap operands to reduce chance of generating a move or to normalize + // constants into val2 + if (val2.similar(result) || val1.isConstant()) { + OPT_Operand temp = val1; + val1 = val2; + val2 = temp; + } + // Do we need to move prior to the operator - result = val1 + if (!result.similar(val1)) { + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copy(), val1))); + } + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + + /** + * Create the MIR instruction given by operator from the Binary LIR operands + * @param operator the MIR operator + * @param s the instruction being replaced + * @param result the destination register/memory + * @param val1 the first operand + * @param val2 the second operand + */ + protected void EMIT_NonCommutative(OPT_Operator operator, OPT_Instruction s, OPT_Operand result, OPT_Operand val1, OPT_Operand val2) { + if(VM.VerifyAssertions) VM._assert(result.isRegister() || result.isMemory()); + if (result.similar(val1)) { + // Straight forward case where instruction is already in accumulate form + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + else if (!result.similar(val2)) { + // Move first operand to result and perform operator on result, if + // possible redundant moves should be remove by register allocator + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copy(), val1))); + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + else { + // Potential to clobber second operand during move to result. Use a + // temporary register to perform the operation and rely on register + // allocator to remove redundant moves + OPT_RegisterOperand temp = regpool.makeTemp(result); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, temp, val1))); + EMIT(MIR_BinaryAcc.mutate(s, operator, temp.copyRO(), val2)); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result, temp.copyRO()))); + } + } + + /** + * Create the MIR instruction given by operator from the Binary LIR operands + * @param operator the MIR operator + * @param s the instruction being replaced + * @param result the destination register/memory + * @param value the first operand + */ + protected void EMIT_Unary(OPT_Operator operator, OPT_Instruction s, OPT_Operand result, OPT_Operand value) { + if(VM.VerifyAssertions) VM._assert(result.isRegister() || result.isMemory()); + // Do we need to move prior to the operator - result = val1 + if (!result.similar(value)) { + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copy(), value))); + } + EMIT(MIR_UnaryAcc.mutate(s, operator, result)); + } + + /** + * Convert the given comparison with a boolean (int) value into a condition + * suitable for the carry flag + * @param x the value 1 (true) or 0 (false) + * @param cond either equal or not equal + * @return lower or higher equal + */ + protected static OPT_ConditionOperand BIT_TEST(int x, OPT_ConditionOperand cond) { + if (VM.VerifyAssertions) VM._assert((x==0)||(x==1)); + if (VM.VerifyAssertions) VM._assert(EQ_NE(cond)); + if ((x == 1 && cond.isEQUAL())|| + (x == 0 && cond.isNOT_EQUAL())) { + return OPT_ConditionOperand.LOWER(); + } else { + return OPT_ConditionOperand.HIGHER_EQUAL(); + } + } + + /** * Follow a chain of Move operations filtering back to a def * * @param use the place to start from @@ -351,8 +451,7 @@ return IA32_FLDL2T; } } - throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", - "unexpected 387 constant " + val); + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", "unexpected 387 constant " + val); } protected final OPT_IA32ConditionOperand COND(OPT_ConditionOperand op) { @@ -403,12 +502,15 @@ protected final OPT_Operand myFP1() { return new OPT_BURSManagedFPROperand(1); } + + protected final OPT_Register getST0() { + return getIR().regpool.getPhysicalRegisterSet().getST0(); + } /** * Move op into a register operand if it isn't one already. */ - private OPT_Operand asReg(OPT_Instruction s, OPT_Operator movop, - OPT_Operand op) { + private OPT_Operand asReg(OPT_Instruction s, OPT_Operator movop, OPT_Operand op) { if (op.isRegister()) { return op; } @@ -450,16 +552,12 @@ OPT_RegisterOperand hval = (OPT_RegisterOperand) op; OPT_RegisterOperand lval = new OPT_RegisterOperand(regpool .getSecondReg(hval.register), VM_TypeReference.Int); - EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, - offset + 4, DW), hval)); - EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset, - DW), lval)); + EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset + 4, DW), hval)); + EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset, DW), lval)); } else { OPT_LongConstantOperand val = LC(op); - EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, - offset + 4, DW), IC(val.upper32()))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset, - DW), IC(val.lower32()))); + EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset + 4, DW), IC(val.upper32()))); + EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset, DW), IC(val.lower32()))); } } @@ -472,8 +570,7 @@ private OPT_MemoryOperand loadFromJTOC(Offset offset) { OPT_LocationOperand loc = new OPT_LocationOperand(offset); OPT_Operand guard = TG(); - return OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus(offset), (byte) 4, - loc, guard); + return OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus(offset), (byte) 4, loc, guard); } /* @@ -513,18 +610,25 @@ * @param s the instruction to expand * @param result the result operand * @param value the second operand + * @param signExtend should the value be sign or zero extended? */ protected final void INT_2LONG(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { +OPT_Operand value, boolean signExtend) { OPT_Register hr = result.register; OPT_Register lr = regpool.getSecondReg(hr); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lr, - VM_TypeReference.Int), value)); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(hr, - VM_TypeReference.Int), - new OPT_RegisterOperand(lr, VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_SAR, new OPT_RegisterOperand(hr, - VM_TypeReference.Int), IC(31))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lr, VM_TypeReference.Int), value))); + if (signExtend) { + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(hr, VM_TypeReference.Int), + new OPT_RegisterOperand(lr, VM_TypeReference.Int)))); + EMIT(MIR_BinaryAcc.mutate(s,IA32_SAR, + new OPT_RegisterOperand(hr, VM_TypeReference.Int), + IC(31))); + } else { + EMIT(MIR_Move.mutate(s, IA32_MOV, + new OPT_RegisterOperand(hr, VM_TypeReference.Int), + IC(0))); + } } /** @@ -537,15 +641,14 @@ * @param result the result operand * @param value the second operand */ - protected final void FPR_2INT(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { + protected final void FPR_2INT(OPT_Instruction s, OPT_RegisterOperand result, OPT_Operand value) { OPT_MemoryOperand M; // Step 1: Get value to be converted into myFP0 // and in 'strict' IEEE mode. if (value instanceof OPT_MemoryOperand) { // value is in memory, all we have to do is load it - EMIT(MIR_Move.create(IA32_FLD, myFP0(), value)); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), value))); } else { // sigh. value is an FP register. Unfortunately, // SPECjbb requires some 'strict' FP semantics. Naturally, we don't @@ -558,16 +661,16 @@ if (VM.VerifyAssertions) { VM._assert(value.similar(myFP0())); } - EMIT(MIR_Move.create(IA32_FSTP, MO_CONV(DW), value)); - EMIT(MIR_Move.create(IA32_FLD, myFP0(), MO_CONV(DW))); + EMIT(CPOS(s, MIR_Move.create(IA32_FSTP, MO_CONV(DW), value))); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), MO_CONV(DW)))); } else { - EMIT(MIR_Move.create(IA32_FMOV, MO_CONV(DW), value)); - EMIT(MIR_Move.create(IA32_FLD, myFP0(), MO_CONV(DW))); + EMIT(CPOS(s, MIR_Move.create(IA32_FMOV, MO_CONV(DW), value))); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), MO_CONV(DW)))); } } // FP Stack: myFP0 = value - EMIT(MIR_Move.create(IA32_FIST, MO_CONV(DW), myFP0())); + EMIT(CPOS(s, MIR_Move.create(IA32_FIST, MO_CONV(DW), myFP0()))); // MO_CONV now holds myFP0 converted to an integer (round-toward nearest) // FP Stack: myFP0 == value @@ -576,112 +679,93 @@ OPT_Register one = regpool.getInteger(); OPT_Register isPositive = regpool.getInteger(); OPT_Register isNegative = regpool.getInteger(); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(one, - VM_TypeReference.Int), IC(1))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(isPositive, - VM_TypeReference.Int), IC(0))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(isNegative, - VM_TypeReference.Int), IC(0))); - EMIT(MIR_Nullary.create(IA32_FLDZ, myFP0())); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(one, VM_TypeReference.Int), IC(1)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(isPositive, VM_TypeReference.Int), IC(0)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(isNegative, VM_TypeReference.Int), IC(0)))); + EMIT(CPOS(s, MIR_Nullary.create(IA32_FLDZ, myFP0()))); // FP Stack: myFP0 = 0.0; myFP1 = value - EMIT(MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())); + EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1()))); // FP Stack: myFP0 = value - EMIT(MIR_CondMove.create(IA32_CMOV, - new OPT_RegisterOperand(isPositive, - VM_TypeReference.Int), - new OPT_RegisterOperand(one, - VM_TypeReference.Int), - OPT_IA32ConditionOperand.LLT())); - EMIT(MIR_CondMove.create(IA32_CMOV, - new OPT_RegisterOperand(isNegative, - VM_TypeReference.Int), - new OPT_RegisterOperand(one, - VM_TypeReference.Int), - OPT_IA32ConditionOperand.LGT())); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + new OPT_RegisterOperand(isPositive, VM_TypeReference.Int), + new OPT_RegisterOperand(one, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LLT()))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + new OPT_RegisterOperand(isNegative, VM_TypeReference.Int), + new OPT_RegisterOperand(one, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LGT()))); - EMIT(MIR_Move.create(IA32_FILD, myFP0(), MO_CONV(DW))); + EMIT(CPOS(s, MIR_Move.create(IA32_FILD, myFP0(), MO_CONV(DW)))); // FP Stack: myFP0 = round(value), myFP1 = value // addee = 1 iff round(x) < x // subtractee = 1 iff round(x) > x OPT_Register addee = regpool.getInteger(); OPT_Register subtractee = regpool.getInteger(); - EMIT(MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())); + EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1()))); // FP Stack: myFP0 = value - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(addee, - VM_TypeReference.Int), IC(0))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(subtractee, - VM_TypeReference.Int), IC(0))); - EMIT(MIR_CondMove.create(IA32_CMOV, - new OPT_RegisterOperand(addee, - VM_TypeReference.Int), - new OPT_RegisterOperand(one, - VM_TypeReference.Int), - OPT_IA32ConditionOperand.LLT())); - EMIT(MIR_CondMove.create(IA32_CMOV, - new OPT_RegisterOperand(subtractee, - VM_TypeReference.Int), - new OPT_RegisterOperand(one, - VM_TypeReference.Int), - OPT_IA32ConditionOperand.LGT())); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(addee, VM_TypeReference.Int), IC(0)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(subtractee, VM_TypeReference.Int), IC(0)))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + new OPT_RegisterOperand(addee, VM_TypeReference.Int), + new OPT_RegisterOperand(one, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LLT()))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + new OPT_RegisterOperand(subtractee, VM_TypeReference.Int), + new OPT_RegisterOperand(one, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LGT()))); // Now a little tricky part. // We will add 1 iff isNegative and x > round(x) // We will subtract 1 iff isPositive and x < round(x) - EMIT(MIR_BinaryAcc.create(IA32_AND, - new OPT_RegisterOperand(addee, - VM_TypeReference.Int), - new OPT_RegisterOperand(isNegative, - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_AND, - new OPT_RegisterOperand(subtractee, - VM_TypeReference.Int), - new OPT_RegisterOperand(isPositive, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, result.copy(), MO_CONV(DW))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, result.copy(), new OPT_RegisterOperand( - addee, VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_SUB, result.copy(), new OPT_RegisterOperand( - subtractee, VM_TypeReference.Int))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_AND, + new OPT_RegisterOperand(addee, VM_TypeReference.Int), + new OPT_RegisterOperand(isNegative, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_AND, + new OPT_RegisterOperand(subtractee, VM_TypeReference.Int), + new OPT_RegisterOperand(isPositive, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copy(), MO_CONV(DW)))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_ADD, result.copy(), new OPT_RegisterOperand(addee, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, result.copy(), new OPT_RegisterOperand(subtractee, VM_TypeReference.Int)))); // Compare myFP0 with (double)Integer.MAX_VALUE - M = OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus( - VM_Entrypoints.maxintField.getOffset()), QW, null, null); - EMIT(MIR_Move.create(IA32_FLD, myFP0(), M)); + M = OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus(VM_Entrypoints.maxintField.getOffset()), QW, null, null); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), M))); // FP Stack: myFP0 = (double)Integer.MAX_VALUE; myFP1 = value - EMIT(MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())); + EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1()))); // FP Stack: myFP0 = value // If MAX_VALUE < value, then result := MAX_INT OPT_Register maxInt = regpool.getInteger(); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(maxInt, - VM_TypeReference.Int), IC(Integer.MAX_VALUE))); - EMIT(MIR_CondMove.create(IA32_CMOV, result.copy(), new OPT_RegisterOperand( - maxInt, VM_TypeReference.Int), OPT_IA32ConditionOperand.LLT())); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(maxInt, VM_TypeReference.Int), IC(Integer.MAX_VALUE)))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + result.copy(), + new OPT_RegisterOperand(maxInt, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LLT()))); // Compare myFP0 with (double)Integer.MIN_VALUE - M = OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus( - VM_Entrypoints.minintField.getOffset()), QW, null, null); - EMIT(MIR_Move.create(IA32_FLD, myFP0(), M)); + M = OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus(VM_Entrypoints.minintField.getOffset()), QW, null, null); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), M))); // FP Stack: myFP0 = (double)Integer.MIN_VALUE; myFP1 = value - EMIT(MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())); + EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1()))); // FP Stack: myFP0 = value // If MIN_VALUE > value, then result := MIN_INT OPT_Register minInt = regpool.getInteger(); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(minInt, - VM_TypeReference.Int), IC(Integer.MIN_VALUE))); - EMIT(MIR_CondMove.create(IA32_CMOV, result.copy(), new OPT_RegisterOperand( - minInt, VM_TypeReference.Int), OPT_IA32ConditionOperand.LGT())); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(minInt, VM_TypeReference.Int), IC(Integer.MIN_VALUE)))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + result.copy(), + new OPT_RegisterOperand(minInt, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LGT()))); // Set condition flags: set PE iff myFP0 is a NaN - EMIT(MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP0())); + EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP0()))); // FP Stack: back to original level (all BURS managed slots freed) // If FP0 was classified as a NaN, then result := 0 OPT_Register zero = regpool.getInteger(); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(zero, - VM_TypeReference.Int), IC(0))); - EMIT(MIR_CondMove.create(IA32_CMOV, result.copy(), new OPT_RegisterOperand( - zero, VM_TypeReference.Int), OPT_IA32ConditionOperand.PE())); - + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(zero, VM_TypeReference.Int), IC(0)))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + result.copy(), + new OPT_RegisterOperand(zero, VM_TypeReference.Int), + OPT_IA32ConditionOperand.PE()))); } /** @@ -690,15 +774,13 @@ protected final void FPR2GPR_64(OPT_Instruction s) { int offset = -burs.ir.stackManager.allocateSpaceForConversion(); OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, QW); - OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, - offset + 4, DW); - OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, - DW); - EMIT(MIR_Move.create(IA32_FMOV, sl, Unary.getVal(s))); + OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, offset + 4, DW); + OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, DW); + EMIT(CPOS(s, MIR_Move.create(IA32_FMOV, sl, Unary.getVal(s)))); OPT_RegisterOperand i1 = Unary.getResult(s); OPT_RegisterOperand i2 = new OPT_RegisterOperand(regpool .getSecondReg(i1.register), VM_TypeReference.Int); - EMIT(MIR_Move.create(IA32_MOV, i1, sl1)); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, i1, sl1))); EMIT(MIR_Move.mutate(s, IA32_MOV, i2, sl2)); } @@ -708,28 +790,216 @@ protected final void GPR2FPR_64(OPT_Instruction s) { int offset = -burs.ir.stackManager.allocateSpaceForConversion(); OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, QW); - OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, - offset + 4, DW); - OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, - DW); + OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, offset + 4, DW); + OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, DW); OPT_Operand i1, i2; OPT_Operand val = Unary.getVal(s); if (val instanceof OPT_RegisterOperand) { OPT_RegisterOperand rval = (OPT_RegisterOperand) val; i1 = val; - i2 = new OPT_RegisterOperand(regpool.getSecondReg(rval.register), - VM_TypeReference.Int); + i2 = new OPT_RegisterOperand(regpool.getSecondReg(rval.register), VM_TypeReference.Int); } else { OPT_LongConstantOperand rhs = (OPT_LongConstantOperand) val; i1 = IC(rhs.upper32()); i2 = IC(rhs.lower32()); } - EMIT(MIR_Move.create(IA32_MOV, sl1, i1)); - EMIT(MIR_Move.create(IA32_MOV, sl2, i2)); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl1, i1))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl2, i2))); EMIT(MIR_Move.mutate(s, IA32_FMOV, Unary.getResult(s), sl)); } + + /** + * Returns the appropriate move operator based on the type of operand. + */ + protected final OPT_Operator SSE2_MOVE(OPT_Operand o) { + return o.isFloat() ? IA32_MOVSS : IA32_MOVSD; + } + + /** + * Returns the size based on the type of operand. + */ + protected final byte SSE2_SIZE(OPT_Operand o) { + return o.isFloat() ? DW : QW; + } + + /** + * Performs a long -> double/float conversion using x87 and marshalls back to XMMs. + */ + protected final void SSE2_X87_FROMLONG(OPT_Instruction s) { + OPT_Operand result = Unary.getResult(s); + STORE_LONG_FOR_CONV(Unary.getVal(s)); + // conversion space allocated, contains the long to load. + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, SSE2_SIZE(result)); + OPT_RegisterOperand st0 = new OPT_RegisterOperand(getST0(), result.getType()); + EMIT(CPOS(s, MIR_Move.create(IA32_FILD, st0, sl))); + EMIT(CPOS(s, MIR_Move.create(IA32_FSTP, sl.copy(), st0.copyD2U()))); + EMIT(CPOS(s, MIR_Move.mutate(s, SSE2_MOVE(result), result, sl.copy()))); + } + + /** + * Performs a long -> double/float conversion using x87 and marshalls between to XMMs. + */ + protected final void SSE2_X87_REM(OPT_Instruction s) { + OPT_Operand result = Move.getClearResult(s); + OPT_RegisterOperand st0 = new OPT_RegisterOperand(getST0(), result.getType()); + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, SSE2_SIZE(result)); + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), sl, Binary.getVal2(s)))); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, st0, sl.copy()))); + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), sl.copy(), Binary.getVal1(s)))); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, st0.copy(), sl.copy()))); + EMIT(CPOS(s, MIR_Nullary.create(IA32_FPREM, st0.copy()))); + EMIT(CPOS(s, MIR_Move.create(IA32_FSTP, sl.copy(), st0.copy()))); + EMIT(MIR_Move.mutate(s, SSE2_MOVE(result), result, sl.copy())); + } + + /** + * Emit code to move 64 bits from SSE2 FPRs to GPRs + */ + protected final void SSE2_FPR2GPR_64(OPT_Instruction s) { + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, QW); + OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, offset + 4, DW); + OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, DW); + EMIT(CPOS(s, MIR_Move.create(IA32_MOVSD, sl, Unary.getVal(s)))); + OPT_RegisterOperand i1 = Unary.getResult(s); + OPT_RegisterOperand i2 = new OPT_RegisterOperand(regpool + .getSecondReg(i1.register), VM_TypeReference.Int); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, i1, sl1))); + EMIT(MIR_Move.mutate(s, IA32_MOV, i2, sl2)); + } /** + * Emit code to move 64 bits from GPRs to SSE2 FPRs + */ + protected final void SSE2_GPR2FPR_64(OPT_Instruction s) { + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, QW); + OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, offset + 4, DW); + OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, DW); + OPT_Operand i1, i2; + OPT_Operand val = Unary.getVal(s); + if (val instanceof OPT_RegisterOperand) { + OPT_RegisterOperand rval = (OPT_RegisterOperand) val; + i1 = val; + i2 = new OPT_RegisterOperand(regpool.getSecondReg(rval.register), VM_TypeReference.Int); + } else { + OPT_LongConstantOperand rhs = (OPT_LongConstantOperand) val; + i1 = IC(rhs.upper32()); + i2 = IC(rhs.lower32()); + } + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl1, i1))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl2, i2))); + EMIT(MIR_Move.mutate(s, IA32_MOVSD, Unary.getResult(s), sl)); + } + + /** + * Emit code to move 32 bits from FPRs to GPRs + */ + protected final void SSE2_FPR2GPR_32(OPT_Instruction s) { + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, DW); + EMIT(CPOS(s, MIR_Move.create(IA32_MOVSS, sl, Unary.getVal(s)))); + EMIT(MIR_Move.mutate(s, IA32_MOV, Unary.getResult(s), sl.copy())); + } + + /** + * Emit code to move 32 bits from GPRs to FPRs + */ + protected final void SSE2_GPR2FPR_32(OPT_Instruction s) { + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, DW); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl, Unary.getVal(s)))); + EMIT(MIR_Move.mutate(s, IA32_MOVSS, Unary.getResult(s), sl.copy())); + } + + /** + * BURS expansion of a commutative SSE2 operation. + */ + protected void SSE2_COP(OPT_Operator operator, OPT_Instruction s, OPT_Operand result, OPT_Operand val1, OPT_Operand val2) { + if(VM.VerifyAssertions) VM._assert(result.isRegister()); + // Swap operands to reduce chance of generating a move or to normalize + // constants into val2 + if (val2.similar(result)) { + OPT_Operand temp = val1; + val1 = val2; + val2 = temp; + } + // Do we need to move prior to the operator - result = val1 + if (!result.similar(val1)) { + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), result.copy(), val1))); + } + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + + /** + * BURS expansion of a non commutative SSE2 operation. + */ + protected void SSE2_NCOP(OPT_Operator operator, OPT_Instruction s, OPT_Operand result, OPT_Operand val1, OPT_Operand val2) { + if(VM.VerifyAssertions) VM._assert(result.isRegister()); + if (result.similar(val1)) { + // Straight forward case where instruction is already in accumulate form + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + else if (!result.similar(val2)) { + // Move first operand to result and perform operator on result, if + // possible redundant moves should be remove by register allocator + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), result.copy(), val1))); + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + else { + // Potential to clobber second operand during move to result. Use a + // temporary register to perform the operation and rely on register + // allocator to remove redundant moves + OPT_RegisterOperand temp = regpool.makeTemp(result); + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), temp, val1))); + EMIT(MIR_BinaryAcc.mutate(s, operator, temp.copyRO(), val2)); + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), result, temp.copyRO()))); + } + } + + /** + * Expansion of SSE2 negation ops + */ + protected final void SSE2_NEG(OPT_Operator xorOp, OPT_Operator subOp, OPT_Instruction s, OPT_Operand result, OPT_Operand value) { + if(VM.VerifyAssertions) VM._assert(result.isRegister()); + if (!result.similar(value)) { + EMIT(CPOS(s, MIR_BinaryAcc.create(xorOp, result.copy(), result.copy()))); + EMIT(MIR_BinaryAcc.mutate(s, subOp, result, value)); + } else { + OPT_RegisterOperand temp = regpool.makeTemp(value.getType()); + EMIT(CPOS(s, MIR_Move.create(xorOp, temp.copyRO(), temp))); + EMIT(MIR_BinaryAcc.mutate(s, subOp, temp.copyRO(), value)); + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), result, temp.copyRO()))); + } + } + + /** + * Expansion of SSE2 conversions double <-> float + */ + protected final void SSE2_CONV(OPT_Operator op, OPT_Instruction s, OPT_Operand result, OPT_Operand value) { + if(VM.VerifyAssertions) VM._assert(result.isRegister()); + if(VM.VerifyAssertions) VM._assert(value.isRegister()); + EMIT(MIR_Unary.mutate(s, op, result, value)); + } + + /** + * Expansion of SSE2 comparison operations + */ + protected final void SSE2_IFCMP(OPT_Operator op, OPT_Instruction s, OPT_Operand val1, OPT_Operand val2) { + EMIT(CPOS(s, MIR_Compare.create(op, val1, val2))); + EMIT(s); // OPT_ComplexLIR2MIRExpansion will handle rest of the work. + } + + /** + * Expansion of SSE2 floating point constant loads + */ + protected final void SSE2_FPCONSTANT(OPT_Instruction s) { + EMIT(MIR_Move.mutate(s, SSE2_MOVE(Unary.getResult(s)), Binary.getResult(s), MO_MC(s))); + } + + /** * Expansion of ROUND_TO_ZERO. * * @param s the instruction to expand @@ -741,16 +1011,16 @@ OPT_Operand jtoc = OPT_MemoryOperand.BD(PR, VM_Entrypoints.jtocField .getOffset(), DW, null, null); OPT_RegisterOperand regOp = regpool.makeTempInt(); - EMIT(MIR_Move.create(IA32_MOV, regOp, jtoc)); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, regOp, jtoc))); // Store the FPU Control Word to a JTOC slot - OPT_MemoryOperand M = OPT_MemoryOperand.BD(regOp.copyRO(), - VM_Entrypoints.FPUControlWordField.getOffset(), W, null, null); - EMIT(MIR_UnaryNoRes.create(IA32_FNSTCW, M)); + OPT_MemoryOperand M = + OPT_MemoryOperand.BD(regOp.copyRO(), VM_Entrypoints.FPUControlWordField.getOffset(), W, null, null); + EMIT(CPOS(s, MIR_UnaryNoRes.create(IA32_FNSTCW, M))); // Set the bits in the status word that control round to zero. // Note that we use a 32-bit and, even though we only care about the // low-order 16 bits - EMIT(MIR_BinaryAcc.create(IA32_OR, M.copy(), IC(0x00000c00))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_OR, M.copy(), IC(0x00000c00)))); // Now store the result back into the FPU Control Word EMIT(MIR_Nullary.mutate(s, IA32_FLDCW, M.copy())); } @@ -764,196 +1034,315 @@ * @param val2 the second operand * @param isDiv true for div, false for rem */ - protected final void INT_DIVIDES(OPT_Instruction s, - OPT_RegisterOperand result, OPT_Operand val1, OPT_Operand val2, + protected final void INT_DIVIDES(OPT_Instruction s, OPT_RegisterOperand result, OPT_Operand val1, OPT_Operand val2, boolean isDiv) { - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), val1)); - EMIT(MIR_ConvertDW2QW.create(IA32_CDQ, - new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), - new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(getEAX(), VM_TypeReference.Int), val1))); + EMIT(CPOS(s, MIR_ConvertDW2QW.create(IA32_CDQ, + new OPT_RegisterOperand(getEDX(), VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), VM_TypeReference.Int)))); if (val2 instanceof OPT_IntConstantOperand) { OPT_RegisterOperand temp = regpool.makeTempInt(); - EMIT(MIR_Move.create(IA32_MOV, temp, val2)); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, temp, val2))); val2 = temp.copyRO(); } EMIT(MIR_Divide.mutate(s, IA32_IDIV, - new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), - new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), + new OPT_RegisterOperand(getEDX(), VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), VM_TypeReference.Int), val2, GuardedBinary.getGuard(s))); if (isDiv) { - EMIT(MIR_Move.create(IA32_MOV, result.copyD2D(), new OPT_RegisterOperand( - getEAX(), VM_TypeReference.Int))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copyD2D(), new OPT_RegisterOperand(getEAX(), VM_TypeReference.Int)))); } else { - EMIT(MIR_Move.create(IA32_MOV, result.copyD2D(), new OPT_RegisterOperand( - getEDX(), VM_TypeReference.Int))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copyD2D(), new OPT_RegisterOperand(getEDX(), VM_TypeReference.Int)))); } } /** - * Expansion of LONG_ADD_ACC + * Expansion of LONG_ADD * * @param s the instruction to expand - * @param result the result/first operand - * @param value the second operand + * @param result the result operand + * @param value1 the first operand + * @param value2 the second operand */ protected final void LONG_ADD(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { + OPT_Operand value1, OPT_Operand value2) { + // The value of value1 should be identical to result, to avoid moves, and a + // register in the case of addition with a constant + if ((value2.similar(result)) || value1.isLongConstant()) { + OPT_Operand temp = value1; + value1 = value2; + value2 = temp; + } OPT_Register lhsReg = result.register; OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); - if (value instanceof OPT_RegisterOperand) { - OPT_Register rhsReg = ((OPT_RegisterOperand) value).register; - OPT_Register lowrhsReg = regpool.getSecondReg(rhsReg); - EMIT(MIR_BinaryAcc.create(IA32_ADD, - new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), - new OPT_RegisterOperand(lowrhsReg, - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.mutate(s, - IA32_ADC, - new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), - new OPT_RegisterOperand(rhsReg, - VM_TypeReference.Int))); - } else { - OPT_LongConstantOperand rhs = (OPT_LongConstantOperand) value; - int low = rhs.lower32(); - int high = rhs.upper32(); + if (value1.isRegister() && value2.isRegister()) { + OPT_Register rhsReg1 = ((OPT_RegisterOperand) value1).register; + OPT_Register lowrhsReg1 = regpool.getSecondReg(rhsReg1); + OPT_Register rhsReg2 = ((OPT_RegisterOperand) value2).register; + OPT_Register lowrhsReg2 = regpool.getSecondReg(rhsReg2); + // Do we need to move prior to the add - result = value1 + if (!value1.similar(result)) { + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg1, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg1, VM_TypeReference.Int)))); + } + // Perform add - result += value2 + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg2, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_ADC, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg2, VM_TypeReference.Int)))); + } else if (value1.isRegister()){ + OPT_Register rhsReg1 = ((OPT_RegisterOperand) value1).register; + OPT_Register lowrhsReg1 = regpool.getSecondReg(rhsReg1); + OPT_LongConstantOperand rhs2 = (OPT_LongConstantOperand) value2; + int low = rhs2.lower32(); + int high = rhs2.upper32(); + // Do we need to move prior to the add - result = value1 + if (!value1.similar(result)) { + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg1, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg1, VM_TypeReference.Int)))); + } + // Perform add - result += value2 if (low == 0) { - EMIT(MIR_BinaryAcc.mutate(s, IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_ADD, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + IC(high)))); } else { - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), IC(low))); - EMIT(MIR_BinaryAcc.mutate(s, IA32_ADC, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + IC(low)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_ADC, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + IC(high)))); } + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + value1 + "+" + value2); } } /** - * Expansion of LONG_SUB_ACC + * Expansion of LONG_SUB * * @param s the instruction to expand - * @param result the result/first operand - * @param value the second operand + * @param result the result operand + * @param value1 the first operand + * @param value2 the second operand */ - protected final void LONG_SUB(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { - OPT_Register lhsReg = result.register; - OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); - if (value instanceof OPT_RegisterOperand) { - OPT_Register rhsReg = ((OPT_RegisterOperand) value).register; - OPT_Register lowrhsReg = regpool.getSecondReg(rhsReg); - EMIT(MIR_BinaryAcc.create(IA32_SUB, - new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), - new OPT_RegisterOperand(lowrhsReg, - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.mutate(s, - IA32_SBB, - new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), - new OPT_RegisterOperand(rhsReg, - VM_TypeReference.Int))); - } else { - OPT_LongConstantOperand rhs = (OPT_LongConstantOperand) value; - int low = rhs.lower32(); - int high = rhs.upper32(); - if (low == 0) { - EMIT(MIR_BinaryAcc.mutate(s, IA32_SUB, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); + protected final void LONG_SUB(OPT_Instruction s, OPT_Operand result, + OPT_Operand val1, OPT_Operand val2) { + + if (result.similar(val1)) { + // Straight forward case where instruction is already in accumulate form + if (result.isRegister()) { + OPT_Register lhsReg = result.asRegister().register; + OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); + if (val2.isRegister()) { + OPT_Register rhsReg2 = val2.asRegister().register; + OPT_Register lowrhsReg2 = regpool.getSecondReg(rhsReg2); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg2, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg2, VM_TypeReference.Int)))); + } else if (val2.isLongConstant()) { + OPT_LongConstantOperand rhs2 = val2.asLongConstant(); + int low = rhs2.lower32(); + int high = rhs2.upper32(); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + IC(low)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + IC(high)))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } } else { - EMIT(MIR_BinaryAcc.create(IA32_SUB, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), IC(low))); - EMIT(MIR_BinaryAcc.mutate(s, IA32_SBB, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); } + } + else if (!result.similar(val2)) { + // Move first operand to result and perform operator on result, if + // possible redundant moves should be remove by register allocator + if (result.isRegister()) { + OPT_Register lhsReg = result.asRegister().register; + OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); + // Move val1 into result + if (val1.isRegister()) { + OPT_Register rhsReg1 = val1.asRegister().register; + OPT_Register lowrhsReg1 = regpool.getSecondReg(rhsReg1); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg1, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg1, VM_TypeReference.Int)))); + } else if (val1.isLongConstant()) { + OPT_LongConstantOperand rhs1 = val1.asLongConstant(); + int low = rhs1.lower32(); + int high = rhs1.upper32(); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + IC(low)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + IC(high)))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } + // Perform subtract + if (val2.isRegister()) { + OPT_Register rhsReg2 = val2.asRegister().register; + OPT_Register lowrhsReg2 = regpool.getSecondReg(rhsReg2); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg2, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg2, VM_TypeReference.Int)))); + } else if (val2.isLongConstant()) { + OPT_LongConstantOperand rhs2 = val2.asLongConstant(); + int low = rhs2.lower32(); + int high = rhs2.upper32(); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + IC(low)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + IC(high)))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } } + else { + // Potential to clobber second operand during move to result. Use a + // temporary register to perform the operation and rely on register + // allocator to remove redundant moves + OPT_RegisterOperand temp1 = regpool.makeTempInt(); + OPT_RegisterOperand temp2 = regpool.makeTempInt(); + // Move val1 into temp + if (val1.isRegister()) { + OPT_Register rhsReg1 = val1.asRegister().register; + OPT_Register lowrhsReg1 = regpool.getSecondReg(rhsReg1); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + temp1, + new OPT_RegisterOperand(lowrhsReg1, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + temp2, + new OPT_RegisterOperand(rhsReg1, VM_TypeReference.Int)))); + } else if (val1.isLongConstant()) { + OPT_LongConstantOperand rhs1 = val1.asLongConstant(); + int low = rhs1.lower32(); + int high = rhs1.upper32(); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + temp1, + IC(low)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + temp2, + IC(high)))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } + // Perform subtract + if (val2.isRegister()) { + OPT_Register rhsReg2 = val2.asRegister().register; + OPT_Register lowrhsReg2 = regpool.getSecondReg(rhsReg2); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + temp1.copyRO(), + new OPT_RegisterOperand(lowrhsReg2, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + temp2.copyRO(), + new OPT_RegisterOperand(rhsReg2, VM_TypeReference.Int)))); + } else if (val2.isLongConstant()) { + OPT_LongConstantOperand rhs2 = val2.asLongConstant(); + int low = rhs2.lower32(); + int high = rhs2.upper32(); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + temp1.copyRO(), + IC(low)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + temp2.copyRO(), + IC(high)))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } + // Move result back + if (result.isRegister()) { + OPT_Register lhsReg = result.asRegister().register; + OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + temp1.copyRO()))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + temp2.copyRO()))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } + } } /** - * Expansion of RDTSC (called GET_TIME_BASE for consistency with PPC) + * Expansion of LONG_MUL * * @param s the instruction to expand - * @param result the result/first operand + * @param result the result operand + * @param value1 the first operand + * @param value2 the second operand */ - protected final void GET_TIME_BASE(OPT_Instruction s, - OPT_RegisterOperand result) { - OPT_Register highReg = result.register; - OPT_Register lowReg = regpool.getSecondReg(highReg); - EMIT(MIR_RDTSC.create(IA32_RDTSC, new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(highReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int))); - } - - /** - * Expansion of LONG_MUL_ACC - * - * @param s the instruction to expand - * @param result the result/first operand - * @param value the second operand - */ protected final void LONG_MUL(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { - // In general, (a,b) * (c,d) = (l(a imul d)+l(b imul c)+u(b mul d), l(b mul - // d)) - OPT_Register lhsReg = result.register; - OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); - if (value instanceof OPT_RegisterOperand) { - OPT_Register rhsReg = ((OPT_RegisterOperand) value).register; - OPT_Register lowrhsReg = regpool.getSecondReg(rhsReg); - OPT_Register tmp = regpool.getInteger(); - EMIT(MIR_BinaryAcc.create(IA32_IMUL2, - new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), - new OPT_RegisterOperand(lowrhsReg, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(tmp, - VM_TypeReference.Int), new OPT_RegisterOperand(rhsReg, - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_IMUL2, - new OPT_RegisterOperand(tmp, - VM_TypeReference.Int), - new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(tmp, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); - EMIT(MIR_Multiply.create(IA32_MUL, - new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), - new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), - new OPT_RegisterOperand(lowrhsReg, - ... [truncated message content] |