# HG changeset patch # User Doug Simon # Date 1349275791 -7200 # Node ID 16d1411409b46bdbcb0171aa69cc9830e44cb0de # Parent 75f130f2b30f26d497609606eba9ed3d584593b0 moved AMD64 specific code into com.oracle.graal.compiler.amd64 diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/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/target/amd64/AMD64DeoptimizationStub.java Wed Oct 03 16:49:51 2012 +0200 @@ -0,0 +1,76 @@ +/* + * 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.meta.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.*; +import com.oracle.max.asm.amd64.*; + +public class AMD64DeoptimizationStub extends AMD64Code { + 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, RuntimeCall.SetDeoptInfo, 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, RuntimeCall.Deoptimize, info); + AMD64Call.shouldNotReachHere(tasm, masm); + } + + @Override + public String description() { + return "deopt stub[reason=" + reason + ", action=" + action + "]"; + } +} diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/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/target/amd64/AMD64LIRGenerator.java Wed Oct 03 16:49:51 2012 +0200 @@ -0,0 +1,688 @@ +/* + * 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.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.util.*; +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.max.asm.*; +import com.oracle.max.asm.amd64.*; +import com.oracle.max.asm.amd64.AMD64Assembler.ConditionFlag; + +/** + * This class implements the AMD64 specific portion of the LIR generator. + */ +public abstract class AMD64LIRGenerator extends LIRGenerator { + + 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: + return emitCall(RuntimeCall.ArithmeticFrem, false, a, b); + case Double: + return emitCall(RuntimeCall.ArithmeticDrem, 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 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Oct 03 01:18:03 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Oct 03 16:49:51 2012 +0200 @@ -980,4 +980,15 @@ public FrameMap frameMap() { return frameMap; } + + public abstract void emitBitScanForward(Variable result, Value operand); + public abstract void emitBitScanReverse(Variable result, Value operand); + + public abstract void emitMathAbs(Variable result, Variable input); + public abstract void emitMathSqrt(Variable result, Variable input); + public abstract void emitMathLog(Variable result, Variable input, boolean base10); + public abstract void emitMathCos(Variable result, Variable input); + public abstract void emitMathSin(Variable result, Variable input); + public abstract void emitMathTan(Variable result, Variable input); + public abstract void emitByteSwap(Variable result, Value operand); } diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Wed Oct 03 01:18:03 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +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.meta.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.max.asm.*; -import com.oracle.max.asm.amd64.*; - -public class AMD64DeoptimizationStub extends AMD64Code { - 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, RuntimeCall.SetDeoptInfo, 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, RuntimeCall.Deoptimize, info); - AMD64Call.shouldNotReachHere(tasm, masm); - } - - @Override - public String description() { - return "deopt stub[reason=" + reason + ", action=" + action + "]"; - } -} diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Wed Oct 03 01:18:03 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,636 +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.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.compiler.util.*; -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.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.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.max.asm.*; -import com.oracle.max.asm.amd64.*; -import com.oracle.max.asm.amd64.AMD64Assembler.*; - -/** - * This class implements the X86-specific portion of the LIR generator. - */ -public abstract class AMD64LIRGenerator extends LIRGenerator { - - 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: - return emitCall(RuntimeCall.ArithmeticFrem, false, a, b); - case Double: - return emitCall(RuntimeCall.ArithmeticDrem, 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 - 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 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitScanOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitScanOp.java Wed Oct 03 16:49:51 2012 +0200 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2012, 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.lir.amd64; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.amd64.*; + + +public class AMD64BitScanOp extends AMD64LIRInstruction { + public enum IntrinsicOpcode { + IBSR, LBSR, + BSF; + } + + @Opcode private final IntrinsicOpcode opcode; + @Def protected Value result; + @Use({OperandFlag.REG, OperandFlag.ADDR}) protected Value input; + + public AMD64BitScanOp(IntrinsicOpcode opcode, Value result, Value input) { + this.opcode = opcode; + this.result = result; + this.input = input; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + Register dst = ValueUtil.asIntReg(result); + if (ValueUtil.isAddress(input)) { + Address src = ValueUtil.asAddress(input); + switch(opcode) { + case BSF: + masm.bsfq(dst, src); + break; + case IBSR: + masm.bsrl(dst, src); + break; + case LBSR: + masm.bsrq(dst, src); + break; + } + } else { + Register src = ValueUtil.asRegister(input); + switch(opcode) { + case BSF: + masm.bsfq(dst, src); + break; + case IBSR: + masm.bsrl(dst, src); + break; + case LBSR: + masm.bsrq(dst, src); + break; + } + } + } + +} diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ByteSwapOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ByteSwapOp.java Wed Oct 03 16:49:51 2012 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012, 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.lir.amd64; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.amd64.*; + +@Opcode("BSWAP") +public class AMD64ByteSwapOp extends AMD64LIRInstruction { + @Def({OperandFlag.REG, OperandFlag.HINT}) protected Value result; + @Use protected Value input; + + public AMD64ByteSwapOp(Value result, Value input) { + this.result = result; + this.input = input; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + AMD64Move.move(tasm, masm, result, input); + switch(input.getKind()) { + case Int: + masm.bswapl(ValueUtil.asIntReg(result)); + break; + case Long: + masm.bswapq(ValueUtil.asLongReg(result)); + } + } +} diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64MathIntrinsicOp.java Wed Oct 03 16:49:51 2012 +0200 @@ -0,0 +1,61 @@ +/* + * 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.lir.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.amd64.*; + +public class AMD64MathIntrinsicOp extends AMD64LIRInstruction { + public enum IntrinsicOpcode { + SQRT, + SIN, COS, TAN, + LOG, LOG10; + } + + @Opcode private final IntrinsicOpcode opcode; + @Def protected Value result; + @Use protected Value input; + + public AMD64MathIntrinsicOp(IntrinsicOpcode opcode, Value result, Value input) { + this.opcode = opcode; + this.result = result; + this.input = input; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + switch (opcode) { + case SQRT: masm.sqrtsd(asDoubleReg(result), asDoubleReg(input)); break; + case LOG: masm.flog(asDoubleReg(result), asDoubleReg(input), false); break; + case LOG10: masm.flog(asDoubleReg(result), asDoubleReg(input), true); break; + case SIN: masm.fsin(asDoubleReg(result), asDoubleReg(input)); break; + case COS: masm.fcos(asDoubleReg(result), asDoubleReg(input)); break; + case TAN: masm.ftan(asDoubleReg(result), asDoubleReg(input)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } +} diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Wed Oct 03 01:18:03 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Wed Oct 03 16:49:51 2012 +0200 @@ -330,7 +330,7 @@ Node curStampNode = null; for (Node node : snippetCopy.getNodes()) { if (node instanceof ValueNode && ((ValueNode) node).stamp() == StampFactory.forNodeIntrinsic()) { - assert curStampNode == null : "Currently limited to stamp node (but this can be converted to a List if necessary)"; + assert curStampNode == null : "Currently limited to one stamp node (but this can be converted to a List if necessary)"; curStampNode = node; } if (node instanceof StateSplit) { diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/BitScanForwardNode.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/BitScanForwardNode.java Wed Oct 03 01:18:03 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/BitScanForwardNode.java Wed Oct 03 16:49:51 2012 +0200 @@ -30,8 +30,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.target.amd64.*; -import com.oracle.graal.snippets.target.amd64.AMD64BitScanOp.IntrinsicOpcode; public class BitScanForwardNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { @@ -61,7 +59,7 @@ @Override public void generate(LIRGenerator gen) { Variable result = gen.newVariable(Kind.Int); - gen.append(new AMD64BitScanOp(IntrinsicOpcode.BSF, result, gen.operand(value))); + gen.emitBitScanForward(result, gen.operand(value)); gen.setResult(this, result); } } diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/BitScanReverseNode.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/BitScanReverseNode.java Wed Oct 03 01:18:03 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/BitScanReverseNode.java Wed Oct 03 16:49:51 2012 +0200 @@ -25,14 +25,11 @@ import com.oracle.graal.api.meta.*; 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.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.target.amd64.*; -import com.oracle.graal.snippets.target.amd64.AMD64BitScanOp.IntrinsicOpcode; public class BitScanReverseNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { @@ -65,15 +62,7 @@ @Override public void generate(LIRGenerator gen) { Variable result = gen.newVariable(Kind.Int); - IntrinsicOpcode opcode; - if (value.kind().isStackInt()) { - opcode = IntrinsicOpcode.IBSR; - } else if (value.kind().isLong()) { - opcode = IntrinsicOpcode.LBSR; - } else { - throw GraalInternalError.shouldNotReachHere(); - } - gen.append(new AMD64BitScanOp(opcode, result, gen.operand(value))); + gen.emitBitScanReverse(result, gen.operand(value)); gen.setResult(this, result); } diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java Wed Oct 03 01:18:03 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java Wed Oct 03 16:49:51 2012 +0200 @@ -22,19 +22,15 @@ */ package com.oracle.graal.snippets.nodes; -import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*; - import com.oracle.graal.api.meta.*; 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.amd64.AMD64Arithmetic.Op2Reg; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.target.amd64.*; public class MathIntrinsicNode extends FloatingNode implements Canonicalizable, LIRGenLowerable { @@ -65,13 +61,13 @@ Variable input = gen.load(gen.operand(x())); Variable result = gen.newVariable(kind()); switch (operation()) { - case ABS: gen.append(new Op2Reg(DAND, result, input, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); break; - case SQRT: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SQRT, result, input)); break; - case LOG: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.LOG, result, input)); break; - case LOG10: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.LOG10, result, input)); break; - case SIN: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SIN, result, input)); break; - case COS: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.COS, result, input)); break; - case TAN: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.TAN, result, input)); break; + case ABS: gen.emitMathAbs(result, input); break; + case SQRT: gen.emitMathSqrt(result, input); break; + case LOG: gen.emitMathLog(result, input, false); break; + case LOG10: gen.emitMathLog(result, input, true); break; + case SIN: gen.emitMathSin(result, input); break; + case COS: gen.emitMathCos(result, input); break; + case TAN: gen.emitMathTan(result, input); break; default: throw GraalInternalError.shouldNotReachHere(); } gen.setResult(this, result); diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/ReverseBytesNode.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/ReverseBytesNode.java Wed Oct 03 01:18:03 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/ReverseBytesNode.java Wed Oct 03 16:49:51 2012 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.snippets.target.amd64.*; public class ReverseBytesNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { @@ -63,7 +62,7 @@ @Override public void generate(LIRGenerator gen) { Variable result = gen.newVariable(value.kind()); - gen.append(new AMD64ByteSwapOp(result, gen.operand(value))); + gen.emitByteSwap(result, gen.operand(value)); gen.setResult(this, result); } } diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64BitScanOp.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64BitScanOp.java Wed Oct 03 01:18:03 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2012, 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.snippets.target.amd64; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.max.asm.amd64.*; - - -public class AMD64BitScanOp extends AMD64LIRInstruction { - public enum IntrinsicOpcode { - IBSR, LBSR, - BSF; - } - - @Opcode private final IntrinsicOpcode opcode; - @Def protected Value result; - @Use({OperandFlag.REG, OperandFlag.ADDR}) protected Value input; - - public AMD64BitScanOp(IntrinsicOpcode opcode, Value result, Value input) { - this.opcode = opcode; - this.result = result; - this.input = input; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Register dst = ValueUtil.asIntReg(result); - if (ValueUtil.isAddress(input)) { - Address src = ValueUtil.asAddress(input); - switch(opcode) { - case BSF: - masm.bsfq(dst, src); - break; - case IBSR: - masm.bsrl(dst, src); - break; - case LBSR: - masm.bsrq(dst, src); - break; - } - } else { - Register src = ValueUtil.asRegister(input); - switch(opcode) { - case BSF: - masm.bsfq(dst, src); - break; - case IBSR: - masm.bsrl(dst, src); - break; - case LBSR: - masm.bsrq(dst, src); - break; - } - } - } - -} diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64ByteSwapOp.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64ByteSwapOp.java Wed Oct 03 01:18:03 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2012, 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.snippets.target.amd64; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.LIRInstruction.*; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.max.asm.amd64.*; - -@Opcode("BSWAP") -public class AMD64ByteSwapOp extends AMD64LIRInstruction { - @Def({OperandFlag.REG, OperandFlag.HINT}) protected Value result; - @Use protected Value input; - - public AMD64ByteSwapOp(Value result, Value input) { - this.result = result; - this.input = input; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - AMD64Move.move(tasm, masm, result, input); - switch(input.getKind()) { - case Int: - masm.bswapl(ValueUtil.asIntReg(result)); - break; - case Long: - masm.bswapq(ValueUtil.asLongReg(result)); - } - } -} diff -r 75f130f2b30f -r 16d1411409b4 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java Wed Oct 03 01:18:03 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +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.snippets.target.amd64; - -import static com.oracle.graal.api.code.ValueUtil.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.max.asm.amd64.*; - -public class AMD64MathIntrinsicOp extends AMD64LIRInstruction { - public enum IntrinsicOpcode { - SQRT, - SIN, COS, TAN, - LOG, LOG10; - } - - @Opcode private final IntrinsicOpcode opcode; - @Def protected Value result; - @Use protected Value input; - - public AMD64MathIntrinsicOp(IntrinsicOpcode opcode, Value result, Value input) { - this.opcode = opcode; - this.result = result; - this.input = input; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - switch (opcode) { - case SQRT: masm.sqrtsd(asDoubleReg(result), asDoubleReg(input)); break; - case LOG: masm.flog(asDoubleReg(result), asDoubleReg(input), false); break; - case LOG10: masm.flog(asDoubleReg(result), asDoubleReg(input), true); break; - case SIN: masm.fsin(asDoubleReg(result), asDoubleReg(input)); break; - case COS: masm.fcos(asDoubleReg(result), asDoubleReg(input)); break; - case TAN: masm.ftan(asDoubleReg(result), asDoubleReg(input)); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - } -} diff -r 75f130f2b30f -r 16d1411409b4 mx/projects --- a/mx/projects Wed Oct 03 01:18:03 2012 +0200 +++ b/mx/projects Wed Oct 03 16:49:51 2012 +0200 @@ -65,7 +65,7 @@ # graal.hotspot.amd64 project@com.oracle.graal.hotspot.amd64@subDir=graal project@com.oracle.graal.hotspot.amd64@sourceDirs=src -project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.hotspot +project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.hotspot,com.oracle.graal.compiler.amd64 project@com.oracle.graal.hotspot.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspot.amd64@javaCompliance=1.7 @@ -168,10 +168,17 @@ # graal.compiler project@com.oracle.graal.compiler@subDir=graal project@com.oracle.graal.compiler@sourceDirs=src -project@com.oracle.graal.compiler@dependencies=com.oracle.graal.compiler.virtual,com.oracle.graal.compiler.loop,com.oracle.graal.alloc,com.oracle.graal.lir.amd64 +project@com.oracle.graal.compiler@dependencies=com.oracle.graal.compiler.virtual,com.oracle.graal.compiler.loop,com.oracle.graal.alloc project@com.oracle.graal.compiler@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler@javaCompliance=1.7 +# graal.compiler.amd64 +project@com.oracle.graal.compiler.amd64@subDir=graal +project@com.oracle.graal.compiler.amd64@sourceDirs=src +project@com.oracle.graal.compiler.amd64@dependencies=com.oracle.graal.compiler,com.oracle.graal.lir.amd64 +project@com.oracle.graal.compiler.amd64@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.compiler.amd64@javaCompliance=1.7 + # graal.boot project@com.oracle.graal.boot@subDir=graal project@com.oracle.graal.boot@sourceDirs=src diff -r 75f130f2b30f -r 16d1411409b4 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Wed Oct 03 01:18:03 2012 +0200 +++ b/src/share/vm/runtime/arguments.cpp Wed Oct 03 16:49:51 2012 +0200 @@ -2150,6 +2150,7 @@ #ifdef AMD64 "com.oracle.max.asm.amd64", "com.oracle.graal.lir.amd64", + "com.oracle.graal.compiler.amd64", "com.oracle.graal.hotspot.amd64", #endif "com.oracle.graal.api",