# HG changeset patch # User Doug Simon # Date 1349710611 -7200 # Node ID 0c6030872cd0028a7a2486c2b0e5d75d40da7ba5 # Parent 4afe23aa0a00a3f3a2053d4773b85fdc884f99b8 renamed package: com.oracle.graal.compiler.target.amd64 -> com.oracle.graal.compiler.amd64 diff -r 4afe23aa0a00 -r 0c6030872cd0 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java Mon Oct 08 17:36:51 2012 +0200 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.amd64; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCall.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.phases.*; + +public class AMD64DeoptimizationStub extends AMD64Code { + + public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", Kind.Void); + public static final Descriptor SET_DEOPT_INFO = new Descriptor("setDeoptInfo", Kind.Void, Kind.Object); + + public final Label label = new Label(); + public final LIRFrameState info; + public final DeoptimizationAction action; + public final DeoptimizationReason reason; + public final Object deoptInfo; + + public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { + this.action = action; + this.reason = reason; + this.info = info; + this.deoptInfo = deoptInfo; + } + + private static ArrayList keepAlive = new ArrayList<>(); + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + // TODO (cwimmer): we want to get rid of a generally reserved scratch register. + Register scratch = tasm.frameMap.registerConfig.getScratchRegister(); + + masm.bind(label); + if (GraalOptions.CreateDeoptInfo && deoptInfo != null) { + masm.nop(); + keepAlive.add(deoptInfo.toString()); + AMD64Move.move(tasm, masm, scratch.asValue(), Constant.forObject(deoptInfo)); + // TODO Make this an explicit calling convention instead of using a scratch register + AMD64Call.directCall(tasm, masm, tasm.runtime.getRuntimeCall(SET_DEOPT_INFO), info); + } + + masm.movl(scratch, tasm.runtime.encodeDeoptActionAndReason(action, reason)); + // TODO Make this an explicit calling convention instead of using a scratch register + AMD64Call.directCall(tasm, masm, tasm.runtime.getRuntimeCall(DEOPTIMIZE), info); + AMD64Call.shouldNotReachHere(tasm, masm); + } + + @Override + public String description() { + return "deopt stub[reason=" + reason + ", action=" + action + "]"; + } +} diff -r 4afe23aa0a00 -r 0c6030872cd0 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Oct 08 17:36:51 2012 +0200 @@ -0,0 +1,696 @@ +/* + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.compiler.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*; +import static com.oracle.graal.lir.amd64.AMD64Compare.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCall.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.amd64.AMD64Assembler.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.StandardOp.LabelOp; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.DivOp; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Reg; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Stack; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Reg; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Stack; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.ShiftOp; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; +import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp; +import com.oracle.graal.lir.amd64.AMD64Compare.CompareOp; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatBranchOp; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatCondMoveOp; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.ReturnOp; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.SequentialSwitchOp; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.SwitchRangesOp; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp; +import com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode; +import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; +import com.oracle.graal.lir.amd64.AMD64Move.LeaOp; +import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; +import com.oracle.graal.lir.amd64.AMD64Move.MembarOp; +import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp; +import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; +import com.oracle.graal.lir.amd64.AMD64Move.NullCheckOp; +import com.oracle.graal.lir.amd64.AMD64Move.SpillMoveOp; +import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.util.*; + +/** + * This class implements the AMD64 specific portion of the LIR generator. + */ +public abstract class AMD64LIRGenerator extends LIRGenerator { + + public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", Kind.Float, Kind.Float, Kind.Float); + public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", Kind.Double, Kind.Double, Kind.Double); + + private static final RegisterValue RAX_I = AMD64.rax.asValue(Kind.Int); + private static final RegisterValue RAX_L = AMD64.rax.asValue(Kind.Long); + private static final RegisterValue RDX_I = AMD64.rdx.asValue(Kind.Int); + private static final RegisterValue RDX_L = AMD64.rdx.asValue(Kind.Long); + private static final RegisterValue RCX_I = AMD64.rcx.asValue(Kind.Int); + + public static class AMD64SpillMoveFactory implements LIR.SpillMoveFactory { + @Override + public LIRInstruction createMove(Value result, Value input) { + return new SpillMoveOp(result, input); + } + + @Override + public LIRInstruction createExchange(Value input1, Value input2) { + // TODO (cwimmer) implement XCHG operation for LIR + return null; + } + } + + public AMD64LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { + super(graph, runtime, target, frameMap, method, lir); + lir.spillMoveFactory = new AMD64SpillMoveFactory(); + } + + @Override + protected void emitNode(ValueNode node) { + if (node instanceof LIRGenLowerable) { + ((LIRGenLowerable) node).generate(this); + } else { + super.emitNode(node); + } + } + + @Override + public boolean canStoreConstant(Constant c) { + // there is no immediate move of 64-bit constants on Intel + switch (c.getKind()) { + case Long: return Util.isInt(c.asLong()); + case Double: return false; + case Object: return c.isNull(); + default: return true; + } + } + + @Override + public boolean canInlineConstant(Constant c) { + switch (c.getKind()) { + case Long: return NumUtil.isInt(c.asLong()); + case Object: return c.isNull(); + default: return true; + } + } + + @Override + public Address makeAddress(LocationNode location, ValueNode object) { + Value base = operand(object); + Value index = Value.IllegalValue; + int scale = 1; + int displacement = location.displacement(); + + if (isConstant(base)) { + if (asConstant(base).isNull()) { + base = Value.IllegalValue; + } else if (asConstant(base).getKind() != Kind.Object) { + long newDisplacement = displacement + asConstant(base).asLong(); + if (NumUtil.isInt(newDisplacement)) { + displacement = (int) newDisplacement; + base = Value.IllegalValue; + } + } + } + + if (location instanceof IndexedLocationNode) { + IndexedLocationNode indexedLoc = (IndexedLocationNode) location; + + index = operand(indexedLoc.index()); + if (indexedLoc.indexScalingEnabled()) { + scale = target().sizeInBytes(location.getValueKind()); + } + if (isConstant(index)) { + long newDisplacement = displacement + asConstant(index).asLong() * scale; + // only use the constant index if the resulting displacement fits into a 32 bit offset + if (NumUtil.isInt(newDisplacement)) { + displacement = (int) newDisplacement; + index = Value.IllegalValue; + } else { + // create a temporary variable for the index, the pointer load cannot handle a constant index + Value newIndex = newVariable(Kind.Long); + emitMove(index, newIndex); + index = newIndex; + } + } + } + + return new Address(location.getValueKind(), base, index, Address.Scale.fromInt(scale), displacement); + } + + @Override + public Variable emitMove(Value input) { + Variable result = newVariable(input.getKind()); + emitMove(input, result); + return result; + } + + @Override + public void emitMove(Value src, Value dst) { + if (isRegister(src) || isStackSlot(dst)) { + append(new MoveFromRegOp(dst, src)); + } else { + append(new MoveToRegOp(dst, src)); + } + } + + @Override + public Variable emitLoad(Value loadAddress, boolean canTrap) { + Variable result = newVariable(loadAddress.getKind()); + append(new LoadOp(result, loadAddress, canTrap ? state() : null)); + return result; + } + + @Override + public void emitStore(Value storeAddress, Value inputVal, boolean canTrap) { + Value input = loadForStore(inputVal, storeAddress.getKind()); + append(new StoreOp(storeAddress, input, canTrap ? state() : null)); + } + + @Override + public Variable emitLea(Value address) { + Variable result = newVariable(target().wordKind); + append(new LeaOp(result, address)); + return result; + } + + @Override + public void emitLabel(Label label, boolean align) { + append(new LabelOp(label, align)); + } + + @Override + public void emitJump(LabelRef label, LIRFrameState info) { + append(new JumpOp(label, info)); + } + + @Override + public void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) { + boolean mirrored = emitCompare(left, right); + Condition finalCondition = mirrored ? cond.mirror() : cond; + switch (left.getKind().stackKind()) { + case Int: + case Long: + case Object: append(new BranchOp(finalCondition, label, info)); break; + case Float: + case Double: append(new FloatBranchOp(finalCondition, unorderedIsTrue, label, info)); break; + default: throw GraalInternalError.shouldNotReachHere("" + left.getKind()); + } + } + + @Override + public Variable emitCMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { + boolean mirrored = emitCompare(left, right); + Condition finalCondition = mirrored ? cond.mirror() : cond; + + Variable result = newVariable(trueValue.getKind()); + switch (left.getKind().stackKind()) { + case Int: + case Long: + case Object: append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue))); break; + case Float: + case Double: append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); break; + + } + return result; + } + + /** + * This method emits the compare instruction, and may reorder the operands. It returns true if it did so. + * + * @param a the left operand of the comparison + * @param b the right operand of the comparison + * @return true if the left and right operands were switched, false otherwise + */ + private boolean emitCompare(Value a, Value b) { + Variable left; + Value right; + boolean mirrored; + if (LIRValueUtil.isVariable(b)) { + left = load(b); + right = loadNonConst(a); + mirrored = true; + } else { + left = load(a); + right = loadNonConst(b); + mirrored = false; + } + switch (left.getKind().stackKind()) { + case Jsr: + case Int: append(new CompareOp(ICMP, left, right)); break; + case Long: append(new CompareOp(LCMP, left, right)); break; + case Object: append(new CompareOp(ACMP, left, right)); break; + case Float: append(new CompareOp(FCMP, left, right)); break; + case Double: append(new CompareOp(DCMP, left, right)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + return mirrored; + } + + @Override + public Variable emitNegate(Value input) { + Variable result = newVariable(input.getKind()); + switch (input.getKind()) { + case Int: append(new Op1Stack(INEG, result, input)); break; + case Long: append(new Op1Stack(LNEG, result, input)); break; + case Float: append(new Op2Reg(FXOR, result, input, Constant.forFloat(Float.intBitsToFloat(0x80000000)))); break; + case Double: append(new Op2Reg(DXOR, result, input, Constant.forDouble(Double.longBitsToDouble(0x8000000000000000L)))); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitAdd(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch(a.getKind()) { + case Int: append(new Op2Stack(IADD, result, a, loadNonConst(b))); break; + case Long: append(new Op2Stack(LADD, result, a, loadNonConst(b))); break; + case Float: append(new Op2Stack(FADD, result, a, loadNonConst(b))); break; + case Double: append(new Op2Stack(DADD, result, a, loadNonConst(b))); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitSub(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch(a.getKind()) { + case Int: append(new Op2Stack(ISUB, result, a, loadNonConst(b))); break; + case Long: append(new Op2Stack(LSUB, result, a, loadNonConst(b))); break; + case Float: append(new Op2Stack(FSUB, result, a, loadNonConst(b))); break; + case Double: append(new Op2Stack(DSUB, result, a, loadNonConst(b))); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitMul(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch(a.getKind()) { + case Int: append(new Op2Reg(IMUL, result, a, loadNonConst(b))); break; + case Long: append(new Op2Reg(LMUL, result, a, loadNonConst(b))); break; + case Float: append(new Op2Stack(FMUL, result, a, loadNonConst(b))); break; + case Double: append(new Op2Stack(DMUL, result, a, loadNonConst(b))); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitDiv(Value a, Value b) { + switch(a.getKind()) { + case Int: + emitMove(a, RAX_I); + append(new DivOp(IDIV, RAX_I, RAX_I, load(b), state())); + return emitMove(RAX_I); + case Long: + emitMove(a, RAX_L); + append(new DivOp(LDIV, RAX_L, RAX_L, load(b), state())); + return emitMove(RAX_L); + case Float: { + Variable result = newVariable(a.getKind()); + append(new Op2Stack(FDIV, result, a, loadNonConst(b))); + return result; + } + case Double: { + Variable result = newVariable(a.getKind()); + append(new Op2Stack(DDIV, result, a, loadNonConst(b))); + return result; + } + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Value emitRem(Value a, Value b) { + switch(a.getKind()) { + case Int: + emitMove(a, RAX_I); + append(new DivOp(IREM, RDX_I, RAX_I, load(b), state())); + return emitMove(RDX_I); + case Long: + emitMove(a, RAX_L); + append(new DivOp(LREM, RDX_L, RAX_L, load(b), state())); + return emitMove(RDX_L); + case Float: { + RuntimeCall stub = runtime.getRuntimeCall(ARITHMETIC_FREM); + return emitCall(stub, stub.getCallingConvention(), false, a, b); + } + case Double: { + RuntimeCall stub = runtime.getRuntimeCall(ARITHMETIC_DREM); + return emitCall(stub, stub.getCallingConvention(), false, a, b); + } + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Variable emitUDiv(Value a, Value b) { + switch(a.getKind()) { + case Int: + emitMove(a, RAX_I); + append(new DivOp(IUDIV, RAX_I, RAX_I, load(b), state())); + return emitMove(RAX_I); + case Long: + emitMove(a, RAX_L); + append(new DivOp(LUDIV, RAX_L, RAX_L, load(b), state())); + return emitMove(RAX_L); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Variable emitURem(Value a, Value b) { + switch(a.getKind()) { + case Int: + emitMove(a, RAX_I); + append(new DivOp(IUREM, RDX_I, RAX_I, load(b), state())); + return emitMove(RDX_I); + case Long: + emitMove(a, RAX_L); + append(new DivOp(LUREM, RDX_L, RAX_L, load(b), state())); + return emitMove(RDX_L); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + + @Override + public Variable emitAnd(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch(a.getKind()) { + case Int: append(new Op2Stack(IAND, result, a, loadNonConst(b))); break; + case Long: append(new Op2Stack(LAND, result, a, loadNonConst(b))); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitOr(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch(a.getKind()) { + case Int: append(new Op2Stack(IOR, result, a, loadNonConst(b))); break; + case Long: append(new Op2Stack(LOR, result, a, loadNonConst(b))); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitXor(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch(a.getKind()) { + case Int: append(new Op2Stack(IXOR, result, a, loadNonConst(b))); break; + case Long: append(new Op2Stack(LXOR, result, a, loadNonConst(b))); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + + @Override + public Variable emitShl(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: append(new ShiftOp(ISHL, result, a, loadShiftCount(b))); break; + case Long: append(new ShiftOp(LSHL, result, a, loadShiftCount(b))); break; + default: GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitShr(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: append(new ShiftOp(ISHR, result, a, loadShiftCount(b))); break; + case Long: append(new ShiftOp(LSHR, result, a, loadShiftCount(b))); break; + default: GraalInternalError.shouldNotReachHere(); + } + return result; + } + + @Override + public Variable emitUShr(Value a, Value b) { + Variable result = newVariable(a.getKind()); + switch (a.getKind()) { + case Int: append(new ShiftOp(IUSHR, result, a, loadShiftCount(b))); break; + case Long: append(new ShiftOp(LUSHR, result, a, loadShiftCount(b))); break; + default: GraalInternalError.shouldNotReachHere(); + } + return result; + } + + private Value loadShiftCount(Value value) { + if (isConstant(value)) { + return value; + } + // Non-constant shift count must be in RCX + emitMove(value, RCX_I); + return RCX_I; + } + + + @Override + public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) { + Variable input = load(inputVal); + Variable result = newVariable(opcode.to); + switch (opcode) { + case I2L: append(new Op1Reg(I2L, result, input)); break; + case L2I: append(new Op1Stack(L2I, result, input)); break; + case I2B: append(new Op1Stack(I2B, result, input)); break; + case I2C: append(new Op1Stack(I2C, result, input)); break; + case I2S: append(new Op1Stack(I2S, result, input)); break; + case F2D: append(new Op1Reg(F2D, result, input)); break; + case D2F: append(new Op1Reg(D2F, result, input)); break; + case I2F: append(new Op1Reg(I2F, result, input)); break; + case I2D: append(new Op1Reg(I2D, result, input)); break; + case F2I: append(new Op1Reg(F2I, result, input)); break; + case D2I: append(new Op1Reg(D2I, result, input)); break; + case L2F: append(new Op1Reg(L2F, result, input)); break; + case L2D: append(new Op1Reg(L2D, result, input)); break; + case F2L: append(new Op1Reg(F2L, result, input)); break; + case D2L: append(new Op1Reg(D2L, result, input)); break; + case MOV_I2F: append(new Op1Reg(MOV_I2F, result, input)); break; + case MOV_L2D: append(new Op1Reg(MOV_L2D, result, input)); break; + case MOV_F2I: append(new Op1Reg(MOV_F2I, result, input)); break; + case MOV_D2L: append(new Op1Reg(MOV_D2L, result, input)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + return result; + } + + + @Override + public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { + LIRFrameState info = state(); + LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo); + append(new BranchOp(ConditionFlag.overflow, stubEntry, info)); + } + + + @Override + public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo, long leafGraphId) { + LIRFrameState info = state(leafGraphId); + LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo); + append(new JumpOp(stubEntry, info)); + } + + @Override + public void emitMembar(int barriers) { + int necessaryBarriers = target.arch.requiredBarriers(barriers); + if (target.isMP && necessaryBarriers != 0) { + append(new MembarOp(necessaryBarriers)); + } + } + + @Override + protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + append(new DirectCallOp(callTarget.target(), result, parameters, temps, callState)); + } + + @Override + protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + // The current register allocator cannot handle variables at call sites, need a fixed register. + Value targetAddress = AMD64.rax.asValue(); + emitMove(operand(callTarget.computedAddress()), targetAddress); + append(new IndirectCallOp(callTarget.target(), result, parameters, temps, targetAddress, callState)); + } + + @Override + protected void emitCall(Object targetMethod, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info) { + if (isConstant(targetAddress)) { + append(new DirectCallOp(targetMethod, result, arguments, temps, info)); + } else { + append(new IndirectCallOp(targetMethod, result, arguments, temps, targetAddress, info)); + } + } + + @Override + public void emitBitScanForward(Variable result, Value value) { + append(new AMD64BitScanOp(AMD64BitScanOp.IntrinsicOpcode.BSF, result, value)); + } + + @Override + public void emitBitScanReverse(Variable result, Value value) { + if (value.getKind().isStackInt()) { + append(new AMD64BitScanOp(AMD64BitScanOp.IntrinsicOpcode.IBSR, result, value)); + } else { + append(new AMD64BitScanOp(AMD64BitScanOp.IntrinsicOpcode.LBSR, result, value)); + } + } + + @Override + public void emitMathAbs(Variable result, Variable input) { + append(new Op2Reg(DAND, result, input, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); + } + + @Override + public void emitMathSqrt(Variable result, Variable input) { + append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SQRT, result, input)); + } + + @Override + public void emitMathLog(Variable result, Variable input, boolean base10) { + IntrinsicOpcode opcode = base10 ? AMD64MathIntrinsicOp.IntrinsicOpcode.LOG10 : AMD64MathIntrinsicOp.IntrinsicOpcode.LOG; + append(new AMD64MathIntrinsicOp(opcode, result, input)); + } + + @Override + public void emitMathCos(Variable result, Variable input) { + append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.COS, result, input)); + } + + @Override + public void emitMathSin(Variable result, Variable input) { + append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SIN, result, input)); + } + + @Override + public void emitMathTan(Variable result, Variable input) { + append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.TAN, result, input)); + } + + @Override + public void emitByteSwap(Variable result, Value input) { + append(new AMD64ByteSwapOp(result, input)); + } + + @Override + protected void emitReturn(Value input) { + append(new ReturnOp(input)); + } + + @Override + protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) { + // Making a copy of the switch value is necessary because jump table destroys the input value + if (key.getKind() == Kind.Int) { + append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.IllegalValue)); + } else { + assert key.getKind() == Kind.Object; + append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object))); + } + } + + @Override + protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) { + append(new SwitchRangesOp(lowKeys, highKeys, targets, defaultTarget, key)); + } + + @Override + protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { + // Making a copy of the switch value is necessary because jump table destroys the input value + Variable tmp = emitMove(key); + append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind))); + } + + @Override + protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { + assert info.topFrame.getBCI() >= 0 : "invalid bci for deopt framestate"; + AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, reason, info, deoptInfo); + lir.stubs.add(stub); + return LabelRef.forLabel(stub.label); + } + + @Override + protected void emitNullCheckGuard(ValueNode object, long leafGraphId) { + Variable value = load(operand(object)); + LIRFrameState info = state(leafGraphId); + append(new NullCheckOp(value, info)); + } + + @Override + public void visitCompareAndSwap(CompareAndSwapNode node) { + Kind kind = node.newValue().kind(); + assert kind == node.expected().kind(); + + Value expected = loadNonConst(operand(node.expected())); + Variable newValue = load(operand(node.newValue())); + + Address address; + int displacement = node.displacement(); + Value index = operand(node.offset()); + if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) { + displacement += (int) asConstant(index).asLong(); + address = new Address(kind, load(operand(node.object())), displacement); + } else { + address = new Address(kind, load(operand(node.object())), load(index), Address.Scale.Times1, displacement); + } + + RegisterValue rax = AMD64.rax.asValue(kind); + emitMove(expected, rax); + append(new CompareAndSwapOp(rax, address, rax, newValue)); + + Variable result = newVariable(node.kind()); + append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE)); + setResult(node, result); + } +} diff -r 4afe23aa0a00 -r 0c6030872cd0 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Mon Oct 08 17:35:03 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.target.amd64; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.graal.phases.*; - -public class AMD64DeoptimizationStub extends AMD64Code { - - public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", Kind.Void); - public static final Descriptor SET_DEOPT_INFO = new Descriptor("setDeoptInfo", Kind.Void, Kind.Object); - - public final Label label = new Label(); - public final LIRFrameState info; - public final DeoptimizationAction action; - public final DeoptimizationReason reason; - public final Object deoptInfo; - - public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { - this.action = action; - this.reason = reason; - this.info = info; - this.deoptInfo = deoptInfo; - } - - private static ArrayList keepAlive = new ArrayList<>(); - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - // TODO (cwimmer): we want to get rid of a generally reserved scratch register. - Register scratch = tasm.frameMap.registerConfig.getScratchRegister(); - - masm.bind(label); - if (GraalOptions.CreateDeoptInfo && deoptInfo != null) { - masm.nop(); - keepAlive.add(deoptInfo.toString()); - AMD64Move.move(tasm, masm, scratch.asValue(), Constant.forObject(deoptInfo)); - // TODO Make this an explicit calling convention instead of using a scratch register - AMD64Call.directCall(tasm, masm, tasm.runtime.getRuntimeCall(SET_DEOPT_INFO), info); - } - - masm.movl(scratch, tasm.runtime.encodeDeoptActionAndReason(action, reason)); - // TODO Make this an explicit calling convention instead of using a scratch register - AMD64Call.directCall(tasm, masm, tasm.runtime.getRuntimeCall(DEOPTIMIZE), info); - AMD64Call.shouldNotReachHere(tasm, masm); - } - - @Override - public String description() { - return "deopt stub[reason=" + reason + ", action=" + action + "]"; - } -} diff -r 4afe23aa0a00 -r 0c6030872cd0 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Mon Oct 08 17:35:03 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,696 +0,0 @@ -/* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.oracle.graal.compiler.target.amd64; - -import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*; -import static com.oracle.graal.lir.amd64.AMD64Compare.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.asm.amd64.AMD64Assembler.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.JumpOp; -import com.oracle.graal.lir.StandardOp.LabelOp; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.DivOp; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Reg; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op1Stack; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Reg; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Stack; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.ShiftOp; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; -import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp; -import com.oracle.graal.lir.amd64.AMD64Compare.CompareOp; -import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp; -import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp; -import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatBranchOp; -import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatCondMoveOp; -import com.oracle.graal.lir.amd64.AMD64ControlFlow.ReturnOp; -import com.oracle.graal.lir.amd64.AMD64ControlFlow.SequentialSwitchOp; -import com.oracle.graal.lir.amd64.AMD64ControlFlow.SwitchRangesOp; -import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp; -import com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode; -import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; -import com.oracle.graal.lir.amd64.AMD64Move.LeaOp; -import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; -import com.oracle.graal.lir.amd64.AMD64Move.MembarOp; -import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp; -import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; -import com.oracle.graal.lir.amd64.AMD64Move.NullCheckOp; -import com.oracle.graal.lir.amd64.AMD64Move.SpillMoveOp; -import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.phases.util.*; - -/** - * This class implements the AMD64 specific portion of the LIR generator. - */ -public abstract class AMD64LIRGenerator extends LIRGenerator { - - public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", Kind.Float, Kind.Float, Kind.Float); - public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", Kind.Double, Kind.Double, Kind.Double); - - private static final RegisterValue RAX_I = AMD64.rax.asValue(Kind.Int); - private static final RegisterValue RAX_L = AMD64.rax.asValue(Kind.Long); - private static final RegisterValue RDX_I = AMD64.rdx.asValue(Kind.Int); - private static final RegisterValue RDX_L = AMD64.rdx.asValue(Kind.Long); - private static final RegisterValue RCX_I = AMD64.rcx.asValue(Kind.Int); - - public static class AMD64SpillMoveFactory implements LIR.SpillMoveFactory { - @Override - public LIRInstruction createMove(Value result, Value input) { - return new SpillMoveOp(result, input); - } - - @Override - public LIRInstruction createExchange(Value input1, Value input2) { - // TODO (cwimmer) implement XCHG operation for LIR - return null; - } - } - - public AMD64LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { - super(graph, runtime, target, frameMap, method, lir); - lir.spillMoveFactory = new AMD64SpillMoveFactory(); - } - - @Override - protected void emitNode(ValueNode node) { - if (node instanceof LIRGenLowerable) { - ((LIRGenLowerable) node).generate(this); - } else { - super.emitNode(node); - } - } - - @Override - public boolean canStoreConstant(Constant c) { - // there is no immediate move of 64-bit constants on Intel - switch (c.getKind()) { - case Long: return Util.isInt(c.asLong()); - case Double: return false; - case Object: return c.isNull(); - default: return true; - } - } - - @Override - public boolean canInlineConstant(Constant c) { - switch (c.getKind()) { - case Long: return NumUtil.isInt(c.asLong()); - case Object: return c.isNull(); - default: return true; - } - } - - @Override - public Address makeAddress(LocationNode location, ValueNode object) { - Value base = operand(object); - Value index = Value.IllegalValue; - int scale = 1; - int displacement = location.displacement(); - - if (isConstant(base)) { - if (asConstant(base).isNull()) { - base = Value.IllegalValue; - } else if (asConstant(base).getKind() != Kind.Object) { - long newDisplacement = displacement + asConstant(base).asLong(); - if (NumUtil.isInt(newDisplacement)) { - displacement = (int) newDisplacement; - base = Value.IllegalValue; - } - } - } - - if (location instanceof IndexedLocationNode) { - IndexedLocationNode indexedLoc = (IndexedLocationNode) location; - - index = operand(indexedLoc.index()); - if (indexedLoc.indexScalingEnabled()) { - scale = target().sizeInBytes(location.getValueKind()); - } - if (isConstant(index)) { - long newDisplacement = displacement + asConstant(index).asLong() * scale; - // only use the constant index if the resulting displacement fits into a 32 bit offset - if (NumUtil.isInt(newDisplacement)) { - displacement = (int) newDisplacement; - index = Value.IllegalValue; - } else { - // create a temporary variable for the index, the pointer load cannot handle a constant index - Value newIndex = newVariable(Kind.Long); - emitMove(index, newIndex); - index = newIndex; - } - } - } - - return new Address(location.getValueKind(), base, index, Address.Scale.fromInt(scale), displacement); - } - - @Override - public Variable emitMove(Value input) { - Variable result = newVariable(input.getKind()); - emitMove(input, result); - return result; - } - - @Override - public void emitMove(Value src, Value dst) { - if (isRegister(src) || isStackSlot(dst)) { - append(new MoveFromRegOp(dst, src)); - } else { - append(new MoveToRegOp(dst, src)); - } - } - - @Override - public Variable emitLoad(Value loadAddress, boolean canTrap) { - Variable result = newVariable(loadAddress.getKind()); - append(new LoadOp(result, loadAddress, canTrap ? state() : null)); - return result; - } - - @Override - public void emitStore(Value storeAddress, Value inputVal, boolean canTrap) { - Value input = loadForStore(inputVal, storeAddress.getKind()); - append(new StoreOp(storeAddress, input, canTrap ? state() : null)); - } - - @Override - public Variable emitLea(Value address) { - Variable result = newVariable(target().wordKind); - append(new LeaOp(result, address)); - return result; - } - - @Override - public void emitLabel(Label label, boolean align) { - append(new LabelOp(label, align)); - } - - @Override - public void emitJump(LabelRef label, LIRFrameState info) { - append(new JumpOp(label, info)); - } - - @Override - public void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) { - boolean mirrored = emitCompare(left, right); - Condition finalCondition = mirrored ? cond.mirror() : cond; - switch (left.getKind().stackKind()) { - case Int: - case Long: - case Object: append(new BranchOp(finalCondition, label, info)); break; - case Float: - case Double: append(new FloatBranchOp(finalCondition, unorderedIsTrue, label, info)); break; - default: throw GraalInternalError.shouldNotReachHere("" + left.getKind()); - } - } - - @Override - public Variable emitCMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { - boolean mirrored = emitCompare(left, right); - Condition finalCondition = mirrored ? cond.mirror() : cond; - - Variable result = newVariable(trueValue.getKind()); - switch (left.getKind().stackKind()) { - case Int: - case Long: - case Object: append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue))); break; - case Float: - case Double: append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); break; - - } - return result; - } - - /** - * This method emits the compare instruction, and may reorder the operands. It returns true if it did so. - * - * @param a the left operand of the comparison - * @param b the right operand of the comparison - * @return true if the left and right operands were switched, false otherwise - */ - private boolean emitCompare(Value a, Value b) { - Variable left; - Value right; - boolean mirrored; - if (LIRValueUtil.isVariable(b)) { - left = load(b); - right = loadNonConst(a); - mirrored = true; - } else { - left = load(a); - right = loadNonConst(b); - mirrored = false; - } - switch (left.getKind().stackKind()) { - case Jsr: - case Int: append(new CompareOp(ICMP, left, right)); break; - case Long: append(new CompareOp(LCMP, left, right)); break; - case Object: append(new CompareOp(ACMP, left, right)); break; - case Float: append(new CompareOp(FCMP, left, right)); break; - case Double: append(new CompareOp(DCMP, left, right)); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - return mirrored; - } - - @Override - public Variable emitNegate(Value input) { - Variable result = newVariable(input.getKind()); - switch (input.getKind()) { - case Int: append(new Op1Stack(INEG, result, input)); break; - case Long: append(new Op1Stack(LNEG, result, input)); break; - case Float: append(new Op2Reg(FXOR, result, input, Constant.forFloat(Float.intBitsToFloat(0x80000000)))); break; - case Double: append(new Op2Reg(DXOR, result, input, Constant.forDouble(Double.longBitsToDouble(0x8000000000000000L)))); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - return result; - } - - @Override - public Variable emitAdd(Value a, Value b) { - Variable result = newVariable(a.getKind()); - switch(a.getKind()) { - case Int: append(new Op2Stack(IADD, result, a, loadNonConst(b))); break; - case Long: append(new Op2Stack(LADD, result, a, loadNonConst(b))); break; - case Float: append(new Op2Stack(FADD, result, a, loadNonConst(b))); break; - case Double: append(new Op2Stack(DADD, result, a, loadNonConst(b))); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - return result; - } - - @Override - public Variable emitSub(Value a, Value b) { - Variable result = newVariable(a.getKind()); - switch(a.getKind()) { - case Int: append(new Op2Stack(ISUB, result, a, loadNonConst(b))); break; - case Long: append(new Op2Stack(LSUB, result, a, loadNonConst(b))); break; - case Float: append(new Op2Stack(FSUB, result, a, loadNonConst(b))); break; - case Double: append(new Op2Stack(DSUB, result, a, loadNonConst(b))); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - return result; - } - - @Override - public Variable emitMul(Value a, Value b) { - Variable result = newVariable(a.getKind()); - switch(a.getKind()) { - case Int: append(new Op2Reg(IMUL, result, a, loadNonConst(b))); break; - case Long: append(new Op2Reg(LMUL, result, a, loadNonConst(b))); break; - case Float: append(new Op2Stack(FMUL, result, a, loadNonConst(b))); break; - case Double: append(new Op2Stack(DMUL, result, a, loadNonConst(b))); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - return result; - } - - @Override - public Variable emitDiv(Value a, Value b) { - switch(a.getKind()) { - case Int: - emitMove(a, RAX_I); - append(new DivOp(IDIV, RAX_I, RAX_I, load(b), state())); - return emitMove(RAX_I); - case Long: - emitMove(a, RAX_L); - append(new DivOp(LDIV, RAX_L, RAX_L, load(b), state())); - return emitMove(RAX_L); - case Float: { - Variable result = newVariable(a.getKind()); - append(new Op2Stack(FDIV, result, a, loadNonConst(b))); - return result; - } - case Double: { - Variable result = newVariable(a.getKind()); - append(new Op2Stack(DDIV, result, a, loadNonConst(b))); - return result; - } - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - @Override - public Value emitRem(Value a, Value b) { - switch(a.getKind()) { - case Int: - emitMove(a, RAX_I); - append(new DivOp(IREM, RDX_I, RAX_I, load(b), state())); - return emitMove(RDX_I); - case Long: - emitMove(a, RAX_L); - append(new DivOp(LREM, RDX_L, RAX_L, load(b), state())); - return emitMove(RDX_L); - case Float: { - RuntimeCall stub = runtime.getRuntimeCall(ARITHMETIC_FREM); - return emitCall(stub, stub.getCallingConvention(), false, a, b); - } - case Double: { - RuntimeCall stub = runtime.getRuntimeCall(ARITHMETIC_DREM); - return emitCall(stub, stub.getCallingConvention(), false, a, b); - } - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - @Override - public Variable emitUDiv(Value a, Value b) { - switch(a.getKind()) { - case Int: - emitMove(a, RAX_I); - append(new DivOp(IUDIV, RAX_I, RAX_I, load(b), state())); - return emitMove(RAX_I); - case Long: - emitMove(a, RAX_L); - append(new DivOp(LUDIV, RAX_L, RAX_L, load(b), state())); - return emitMove(RAX_L); - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - @Override - public Variable emitURem(Value a, Value b) { - switch(a.getKind()) { - case Int: - emitMove(a, RAX_I); - append(new DivOp(IUREM, RDX_I, RAX_I, load(b), state())); - return emitMove(RDX_I); - case Long: - emitMove(a, RAX_L); - append(new DivOp(LUREM, RDX_L, RAX_L, load(b), state())); - return emitMove(RDX_L); - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - - @Override - public Variable emitAnd(Value a, Value b) { - Variable result = newVariable(a.getKind()); - switch(a.getKind()) { - case Int: append(new Op2Stack(IAND, result, a, loadNonConst(b))); break; - case Long: append(new Op2Stack(LAND, result, a, loadNonConst(b))); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - return result; - } - - @Override - public Variable emitOr(Value a, Value b) { - Variable result = newVariable(a.getKind()); - switch(a.getKind()) { - case Int: append(new Op2Stack(IOR, result, a, loadNonConst(b))); break; - case Long: append(new Op2Stack(LOR, result, a, loadNonConst(b))); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - return result; - } - - @Override - public Variable emitXor(Value a, Value b) { - Variable result = newVariable(a.getKind()); - switch(a.getKind()) { - case Int: append(new Op2Stack(IXOR, result, a, loadNonConst(b))); break; - case Long: append(new Op2Stack(LXOR, result, a, loadNonConst(b))); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - return result; - } - - - @Override - public Variable emitShl(Value a, Value b) { - Variable result = newVariable(a.getKind()); - switch (a.getKind()) { - case Int: append(new ShiftOp(ISHL, result, a, loadShiftCount(b))); break; - case Long: append(new ShiftOp(LSHL, result, a, loadShiftCount(b))); break; - default: GraalInternalError.shouldNotReachHere(); - } - return result; - } - - @Override - public Variable emitShr(Value a, Value b) { - Variable result = newVariable(a.getKind()); - switch (a.getKind()) { - case Int: append(new ShiftOp(ISHR, result, a, loadShiftCount(b))); break; - case Long: append(new ShiftOp(LSHR, result, a, loadShiftCount(b))); break; - default: GraalInternalError.shouldNotReachHere(); - } - return result; - } - - @Override - public Variable emitUShr(Value a, Value b) { - Variable result = newVariable(a.getKind()); - switch (a.getKind()) { - case Int: append(new ShiftOp(IUSHR, result, a, loadShiftCount(b))); break; - case Long: append(new ShiftOp(LUSHR, result, a, loadShiftCount(b))); break; - default: GraalInternalError.shouldNotReachHere(); - } - return result; - } - - private Value loadShiftCount(Value value) { - if (isConstant(value)) { - return value; - } - // Non-constant shift count must be in RCX - emitMove(value, RCX_I); - return RCX_I; - } - - - @Override - public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) { - Variable input = load(inputVal); - Variable result = newVariable(opcode.to); - switch (opcode) { - case I2L: append(new Op1Reg(I2L, result, input)); break; - case L2I: append(new Op1Stack(L2I, result, input)); break; - case I2B: append(new Op1Stack(I2B, result, input)); break; - case I2C: append(new Op1Stack(I2C, result, input)); break; - case I2S: append(new Op1Stack(I2S, result, input)); break; - case F2D: append(new Op1Reg(F2D, result, input)); break; - case D2F: append(new Op1Reg(D2F, result, input)); break; - case I2F: append(new Op1Reg(I2F, result, input)); break; - case I2D: append(new Op1Reg(I2D, result, input)); break; - case F2I: append(new Op1Reg(F2I, result, input)); break; - case D2I: append(new Op1Reg(D2I, result, input)); break; - case L2F: append(new Op1Reg(L2F, result, input)); break; - case L2D: append(new Op1Reg(L2D, result, input)); break; - case F2L: append(new Op1Reg(F2L, result, input)); break; - case D2L: append(new Op1Reg(D2L, result, input)); break; - case MOV_I2F: append(new Op1Reg(MOV_I2F, result, input)); break; - case MOV_L2D: append(new Op1Reg(MOV_L2D, result, input)); break; - case MOV_F2I: append(new Op1Reg(MOV_F2I, result, input)); break; - case MOV_D2L: append(new Op1Reg(MOV_D2L, result, input)); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - return result; - } - - - @Override - public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { - LIRFrameState info = state(); - LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo); - append(new BranchOp(ConditionFlag.overflow, stubEntry, info)); - } - - - @Override - public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo, long leafGraphId) { - LIRFrameState info = state(leafGraphId); - LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo); - append(new JumpOp(stubEntry, info)); - } - - @Override - public void emitMembar(int barriers) { - int necessaryBarriers = target.arch.requiredBarriers(barriers); - if (target.isMP && necessaryBarriers != 0) { - append(new MembarOp(necessaryBarriers)); - } - } - - @Override - protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - append(new DirectCallOp(callTarget.target(), result, parameters, temps, callState)); - } - - @Override - protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - // The current register allocator cannot handle variables at call sites, need a fixed register. - Value targetAddress = AMD64.rax.asValue(); - emitMove(operand(callTarget.computedAddress()), targetAddress); - append(new IndirectCallOp(callTarget.target(), result, parameters, temps, targetAddress, callState)); - } - - @Override - protected void emitCall(Object targetMethod, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info) { - if (isConstant(targetAddress)) { - append(new DirectCallOp(targetMethod, result, arguments, temps, info)); - } else { - append(new IndirectCallOp(targetMethod, result, arguments, temps, targetAddress, info)); - } - } - - @Override - public void emitBitScanForward(Variable result, Value value) { - append(new AMD64BitScanOp(AMD64BitScanOp.IntrinsicOpcode.BSF, result, value)); - } - - @Override - public void emitBitScanReverse(Variable result, Value value) { - if (value.getKind().isStackInt()) { - append(new AMD64BitScanOp(AMD64BitScanOp.IntrinsicOpcode.IBSR, result, value)); - } else { - append(new AMD64BitScanOp(AMD64BitScanOp.IntrinsicOpcode.LBSR, result, value)); - } - } - - @Override - public void emitMathAbs(Variable result, Variable input) { - append(new Op2Reg(DAND, result, input, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); - } - - @Override - public void emitMathSqrt(Variable result, Variable input) { - append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SQRT, result, input)); - } - - @Override - public void emitMathLog(Variable result, Variable input, boolean base10) { - IntrinsicOpcode opcode = base10 ? AMD64MathIntrinsicOp.IntrinsicOpcode.LOG10 : AMD64MathIntrinsicOp.IntrinsicOpcode.LOG; - append(new AMD64MathIntrinsicOp(opcode, result, input)); - } - - @Override - public void emitMathCos(Variable result, Variable input) { - append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.COS, result, input)); - } - - @Override - public void emitMathSin(Variable result, Variable input) { - append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SIN, result, input)); - } - - @Override - public void emitMathTan(Variable result, Variable input) { - append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.TAN, result, input)); - } - - @Override - public void emitByteSwap(Variable result, Value input) { - append(new AMD64ByteSwapOp(result, input)); - } - - @Override - protected void emitReturn(Value input) { - append(new ReturnOp(input)); - } - - @Override - protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) { - // Making a copy of the switch value is necessary because jump table destroys the input value - if (key.getKind() == Kind.Int) { - append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.IllegalValue)); - } else { - assert key.getKind() == Kind.Object; - append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object))); - } - } - - @Override - protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) { - append(new SwitchRangesOp(lowKeys, highKeys, targets, defaultTarget, key)); - } - - @Override - protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { - // Making a copy of the switch value is necessary because jump table destroys the input value - Variable tmp = emitMove(key); - append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind))); - } - - @Override - protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { - assert info.topFrame.getBCI() >= 0 : "invalid bci for deopt framestate"; - AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, reason, info, deoptInfo); - lir.stubs.add(stub); - return LabelRef.forLabel(stub.label); - } - - @Override - protected void emitNullCheckGuard(ValueNode object, long leafGraphId) { - Variable value = load(operand(object)); - LIRFrameState info = state(leafGraphId); - append(new NullCheckOp(value, info)); - } - - @Override - public void visitCompareAndSwap(CompareAndSwapNode node) { - Kind kind = node.newValue().kind(); - assert kind == node.expected().kind(); - - Value expected = loadNonConst(operand(node.expected())); - Variable newValue = load(operand(node.newValue())); - - Address address; - int displacement = node.displacement(); - Value index = operand(node.offset()); - if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) { - displacement += (int) asConstant(index).asLong(); - address = new Address(kind, load(operand(node.object())), displacement); - } else { - address = new Address(kind, load(operand(node.object())), load(index), Address.Scale.Times1, displacement); - } - - RegisterValue rax = AMD64.rax.asValue(kind); - emitMove(expected, rax); - append(new CompareAndSwapOp(rax, address, rax, newValue)); - - Variable result = newVariable(node.kind()); - append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE)); - setResult(node, result); - } -} diff -r 4afe23aa0a00 -r 0c6030872cd0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Oct 08 17:35:03 2012 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Oct 08 17:36:51 2012 +0200 @@ -33,8 +33,8 @@ import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.asm.amd64.AMD64Assembler.*; +import com.oracle.graal.compiler.amd64.*; import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.amd64.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; diff -r 4afe23aa0a00 -r 0c6030872cd0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Mon Oct 08 17:35:03 2012 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Mon Oct 08 17:36:51 2012 +0200 @@ -23,8 +23,8 @@ package com.oracle.graal.hotspot.amd64; import static com.oracle.graal.asm.amd64.AMD64.*; -import static com.oracle.graal.compiler.target.amd64.AMD64DeoptimizationStub.*; -import static com.oracle.graal.compiler.target.amd64.AMD64LIRGenerator.*; +import static com.oracle.graal.compiler.amd64.AMD64DeoptimizationStub.*; +import static com.oracle.graal.compiler.amd64.AMD64LIRGenerator.*; import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*; import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*; import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;