changeset 22788:26bbed810326

Split ArithmeticLIRGenerator and LIRGenerator code to allow independent subclasses
author Christian Wimmer <christian.wimmer@oracle.com>
date Thu, 08 Oct 2015 15:58:13 -0700
parents a9363c9d0f58
children a9e0431279e5
files graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64ArithmeticLIRGenerator.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeMatchRules.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCArithmeticLIRGenerator.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeMatchRules.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArithmeticLIRGenerator.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArithmeticLIRGeneratorTool.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGeneratorTool.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathIntrinsicNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerAddExactSplitNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerMulExactSplitNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerMulHighNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerSubExactSplitNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/UnsignedMulHighNode.java
diffstat 56 files changed, 1988 insertions(+), 1796 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64ArithmeticLIRGenerator.java	Thu Oct 08 15:58:13 2015 -0700
@@ -0,0 +1,896 @@
+/*
+ * Copyright (c) 2009, 2015, 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.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.ADD;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.AND;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.OR;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.SUB;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.XOR;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MOp.NEG;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MOp.NOT;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.BSF;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.BSR;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.LZCNT;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOV;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSX;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXB;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXD;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVZX;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVZXB;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.POPCNT;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.TZCNT;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift.ROL;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift.ROR;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift.SAR;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift.SHL;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift.SHR;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.DWORD;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.PD;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.PS;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.QWORD;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.SD;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.SS;
+import static com.oracle.graal.lir.LIRValueUtil.asConstantValue;
+import static com.oracle.graal.lir.LIRValueUtil.asJavaConstant;
+import static com.oracle.graal.lir.LIRValueUtil.isJavaConstant;
+import static com.oracle.graal.lir.amd64.AMD64Arithmetic.DREM;
+import static com.oracle.graal.lir.amd64.AMD64Arithmetic.FREM;
+import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.COS;
+import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.LOG;
+import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.LOG10;
+import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.SIN;
+import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.TAN;
+import jdk.internal.jvmci.amd64.AMD64;
+import jdk.internal.jvmci.amd64.AMD64Kind;
+import jdk.internal.jvmci.code.CodeUtil;
+import jdk.internal.jvmci.code.Register;
+import jdk.internal.jvmci.code.RegisterValue;
+import jdk.internal.jvmci.common.JVMCIError;
+import jdk.internal.jvmci.meta.AllocatableValue;
+import jdk.internal.jvmci.meta.JavaConstant;
+import jdk.internal.jvmci.meta.LIRKind;
+import jdk.internal.jvmci.meta.PlatformKind;
+import jdk.internal.jvmci.meta.Value;
+
+import com.oracle.graal.asm.NumUtil;
+import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
+import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MOp;
+import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MROp;
+import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMIOp;
+import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp;
+import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift;
+import com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize;
+import com.oracle.graal.asm.amd64.AMD64Assembler.SSEOp;
+import com.oracle.graal.compiler.common.calc.FloatConvert;
+import com.oracle.graal.lir.ConstantValue;
+import com.oracle.graal.lir.LIRFrameState;
+import com.oracle.graal.lir.Variable;
+import com.oracle.graal.lir.amd64.AMD64AddressValue;
+import com.oracle.graal.lir.amd64.AMD64Arithmetic.FPDivRemOp;
+import com.oracle.graal.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
+import com.oracle.graal.lir.amd64.AMD64Binary;
+import com.oracle.graal.lir.amd64.AMD64ClearRegisterOp;
+import com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp;
+import com.oracle.graal.lir.amd64.AMD64MulDivOp;
+import com.oracle.graal.lir.amd64.AMD64ShiftOp;
+import com.oracle.graal.lir.amd64.AMD64SignExtendOp;
+import com.oracle.graal.lir.amd64.AMD64Unary;
+import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+
+/**
+ * This class implements the AMD64 specific portion of the LIR generator.
+ */
+public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implements AMD64ArithmeticLIRGeneratorTool {
+
+    private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(AMD64Kind.DWORD));
+
+    @Override
+    public Variable emitNegate(Value inputVal) {
+        AllocatableValue input = getLIRGen().asAllocatable(inputVal);
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        switch ((AMD64Kind) input.getPlatformKind()) {
+            case DWORD:
+                getLIRGen().append(new AMD64Unary.MOp(NEG, DWORD, result, input));
+                break;
+            case QWORD:
+                getLIRGen().append(new AMD64Unary.MOp(NEG, QWORD, result, input));
+                break;
+            case SINGLE:
+                getLIRGen().append(new AMD64Binary.DataOp(SSEOp.XOR, PS, result, input, JavaConstant.forFloat(Float.intBitsToFloat(0x80000000)), 16));
+                break;
+            case DOUBLE:
+                getLIRGen().append(new AMD64Binary.DataOp(SSEOp.XOR, PD, result, input, JavaConstant.forDouble(Double.longBitsToDouble(0x8000000000000000L)), 16));
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    @Override
+    public Variable emitNot(Value inputVal) {
+        AllocatableValue input = getLIRGen().asAllocatable(inputVal);
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        switch ((AMD64Kind) input.getPlatformKind()) {
+            case DWORD:
+                getLIRGen().append(new AMD64Unary.MOp(NOT, DWORD, result, input));
+                break;
+            case QWORD:
+                getLIRGen().append(new AMD64Unary.MOp(NOT, QWORD, result, input));
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    private Variable emitBinary(LIRKind resultKind, AMD64BinaryArithmetic op, OperandSize size, boolean commutative, Value a, Value b, boolean setFlags) {
+        if (isJavaConstant(b)) {
+            return emitBinaryConst(resultKind, op, size, commutative, getLIRGen().asAllocatable(a), asConstantValue(b), setFlags);
+        } else if (commutative && isJavaConstant(a)) {
+            return emitBinaryConst(resultKind, op, size, commutative, getLIRGen().asAllocatable(b), asConstantValue(a), setFlags);
+        } else {
+            return emitBinaryVar(resultKind, op.getRMOpcode(size), size, commutative, getLIRGen().asAllocatable(a), getLIRGen().asAllocatable(b));
+        }
+    }
+
+    private Variable emitBinary(LIRKind resultKind, AMD64RMOp op, OperandSize size, boolean commutative, Value a, Value b) {
+        if (isJavaConstant(b)) {
+            return emitBinaryConst(resultKind, op, size, getLIRGen().asAllocatable(a), asJavaConstant(b));
+        } else if (commutative && isJavaConstant(a)) {
+            return emitBinaryConst(resultKind, op, size, getLIRGen().asAllocatable(b), asJavaConstant(a));
+        } else {
+            return emitBinaryVar(resultKind, op, size, commutative, getLIRGen().asAllocatable(a), getLIRGen().asAllocatable(b));
+        }
+    }
+
+    private Variable emitBinaryConst(LIRKind resultKind, AMD64BinaryArithmetic op, OperandSize size, boolean commutative, AllocatableValue a, ConstantValue b, boolean setFlags) {
+        long value = b.getJavaConstant().asLong();
+        if (NumUtil.isInt(value)) {
+            Variable result = getLIRGen().newVariable(resultKind);
+            int constant = (int) value;
+
+            if (!setFlags) {
+                AMD64MOp mop = getMOp(op, constant);
+                if (mop != null) {
+                    getLIRGen().append(new AMD64Unary.MOp(mop, size, result, a));
+                    return result;
+                }
+            }
+
+            getLIRGen().append(new AMD64Binary.ConstOp(op, size, result, a, constant));
+            return result;
+        } else {
+            return emitBinaryVar(resultKind, op.getRMOpcode(size), size, commutative, a, getLIRGen().asAllocatable(b));
+        }
+    }
+
+    private static AMD64MOp getMOp(AMD64BinaryArithmetic op, int constant) {
+        if (constant == 1) {
+            if (op.equals(AMD64BinaryArithmetic.ADD)) {
+                return AMD64MOp.INC;
+            }
+            if (op.equals(AMD64BinaryArithmetic.SUB)) {
+                return AMD64MOp.DEC;
+            }
+        } else if (constant == -1) {
+            if (op.equals(AMD64BinaryArithmetic.ADD)) {
+                return AMD64MOp.DEC;
+            }
+            if (op.equals(AMD64BinaryArithmetic.SUB)) {
+                return AMD64MOp.INC;
+            }
+        }
+        return null;
+    }
+
+    private Variable emitBinaryConst(LIRKind resultKind, AMD64RMOp op, OperandSize size, AllocatableValue a, JavaConstant b) {
+        Variable result = getLIRGen().newVariable(resultKind);
+        getLIRGen().append(new AMD64Binary.DataOp(op, size, result, a, b));
+        return result;
+    }
+
+    private Variable emitBinaryVar(LIRKind resultKind, AMD64RMOp op, OperandSize size, boolean commutative, AllocatableValue a, AllocatableValue b) {
+        Variable result = getLIRGen().newVariable(resultKind);
+        if (commutative) {
+            getLIRGen().append(new AMD64Binary.CommutativeOp(op, size, result, a, b));
+        } else {
+            getLIRGen().append(new AMD64Binary.Op(op, size, result, a, b));
+        }
+        return result;
+    }
+
+    @Override
+    protected boolean isNumericInteger(PlatformKind kind) {
+        return ((AMD64Kind) kind).isInteger();
+    }
+
+    @Override
+    public Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitBinary(resultKind, ADD, DWORD, true, a, b, setFlags);
+            case QWORD:
+                return emitBinary(resultKind, ADD, QWORD, true, a, b, setFlags);
+            case SINGLE:
+                return emitBinary(resultKind, SSEOp.ADD, SS, true, a, b);
+            case DOUBLE:
+                return emitBinary(resultKind, SSEOp.ADD, SD, true, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitBinary(resultKind, SUB, DWORD, false, a, b, setFlags);
+            case QWORD:
+                return emitBinary(resultKind, SUB, QWORD, false, a, b, setFlags);
+            case SINGLE:
+                return emitBinary(resultKind, SSEOp.SUB, SS, false, a, b);
+            case DOUBLE:
+                return emitBinary(resultKind, SSEOp.SUB, SD, false, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    private Variable emitIMULConst(OperandSize size, AllocatableValue a, ConstantValue b) {
+        long value = b.getJavaConstant().asLong();
+        if (NumUtil.isInt(value)) {
+            int imm = (int) value;
+            AMD64RMIOp op;
+            if (NumUtil.isByte(imm)) {
+                op = AMD64RMIOp.IMUL_SX;
+            } else {
+                op = AMD64RMIOp.IMUL;
+            }
+
+            Variable ret = getLIRGen().newVariable(LIRKind.combine(a, b));
+            getLIRGen().append(new AMD64Binary.RMIOp(op, size, ret, a, imm));
+            return ret;
+        } else {
+            return emitBinaryVar(LIRKind.combine(a, b), AMD64RMOp.IMUL, size, true, a, getLIRGen().asAllocatable(b));
+        }
+    }
+
+    private Variable emitIMUL(OperandSize size, Value a, Value b) {
+        if (isJavaConstant(b)) {
+            return emitIMULConst(size, getLIRGen().asAllocatable(a), asConstantValue(b));
+        } else if (isJavaConstant(a)) {
+            return emitIMULConst(size, getLIRGen().asAllocatable(b), asConstantValue(a));
+        } else {
+            return emitBinaryVar(LIRKind.combine(a, b), AMD64RMOp.IMUL, size, true, getLIRGen().asAllocatable(a), getLIRGen().asAllocatable(b));
+        }
+    }
+
+    @Override
+    public Variable emitMul(Value a, Value b, boolean setFlags) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitIMUL(DWORD, a, b);
+            case QWORD:
+                return emitIMUL(QWORD, a, b);
+            case SINGLE:
+                return emitBinary(LIRKind.combine(a, b), SSEOp.MUL, SS, true, a, b);
+            case DOUBLE:
+                return emitBinary(LIRKind.combine(a, b), SSEOp.MUL, SD, true, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    private RegisterValue moveToReg(Register reg, Value v) {
+        RegisterValue ret = reg.asValue(v.getLIRKind());
+        getLIRGen().emitMove(ret, v);
+        return ret;
+    }
+
+    private Value emitMulHigh(AMD64MOp opcode, OperandSize size, Value a, Value b) {
+        AMD64MulDivOp mulHigh = getLIRGen().append(new AMD64MulDivOp(opcode, size, LIRKind.combine(a, b), moveToReg(AMD64.rax, a), getLIRGen().asAllocatable(b)));
+        return getLIRGen().emitMove(mulHigh.getHighResult());
+    }
+
+    @Override
+    public Value emitMulHigh(Value a, Value b) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitMulHigh(AMD64MOp.IMUL, DWORD, a, b);
+            case QWORD:
+                return emitMulHigh(AMD64MOp.IMUL, QWORD, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Value emitUMulHigh(Value a, Value b) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitMulHigh(AMD64MOp.MUL, DWORD, a, b);
+            case QWORD:
+                return emitMulHigh(AMD64MOp.MUL, QWORD, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    public Value emitBinaryMemory(AMD64RMOp op, OperandSize size, AllocatableValue a, AMD64AddressValue location, LIRFrameState state) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(a));
+        getLIRGen().append(new AMD64Binary.MemoryOp(op, size, result, a, location, state));
+        return result;
+    }
+
+    protected Value emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, AMD64AddressValue address, LIRFrameState state) {
+        Variable result = getLIRGen().newVariable(LIRKind.value(kind));
+        getLIRGen().append(new AMD64Unary.MemoryOp(op, size, result, address, state));
+        return result;
+    }
+
+    protected Value emitZeroExtendMemory(AMD64Kind memoryKind, int resultBits, AMD64AddressValue address, LIRFrameState state) {
+        // Issue a zero extending load of the proper bit size and set the result to
+        // the proper kind.
+        Variable result = getLIRGen().newVariable(LIRKind.value(resultBits == 32 ? AMD64Kind.DWORD : AMD64Kind.QWORD));
+        switch (memoryKind) {
+            case BYTE:
+                getLIRGen().append(new AMD64Unary.MemoryOp(MOVZXB, DWORD, result, address, state));
+                break;
+            case WORD:
+                getLIRGen().append(new AMD64Unary.MemoryOp(MOVZX, DWORD, result, address, state));
+                break;
+            case DWORD:
+                getLIRGen().append(new AMD64Unary.MemoryOp(MOV, DWORD, result, address, state));
+                break;
+            case QWORD:
+                getLIRGen().append(new AMD64Unary.MemoryOp(MOV, QWORD, result, address, state));
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    private AMD64MulDivOp emitIDIV(OperandSize size, Value a, Value b, LIRFrameState state) {
+        LIRKind kind = LIRKind.combine(a, b);
+
+        AMD64SignExtendOp sx = getLIRGen().append(new AMD64SignExtendOp(size, kind, moveToReg(AMD64.rax, a)));
+        return getLIRGen().append(new AMD64MulDivOp(AMD64MOp.IDIV, size, kind, sx.getHighResult(), sx.getLowResult(), getLIRGen().asAllocatable(b), state));
+    }
+
+    private AMD64MulDivOp emitDIV(OperandSize size, Value a, Value b, LIRFrameState state) {
+        LIRKind kind = LIRKind.combine(a, b);
+
+        RegisterValue rax = moveToReg(AMD64.rax, a);
+        RegisterValue rdx = AMD64.rdx.asValue(kind);
+        getLIRGen().append(new AMD64ClearRegisterOp(size, rdx));
+        return getLIRGen().append(new AMD64MulDivOp(AMD64MOp.DIV, size, kind, rdx, rax, getLIRGen().asAllocatable(b), state));
+    }
+
+    public Value[] emitIntegerDivRem(Value a, Value b, LIRFrameState state) {
+        AMD64MulDivOp op;
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                op = emitIDIV(DWORD, a, b, state);
+                break;
+            case QWORD:
+                op = emitIDIV(QWORD, a, b, state);
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return new Value[]{getLIRGen().emitMove(op.getQuotient()), getLIRGen().emitMove(op.getRemainder())};
+    }
+
+    @Override
+    public Value emitDiv(Value a, Value b, LIRFrameState state) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                AMD64MulDivOp op = emitIDIV(DWORD, a, b, state);
+                return getLIRGen().emitMove(op.getQuotient());
+            case QWORD:
+                AMD64MulDivOp lop = emitIDIV(QWORD, a, b, state);
+                return getLIRGen().emitMove(lop.getQuotient());
+            case SINGLE:
+                return emitBinary(LIRKind.combine(a, b), SSEOp.DIV, SS, false, a, b);
+            case DOUBLE:
+                return emitBinary(LIRKind.combine(a, b), SSEOp.DIV, SD, false, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Value emitRem(Value a, Value b, LIRFrameState state) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                AMD64MulDivOp op = emitIDIV(DWORD, a, b, state);
+                return getLIRGen().emitMove(op.getRemainder());
+            case QWORD:
+                AMD64MulDivOp lop = emitIDIV(QWORD, a, b, state);
+                return getLIRGen().emitMove(lop.getRemainder());
+            case SINGLE: {
+                Variable result = getLIRGen().newVariable(LIRKind.combine(a, b));
+                getLIRGen().append(new FPDivRemOp(FREM, result, getLIRGen().load(a), getLIRGen().load(b)));
+                return result;
+            }
+            case DOUBLE: {
+                Variable result = getLIRGen().newVariable(LIRKind.combine(a, b));
+                getLIRGen().append(new FPDivRemOp(DREM, result, getLIRGen().load(a), getLIRGen().load(b)));
+                return result;
+            }
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Variable emitUDiv(Value a, Value b, LIRFrameState state) {
+        AMD64MulDivOp op;
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                op = emitDIV(DWORD, a, b, state);
+                break;
+            case QWORD:
+                op = emitDIV(QWORD, a, b, state);
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return getLIRGen().emitMove(op.getQuotient());
+    }
+
+    @Override
+    public Variable emitURem(Value a, Value b, LIRFrameState state) {
+        AMD64MulDivOp op;
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                op = emitDIV(DWORD, a, b, state);
+                break;
+            case QWORD:
+                op = emitDIV(QWORD, a, b, state);
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return getLIRGen().emitMove(op.getRemainder());
+    }
+
+    @Override
+    public Variable emitAnd(Value a, Value b) {
+        LIRKind resultKind = LIRKind.combine(a, b);
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitBinary(resultKind, AND, DWORD, true, a, b, false);
+            case QWORD:
+                return emitBinary(resultKind, AND, QWORD, true, a, b, false);
+            case SINGLE:
+                return emitBinary(resultKind, SSEOp.AND, PS, true, a, b);
+            case DOUBLE:
+                return emitBinary(resultKind, SSEOp.AND, PD, true, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Variable emitOr(Value a, Value b) {
+        LIRKind resultKind = LIRKind.combine(a, b);
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitBinary(resultKind, OR, DWORD, true, a, b, false);
+            case QWORD:
+                return emitBinary(resultKind, OR, QWORD, true, a, b, false);
+            case SINGLE:
+                return emitBinary(resultKind, SSEOp.OR, PS, true, a, b);
+            case DOUBLE:
+                return emitBinary(resultKind, SSEOp.OR, PD, true, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Variable emitXor(Value a, Value b) {
+        LIRKind resultKind = LIRKind.combine(a, b);
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitBinary(resultKind, XOR, DWORD, true, a, b, false);
+            case QWORD:
+                return emitBinary(resultKind, XOR, QWORD, true, a, b, false);
+            case SINGLE:
+                return emitBinary(resultKind, SSEOp.XOR, PS, true, a, b);
+            case DOUBLE:
+                return emitBinary(resultKind, SSEOp.XOR, PD, true, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    private Variable emitShift(AMD64Shift op, OperandSize size, Value a, Value b) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(a, b).changeType(a.getPlatformKind()));
+        AllocatableValue input = getLIRGen().asAllocatable(a);
+        if (isJavaConstant(b)) {
+            JavaConstant c = asJavaConstant(b);
+            if (c.asLong() == 1) {
+                getLIRGen().append(new AMD64Unary.MOp(op.m1Op, size, result, input));
+            } else {
+                /*
+                 * c is implicitly masked to 5 or 6 bits by the CPU, so casting it to (int) is
+                 * always correct, even without the NumUtil.is32bit() test.
+                 */
+                getLIRGen().append(new AMD64Binary.ConstOp(op.miOp, size, result, input, (int) c.asLong()));
+            }
+        } else {
+            getLIRGen().emitMove(RCX_I, b);
+            getLIRGen().append(new AMD64ShiftOp(op.mcOp, size, result, input, RCX_I));
+        }
+        return result;
+    }
+
+    @Override
+    public Variable emitShl(Value a, Value b) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitShift(SHL, DWORD, a, b);
+            case QWORD:
+                return emitShift(SHL, QWORD, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Variable emitShr(Value a, Value b) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitShift(SAR, DWORD, a, b);
+            case QWORD:
+                return emitShift(SAR, QWORD, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Variable emitUShr(Value a, Value b) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitShift(SHR, DWORD, a, b);
+            case QWORD:
+                return emitShift(SHR, QWORD, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    public Variable emitRol(Value a, Value b) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitShift(ROL, DWORD, a, b);
+            case QWORD:
+                return emitShift(ROL, QWORD, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    public Variable emitRor(Value a, Value b) {
+        switch ((AMD64Kind) a.getPlatformKind()) {
+            case DWORD:
+                return emitShift(ROR, DWORD, a, b);
+            case QWORD:
+                return emitShift(ROR, QWORD, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    private AllocatableValue emitConvertOp(LIRKind kind, AMD64RMOp op, OperandSize size, Value input) {
+        Variable result = getLIRGen().newVariable(kind);
+        getLIRGen().append(new AMD64Unary.RMOp(op, size, result, getLIRGen().asAllocatable(input)));
+        return result;
+    }
+
+    private AllocatableValue emitConvertOp(LIRKind kind, AMD64MROp op, OperandSize size, Value input) {
+        Variable result = getLIRGen().newVariable(kind);
+        getLIRGen().append(new AMD64Unary.MROp(op, size, result, getLIRGen().asAllocatable(input)));
+        return result;
+    }
+
+    @Override
+    public Value emitReinterpret(LIRKind to, Value inputVal) {
+        LIRKind from = inputVal.getLIRKind();
+        if (to.equals(from)) {
+            return inputVal;
+        }
+
+        AllocatableValue input = getLIRGen().asAllocatable(inputVal);
+        /*
+         * Conversions between integer to floating point types require moves between CPU and FPU
+         * registers.
+         */
+        AMD64Kind fromKind = (AMD64Kind) from.getPlatformKind();
+        switch ((AMD64Kind) to.getPlatformKind()) {
+            case DWORD:
+                switch (fromKind) {
+                    case SINGLE:
+                        return emitConvertOp(to, AMD64MROp.MOVD, DWORD, input);
+                }
+                break;
+            case QWORD:
+                switch (fromKind) {
+                    case DOUBLE:
+                        return emitConvertOp(to, AMD64MROp.MOVQ, QWORD, input);
+                }
+                break;
+            case SINGLE:
+                switch (fromKind) {
+                    case DWORD:
+                        return emitConvertOp(to, AMD64RMOp.MOVD, DWORD, input);
+                }
+                break;
+            case DOUBLE:
+                switch (fromKind) {
+                    case QWORD:
+                        return emitConvertOp(to, AMD64RMOp.MOVQ, QWORD, input);
+                }
+                break;
+        }
+        throw JVMCIError.shouldNotReachHere();
+    }
+
+    public Value emitFloatConvert(FloatConvert op, Value input) {
+        switch (op) {
+            case D2F:
+                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.SINGLE), SSEOp.CVTSD2SS, SD, input);
+            case D2I:
+                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DWORD), SSEOp.CVTTSD2SI, DWORD, input);
+            case D2L:
+                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.QWORD), SSEOp.CVTTSD2SI, QWORD, input);
+            case F2D:
+                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DOUBLE), SSEOp.CVTSS2SD, SS, input);
+            case F2I:
+                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DWORD), SSEOp.CVTTSS2SI, DWORD, input);
+            case F2L:
+                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.QWORD), SSEOp.CVTTSS2SI, QWORD, input);
+            case I2D:
+                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DOUBLE), SSEOp.CVTSI2SD, DWORD, input);
+            case I2F:
+                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.SINGLE), SSEOp.CVTSI2SS, DWORD, input);
+            case L2D:
+                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DOUBLE), SSEOp.CVTSI2SD, QWORD, input);
+            case L2F:
+                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.SINGLE), SSEOp.CVTSI2SS, QWORD, input);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Value emitNarrow(Value inputVal, int bits) {
+        if (inputVal.getPlatformKind() == AMD64Kind.QWORD && bits <= 32) {
+            // TODO make it possible to reinterpret Long as Int in LIR without move
+            return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.DWORD), AMD64RMOp.MOV, DWORD, inputVal);
+        } else {
+            return inputVal;
+        }
+    }
+
+    @Override
+    public Value emitSignExtend(Value inputVal, int fromBits, int toBits) {
+        assert fromBits <= toBits && toBits <= 64;
+        if (fromBits == toBits) {
+            return inputVal;
+        } else if (toBits > 32) {
+            // sign extend to 64 bits
+            switch (fromBits) {
+                case 8:
+                    return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.QWORD), MOVSXB, QWORD, inputVal);
+                case 16:
+                    return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.QWORD), MOVSX, QWORD, inputVal);
+                case 32:
+                    return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.QWORD), MOVSXD, QWORD, inputVal);
+                default:
+                    throw JVMCIError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
+            }
+        } else {
+            // sign extend to 32 bits (smaller values are internally represented as 32 bit values)
+            switch (fromBits) {
+                case 8:
+                    return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.DWORD), MOVSXB, DWORD, inputVal);
+                case 16:
+                    return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.DWORD), MOVSX, DWORD, inputVal);
+                case 32:
+                    return inputVal;
+                default:
+                    throw JVMCIError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
+            }
+        }
+    }
+
+    @Override
+    public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) {
+        assert fromBits <= toBits && toBits <= 64;
+        if (fromBits == toBits) {
+            return inputVal;
+        } else if (fromBits > 32) {
+            assert inputVal.getPlatformKind() == AMD64Kind.QWORD;
+            Variable result = getLIRGen().newVariable(LIRKind.combine(inputVal));
+            long mask = CodeUtil.mask(fromBits);
+            getLIRGen().append(new AMD64Binary.DataOp(AND.getRMOpcode(QWORD), QWORD, result, getLIRGen().asAllocatable(inputVal), JavaConstant.forLong(mask)));
+            return result;
+        } else {
+            LIRKind resultKind = LIRKind.combine(inputVal);
+            if (toBits > 32) {
+                resultKind = resultKind.changeType(AMD64Kind.QWORD);
+            } else {
+                resultKind = resultKind.changeType(AMD64Kind.DWORD);
+            }
+
+            /*
+             * Always emit DWORD operations, even if the resultKind is Long. On AMD64, all DWORD
+             * operations implicitly set the upper half of the register to 0, which is what we want
+             * anyway. Compared to the QWORD oparations, the encoding of the DWORD operations is
+             * sometimes one byte shorter.
+             */
+            switch (fromBits) {
+                case 8:
+                    return emitConvertOp(resultKind, MOVZXB, DWORD, inputVal);
+                case 16:
+                    return emitConvertOp(resultKind, MOVZX, DWORD, inputVal);
+                case 32:
+                    return emitConvertOp(resultKind, MOV, DWORD, inputVal);
+            }
+
+            // odd bit count, fall back on manual masking
+            Variable result = getLIRGen().newVariable(resultKind);
+            JavaConstant mask;
+            if (toBits > 32) {
+                mask = JavaConstant.forLong(CodeUtil.mask(fromBits));
+            } else {
+                mask = JavaConstant.forInt((int) CodeUtil.mask(fromBits));
+            }
+            getLIRGen().append(new AMD64Binary.DataOp(AND.getRMOpcode(DWORD), DWORD, result, getLIRGen().asAllocatable(inputVal), mask));
+            return result;
+        }
+    }
+
+    @Override
+    public Variable emitBitCount(Value value) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AMD64Kind.DWORD));
+        assert ((AMD64Kind) value.getPlatformKind()).isInteger();
+        if (value.getPlatformKind() == AMD64Kind.QWORD) {
+            getLIRGen().append(new AMD64Unary.RMOp(POPCNT, QWORD, result, getLIRGen().asAllocatable(value)));
+        } else {
+            getLIRGen().append(new AMD64Unary.RMOp(POPCNT, DWORD, result, getLIRGen().asAllocatable(value)));
+        }
+        return result;
+    }
+
+    @Override
+    public Variable emitBitScanForward(Value value) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AMD64Kind.DWORD));
+        getLIRGen().append(new AMD64Unary.RMOp(BSF, QWORD, result, getLIRGen().asAllocatable(value)));
+        return result;
+    }
+
+    @Override
+    public Variable emitBitScanReverse(Value value) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AMD64Kind.DWORD));
+        assert ((AMD64Kind) value.getPlatformKind()).isInteger();
+        if (value.getPlatformKind() == AMD64Kind.QWORD) {
+            getLIRGen().append(new AMD64Unary.RMOp(BSR, QWORD, result, getLIRGen().asAllocatable(value)));
+        } else {
+            getLIRGen().append(new AMD64Unary.RMOp(BSR, DWORD, result, getLIRGen().asAllocatable(value)));
+        }
+        return result;
+    }
+
+    @Override
+    public Value emitCountLeadingZeros(Value value) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AMD64Kind.DWORD));
+        assert ((AMD64Kind) value.getPlatformKind()).isInteger();
+        if (value.getPlatformKind() == AMD64Kind.QWORD) {
+            getLIRGen().append(new AMD64Unary.RMOp(LZCNT, QWORD, result, getLIRGen().asAllocatable(value)));
+        } else {
+            getLIRGen().append(new AMD64Unary.RMOp(LZCNT, DWORD, result, getLIRGen().asAllocatable(value)));
+        }
+        return result;
+    }
+
+    @Override
+    public Value emitCountTrailingZeros(Value value) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AMD64Kind.DWORD));
+        assert ((AMD64Kind) value.getPlatformKind()).isInteger();
+        if (value.getPlatformKind() == AMD64Kind.QWORD) {
+            getLIRGen().append(new AMD64Unary.RMOp(TZCNT, QWORD, result, getLIRGen().asAllocatable(value)));
+        } else {
+            getLIRGen().append(new AMD64Unary.RMOp(TZCNT, DWORD, result, getLIRGen().asAllocatable(value)));
+        }
+        return result;
+    }
+
+    @Override
+    public Value emitMathAbs(Value input) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        switch ((AMD64Kind) input.getPlatformKind()) {
+            case SINGLE:
+                getLIRGen().append(new AMD64Binary.DataOp(SSEOp.AND, PS, result, getLIRGen().asAllocatable(input), JavaConstant.forFloat(Float.intBitsToFloat(0x7FFFFFFF)), 16));
+                break;
+            case DOUBLE:
+                getLIRGen().append(new AMD64Binary.DataOp(SSEOp.AND, PD, result, getLIRGen().asAllocatable(input), JavaConstant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)), 16));
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    @Override
+    public Value emitMathSqrt(Value input) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        switch ((AMD64Kind) input.getPlatformKind()) {
+            case SINGLE:
+                getLIRGen().append(new AMD64Unary.RMOp(SSEOp.SQRT, SS, result, getLIRGen().asAllocatable(input)));
+                break;
+            case DOUBLE:
+                getLIRGen().append(new AMD64Unary.RMOp(SSEOp.SQRT, SD, result, getLIRGen().asAllocatable(input)));
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    @Override
+    public Value emitMathLog(Value input, boolean base10) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        getLIRGen().append(new AMD64MathIntrinsicOp(base10 ? LOG10 : LOG, result, getLIRGen().asAllocatable(input)));
+        return result;
+    }
+
+    @Override
+    public Value emitMathCos(Value input) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        getLIRGen().append(new AMD64MathIntrinsicOp(COS, result, getLIRGen().asAllocatable(input)));
+        return result;
+    }
+
+    @Override
+    public Value emitMathSin(Value input) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        getLIRGen().append(new AMD64MathIntrinsicOp(SIN, result, getLIRGen().asAllocatable(input)));
+        return result;
+    }
+
+    @Override
+    public Value emitMathTan(Value input) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        getLIRGen().append(new AMD64MathIntrinsicOp(TAN, result, getLIRGen().asAllocatable(input)));
+        return result;
+    }
+}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Oct 08 15:58:13 2015 -0700
@@ -23,34 +23,14 @@
 
 package com.oracle.graal.compiler.amd64;
 
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.ADD;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.AND;
 import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.OR;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.SUB;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.XOR;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MOp.NEG;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MOp.NOT;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.BSF;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.BSR;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.LZCNT;
 import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOV;
 import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSD;
 import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSS;
 import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSX;
 import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXB;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXD;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVZX;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.MOVZXB;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.POPCNT;
 import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.TEST;
 import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.TESTB;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.TZCNT;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift.ROL;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift.ROR;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift.SAR;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift.SHL;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift.SHR;
 import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.BYTE;
 import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.DWORD;
 import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.PD;
@@ -62,13 +42,6 @@
 import static com.oracle.graal.lir.LIRValueUtil.asConstantValue;
 import static com.oracle.graal.lir.LIRValueUtil.asJavaConstant;
 import static com.oracle.graal.lir.LIRValueUtil.isJavaConstant;
-import static com.oracle.graal.lir.amd64.AMD64Arithmetic.DREM;
-import static com.oracle.graal.lir.amd64.AMD64Arithmetic.FREM;
-import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.COS;
-import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.LOG;
-import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.LOG10;
-import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.SIN;
-import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.TAN;
 import static jdk.internal.jvmci.code.ValueUtil.isAllocatableValue;
 import static jdk.internal.jvmci.code.ValueUtil.isRegister;
 import static jdk.internal.jvmci.code.ValueUtil.isStackSlotValue;
@@ -80,7 +53,6 @@
 import jdk.internal.jvmci.amd64.AMD64Kind;
 import jdk.internal.jvmci.code.Architecture;
 import jdk.internal.jvmci.code.CallingConvention;
-import jdk.internal.jvmci.code.CodeUtil;
 import jdk.internal.jvmci.code.Register;
 import jdk.internal.jvmci.code.RegisterConfig;
 import jdk.internal.jvmci.code.RegisterValue;
@@ -96,18 +68,13 @@
 import jdk.internal.jvmci.meta.Value;
 
 import com.oracle.graal.asm.NumUtil;
-import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
 import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MIOp;
-import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MOp;
 import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MROp;
-import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMIOp;
 import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp;
-import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64Shift;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize;
 import com.oracle.graal.asm.amd64.AMD64Assembler.SSEOp;
 import com.oracle.graal.compiler.common.calc.Condition;
-import com.oracle.graal.compiler.common.calc.FloatConvert;
 import com.oracle.graal.compiler.common.spi.ForeignCallLinkage;
 import com.oracle.graal.compiler.common.spi.LIRKindTool;
 import com.oracle.graal.compiler.common.util.Util;
@@ -120,14 +87,10 @@
 import com.oracle.graal.lir.SwitchStrategy;
 import com.oracle.graal.lir.Variable;
 import com.oracle.graal.lir.amd64.AMD64AddressValue;
-import com.oracle.graal.lir.amd64.AMD64Arithmetic.FPDivRemOp;
-import com.oracle.graal.lir.amd64.AMD64ArithmeticLIRGenerator;
 import com.oracle.graal.lir.amd64.AMD64ArrayEqualsOp;
-import com.oracle.graal.lir.amd64.AMD64Binary;
 import com.oracle.graal.lir.amd64.AMD64BinaryConsumer;
 import com.oracle.graal.lir.amd64.AMD64ByteSwapOp;
 import com.oracle.graal.lir.amd64.AMD64Call;
-import com.oracle.graal.lir.amd64.AMD64ClearRegisterOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.BranchOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.FloatBranchOp;
@@ -136,7 +99,6 @@
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp;
 import com.oracle.graal.lir.amd64.AMD64LIRInstruction;
-import com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp;
 import com.oracle.graal.lir.amd64.AMD64Move;
 import com.oracle.graal.lir.amd64.AMD64Move.AMD64PushPopStackMove;
 import com.oracle.graal.lir.amd64.AMD64Move.AMD64StackMove;
@@ -148,9 +110,6 @@
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp;
-import com.oracle.graal.lir.amd64.AMD64MulDivOp;
-import com.oracle.graal.lir.amd64.AMD64ShiftOp;
-import com.oracle.graal.lir.amd64.AMD64SignExtendOp;
 import com.oracle.graal.lir.amd64.AMD64Unary;
 import com.oracle.graal.lir.framemap.FrameMapBuilder;
 import com.oracle.graal.lir.gen.LIRGenerationResult;
@@ -161,9 +120,7 @@
 /**
  * This class implements the AMD64 specific portion of the LIR generator.
  */
-public abstract class AMD64LIRGenerator extends LIRGenerator implements AMD64ArithmeticLIRGenerator {
-
-    private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(AMD64Kind.DWORD));
+public abstract class AMD64LIRGenerator extends LIRGenerator {
 
     private AMD64SpillMoveFactory moveFactory;
     private Map<PlatformKind.Key, RegisterBackupPair> categorized;
@@ -196,8 +153,8 @@
         }
     }
 
-    public AMD64LIRGenerator(LIRKindTool lirKindTool, Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) {
-        super(lirKindTool, providers, cc, lirGenRes);
+    public AMD64LIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        super(lirKindTool, arithmeticLIRGen, providers, cc, lirGenRes);
     }
 
     public SpillMoveFactory getSpillMoveFactory() {
@@ -727,679 +684,6 @@
     }
 
     @Override
-    public Variable emitNegate(Value inputVal) {
-        AllocatableValue input = asAllocatable(inputVal);
-        Variable result = newVariable(LIRKind.combine(input));
-        switch ((AMD64Kind) input.getPlatformKind()) {
-            case DWORD:
-                append(new AMD64Unary.MOp(NEG, DWORD, result, input));
-                break;
-            case QWORD:
-                append(new AMD64Unary.MOp(NEG, QWORD, result, input));
-                break;
-            case SINGLE:
-                append(new AMD64Binary.DataOp(SSEOp.XOR, PS, result, input, JavaConstant.forFloat(Float.intBitsToFloat(0x80000000)), 16));
-                break;
-            case DOUBLE:
-                append(new AMD64Binary.DataOp(SSEOp.XOR, PD, result, input, JavaConstant.forDouble(Double.longBitsToDouble(0x8000000000000000L)), 16));
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return result;
-    }
-
-    @Override
-    public Variable emitNot(Value inputVal) {
-        AllocatableValue input = asAllocatable(inputVal);
-        Variable result = newVariable(LIRKind.combine(input));
-        switch ((AMD64Kind) input.getPlatformKind()) {
-            case DWORD:
-                append(new AMD64Unary.MOp(NOT, DWORD, result, input));
-                break;
-            case QWORD:
-                append(new AMD64Unary.MOp(NOT, QWORD, result, input));
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return result;
-    }
-
-    private Variable emitBinary(LIRKind resultKind, AMD64BinaryArithmetic op, OperandSize size, boolean commutative, Value a, Value b, boolean setFlags) {
-        if (isJavaConstant(b)) {
-            return emitBinaryConst(resultKind, op, size, commutative, asAllocatable(a), asConstantValue(b), setFlags);
-        } else if (commutative && isJavaConstant(a)) {
-            return emitBinaryConst(resultKind, op, size, commutative, asAllocatable(b), asConstantValue(a), setFlags);
-        } else {
-            return emitBinaryVar(resultKind, op.getRMOpcode(size), size, commutative, asAllocatable(a), asAllocatable(b));
-        }
-    }
-
-    private Variable emitBinary(LIRKind resultKind, AMD64RMOp op, OperandSize size, boolean commutative, Value a, Value b) {
-        if (isJavaConstant(b)) {
-            return emitBinaryConst(resultKind, op, size, asAllocatable(a), asJavaConstant(b));
-        } else if (commutative && isJavaConstant(a)) {
-            return emitBinaryConst(resultKind, op, size, asAllocatable(b), asJavaConstant(a));
-        } else {
-            return emitBinaryVar(resultKind, op, size, commutative, asAllocatable(a), asAllocatable(b));
-        }
-    }
-
-    private Variable emitBinaryConst(LIRKind resultKind, AMD64BinaryArithmetic op, OperandSize size, boolean commutative, AllocatableValue a, ConstantValue b, boolean setFlags) {
-        long value = b.getJavaConstant().asLong();
-        if (NumUtil.isInt(value)) {
-            Variable result = newVariable(resultKind);
-            int constant = (int) value;
-
-            if (!setFlags) {
-                AMD64MOp mop = getMOp(op, constant);
-                if (mop != null) {
-                    append(new AMD64Unary.MOp(mop, size, result, a));
-                    return result;
-                }
-            }
-
-            append(new AMD64Binary.ConstOp(op, size, result, a, constant));
-            return result;
-        } else {
-            return emitBinaryVar(resultKind, op.getRMOpcode(size), size, commutative, a, asAllocatable(b));
-        }
-    }
-
-    private static AMD64MOp getMOp(AMD64BinaryArithmetic op, int constant) {
-        if (constant == 1) {
-            if (op.equals(AMD64BinaryArithmetic.ADD)) {
-                return AMD64MOp.INC;
-            }
-            if (op.equals(AMD64BinaryArithmetic.SUB)) {
-                return AMD64MOp.DEC;
-            }
-        } else if (constant == -1) {
-            if (op.equals(AMD64BinaryArithmetic.ADD)) {
-                return AMD64MOp.DEC;
-            }
-            if (op.equals(AMD64BinaryArithmetic.SUB)) {
-                return AMD64MOp.INC;
-            }
-        }
-        return null;
-    }
-
-    private Variable emitBinaryConst(LIRKind resultKind, AMD64RMOp op, OperandSize size, AllocatableValue a, JavaConstant b) {
-        Variable result = newVariable(resultKind);
-        append(new AMD64Binary.DataOp(op, size, result, a, b));
-        return result;
-    }
-
-    private Variable emitBinaryVar(LIRKind resultKind, AMD64RMOp op, OperandSize size, boolean commutative, AllocatableValue a, AllocatableValue b) {
-        Variable result = newVariable(resultKind);
-        if (commutative) {
-            append(new AMD64Binary.CommutativeOp(op, size, result, a, b));
-        } else {
-            append(new AMD64Binary.Op(op, size, result, a, b));
-        }
-        return result;
-    }
-
-    @Override
-    protected boolean isNumericInteger(PlatformKind kind) {
-        return ((AMD64Kind) kind).isInteger();
-    }
-
-    @Override
-    public Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitBinary(resultKind, ADD, DWORD, true, a, b, setFlags);
-            case QWORD:
-                return emitBinary(resultKind, ADD, QWORD, true, a, b, setFlags);
-            case SINGLE:
-                return emitBinary(resultKind, SSEOp.ADD, SS, true, a, b);
-            case DOUBLE:
-                return emitBinary(resultKind, SSEOp.ADD, SD, true, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    @Override
-    public Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitBinary(resultKind, SUB, DWORD, false, a, b, setFlags);
-            case QWORD:
-                return emitBinary(resultKind, SUB, QWORD, false, a, b, setFlags);
-            case SINGLE:
-                return emitBinary(resultKind, SSEOp.SUB, SS, false, a, b);
-            case DOUBLE:
-                return emitBinary(resultKind, SSEOp.SUB, SD, false, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    private Variable emitIMULConst(OperandSize size, AllocatableValue a, ConstantValue b) {
-        long value = b.getJavaConstant().asLong();
-        if (NumUtil.isInt(value)) {
-            int imm = (int) value;
-            AMD64RMIOp op;
-            if (NumUtil.isByte(imm)) {
-                op = AMD64RMIOp.IMUL_SX;
-            } else {
-                op = AMD64RMIOp.IMUL;
-            }
-
-            Variable ret = newVariable(LIRKind.combine(a, b));
-            append(new AMD64Binary.RMIOp(op, size, ret, a, imm));
-            return ret;
-        } else {
-            return emitBinaryVar(LIRKind.combine(a, b), AMD64RMOp.IMUL, size, true, a, asAllocatable(b));
-        }
-    }
-
-    private Variable emitIMUL(OperandSize size, Value a, Value b) {
-        if (isJavaConstant(b)) {
-            return emitIMULConst(size, asAllocatable(a), asConstantValue(b));
-        } else if (isJavaConstant(a)) {
-            return emitIMULConst(size, asAllocatable(b), asConstantValue(a));
-        } else {
-            return emitBinaryVar(LIRKind.combine(a, b), AMD64RMOp.IMUL, size, true, asAllocatable(a), asAllocatable(b));
-        }
-    }
-
-    @Override
-    public Variable emitMul(Value a, Value b, boolean setFlags) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitIMUL(DWORD, a, b);
-            case QWORD:
-                return emitIMUL(QWORD, a, b);
-            case SINGLE:
-                return emitBinary(LIRKind.combine(a, b), SSEOp.MUL, SS, true, a, b);
-            case DOUBLE:
-                return emitBinary(LIRKind.combine(a, b), SSEOp.MUL, SD, true, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    private RegisterValue moveToReg(Register reg, Value v) {
-        RegisterValue ret = reg.asValue(v.getLIRKind());
-        emitMove(ret, v);
-        return ret;
-    }
-
-    private Value emitMulHigh(AMD64MOp opcode, OperandSize size, Value a, Value b) {
-        AMD64MulDivOp mulHigh = append(new AMD64MulDivOp(opcode, size, LIRKind.combine(a, b), moveToReg(AMD64.rax, a), asAllocatable(b)));
-        return emitMove(mulHigh.getHighResult());
-    }
-
-    @Override
-    public Value emitMulHigh(Value a, Value b) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitMulHigh(AMD64MOp.IMUL, DWORD, a, b);
-            case QWORD:
-                return emitMulHigh(AMD64MOp.IMUL, QWORD, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    @Override
-    public Value emitUMulHigh(Value a, Value b) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitMulHigh(AMD64MOp.MUL, DWORD, a, b);
-            case QWORD:
-                return emitMulHigh(AMD64MOp.MUL, QWORD, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    public Value emitBinaryMemory(AMD64RMOp op, OperandSize size, AllocatableValue a, AMD64AddressValue location, LIRFrameState state) {
-        Variable result = newVariable(LIRKind.combine(a));
-        append(new AMD64Binary.MemoryOp(op, size, result, a, location, state));
-        return result;
-    }
-
-    protected Value emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, AMD64AddressValue address, LIRFrameState state) {
-        Variable result = newVariable(LIRKind.value(kind));
-        append(new AMD64Unary.MemoryOp(op, size, result, address, state));
-        return result;
-    }
-
-    protected Value emitZeroExtendMemory(AMD64Kind memoryKind, int resultBits, AMD64AddressValue address, LIRFrameState state) {
-        // Issue a zero extending load of the proper bit size and set the result to
-        // the proper kind.
-        Variable result = newVariable(LIRKind.value(resultBits == 32 ? AMD64Kind.DWORD : AMD64Kind.QWORD));
-        switch (memoryKind) {
-            case BYTE:
-                append(new AMD64Unary.MemoryOp(MOVZXB, DWORD, result, address, state));
-                break;
-            case WORD:
-                append(new AMD64Unary.MemoryOp(MOVZX, DWORD, result, address, state));
-                break;
-            case DWORD:
-                append(new AMD64Unary.MemoryOp(MOV, DWORD, result, address, state));
-                break;
-            case QWORD:
-                append(new AMD64Unary.MemoryOp(MOV, QWORD, result, address, state));
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return result;
-    }
-
-    private AMD64MulDivOp emitIDIV(OperandSize size, Value a, Value b, LIRFrameState state) {
-        LIRKind kind = LIRKind.combine(a, b);
-
-        AMD64SignExtendOp sx = append(new AMD64SignExtendOp(size, kind, moveToReg(AMD64.rax, a)));
-        return append(new AMD64MulDivOp(AMD64MOp.IDIV, size, kind, sx.getHighResult(), sx.getLowResult(), asAllocatable(b), state));
-    }
-
-    private AMD64MulDivOp emitDIV(OperandSize size, Value a, Value b, LIRFrameState state) {
-        LIRKind kind = LIRKind.combine(a, b);
-
-        RegisterValue rax = moveToReg(AMD64.rax, a);
-        RegisterValue rdx = AMD64.rdx.asValue(kind);
-        append(new AMD64ClearRegisterOp(size, rdx));
-        return append(new AMD64MulDivOp(AMD64MOp.DIV, size, kind, rdx, rax, asAllocatable(b), state));
-    }
-
-    public Value[] emitIntegerDivRem(Value a, Value b, LIRFrameState state) {
-        AMD64MulDivOp op;
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                op = emitIDIV(DWORD, a, b, state);
-                break;
-            case QWORD:
-                op = emitIDIV(QWORD, a, b, state);
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return new Value[]{emitMove(op.getQuotient()), emitMove(op.getRemainder())};
-    }
-
-    @Override
-    public Value emitDiv(Value a, Value b, LIRFrameState state) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                AMD64MulDivOp op = emitIDIV(DWORD, a, b, state);
-                return emitMove(op.getQuotient());
-            case QWORD:
-                AMD64MulDivOp lop = emitIDIV(QWORD, a, b, state);
-                return emitMove(lop.getQuotient());
-            case SINGLE:
-                return emitBinary(LIRKind.combine(a, b), SSEOp.DIV, SS, false, a, b);
-            case DOUBLE:
-                return emitBinary(LIRKind.combine(a, b), SSEOp.DIV, SD, false, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    @Override
-    public Value emitRem(Value a, Value b, LIRFrameState state) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                AMD64MulDivOp op = emitIDIV(DWORD, a, b, state);
-                return emitMove(op.getRemainder());
-            case QWORD:
-                AMD64MulDivOp lop = emitIDIV(QWORD, a, b, state);
-                return emitMove(lop.getRemainder());
-            case SINGLE: {
-                Variable result = newVariable(LIRKind.combine(a, b));
-                append(new FPDivRemOp(FREM, result, load(a), load(b)));
-                return result;
-            }
-            case DOUBLE: {
-                Variable result = newVariable(LIRKind.combine(a, b));
-                append(new FPDivRemOp(DREM, result, load(a), load(b)));
-                return result;
-            }
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    @Override
-    public Variable emitUDiv(Value a, Value b, LIRFrameState state) {
-        AMD64MulDivOp op;
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                op = emitDIV(DWORD, a, b, state);
-                break;
-            case QWORD:
-                op = emitDIV(QWORD, a, b, state);
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return emitMove(op.getQuotient());
-    }
-
-    @Override
-    public Variable emitURem(Value a, Value b, LIRFrameState state) {
-        AMD64MulDivOp op;
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                op = emitDIV(DWORD, a, b, state);
-                break;
-            case QWORD:
-                op = emitDIV(QWORD, a, b, state);
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return emitMove(op.getRemainder());
-    }
-
-    @Override
-    public Variable emitAnd(Value a, Value b) {
-        LIRKind resultKind = LIRKind.combine(a, b);
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitBinary(resultKind, AND, DWORD, true, a, b, false);
-            case QWORD:
-                return emitBinary(resultKind, AND, QWORD, true, a, b, false);
-            case SINGLE:
-                return emitBinary(resultKind, SSEOp.AND, PS, true, a, b);
-            case DOUBLE:
-                return emitBinary(resultKind, SSEOp.AND, PD, true, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    @Override
-    public Variable emitOr(Value a, Value b) {
-        LIRKind resultKind = LIRKind.combine(a, b);
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitBinary(resultKind, OR, DWORD, true, a, b, false);
-            case QWORD:
-                return emitBinary(resultKind, OR, QWORD, true, a, b, false);
-            case SINGLE:
-                return emitBinary(resultKind, SSEOp.OR, PS, true, a, b);
-            case DOUBLE:
-                return emitBinary(resultKind, SSEOp.OR, PD, true, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    @Override
-    public Variable emitXor(Value a, Value b) {
-        LIRKind resultKind = LIRKind.combine(a, b);
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitBinary(resultKind, XOR, DWORD, true, a, b, false);
-            case QWORD:
-                return emitBinary(resultKind, XOR, QWORD, true, a, b, false);
-            case SINGLE:
-                return emitBinary(resultKind, SSEOp.XOR, PS, true, a, b);
-            case DOUBLE:
-                return emitBinary(resultKind, SSEOp.XOR, PD, true, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    private Variable emitShift(AMD64Shift op, OperandSize size, Value a, Value b) {
-        Variable result = newVariable(LIRKind.combine(a, b).changeType(a.getPlatformKind()));
-        AllocatableValue input = asAllocatable(a);
-        if (isJavaConstant(b)) {
-            JavaConstant c = asJavaConstant(b);
-            if (c.asLong() == 1) {
-                append(new AMD64Unary.MOp(op.m1Op, size, result, input));
-            } else {
-                /*
-                 * c is implicitly masked to 5 or 6 bits by the CPU, so casting it to (int) is
-                 * always correct, even without the NumUtil.is32bit() test.
-                 */
-                append(new AMD64Binary.ConstOp(op.miOp, size, result, input, (int) c.asLong()));
-            }
-        } else {
-            emitMove(RCX_I, b);
-            append(new AMD64ShiftOp(op.mcOp, size, result, input, RCX_I));
-        }
-        return result;
-    }
-
-    @Override
-    public Variable emitShl(Value a, Value b) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitShift(SHL, DWORD, a, b);
-            case QWORD:
-                return emitShift(SHL, QWORD, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    @Override
-    public Variable emitShr(Value a, Value b) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitShift(SAR, DWORD, a, b);
-            case QWORD:
-                return emitShift(SAR, QWORD, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    @Override
-    public Variable emitUShr(Value a, Value b) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitShift(SHR, DWORD, a, b);
-            case QWORD:
-                return emitShift(SHR, QWORD, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    public Variable emitRol(Value a, Value b) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitShift(ROL, DWORD, a, b);
-            case QWORD:
-                return emitShift(ROL, QWORD, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    public Variable emitRor(Value a, Value b) {
-        switch ((AMD64Kind) a.getPlatformKind()) {
-            case DWORD:
-                return emitShift(ROR, DWORD, a, b);
-            case QWORD:
-                return emitShift(ROR, QWORD, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    private AllocatableValue emitConvertOp(LIRKind kind, AMD64RMOp op, OperandSize size, Value input) {
-        Variable result = newVariable(kind);
-        append(new AMD64Unary.RMOp(op, size, result, asAllocatable(input)));
-        return result;
-    }
-
-    private AllocatableValue emitConvertOp(LIRKind kind, AMD64MROp op, OperandSize size, Value input) {
-        Variable result = newVariable(kind);
-        append(new AMD64Unary.MROp(op, size, result, asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Value emitReinterpret(LIRKind to, Value inputVal) {
-        LIRKind from = inputVal.getLIRKind();
-        if (to.equals(from)) {
-            return inputVal;
-        }
-
-        AllocatableValue input = asAllocatable(inputVal);
-        /*
-         * Conversions between integer to floating point types require moves between CPU and FPU
-         * registers.
-         */
-        AMD64Kind fromKind = (AMD64Kind) from.getPlatformKind();
-        switch ((AMD64Kind) to.getPlatformKind()) {
-            case DWORD:
-                switch (fromKind) {
-                    case SINGLE:
-                        return emitConvertOp(to, AMD64MROp.MOVD, DWORD, input);
-                }
-                break;
-            case QWORD:
-                switch (fromKind) {
-                    case DOUBLE:
-                        return emitConvertOp(to, AMD64MROp.MOVQ, QWORD, input);
-                }
-                break;
-            case SINGLE:
-                switch (fromKind) {
-                    case DWORD:
-                        return emitConvertOp(to, AMD64RMOp.MOVD, DWORD, input);
-                }
-                break;
-            case DOUBLE:
-                switch (fromKind) {
-                    case QWORD:
-                        return emitConvertOp(to, AMD64RMOp.MOVQ, QWORD, input);
-                }
-                break;
-        }
-        throw JVMCIError.shouldNotReachHere();
-    }
-
-    public Value emitFloatConvert(FloatConvert op, Value input) {
-        switch (op) {
-            case D2F:
-                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.SINGLE), SSEOp.CVTSD2SS, SD, input);
-            case D2I:
-                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DWORD), SSEOp.CVTTSD2SI, DWORD, input);
-            case D2L:
-                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.QWORD), SSEOp.CVTTSD2SI, QWORD, input);
-            case F2D:
-                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DOUBLE), SSEOp.CVTSS2SD, SS, input);
-            case F2I:
-                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DWORD), SSEOp.CVTTSS2SI, DWORD, input);
-            case F2L:
-                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.QWORD), SSEOp.CVTTSS2SI, QWORD, input);
-            case I2D:
-                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DOUBLE), SSEOp.CVTSI2SD, DWORD, input);
-            case I2F:
-                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.SINGLE), SSEOp.CVTSI2SS, DWORD, input);
-            case L2D:
-                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DOUBLE), SSEOp.CVTSI2SD, QWORD, input);
-            case L2F:
-                return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.SINGLE), SSEOp.CVTSI2SS, QWORD, input);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    @Override
-    public Value emitNarrow(Value inputVal, int bits) {
-        if (inputVal.getPlatformKind() == AMD64Kind.QWORD && bits <= 32) {
-            // TODO make it possible to reinterpret Long as Int in LIR without move
-            return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.DWORD), AMD64RMOp.MOV, DWORD, inputVal);
-        } else {
-            return inputVal;
-        }
-    }
-
-    @Override
-    public Value emitSignExtend(Value inputVal, int fromBits, int toBits) {
-        assert fromBits <= toBits && toBits <= 64;
-        if (fromBits == toBits) {
-            return inputVal;
-        } else if (toBits > 32) {
-            // sign extend to 64 bits
-            switch (fromBits) {
-                case 8:
-                    return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.QWORD), MOVSXB, QWORD, inputVal);
-                case 16:
-                    return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.QWORD), MOVSX, QWORD, inputVal);
-                case 32:
-                    return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.QWORD), MOVSXD, QWORD, inputVal);
-                default:
-                    throw JVMCIError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
-            }
-        } else {
-            // sign extend to 32 bits (smaller values are internally represented as 32 bit values)
-            switch (fromBits) {
-                case 8:
-                    return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.DWORD), MOVSXB, DWORD, inputVal);
-                case 16:
-                    return emitConvertOp(LIRKind.combine(inputVal).changeType(AMD64Kind.DWORD), MOVSX, DWORD, inputVal);
-                case 32:
-                    return inputVal;
-                default:
-                    throw JVMCIError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)");
-            }
-        }
-    }
-
-    @Override
-    public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) {
-        assert fromBits <= toBits && toBits <= 64;
-        if (fromBits == toBits) {
-            return inputVal;
-        } else if (fromBits > 32) {
-            assert inputVal.getPlatformKind() == AMD64Kind.QWORD;
-            Variable result = newVariable(LIRKind.combine(inputVal));
-            long mask = CodeUtil.mask(fromBits);
-            append(new AMD64Binary.DataOp(AND.getRMOpcode(QWORD), QWORD, result, asAllocatable(inputVal), JavaConstant.forLong(mask)));
-            return result;
-        } else {
-            LIRKind resultKind = LIRKind.combine(inputVal);
-            if (toBits > 32) {
-                resultKind = resultKind.changeType(AMD64Kind.QWORD);
-            } else {
-                resultKind = resultKind.changeType(AMD64Kind.DWORD);
-            }
-
-            /*
-             * Always emit DWORD operations, even if the resultKind is Long. On AMD64, all DWORD
-             * operations implicitly set the upper half of the register to 0, which is what we want
-             * anyway. Compared to the QWORD oparations, the encoding of the DWORD operations is
-             * sometimes one byte shorter.
-             */
-            switch (fromBits) {
-                case 8:
-                    return emitConvertOp(resultKind, MOVZXB, DWORD, inputVal);
-                case 16:
-                    return emitConvertOp(resultKind, MOVZX, DWORD, inputVal);
-                case 32:
-                    return emitConvertOp(resultKind, MOV, DWORD, inputVal);
-            }
-
-            // odd bit count, fall back on manual masking
-            Variable result = newVariable(resultKind);
-            JavaConstant mask;
-            if (toBits > 32) {
-                mask = JavaConstant.forLong(CodeUtil.mask(fromBits));
-            } else {
-                mask = JavaConstant.forInt((int) CodeUtil.mask(fromBits));
-            }
-            append(new AMD64Binary.DataOp(AND.getRMOpcode(DWORD), DWORD, result, asAllocatable(inputVal), mask));
-            return result;
-        }
-    }
-
-    @Override
     public void emitMembar(int barriers) {
         int necessaryBarriers = target().arch.requiredBarriers(barriers);
         if (target().isMP && necessaryBarriers != 0) {
@@ -1420,119 +704,6 @@
     }
 
     @Override
-    public Variable emitBitCount(Value value) {
-        Variable result = newVariable(LIRKind.combine(value).changeType(AMD64Kind.DWORD));
-        assert ((AMD64Kind) value.getPlatformKind()).isInteger();
-        if (value.getPlatformKind() == AMD64Kind.QWORD) {
-            append(new AMD64Unary.RMOp(POPCNT, QWORD, result, asAllocatable(value)));
-        } else {
-            append(new AMD64Unary.RMOp(POPCNT, DWORD, result, asAllocatable(value)));
-        }
-        return result;
-    }
-
-    @Override
-    public Variable emitBitScanForward(Value value) {
-        Variable result = newVariable(LIRKind.combine(value).changeType(AMD64Kind.DWORD));
-        append(new AMD64Unary.RMOp(BSF, QWORD, result, asAllocatable(value)));
-        return result;
-    }
-
-    @Override
-    public Variable emitBitScanReverse(Value value) {
-        Variable result = newVariable(LIRKind.combine(value).changeType(AMD64Kind.DWORD));
-        assert ((AMD64Kind) value.getPlatformKind()).isInteger();
-        if (value.getPlatformKind() == AMD64Kind.QWORD) {
-            append(new AMD64Unary.RMOp(BSR, QWORD, result, asAllocatable(value)));
-        } else {
-            append(new AMD64Unary.RMOp(BSR, DWORD, result, asAllocatable(value)));
-        }
-        return result;
-    }
-
-    public Value emitCountLeadingZeros(Value value) {
-        Variable result = newVariable(LIRKind.combine(value).changeType(AMD64Kind.DWORD));
-        assert ((AMD64Kind) value.getPlatformKind()).isInteger();
-        if (value.getPlatformKind() == AMD64Kind.QWORD) {
-            append(new AMD64Unary.RMOp(LZCNT, QWORD, result, asAllocatable(value)));
-        } else {
-            append(new AMD64Unary.RMOp(LZCNT, DWORD, result, asAllocatable(value)));
-        }
-        return result;
-    }
-
-    public Value emitCountTrailingZeros(Value value) {
-        Variable result = newVariable(LIRKind.combine(value).changeType(AMD64Kind.DWORD));
-        assert ((AMD64Kind) value.getPlatformKind()).isInteger();
-        if (value.getPlatformKind() == AMD64Kind.QWORD) {
-            append(new AMD64Unary.RMOp(TZCNT, QWORD, result, asAllocatable(value)));
-        } else {
-            append(new AMD64Unary.RMOp(TZCNT, DWORD, result, asAllocatable(value)));
-        }
-        return result;
-    }
-
-    @Override
-    public Value emitMathAbs(Value input) {
-        Variable result = newVariable(LIRKind.combine(input));
-        switch ((AMD64Kind) input.getPlatformKind()) {
-            case SINGLE:
-                append(new AMD64Binary.DataOp(SSEOp.AND, PS, result, asAllocatable(input), JavaConstant.forFloat(Float.intBitsToFloat(0x7FFFFFFF)), 16));
-                break;
-            case DOUBLE:
-                append(new AMD64Binary.DataOp(SSEOp.AND, PD, result, asAllocatable(input), JavaConstant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)), 16));
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return result;
-    }
-
-    @Override
-    public Value emitMathSqrt(Value input) {
-        Variable result = newVariable(LIRKind.combine(input));
-        switch ((AMD64Kind) input.getPlatformKind()) {
-            case SINGLE:
-                append(new AMD64Unary.RMOp(SSEOp.SQRT, SS, result, asAllocatable(input)));
-                break;
-            case DOUBLE:
-                append(new AMD64Unary.RMOp(SSEOp.SQRT, SD, result, asAllocatable(input)));
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return result;
-    }
-
-    @Override
-    public Value emitMathLog(Value input, boolean base10) {
-        Variable result = newVariable(LIRKind.combine(input));
-        append(new AMD64MathIntrinsicOp(base10 ? LOG10 : LOG, result, asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Value emitMathCos(Value input) {
-        Variable result = newVariable(LIRKind.combine(input));
-        append(new AMD64MathIntrinsicOp(COS, result, asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Value emitMathSin(Value input) {
-        Variable result = newVariable(LIRKind.combine(input));
-        append(new AMD64MathIntrinsicOp(SIN, result, asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Value emitMathTan(Value input) {
-        Variable result = newVariable(LIRKind.combine(input));
-        append(new AMD64MathIntrinsicOp(TAN, result, asAllocatable(input)));
-        return result;
-    }
-
-    @Override
     public Variable emitByteSwap(Value input) {
         Variable result = newVariable(LIRKind.combine(input));
         append(new AMD64ByteSwapOp(result, input));
@@ -1571,5 +742,4 @@
     protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
         append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(LIRKind.value(target().arch.getWordKind())), newVariable(key.getLIRKind())));
     }
-
 }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Thu Oct 08 15:58:13 2015 -0700
@@ -84,7 +84,7 @@
                 if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) {
                     FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode;
                     if (otherDivRem.getX() == divRem.getX() && otherDivRem.getY() == divRem.getY() && !hasOperand(otherDivRem)) {
-                        Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.getX()), operand(divRem.getY()), state((DeoptimizingNode) valueNode));
+                        Value[] results = ((AMD64ArithmeticLIRGenerator) gen.getArithmetic()).emitIntegerDivRem(operand(divRem.getX()), operand(divRem.getY()), state((DeoptimizingNode) valueNode));
                         if (divRem instanceof IntegerDivNode) {
                             setResult(divRem, results[0]);
                             setResult(otherDivRem, results[1]);
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeMatchRules.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeMatchRules.java	Thu Oct 08 15:58:13 2015 -0700
@@ -196,7 +196,7 @@
         return builder -> {
             AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress());
             LIRFrameState state = getState(access);
-            return getLIRGeneratorTool().emitConvertMemoryOp(kind, op, size, address, state);
+            return getArithmeticLIRGenerator().emitConvertMemoryOp(kind, op, size, address, state);
         };
     }
 
@@ -276,7 +276,7 @@
     @MatchRule("(Or (LeftShift=lshift value Constant) (UnsignedRightShift=rshift value Constant))")
     public ComplexMatchResult rotateLeftConstant(LeftShiftNode lshift, UnsignedRightShiftNode rshift) {
         if ((lshift.getShiftAmountMask() & (lshift.getY().asJavaConstant().asInt() + rshift.getY().asJavaConstant().asInt())) == 0) {
-            return builder -> getLIRGeneratorTool().emitRol(operand(lshift.getX()), operand(lshift.getY()));
+            return builder -> getArithmeticLIRGenerator().emitRol(operand(lshift.getX()), operand(lshift.getY()));
         }
         return null;
     }
@@ -284,7 +284,7 @@
     @MatchRule("(Or (LeftShift value (Sub Constant=delta shiftAmount)) (UnsignedRightShift value shiftAmount))")
     public ComplexMatchResult rotateRightVariable(ValueNode value, ConstantNode delta, ValueNode shiftAmount) {
         if (delta.asJavaConstant().asLong() == 0 || delta.asJavaConstant().asLong() == 32) {
-            return builder -> getLIRGeneratorTool().emitRor(operand(value), operand(shiftAmount));
+            return builder -> getArithmeticLIRGenerator().emitRor(operand(value), operand(shiftAmount));
         }
         return null;
     }
@@ -292,13 +292,14 @@
     @MatchRule("(Or (LeftShift value shiftAmount) (UnsignedRightShift value (Sub Constant=delta shiftAmount)))")
     public ComplexMatchResult rotateLeftVariable(ValueNode value, ValueNode shiftAmount, ConstantNode delta) {
         if (delta.asJavaConstant().asLong() == 0 || delta.asJavaConstant().asLong() == 32) {
-            return builder -> getLIRGeneratorTool().emitRol(operand(value), operand(shiftAmount));
+            return builder -> getArithmeticLIRGenerator().emitRol(operand(value), operand(shiftAmount));
         }
         return null;
     }
 
     private ComplexMatchResult binaryRead(AMD64RMOp op, OperandSize size, ValueNode value, Access access) {
-        return builder -> getLIRGeneratorTool().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()), getState(access));
+        return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()),
+                        getState(access));
     }
 
     @MatchRule("(Add value Read=access)")
@@ -386,7 +387,7 @@
     @MatchRule("(ZeroExtend FloatingRead=access)")
     public ComplexMatchResult zeroExtend(ZeroExtendNode root, Access access) {
         AMD64Kind memoryKind = getMemoryKind(access);
-        return builder -> getLIRGeneratorTool().emitZeroExtendMemory(memoryKind, root.getResultBits(), (AMD64AddressValue) operand(access.getAddress()), getState(access));
+        return builder -> getArithmeticLIRGenerator().emitZeroExtendMemory(memoryKind, root.getResultBits(), (AMD64AddressValue) operand(access.getAddress()), getState(access));
     }
 
     @MatchRule("(FloatConvert Read=access)")
@@ -432,4 +433,8 @@
     public AMD64LIRGenerator getLIRGeneratorTool() {
         return (AMD64LIRGenerator) gen;
     }
+
+    protected AMD64ArithmeticLIRGenerator getArithmeticLIRGenerator() {
+        return (AMD64ArithmeticLIRGenerator) getLIRGeneratorTool().getArithmetic();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCArithmeticLIRGenerator.java	Thu Oct 08 15:58:13 2015 -0700
@@ -0,0 +1,670 @@
+/*
+ * Copyright (c) 2009, 2015, 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.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Add;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Addcc;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.And;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Mulx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Sdivx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Sllx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Sra;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Srax;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Srl;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Sub;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Subcc;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Udivx;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Xnor;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Faddd;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fadds;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fdivd;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fdivs;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fdtos;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fitod;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fitos;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fmuld;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fmuls;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fnegd;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fnegs;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fstod;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fxtod;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.UMulxhi;
+import static com.oracle.graal.lir.LIRValueUtil.asJavaConstant;
+import static com.oracle.graal.lir.LIRValueUtil.isJavaConstant;
+import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.BSF;
+import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.IBSR;
+import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.LBSR;
+import static jdk.internal.jvmci.code.CodeUtil.mask;
+import static jdk.internal.jvmci.meta.JavaConstant.forLong;
+import static jdk.internal.jvmci.sparc.SPARC.g0;
+import static jdk.internal.jvmci.sparc.SPARCKind.DOUBLE;
+import static jdk.internal.jvmci.sparc.SPARCKind.DWORD;
+import static jdk.internal.jvmci.sparc.SPARCKind.SINGLE;
+import static jdk.internal.jvmci.sparc.SPARCKind.WORD;
+import jdk.internal.jvmci.common.JVMCIError;
+import jdk.internal.jvmci.meta.AllocatableValue;
+import jdk.internal.jvmci.meta.JavaConstant;
+import jdk.internal.jvmci.meta.LIRKind;
+import jdk.internal.jvmci.meta.PlatformKind;
+import jdk.internal.jvmci.meta.Value;
+import jdk.internal.jvmci.sparc.SPARC;
+import jdk.internal.jvmci.sparc.SPARC.CPUFeature;
+import jdk.internal.jvmci.sparc.SPARCKind;
+
+import com.oracle.graal.asm.sparc.SPARCAssembler.Op3s;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Opfs;
+import com.oracle.graal.compiler.common.calc.FloatConvert;
+import com.oracle.graal.lir.ConstantValue;
+import com.oracle.graal.lir.LIRFrameState;
+import com.oracle.graal.lir.Variable;
+import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.sparc.SPARCArithmetic;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.FloatConvertOp;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.MulHighOp;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.MulHighOp.MulHigh;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.RemOp;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.RemOp.Rem;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.SPARCIMulccOp;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.SPARCLMulccOp;
+import com.oracle.graal.lir.sparc.SPARCBitManipulationOp;
+import com.oracle.graal.lir.sparc.SPARCMove.MoveFpGp;
+import com.oracle.graal.lir.sparc.SPARCOP3Op;
+import com.oracle.graal.lir.sparc.SPARCOPFOp;
+
+/**
+ * This class implements the SPARC specific portion of the LIR generator.
+ */
+public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator {
+
+    @Override
+    public SPARCLIRGenerator getLIRGen() {
+        return (SPARCLIRGenerator) super.getLIRGen();
+    }
+
+    @Override
+    public Variable emitBitCount(Value operand) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD));
+        Value usedOperand = operand;
+        if (operand.getPlatformKind() == SPARCKind.WORD) { // Zero extend
+            usedOperand = getLIRGen().newVariable(operand.getLIRKind());
+            getLIRGen().append(new SPARCOP3Op(Op3s.Srl, operand, SPARC.g0.asValue(), usedOperand));
+        }
+        getLIRGen().append(new SPARCOP3Op(Op3s.Popc, SPARC.g0.asValue(), usedOperand, result));
+        return result;
+    }
+
+    @Override
+    public Variable emitBitScanForward(Value operand) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD));
+        getLIRGen().append(new SPARCBitManipulationOp(BSF, result, getLIRGen().asAllocatable(operand), getLIRGen()));
+        return result;
+    }
+
+    @Override
+    public Variable emitBitScanReverse(Value operand) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD));
+        if (operand.getPlatformKind() == SPARCKind.DWORD) {
+            getLIRGen().append(new SPARCBitManipulationOp(LBSR, result, getLIRGen().asAllocatable(operand), getLIRGen()));
+        } else {
+            getLIRGen().append(new SPARCBitManipulationOp(IBSR, result, getLIRGen().asAllocatable(operand), getLIRGen()));
+        }
+        return result;
+    }
+
+    @Override
+    public Value emitMathAbs(Value input) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        SPARCKind kind = (SPARCKind) input.getPlatformKind();
+        Opfs opf;
+        switch (kind) {
+            case SINGLE:
+                opf = Opfs.Fabss;
+                break;
+            case DOUBLE:
+                opf = Opfs.Fabsd;
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere("Input kind: " + kind);
+        }
+        getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result));
+        return result;
+    }
+
+    @Override
+    public Value emitMathSqrt(Value input) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        SPARCKind kind = (SPARCKind) input.getPlatformKind();
+        Opfs opf;
+        switch (kind) {
+            case SINGLE:
+                opf = Opfs.Fsqrts;
+                break;
+            case DOUBLE:
+                opf = Opfs.Fsqrtd;
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere("Input kind: " + kind);
+        }
+        getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result));
+        return result;
+    }
+
+    @Override
+    public Value emitNegate(Value input) {
+        PlatformKind inputKind = input.getPlatformKind();
+        if (isNumericInteger(inputKind)) {
+            return emitUnary(Sub, input);
+        } else {
+            return emitUnary(inputKind.equals(DOUBLE) ? Fnegd : Fnegs, input);
+        }
+    }
+
+    @Override
+    public Value emitNot(Value input) {
+        return emitUnary(Xnor, input);
+    }
+
+    private Variable emitUnary(Opfs opf, Value input) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result));
+        return result;
+    }
+
+    private Variable emitUnary(Op3s op3, Value input) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
+        getLIRGen().append(SPARCOP3Op.newUnary(op3, input, result));
+        return result;
+    }
+
+    private Variable emitBinary(LIRKind resultKind, Opfs opf, Value a, Value b) {
+        return emitBinary(resultKind, opf, a, b, null);
+    }
+
+    private Variable emitBinary(LIRKind resultKind, Opfs opf, Value a, Value b, LIRFrameState state) {
+        Variable result = getLIRGen().newVariable(resultKind);
+        if (opf.isCommutative() && isJavaConstant(a) && getLIRGen().canInlineConstant(asJavaConstant(a))) {
+            getLIRGen().append(new SPARCOPFOp(opf, b, a, result, state));
+        } else {
+            getLIRGen().append(new SPARCOPFOp(opf, a, b, result, state));
+        }
+        return result;
+    }
+
+    private Variable emitBinary(LIRKind resultKind, Op3s op3, Value a, int b) {
+        return emitBinary(resultKind, op3, a, new ConstantValue(LIRKind.value(WORD), JavaConstant.forInt(b)));
+    }
+
+    private Variable emitBinary(LIRKind resultKind, Op3s op3, Value a, Value b) {
+        return emitBinary(resultKind, op3, a, b, null);
+    }
+
+    private Variable emitBinary(LIRKind resultKind, Op3s op3, Value a, Value b, LIRFrameState state) {
+        Variable result = getLIRGen().newVariable(resultKind);
+        if (op3.isCommutative() && isJavaConstant(a) && getLIRGen().canInlineConstant(asJavaConstant(a))) {
+            getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), a, result, state));
+        } else {
+            getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), b, result, state));
+        }
+        return result;
+    }
+
+    @Override
+    protected boolean isNumericInteger(PlatformKind kind) {
+        return ((SPARCKind) kind).isInteger();
+    }
+
+    @Override
+    public Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) {
+        if (isNumericInteger(a.getPlatformKind())) {
+            return emitBinary(resultKind, setFlags ? Addcc : Add, a, b);
+        } else {
+            boolean isDouble = a.getPlatformKind().equals(DOUBLE);
+            return emitBinary(resultKind, isDouble ? Faddd : Fadds, a, b);
+        }
+    }
+
+    @Override
+    public Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags) {
+        if (isNumericInteger(a.getPlatformKind())) {
+            return emitBinary(resultKind, setFlags ? Subcc : Sub, a, b);
+        } else {
+            boolean isDouble = a.getPlatformKind().equals(DOUBLE);
+            return emitBinary(resultKind, isDouble ? Opfs.Fsubd : Opfs.Fsubs, a, b);
+        }
+    }
+
+    @Override
+    public Variable emitMul(Value a, Value b, boolean setFlags) {
+        LIRKind resultKind = LIRKind.combine(a, b);
+        PlatformKind aKind = a.getPlatformKind();
+        if (isNumericInteger(aKind)) {
+            if (setFlags) {
+                Variable result = getLIRGen().newVariable(LIRKind.combine(a, b));
+                if (aKind == DWORD) {
+                    getLIRGen().append(new SPARCLMulccOp(result, getLIRGen().load(a), getLIRGen().load(b), getLIRGen()));
+                } else if (aKind == WORD) {
+                    getLIRGen().append(new SPARCIMulccOp(result, getLIRGen().load(a), getLIRGen().load(b)));
+                } else {
+                    throw JVMCIError.shouldNotReachHere();
+                }
+                return result;
+            } else {
+                return emitBinary(resultKind, setFlags ? Op3s.Mulscc : Op3s.Mulx, a, b);
+            }
+        } else {
+            boolean isDouble = a.getPlatformKind().equals(DOUBLE);
+            return emitBinary(resultKind, isDouble ? Fmuld : Fmuls, a, b);
+        }
+    }
+
+    @Override
+    public Value emitMulHigh(Value a, Value b) {
+        MulHigh opcode;
+        switch (((SPARCKind) a.getPlatformKind())) {
+            case WORD:
+                opcode = MulHigh.IMUL;
+                break;
+            case DWORD:
+                opcode = MulHigh.LMUL;
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return emitMulHigh(opcode, a, b);
+    }
+
+    @Override
+    public Value emitUMulHigh(Value a, Value b) {
+        switch (((SPARCKind) a.getPlatformKind())) {
+            case WORD:
+                Value aExtended = emitBinary(LIRKind.combine(a), Srl, a, 0);
+                Value bExtended = emitBinary(LIRKind.combine(b), Srl, b, 0);
+                Value result = emitBinary(LIRKind.combine(a, b), Mulx, aExtended, bExtended);
+                return emitBinary(LIRKind.combine(a, b), Srax, result, WORD.getSizeInBits());
+            case DWORD:
+                return emitBinary(LIRKind.combine(a, b), UMulxhi, a, b);
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+    }
+
+    private Value emitMulHigh(MulHigh opcode, Value a, Value b) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(a, b));
+        MulHighOp mulHigh = new MulHighOp(opcode, getLIRGen().load(a), getLIRGen().load(b), result, getLIRGen().newVariable(LIRKind.combine(a, b)));
+        getLIRGen().append(mulHigh);
+        return result;
+    }
+
+    @Override
+    public Value emitDiv(Value a, Value b, LIRFrameState state) {
+        LIRKind resultKind = LIRKind.combine(a, b);
+        PlatformKind aKind = a.getPlatformKind();
+        PlatformKind bKind = b.getPlatformKind();
+        if (isJavaConstant(b) && asJavaConstant(b).isDefaultForKind()) { // Div by zero
+            Value zero = SPARC.g0.asValue(LIRKind.value(SPARCKind.WORD));
+            return emitBinary(resultKind, Op3s.Sdivx, zero, zero, state);
+        } else if (isNumericInteger(aKind)) {
+            Value fixedA = emitSignExtend(a, aKind.getSizeInBytes() * 8, 64);
+            Value fixedB = emitSignExtend(b, bKind.getSizeInBytes() * 8, 64);
+            return emitBinary(resultKind, Op3s.Sdivx, fixedA, fixedB, state);
+        } else {
+            boolean isDouble = a.getPlatformKind().equals(DOUBLE);
+            return emitBinary(resultKind, isDouble ? Opfs.Fdivd : Opfs.Fdivs, a, b, state);
+        }
+    }
+
+    @Override
+    public Value emitRem(Value a, Value b, LIRFrameState state) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(a, b));
+        Value aLoaded;
+        Value bLoaded;
+        Variable q1; // Intermediate values
+        Variable q2;
+        Variable q3;
+        Variable q4;
+        SPARCKind aKind = (SPARCKind) a.getPlatformKind();
+        switch (aKind) {
+            case WORD:
+                q1 = emitBinary(result.getLIRKind(), Sra, a, g0.asValue(LIRKind.value(WORD)));
+                q2 = emitBinary(q1.getLIRKind(), Sdivx, q1, b, state);
+                q3 = emitBinary(q2.getLIRKind(), Op3s.Mulx, q2, b);
+                result = emitSub(q1, q3, false);
+                break;
+            case DWORD:
+                aLoaded = getLIRGen().load(a); // Reuse the loaded value
+                q1 = emitBinary(result.getLIRKind(), Sdivx, aLoaded, b, state);
+                q2 = emitBinary(result.getLIRKind(), Mulx, q1, b);
+                result = emitSub(aLoaded, q2, false);
+                break;
+            case SINGLE:
+                aLoaded = getLIRGen().load(a);
+                bLoaded = getLIRGen().load(b);
+                q1 = emitBinary(result.getLIRKind(), Fdivs, aLoaded, bLoaded, state);
+                q2 = getLIRGen().newVariable(LIRKind.value(aKind));
+                getLIRGen().append(new FloatConvertOp(FloatConvertOp.FloatConvert.F2I, q1, q2));
+                q3 = emitUnary(Fitos, q2);
+                q4 = emitBinary(LIRKind.value(aKind), Fmuls, q3, bLoaded);
+                result = emitSub(aLoaded, q4, false);
+                break;
+            case DOUBLE:
+                aLoaded = getLIRGen().load(a);
+                bLoaded = getLIRGen().load(b);
+                q1 = emitBinary(result.getLIRKind(), Fdivd, aLoaded, bLoaded, state);
+                q2 = getLIRGen().newVariable(LIRKind.value(aKind));
+                getLIRGen().append(new FloatConvertOp(FloatConvertOp.FloatConvert.D2L, q1, q2));
+                q3 = emitUnary(Fxtod, q2);
+                q4 = emitBinary(result.getLIRKind(), Fmuld, q3, bLoaded);
+                result = emitSub(aLoaded, q4, false);
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere("missing: " + a.getPlatformKind());
+        }
+        return result;
+    }
+
+    @Override
+    public Value emitURem(Value a, Value b, LIRFrameState state) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(a, b));
+        Variable scratch1 = getLIRGen().newVariable(LIRKind.combine(a, b));
+        Variable scratch2 = getLIRGen().newVariable(LIRKind.combine(a, b));
+        Rem opcode;
+        switch (((SPARCKind) a.getPlatformKind())) {
+            case WORD:
+                opcode = Rem.IUREM;
+                break;
+            case DWORD:
+                opcode = Rem.LUREM;
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        getLIRGen().append(new RemOp(opcode, result, getLIRGen().load(a), getLIRGen().load(b), scratch1, scratch2, state));
+        return result;
+
+    }
+
+    @Override
+    public Value emitUDiv(Value a, Value b, LIRFrameState state) {
+        Value actualA = a;
+        Value actualB = b;
+        switch (((SPARCKind) a.getPlatformKind())) {
+            case WORD:
+                actualA = emitZeroExtend(actualA, 32, 64);
+                actualB = emitZeroExtend(actualB, 32, 64);
+                break;
+            case DWORD:
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return emitBinary(LIRKind.combine(actualA, actualB), Udivx, actualA, actualB, state);
+    }
+
+    @Override
+    public Variable emitAnd(Value a, Value b) {
+        LIRKind resultKind = LIRKind.combine(a, b);
+        return emitBinary(resultKind, Op3s.And, a, b);
+    }
+
+    @Override
+    public Variable emitOr(Value a, Value b) {
+        LIRKind resultKind = LIRKind.combine(a, b);
+        return emitBinary(resultKind, Op3s.Or, a, b);
+    }
+
+    @Override
+    public Variable emitXor(Value a, Value b) {
+        LIRKind resultKind = LIRKind.combine(a, b);
+        return emitBinary(resultKind, Op3s.Xor, a, b);
+    }
+
+    @Override
+    public Variable emitShl(Value a, Value b) {
+        SPARCKind aKind = (SPARCKind) a.getPlatformKind();
+        LIRKind resultKind = LIRKind.combine(a, b).changeType(aKind);
+        Op3s op;
+        switch (aKind) {
+            case WORD:
+                op = Op3s.Sll;
+                break;
+            case DWORD:
+                op = Op3s.Sllx;
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return emitBinary(resultKind, op, a, b);
+    }
+
+    @Override
+    public Variable emitShr(Value a, Value b) {
+        SPARCKind aKind = (SPARCKind) a.getPlatformKind();
+        LIRKind resultKind = LIRKind.combine(a, b).changeType(aKind);
+        Op3s op;
+        switch (aKind) {
+            case WORD:
+                op = Op3s.Sra;
+                break;
+            case DWORD:
+                op = Op3s.Srax;
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return emitBinary(resultKind, op, a, b);
+    }
+
+    @Override
+    public Variable emitUShr(Value a, Value b) {
+        SPARCKind aKind = (SPARCKind) a.getPlatformKind();
+        LIRKind resultKind = LIRKind.combine(a, b).changeType(aKind);
+        Op3s op;
+        switch (aKind) {
+            case WORD:
+                op = Op3s.Srl;
+                break;
+            case DWORD:
+                op = Op3s.Srlx;
+                break;
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return emitBinary(resultKind, op, a, b);
+    }
+
+    private AllocatableValue emitConvertMove(LIRKind kind, AllocatableValue input) {
+        Variable result = getLIRGen().newVariable(kind);
+        getLIRGen().emitMove(result, input);
+        return result;
+    }
+
+    @Override
+    public Value emitFloatConvert(FloatConvert op, Value inputVal) {
+        AllocatableValue input = getLIRGen().asAllocatable(inputVal);
+        Value result;
+        switch (op) {
+            case D2F:
+                result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(SINGLE));
+                getLIRGen().append(new SPARCOPFOp(Fdtos, inputVal, result));
+                break;
+            case F2D:
+                result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(DOUBLE));
+                getLIRGen().append(new SPARCOPFOp(Fstod, inputVal, result));
+                break;
+            case I2F: {
+                AllocatableValue intEncodedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE));
+                result = getLIRGen().newVariable(intEncodedFloatReg.getLIRKind());
+                moveBetweenFpGp(intEncodedFloatReg, input);
+                getLIRGen().append(new SPARCOPFOp(Fitos, intEncodedFloatReg, result));
+                break;
+            }
+            case I2D: {
+                // Unfortunately we must do int -> float -> double because fitod has float
+                // and double encoding in one instruction
+                AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE));
+                result = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE));
+                moveBetweenFpGp(convertedFloatReg, input);
+                getLIRGen().append(new SPARCOPFOp(Fitod, convertedFloatReg, result));
+                break;
+            }
+            case L2D: {
+                AllocatableValue longEncodedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE));
+                moveBetweenFpGp(longEncodedDoubleReg, input);
+                AllocatableValue convertedDoubleReg = getLIRGen().newVariable(longEncodedDoubleReg.getLIRKind());
+                getLIRGen().append(new SPARCOPFOp(Fxtod, longEncodedDoubleReg, convertedDoubleReg));
+                result = convertedDoubleReg;
+                break;
+            }
+            case D2I: {
+                AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE));
+                getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2I, input, convertedFloatReg));
+                AllocatableValue convertedIntReg = getLIRGen().newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD));
+                moveBetweenFpGp(convertedIntReg, convertedFloatReg);
+                result = convertedIntReg;
+                break;
+            }
+            case F2L: {
+                AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE));
+                getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2L, input, convertedDoubleReg));
+                AllocatableValue convertedLongReg = getLIRGen().newVariable(LIRKind.combine(convertedDoubleReg).changeType(DWORD));
+                moveBetweenFpGp(convertedLongReg, convertedDoubleReg);
+                result = convertedLongReg;
+                break;
+            }
+            case F2I: {
+                AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE));
+                getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2I, input, convertedFloatReg));
+                AllocatableValue convertedIntReg = getLIRGen().newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD));
+                moveBetweenFpGp(convertedIntReg, convertedFloatReg);
+                result = convertedIntReg;
+                break;
+            }
+            case D2L: {
+                AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE));
+                getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2L, input, convertedDoubleReg));
+                AllocatableValue convertedLongReg = getLIRGen().newVariable(LIRKind.combine(convertedDoubleReg).changeType(DWORD));
+                moveBetweenFpGp(convertedLongReg, convertedDoubleReg);
+                result = convertedLongReg;
+                break;
+            }
+            case L2F: {
+                AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE));
+                result = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE));
+                moveBetweenFpGp(convertedDoubleReg, input);
+                getLIRGen().append(new SPARCOPFOp(Opfs.Fxtos, convertedDoubleReg, result));
+                break;
+            }
+            default:
+                throw JVMCIError.shouldNotReachHere();
+        }
+        return result;
+    }
+
+    private void moveBetweenFpGp(AllocatableValue dst, AllocatableValue src) {
+        AllocatableValue tempSlot;
+        if (getLIRGen().getArchitecture().getFeatures().contains(CPUFeature.VIS3)) {
+            tempSlot = AllocatableValue.ILLEGAL;
+        } else {
+            tempSlot = getLIRGen().getTempSlot(LIRKind.value(DWORD));
+        }
+        getLIRGen().append(new MoveFpGp(dst, src, tempSlot));
+    }
+
+    @Override
+    public Value emitNarrow(Value inputVal, int bits) {
+        if (inputVal.getPlatformKind() == DWORD && bits <= 32) {
+            LIRKind resultKind = LIRKind.combine(inputVal).changeType(WORD);
+            Variable result = getLIRGen().newVariable(resultKind);
+            getLIRGen().emitMove(result, inputVal);
+            return result;
+        } else {
+            return inputVal;
+        }
+    }
+
+    @Override
+    public Value emitSignExtend(Value inputVal, int fromBits, int toBits) {
+        assert fromBits <= toBits && toBits <= DWORD.getSizeInBits();
+        LIRKind shiftKind = LIRKind.value(WORD);
+        LIRKind resultKind = LIRKind.combine(inputVal).changeType(toBits > 32 ? DWORD : WORD);
+        Value result;
+        int shiftCount = DWORD.getSizeInBits() - fromBits;
+        if (fromBits == toBits) {
+            result = inputVal;
+        } else if (isJavaConstant(inputVal)) {
+            JavaConstant javaConstant = asJavaConstant(inputVal);
+            long constant;
+            if (javaConstant.isNull()) {
+                constant = 0;
+            } else {
+                constant = javaConstant.asLong();
+            }
+            return new ConstantValue(resultKind, JavaConstant.forLong((constant << shiftCount) >> shiftCount));
+        } else if (fromBits == WORD.getSizeInBits() && toBits == DWORD.getSizeInBits()) {
+            result = getLIRGen().newVariable(resultKind);
+            getLIRGen().append(new SPARCOP3Op(Sra, inputVal, SPARC.g0.asValue(LIRKind.value(WORD)), result));
+        } else {
+            Variable tmp = getLIRGen().newVariable(resultKind.changeType(DWORD));
+            result = getLIRGen().newVariable(resultKind);
+            getLIRGen().append(new SPARCOP3Op(Sllx, inputVal, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), tmp));
+            getLIRGen().append(new SPARCOP3Op(Srax, tmp, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), result));
+        }
+        return result;
+    }
+
+    @Override
+    public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) {
+        assert fromBits <= toBits && toBits <= 64;
+        if (fromBits == toBits) {
+            return inputVal;
+        }
+        Variable result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(toBits > WORD.getSizeInBits() ? DWORD : WORD));
+        if (fromBits == 32) {
+            getLIRGen().append(new SPARCOP3Op(Srl, inputVal, g0.asValue(), result));
+        } else {
+            Value mask = getLIRGen().emitConstant(LIRKind.value(DWORD), forLong(mask(fromBits)));
+            getLIRGen().append(new SPARCOP3Op(And, inputVal, mask, result));
+        }
+        return result;
+    }
+
+    @Override
+    public AllocatableValue emitReinterpret(LIRKind to, Value inputVal) {
+        SPARCKind fromKind = (SPARCKind) inputVal.getPlatformKind();
+        SPARCKind toKind = (SPARCKind) to.getPlatformKind();
+        AllocatableValue input = getLIRGen().asAllocatable(inputVal);
+        Variable result = getLIRGen().newVariable(to);
+        // These cases require a move between CPU and FPU registers:
+        if (fromKind.isFloat() != toKind.isFloat()) {
+            moveBetweenFpGp(result, input);
+            return result;
+        } else {
+            // Otherwise, just emit an ordinary move instruction.
+            // Instructions that move or generate 32-bit register values also set the upper 32
+            // bits of the register to zero.
+            // Consequently, there is no need for a special zero-extension move.
+            return emitConvertMove(to, input);
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Oct 08 15:58:13 2015 -0700
@@ -27,48 +27,14 @@
 import static com.oracle.graal.asm.sparc.SPARCAssembler.FMOVSCC;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.MOVicc;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.CC.Fcc0;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Add;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Addcc;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.And;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Mulx;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Sdivx;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Sllx;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Sra;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Srax;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Srl;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Sub;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Subcc;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Udivx;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Xnor;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Faddd;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fadds;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fcmpd;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fcmps;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fdivd;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fdivs;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fdtos;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fitod;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fitos;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fmuld;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fmuls;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fnegd;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fnegs;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fstod;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fxtod;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.UMulxhi;
 import static com.oracle.graal.lir.LIRValueUtil.asJavaConstant;
 import static com.oracle.graal.lir.LIRValueUtil.isJavaConstant;
-import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.BSF;
-import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.IBSR;
-import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.LBSR;
-import static jdk.internal.jvmci.code.CodeUtil.mask;
 import static jdk.internal.jvmci.code.ValueUtil.isStackSlotValue;
-import static jdk.internal.jvmci.meta.JavaConstant.forLong;
-import static jdk.internal.jvmci.sparc.SPARC.g0;
-import static jdk.internal.jvmci.sparc.SPARCKind.DOUBLE;
 import static jdk.internal.jvmci.sparc.SPARCKind.DWORD;
 import static jdk.internal.jvmci.sparc.SPARCKind.SINGLE;
-import static jdk.internal.jvmci.sparc.SPARCKind.WORD;
 import jdk.internal.jvmci.code.CallingConvention;
 import jdk.internal.jvmci.code.StackSlotValue;
 import jdk.internal.jvmci.common.JVMCIError;
@@ -80,7 +46,6 @@
 import jdk.internal.jvmci.meta.PlatformKind;
 import jdk.internal.jvmci.meta.Value;
 import jdk.internal.jvmci.sparc.SPARC;
-import jdk.internal.jvmci.sparc.SPARC.CPUFeature;
 import jdk.internal.jvmci.sparc.SPARCKind;
 
 import com.oracle.graal.asm.sparc.SPARCAssembler;
@@ -90,7 +55,6 @@
 import com.oracle.graal.asm.sparc.SPARCAssembler.Op3s;
 import com.oracle.graal.asm.sparc.SPARCAssembler.Opfs;
 import com.oracle.graal.compiler.common.calc.Condition;
-import com.oracle.graal.compiler.common.calc.FloatConvert;
 import com.oracle.graal.compiler.common.spi.ForeignCallLinkage;
 import com.oracle.graal.compiler.common.spi.LIRKindTool;
 import com.oracle.graal.lir.ConstantValue;
@@ -106,16 +70,7 @@
 import com.oracle.graal.lir.gen.LIRGenerator;
 import com.oracle.graal.lir.gen.SpillMoveFactoryBase;
 import com.oracle.graal.lir.sparc.SPARCAddressValue;
-import com.oracle.graal.lir.sparc.SPARCArithmetic;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.MulHighOp;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.MulHighOp.MulHigh;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.RemOp;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.RemOp.Rem;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.SPARCIMulccOp;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.SPARCLMulccOp;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.FloatConvertOp;
 import com.oracle.graal.lir.sparc.SPARCArrayEqualsOp;
-import com.oracle.graal.lir.sparc.SPARCBitManipulationOp;
 import com.oracle.graal.lir.sparc.SPARCByteSwapOp;
 import com.oracle.graal.lir.sparc.SPARCCall;
 import com.oracle.graal.lir.sparc.SPARCControlFlow;
@@ -134,11 +89,9 @@
 import com.oracle.graal.lir.sparc.SPARCMove.LoadOp;
 import com.oracle.graal.lir.sparc.SPARCMove.MembarOp;
 import com.oracle.graal.lir.sparc.SPARCMove.Move;
-import com.oracle.graal.lir.sparc.SPARCMove.MoveFpGp;
 import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp;
 import com.oracle.graal.lir.sparc.SPARCOP3Op;
-import com.oracle.graal.lir.sparc.SPARCOPFOp;
 import com.oracle.graal.phases.util.Providers;
 
 /**
@@ -168,8 +121,8 @@
         }
     }
 
-    public SPARCLIRGenerator(LIRKindTool lirKindTool, Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) {
-        super(lirKindTool, providers, cc, lirGenRes);
+    public SPARCLIRGenerator(LIRKindTool lirKindTool, SPARCArithmeticLIRGenerator arithmeticLIRGen, Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        super(lirKindTool, arithmeticLIRGen, providers, cc, lirGenRes);
     }
 
     public SpillMoveFactory getSpillMoveFactory() {
@@ -373,7 +326,7 @@
             if (from == to) {
                 return v;
             } else {
-                return emitSignExtend(v, fromBytes, toBytes);
+                return arithmeticLIRGen.emitSignExtend(v, fromBytes, toBytes);
             }
         }
     }
@@ -477,10 +430,10 @@
         int compareBytes = cmpKind.getSizeInBytes();
         // SPARC compares 32 or 64 bits
         if (compareBytes < left.getPlatformKind().getSizeInBytes()) {
-            left = emitSignExtend(left, compareBytes * 8, DWORD.getSizeInBytes() * 8);
+            left = arithmeticLIRGen.emitSignExtend(left, compareBytes * 8, DWORD.getSizeInBytes() * 8);
         }
         if (compareBytes < right.getPlatformKind().getSizeInBytes()) {
-            right = emitSignExtend(right, compareBytes * 8, DWORD.getSizeInBytes() * 8);
+            right = arithmeticLIRGen.emitSignExtend(right, compareBytes * 8, DWORD.getSizeInBytes() * 8);
         }
         append(SPARCOP3Op.newBinaryVoid(Subcc, left, right));
         return mirrored;
@@ -548,72 +501,12 @@
         append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(LIRKind.value(target().arch.getWordKind()))));
     }
 
-    @Override
-    public Variable emitBitCount(Value operand) {
-        Variable result = newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD));
-        Value usedOperand = operand;
-        if (operand.getPlatformKind() == SPARCKind.WORD) { // Zero extend
-            usedOperand = newVariable(operand.getLIRKind());
-            append(new SPARCOP3Op(Op3s.Srl, operand, SPARC.g0.asValue(), usedOperand));
-        }
-        append(new SPARCOP3Op(Op3s.Popc, SPARC.g0.asValue(), usedOperand, result));
-        return result;
-    }
-
-    @Override
-    public Variable emitBitScanForward(Value operand) {
-        Variable result = newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD));
-        append(new SPARCBitManipulationOp(BSF, result, asAllocatable(operand), this));
-        return result;
-    }
-
-    @Override
-    public Variable emitBitScanReverse(Value operand) {
-        Variable result = newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD));
-        if (operand.getPlatformKind() == SPARCKind.DWORD) {
-            append(new SPARCBitManipulationOp(LBSR, result, asAllocatable(operand), this));
-        } else {
-            append(new SPARCBitManipulationOp(IBSR, result, asAllocatable(operand), this));
-        }
-        return result;
+    protected StackSlotValue getTempSlot(LIRKind kind) {
+        return getResult().getFrameMapBuilder().allocateSpillSlot(kind);
     }
 
-    @Override
-    public Value emitMathAbs(Value input) {
-        Variable result = newVariable(LIRKind.combine(input));
-        SPARCKind kind = (SPARCKind) input.getPlatformKind();
-        Opfs opf;
-        switch (kind) {
-            case SINGLE:
-                opf = Opfs.Fabss;
-                break;
-            case DOUBLE:
-                opf = Opfs.Fabsd;
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere("Input kind: " + kind);
-        }
-        append(new SPARCOPFOp(opf, g0.asValue(), input, result));
-        return result;
-    }
-
-    @Override
-    public Value emitMathSqrt(Value input) {
-        Variable result = newVariable(LIRKind.combine(input));
-        SPARCKind kind = (SPARCKind) input.getPlatformKind();
-        Opfs opf;
-        switch (kind) {
-            case SINGLE:
-                opf = Opfs.Fsqrts;
-                break;
-            case DOUBLE:
-                opf = Opfs.Fsqrtd;
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere("Input kind: " + kind);
-        }
-        append(new SPARCOPFOp(opf, g0.asValue(), input, result));
-        return result;
+    protected SPARC getArchitecture() {
+        return (SPARC) target().arch;
     }
 
     @Override
@@ -631,512 +524,6 @@
     }
 
     @Override
-    public Value emitNegate(Value input) {
-        PlatformKind inputKind = input.getPlatformKind();
-        if (isNumericInteger(inputKind)) {
-            return emitUnary(Sub, input);
-        } else {
-            return emitUnary(inputKind.equals(DOUBLE) ? Fnegd : Fnegs, input);
-        }
-    }
-
-    @Override
-    public Value emitNot(Value input) {
-        return emitUnary(Xnor, input);
-    }
-
-    private Variable emitUnary(Opfs opf, Value input) {
-        Variable result = newVariable(LIRKind.combine(input));
-        append(new SPARCOPFOp(opf, g0.asValue(), input, result));
-        return result;
-    }
-
-    private Variable emitUnary(Op3s op3, Value input) {
-        Variable result = newVariable(LIRKind.combine(input));
-        append(SPARCOP3Op.newUnary(op3, input, result));
-        return result;
-    }
-
-    private Variable emitBinary(LIRKind resultKind, Opfs opf, Value a, Value b) {
-        return emitBinary(resultKind, opf, a, b, null);
-    }
-
-    private Variable emitBinary(LIRKind resultKind, Opfs opf, Value a, Value b, LIRFrameState state) {
-        Variable result = newVariable(resultKind);
-        if (opf.isCommutative() && isJavaConstant(a) && canInlineConstant(asJavaConstant(a))) {
-            append(new SPARCOPFOp(opf, b, a, result, state));
-        } else {
-            append(new SPARCOPFOp(opf, a, b, result, state));
-        }
-        return result;
-    }
-
-    private Variable emitBinary(LIRKind resultKind, Op3s op3, Value a, int b) {
-        return emitBinary(resultKind, op3, a, new ConstantValue(LIRKind.value(WORD), JavaConstant.forInt(b)));
-    }
-
-    private Variable emitBinary(LIRKind resultKind, Op3s op3, Value a, Value b) {
-        return emitBinary(resultKind, op3, a, b, null);
-    }
-
-    private Variable emitBinary(LIRKind resultKind, Op3s op3, Value a, Value b, LIRFrameState state) {
-        Variable result = newVariable(resultKind);
-        if (op3.isCommutative() && isJavaConstant(a) && canInlineConstant(asJavaConstant(a))) {
-            append(new SPARCOP3Op(op3, load(b), a, result, state));
-        } else {
-            append(new SPARCOP3Op(op3, load(a), b, result, state));
-        }
-        return result;
-    }
-
-    @Override
-    protected boolean isNumericInteger(PlatformKind kind) {
-        return ((SPARCKind) kind).isInteger();
-    }
-
-    @Override
-    public Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) {
-        if (isNumericInteger(a.getPlatformKind())) {
-            return emitBinary(resultKind, setFlags ? Addcc : Add, a, b);
-        } else {
-            boolean isDouble = a.getPlatformKind().equals(DOUBLE);
-            return emitBinary(resultKind, isDouble ? Faddd : Fadds, a, b);
-        }
-    }
-
-    @Override
-    public Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags) {
-        if (isNumericInteger(a.getPlatformKind())) {
-            return emitBinary(resultKind, setFlags ? Subcc : Sub, a, b);
-        } else {
-            boolean isDouble = a.getPlatformKind().equals(DOUBLE);
-            return emitBinary(resultKind, isDouble ? Opfs.Fsubd : Opfs.Fsubs, a, b);
-        }
-    }
-
-    @Override
-    public Variable emitMul(Value a, Value b, boolean setFlags) {
-        LIRKind resultKind = LIRKind.combine(a, b);
-        PlatformKind aKind = a.getPlatformKind();
-        if (isNumericInteger(aKind)) {
-            if (setFlags) {
-                Variable result = newVariable(LIRKind.combine(a, b));
-                if (aKind == DWORD) {
-                    append(new SPARCLMulccOp(result, load(a), load(b), this));
-                } else if (aKind == WORD) {
-                    append(new SPARCIMulccOp(result, load(a), load(b)));
-                } else {
-                    throw JVMCIError.shouldNotReachHere();
-                }
-                return result;
-            } else {
-                return emitBinary(resultKind, setFlags ? Op3s.Mulscc : Op3s.Mulx, a, b);
-            }
-        } else {
-            boolean isDouble = a.getPlatformKind().equals(DOUBLE);
-            return emitBinary(resultKind, isDouble ? Fmuld : Fmuls, a, b);
-        }
-    }
-
-    @Override
-    public Value emitMulHigh(Value a, Value b) {
-        MulHigh opcode;
-        switch (((SPARCKind) a.getPlatformKind())) {
-            case WORD:
-                opcode = MulHigh.IMUL;
-                break;
-            case DWORD:
-                opcode = MulHigh.LMUL;
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return emitMulHigh(opcode, a, b);
-    }
-
-    @Override
-    public Value emitUMulHigh(Value a, Value b) {
-        switch (((SPARCKind) a.getPlatformKind())) {
-            case WORD:
-                Value aExtended = emitBinary(LIRKind.combine(a), Srl, a, 0);
-                Value bExtended = emitBinary(LIRKind.combine(b), Srl, b, 0);
-                Value result = emitBinary(LIRKind.combine(a, b), Mulx, aExtended, bExtended);
-                return emitBinary(LIRKind.combine(a, b), Srax, result, WORD.getSizeInBits());
-            case DWORD:
-                return emitBinary(LIRKind.combine(a, b), UMulxhi, a, b);
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-    private Value emitMulHigh(MulHigh opcode, Value a, Value b) {
-        Variable result = newVariable(LIRKind.combine(a, b));
-        MulHighOp mulHigh = new MulHighOp(opcode, load(a), load(b), result, newVariable(LIRKind.combine(a, b)));
-        append(mulHigh);
-        return result;
-    }
-
-    @Override
-    public Value emitDiv(Value a, Value b, LIRFrameState state) {
-        LIRKind resultKind = LIRKind.combine(a, b);
-        PlatformKind aKind = a.getPlatformKind();
-        PlatformKind bKind = b.getPlatformKind();
-        if (isJavaConstant(b) && asJavaConstant(b).isDefaultForKind()) { // Div by zero
-            Value zero = SPARC.g0.asValue(LIRKind.value(SPARCKind.WORD));
-            return emitBinary(resultKind, Op3s.Sdivx, zero, zero, state);
-        } else if (isNumericInteger(aKind)) {
-            Value fixedA = emitSignExtend(a, aKind.getSizeInBytes() * 8, 64);
-            Value fixedB = emitSignExtend(b, bKind.getSizeInBytes() * 8, 64);
-            return emitBinary(resultKind, Op3s.Sdivx, fixedA, fixedB, state);
-        } else {
-            boolean isDouble = a.getPlatformKind().equals(DOUBLE);
-            return emitBinary(resultKind, isDouble ? Opfs.Fdivd : Opfs.Fdivs, a, b, state);
-        }
-    }
-
-    @Override
-    public Value emitRem(Value a, Value b, LIRFrameState state) {
-        Variable result = newVariable(LIRKind.combine(a, b));
-        Value aLoaded;
-        Value bLoaded;
-        Variable q1; // Intermediate values
-        Variable q2;
-        Variable q3;
-        Variable q4;
-        SPARCKind aKind = (SPARCKind) a.getPlatformKind();
-        switch (aKind) {
-            case WORD:
-                q1 = emitBinary(result.getLIRKind(), Sra, a, g0.asValue(LIRKind.value(WORD)));
-                q2 = emitBinary(q1.getLIRKind(), Sdivx, q1, b, state);
-                q3 = emitBinary(q2.getLIRKind(), Op3s.Mulx, q2, b);
-                result = emitSub(q1, q3, false);
-                break;
-            case DWORD:
-                aLoaded = load(a); // Reuse the loaded value
-                q1 = emitBinary(result.getLIRKind(), Sdivx, aLoaded, b, state);
-                q2 = emitBinary(result.getLIRKind(), Mulx, q1, b);
-                result = emitSub(aLoaded, q2, false);
-                break;
-            case SINGLE:
-                aLoaded = load(a);
-                bLoaded = load(b);
-                q1 = emitBinary(result.getLIRKind(), Fdivs, aLoaded, bLoaded, state);
-                q2 = newVariable(LIRKind.value(aKind));
-                append(new FloatConvertOp(FloatConvertOp.FloatConvert.F2I, q1, q2));
-                q3 = emitUnary(Fitos, q2);
-                q4 = emitBinary(LIRKind.value(aKind), Fmuls, q3, bLoaded);
-                result = emitSub(aLoaded, q4, false);
-                break;
-            case DOUBLE:
-                aLoaded = load(a);
-                bLoaded = load(b);
-                q1 = emitBinary(result.getLIRKind(), Fdivd, aLoaded, bLoaded, state);
-                q2 = newVariable(LIRKind.value(aKind));
-                append(new FloatConvertOp(FloatConvertOp.FloatConvert.D2L, q1, q2));
-                q3 = emitUnary(Fxtod, q2);
-                q4 = emitBinary(result.getLIRKind(), Fmuld, q3, bLoaded);
-                result = emitSub(aLoaded, q4, false);
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere("missing: " + a.getPlatformKind());
-        }
-        return result;
-    }
-
-    @Override
-    public Value emitURem(Value a, Value b, LIRFrameState state) {
-        Variable result = newVariable(LIRKind.combine(a, b));
-        Variable scratch1 = newVariable(LIRKind.combine(a, b));
-        Variable scratch2 = newVariable(LIRKind.combine(a, b));
-        Rem opcode;
-        switch (((SPARCKind) a.getPlatformKind())) {
-            case WORD:
-                opcode = Rem.IUREM;
-                break;
-            case DWORD:
-                opcode = Rem.LUREM;
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        append(new RemOp(opcode, result, load(a), load(b), scratch1, scratch2, state));
-        return result;
-
-    }
-
-    @Override
-    public Value emitUDiv(Value a, Value b, LIRFrameState state) {
-        Value actualA = a;
-        Value actualB = b;
-        switch (((SPARCKind) a.getPlatformKind())) {
-            case WORD:
-                actualA = emitZeroExtend(actualA, 32, 64);
-                actualB = emitZeroExtend(actualB, 32, 64);
-                break;
-            case DWORD:
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return emitBinary(LIRKind.combine(actualA, actualB), Udivx, actualA, actualB, state);
-    }
-
-    @Override
-    public Variable emitAnd(Value a, Value b) {
-        LIRKind resultKind = LIRKind.combine(a, b);
-        return emitBinary(resultKind, Op3s.And, a, b);
-    }
-
-    @Override
-    public Variable emitOr(Value a, Value b) {
-        LIRKind resultKind = LIRKind.combine(a, b);
-        return emitBinary(resultKind, Op3s.Or, a, b);
-    }
-
-    @Override
-    public Variable emitXor(Value a, Value b) {
-        LIRKind resultKind = LIRKind.combine(a, b);
-        return emitBinary(resultKind, Op3s.Xor, a, b);
-    }
-
-    @Override
-    public Variable emitShl(Value a, Value b) {
-        SPARCKind aKind = (SPARCKind) a.getPlatformKind();
-        LIRKind resultKind = LIRKind.combine(a, b).changeType(aKind);
-        Op3s op;
-        switch (aKind) {
-            case WORD:
-                op = Op3s.Sll;
-                break;
-            case DWORD:
-                op = Op3s.Sllx;
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return emitBinary(resultKind, op, a, b);
-    }
-
-    @Override
-    public Variable emitShr(Value a, Value b) {
-        SPARCKind aKind = (SPARCKind) a.getPlatformKind();
-        LIRKind resultKind = LIRKind.combine(a, b).changeType(aKind);
-        Op3s op;
-        switch (aKind) {
-            case WORD:
-                op = Op3s.Sra;
-                break;
-            case DWORD:
-                op = Op3s.Srax;
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return emitBinary(resultKind, op, a, b);
-    }
-
-    @Override
-    public Variable emitUShr(Value a, Value b) {
-        SPARCKind aKind = (SPARCKind) a.getPlatformKind();
-        LIRKind resultKind = LIRKind.combine(a, b).changeType(aKind);
-        Op3s op;
-        switch (aKind) {
-            case WORD:
-                op = Op3s.Srl;
-                break;
-            case DWORD:
-                op = Op3s.Srlx;
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return emitBinary(resultKind, op, a, b);
-    }
-
-    private AllocatableValue emitConvertMove(LIRKind kind, AllocatableValue input) {
-        Variable result = newVariable(kind);
-        emitMove(result, input);
-        return result;
-    }
-
-    @Override
-    public Value emitFloatConvert(FloatConvert op, Value inputVal) {
-        AllocatableValue input = asAllocatable(inputVal);
-        Value result;
-        switch (op) {
-            case D2F:
-                result = newVariable(LIRKind.combine(inputVal).changeType(SINGLE));
-                append(new SPARCOPFOp(Fdtos, inputVal, result));
-                break;
-            case F2D:
-                result = newVariable(LIRKind.combine(inputVal).changeType(DOUBLE));
-                append(new SPARCOPFOp(Fstod, inputVal, result));
-                break;
-            case I2F: {
-                AllocatableValue intEncodedFloatReg = newVariable(LIRKind.combine(input).changeType(SINGLE));
-                result = newVariable(intEncodedFloatReg.getLIRKind());
-                moveBetweenFpGp(intEncodedFloatReg, input);
-                append(new SPARCOPFOp(Fitos, intEncodedFloatReg, result));
-                break;
-            }
-            case I2D: {
-                // Unfortunately we must do int -> float -> double because fitod has float
-                // and double encoding in one instruction
-                AllocatableValue convertedFloatReg = newVariable(LIRKind.combine(input).changeType(SINGLE));
-                result = newVariable(LIRKind.combine(input).changeType(DOUBLE));
-                moveBetweenFpGp(convertedFloatReg, input);
-                append(new SPARCOPFOp(Fitod, convertedFloatReg, result));
-                break;
-            }
-            case L2D: {
-                AllocatableValue longEncodedDoubleReg = newVariable(LIRKind.combine(input).changeType(DOUBLE));
-                moveBetweenFpGp(longEncodedDoubleReg, input);
-                AllocatableValue convertedDoubleReg = newVariable(longEncodedDoubleReg.getLIRKind());
-                append(new SPARCOPFOp(Fxtod, longEncodedDoubleReg, convertedDoubleReg));
-                result = convertedDoubleReg;
-                break;
-            }
-            case D2I: {
-                AllocatableValue convertedFloatReg = newVariable(LIRKind.combine(input).changeType(SINGLE));
-                append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2I, input, convertedFloatReg));
-                AllocatableValue convertedIntReg = newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD));
-                moveBetweenFpGp(convertedIntReg, convertedFloatReg);
-                result = convertedIntReg;
-                break;
-            }
-            case F2L: {
-                AllocatableValue convertedDoubleReg = newVariable(LIRKind.combine(input).changeType(DOUBLE));
-                append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2L, input, convertedDoubleReg));
-                AllocatableValue convertedLongReg = newVariable(LIRKind.combine(convertedDoubleReg).changeType(DWORD));
-                moveBetweenFpGp(convertedLongReg, convertedDoubleReg);
-                result = convertedLongReg;
-                break;
-            }
-            case F2I: {
-                AllocatableValue convertedFloatReg = newVariable(LIRKind.combine(input).changeType(SINGLE));
-                append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2I, input, convertedFloatReg));
-                AllocatableValue convertedIntReg = newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD));
-                moveBetweenFpGp(convertedIntReg, convertedFloatReg);
-                result = convertedIntReg;
-                break;
-            }
-            case D2L: {
-                AllocatableValue convertedDoubleReg = newVariable(LIRKind.combine(input).changeType(DOUBLE));
-                append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2L, input, convertedDoubleReg));
-                AllocatableValue convertedLongReg = newVariable(LIRKind.combine(convertedDoubleReg).changeType(DWORD));
-                moveBetweenFpGp(convertedLongReg, convertedDoubleReg);
-                result = convertedLongReg;
-                break;
-            }
-            case L2F: {
-                AllocatableValue convertedDoubleReg = newVariable(LIRKind.combine(input).changeType(DOUBLE));
-                result = newVariable(LIRKind.combine(input).changeType(SINGLE));
-                moveBetweenFpGp(convertedDoubleReg, input);
-                append(new SPARCOPFOp(Opfs.Fxtos, convertedDoubleReg, result));
-                break;
-            }
-            default:
-                throw JVMCIError.shouldNotReachHere();
-        }
-        return result;
-    }
-
-    private void moveBetweenFpGp(AllocatableValue dst, AllocatableValue src) {
-        AllocatableValue tempSlot;
-        if (getArchitecture().getFeatures().contains(CPUFeature.VIS3)) {
-            tempSlot = AllocatableValue.ILLEGAL;
-        } else {
-            tempSlot = getTempSlot(LIRKind.value(DWORD));
-        }
-        append(new MoveFpGp(dst, src, tempSlot));
-    }
-
-    protected StackSlotValue getTempSlot(LIRKind kind) {
-        return getResult().getFrameMapBuilder().allocateSpillSlot(kind);
-    }
-
-    protected SPARC getArchitecture() {
-        return (SPARC) target().arch;
-    }
-
-    @Override
-    public Value emitNarrow(Value inputVal, int bits) {
-        if (inputVal.getPlatformKind() == DWORD && bits <= 32) {
-            LIRKind resultKind = LIRKind.combine(inputVal).changeType(WORD);
-            Variable result = newVariable(resultKind);
-            emitMove(result, inputVal);
-            return result;
-        } else {
-            return inputVal;
-        }
-    }
-
-    @Override
-    public Value emitSignExtend(Value inputVal, int fromBits, int toBits) {
-        assert fromBits <= toBits && toBits <= DWORD.getSizeInBits();
-        LIRKind shiftKind = LIRKind.value(WORD);
-        LIRKind resultKind = LIRKind.combine(inputVal).changeType(toBits > 32 ? DWORD : WORD);
-        Value result;
-        int shiftCount = DWORD.getSizeInBits() - fromBits;
-        if (fromBits == toBits) {
-            result = inputVal;
-        } else if (isJavaConstant(inputVal)) {
-            JavaConstant javaConstant = asJavaConstant(inputVal);
-            long constant;
-            if (javaConstant.isNull()) {
-                constant = 0;
-            } else {
-                constant = javaConstant.asLong();
-            }
-            return new ConstantValue(resultKind, JavaConstant.forLong((constant << shiftCount) >> shiftCount));
-        } else if (fromBits == WORD.getSizeInBits() && toBits == DWORD.getSizeInBits()) {
-            result = newVariable(resultKind);
-            append(new SPARCOP3Op(Sra, inputVal, SPARC.g0.asValue(LIRKind.value(WORD)), result));
-        } else {
-            Variable tmp = newVariable(resultKind.changeType(DWORD));
-            result = newVariable(resultKind);
-            append(new SPARCOP3Op(Sllx, inputVal, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), tmp));
-            append(new SPARCOP3Op(Srax, tmp, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), result));
-        }
-        return result;
-    }
-
-    @Override
-    public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) {
-        assert fromBits <= toBits && toBits <= 64;
-        if (fromBits == toBits) {
-            return inputVal;
-        }
-        Variable result = newVariable(LIRKind.combine(inputVal).changeType(toBits > WORD.getSizeInBits() ? DWORD : WORD));
-        if (fromBits == 32) {
-            append(new SPARCOP3Op(Srl, inputVal, g0.asValue(), result));
-        } else {
-            Value mask = emitConstant(LIRKind.value(DWORD), forLong(mask(fromBits)));
-            append(new SPARCOP3Op(And, inputVal, mask, result));
-        }
-        return result;
-    }
-
-    @Override
-    public AllocatableValue emitReinterpret(LIRKind to, Value inputVal) {
-        SPARCKind fromKind = (SPARCKind) inputVal.getPlatformKind();
-        SPARCKind toKind = (SPARCKind) to.getPlatformKind();
-        AllocatableValue input = asAllocatable(inputVal);
-        Variable result = newVariable(to);
-        // These cases require a move between CPU and FPU registers:
-        if (fromKind.isFloat() != toKind.isFloat()) {
-            moveBetweenFpGp(result, input);
-            return result;
-        } else {
-            // Otherwise, just emit an ordinary move instruction.
-            // Instructions that move or generate 32-bit register values also set the upper 32
-            // bits of the register to zero.
-            // Consequently, there is no need for a special zero-extension move.
-            return emitConvertMove(to, input);
-        }
-    }
-
-    @Override
     public void emitMembar(int barriers) {
         int necessaryBarriers = target().arch.requiredBarriers(barriers);
         if (target().isMP && necessaryBarriers != 0) {
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeMatchRules.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeMatchRules.java	Thu Oct 08 15:58:13 2015 -0700
@@ -88,7 +88,7 @@
         SPARCKind localToKind = toKind;
         return builder -> {
             Value v = getLIRGeneratorTool().emitSignExtendLoad(LIRKind.value(localFromKind), operand(access.getAddress()), getState(access));
-            return getLIRGeneratorTool().emitReinterpret(LIRKind.value(localToKind), v);
+            return getArithmeticLIRGenerator().emitReinterpret(LIRKind.value(localToKind), v);
         };
     }
 
@@ -123,7 +123,7 @@
         return builder -> {
             // Loads are always zero extending load
             Value v = getLIRGeneratorTool().emitLoad(LIRKind.value(localFromKind), operand(access.getAddress()), getState(access));
-            return getLIRGeneratorTool().emitReinterpret(LIRKind.value(localToKind), v);
+            return getArithmeticLIRGenerator().emitReinterpret(LIRKind.value(localToKind), v);
         };
     }
 
@@ -143,4 +143,8 @@
     public SPARCLIRGenerator getLIRGeneratorTool() {
         return (SPARCLIRGenerator) super.getLIRGeneratorTool();
     }
+
+    protected SPARCArithmeticLIRGenerator getArithmeticLIRGenerator() {
+        return (SPARCArithmeticLIRGenerator) getLIRGeneratorTool().getArithmetic();
+    }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Thu Oct 08 15:58:13 2015 -0700
@@ -105,7 +105,6 @@
 import com.oracle.graal.nodes.cfg.ControlFlowGraph;
 import com.oracle.graal.nodes.extended.IntegerSwitchNode;
 import com.oracle.graal.nodes.extended.SwitchNode;
-import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
 import com.oracle.graal.nodes.spi.LIRLowerable;
 import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 import com.oracle.graal.nodes.spi.NodeValueMap;
@@ -427,8 +426,6 @@
         }
         if (node instanceof LIRLowerable) {
             ((LIRLowerable) node).generate(this);
-        } else if (node instanceof ArithmeticLIRLowerable) {
-            ((ArithmeticLIRLowerable) node).generate(this, gen);
         } else {
             throw JVMCIError.shouldNotReachHere("node is not LIRLowerable: " + node);
         }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Thu Oct 08 15:58:13 2015 -0700
@@ -50,6 +50,7 @@
 import com.oracle.graal.asm.amd64.AMD64Address;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.asm.amd64.AMD64MacroAssembler;
+import com.oracle.graal.compiler.amd64.AMD64ArithmeticLIRGenerator;
 import com.oracle.graal.compiler.amd64.AMD64NodeMatchRules;
 import com.oracle.graal.compiler.common.alloc.RegisterAllocationConfig;
 import com.oracle.graal.compiler.gen.BytecodeLIRBuilder;
@@ -96,7 +97,7 @@
 
     @Override
     public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
-        return new AMD64HotSpotLIRGenerator(getProviders(), config(), cc, lirGenRes);
+        return new AMD64HotSpotLIRGenerator(new AMD64ArithmeticLIRGenerator(), getProviders(), config(), cc, lirGenRes);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Oct 08 15:58:13 2015 -0700
@@ -66,6 +66,7 @@
 import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MIOp;
 import com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize;
+import com.oracle.graal.compiler.amd64.AMD64ArithmeticLIRGenerator;
 import com.oracle.graal.compiler.amd64.AMD64LIRGenerator;
 import com.oracle.graal.compiler.common.GraalOptions;
 import com.oracle.graal.compiler.common.spi.ForeignCallLinkage;
@@ -112,12 +113,13 @@
     final HotSpotVMConfig config;
     private HotSpotLockStack lockStack;
 
-    protected AMD64HotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
-        this(new AMD64HotSpotLIRKindTool(), providers, config, cc, lirGenRes);
+    protected AMD64HotSpotLIRGenerator(AMD64ArithmeticLIRGenerator arithmeticLIRGen, HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        this(new AMD64HotSpotLIRKindTool(), arithmeticLIRGen, providers, config, cc, lirGenRes);
     }
 
-    protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
-        super(lirKindTool, providers, cc, lirGenRes);
+    protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc,
+                    LIRGenerationResult lirGenRes) {
+        super(lirKindTool, arithmeticLIRGen, providers, cc, lirGenRes);
         assert config.basicLockSize == 8;
         this.config = config;
     }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Thu Oct 08 15:58:13 2015 -0700
@@ -64,6 +64,7 @@
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
 import com.oracle.graal.compiler.common.alloc.RegisterAllocationConfig;
 import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
+import com.oracle.graal.compiler.sparc.SPARCArithmeticLIRGenerator;
 import com.oracle.graal.compiler.sparc.SPARCNodeMatchRules;
 import com.oracle.graal.debug.Debug;
 import com.oracle.graal.debug.DebugMetric;
@@ -135,7 +136,7 @@
 
     @Override
     public LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) {
-        return new SPARCHotSpotLIRGenerator(getProviders(), config(), cc, lirGenRes);
+        return new SPARCHotSpotLIRGenerator(new SPARCArithmeticLIRGenerator(), getProviders(), config(), cc, lirGenRes);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Thu Oct 08 15:58:13 2015 -0700
@@ -98,6 +98,7 @@
 import com.oracle.graal.compiler.common.calc.Condition;
 import com.oracle.graal.compiler.common.spi.ForeignCallLinkage;
 import com.oracle.graal.compiler.common.spi.LIRKindTool;
+import com.oracle.graal.compiler.sparc.SPARCArithmeticLIRGenerator;
 import com.oracle.graal.compiler.sparc.SPARCLIRGenerator;
 import com.oracle.graal.hotspot.HotSpotBackend;
 import com.oracle.graal.hotspot.HotSpotForeignCallLinkage;
@@ -132,12 +133,13 @@
     private HotSpotLockStack lockStack;
     private LIRFrameState currentRuntimeCallInfo;
 
-    public SPARCHotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
-        this(new SPARCHotSpotLIRKindTool(), providers, config, cc, lirGenRes);
+    public SPARCHotSpotLIRGenerator(SPARCArithmeticLIRGenerator arithmeticLIRGen, HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
+        this(new SPARCHotSpotLIRKindTool(), arithmeticLIRGen, providers, config, cc, lirGenRes);
     }
 
-    protected SPARCHotSpotLIRGenerator(LIRKindTool lirKindTool, HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) {
-        super(lirKindTool, providers, cc, lirGenRes);
+    protected SPARCHotSpotLIRGenerator(LIRKindTool lirKindTool, SPARCArithmeticLIRGenerator arithmeticLIRGen, HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc,
+                    LIRGenerationResult lirGenRes) {
+        super(lirKindTool, arithmeticLIRGen, providers, cc, lirGenRes);
         assert config.basicLockSize == 8;
         this.config = config;
     }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArithmeticLIRGenerator.java	Thu Oct 08 14:58:22 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, 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 jdk.internal.jvmci.meta.Value;
-
-/**
- * This interface can be used to generate AMD64 LIR for arithmetic operations.
- */
-public interface AMD64ArithmeticLIRGenerator {
-
-    Value emitMathLog(Value input, boolean base10);
-
-    Value emitMathCos(Value input);
-
-    Value emitMathSin(Value input);
-
-    Value emitMathTan(Value input);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArithmeticLIRGeneratorTool.java	Thu Oct 08 15:58:13 2015 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, 2014, 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.lir.gen.ArithmeticLIRGeneratorTool;
+
+import jdk.internal.jvmci.meta.Value;
+
+/**
+ * This interface can be used to generate AMD64 LIR for arithmetic operations.
+ */
+public interface AMD64ArithmeticLIRGeneratorTool extends ArithmeticLIRGeneratorTool {
+
+    Value emitMathLog(Value input, boolean base10);
+
+    Value emitMathCos(Value input);
+
+    Value emitMathSin(Value input);
+
+    Value emitMathTan(Value input);
+
+    Value emitCountLeadingZeros(Value value);
+
+    Value emitCountTrailingZeros(Value value);
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Thu Oct 08 15:58:13 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, 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
@@ -22,71 +22,111 @@
  */
 package com.oracle.graal.lir.gen;
 
+import jdk.internal.jvmci.meta.AllocatableValue;
 import jdk.internal.jvmci.meta.LIRKind;
+import jdk.internal.jvmci.meta.PlatformKind;
 import jdk.internal.jvmci.meta.Value;
 
-import com.oracle.graal.compiler.common.calc.FloatConvert;
-import com.oracle.graal.compiler.common.type.Stamp;
-import com.oracle.graal.lir.LIRFrameState;
+import com.oracle.graal.lir.Variable;
 
 /**
- * This interface can be used to generate LIR for arithmetic operations.
- *
- * The setFlags flag in emitAdd, emitSub and emitMul indicates, that the instruction must set the
- * flags register to be used for a later branch. (On AMD64, the condition codes are set in every
- * arithmetic instruction, but other architectures optionally set the flags register) If setFlags is
- * set, the instruction must set the flags register; if false, the instruction may or may not set
- * the flags register.
+ * This class traverses the HIR instructions and generates LIR instructions from them.
  */
-public interface ArithmeticLIRGenerator {
+public abstract class ArithmeticLIRGenerator implements ArithmeticLIRGeneratorTool {
+
+    LIRGenerator lirGen;
 
-    LIRKind getLIRKind(Stamp stamp);
+    public LIRGenerator getLIRGen() {
+        return lirGen;
+    }
 
-    Value emitNegate(Value input);
+    // automatic derived reference handling
 
-    Value emitAdd(Value a, Value b, boolean setFlags);
-
-    Value emitSub(Value a, Value b, boolean setFlags);
+    protected abstract boolean isNumericInteger(PlatformKind kind);
 
-    Value emitMul(Value a, Value b, boolean setFlags);
-
-    Value emitMulHigh(Value a, Value b);
+    protected abstract Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags);
 
-    Value emitUMulHigh(Value a, Value b);
-
-    Value emitDiv(Value a, Value b, LIRFrameState state);
+    @Override
+    public final Variable emitAdd(Value aVal, Value bVal, boolean setFlags) {
+        LIRKind resultKind;
+        Value a = aVal;
+        Value b = bVal;
 
-    Value emitRem(Value a, Value b, LIRFrameState state);
-
-    Value emitUDiv(Value a, Value b, LIRFrameState state);
+        if (isNumericInteger(a.getPlatformKind())) {
+            LIRKind aKind = a.getLIRKind();
+            LIRKind bKind = b.getLIRKind();
+            assert a.getPlatformKind() == b.getPlatformKind();
 
-    Value emitURem(Value a, Value b, LIRFrameState state);
-
-    Value emitNot(Value input);
-
-    Value emitAnd(Value a, Value b);
+            if (aKind.isUnknownReference()) {
+                resultKind = aKind;
+            } else if (bKind.isUnknownReference()) {
+                resultKind = bKind;
+            } else if (aKind.isValue() && bKind.isValue()) {
+                resultKind = aKind;
+            } else if (aKind.isValue()) {
+                if (bKind.isDerivedReference()) {
+                    resultKind = bKind;
+                } else {
+                    AllocatableValue allocatable = getLIRGen().asAllocatable(b);
+                    resultKind = bKind.makeDerivedReference(allocatable);
+                    b = allocatable;
+                }
+            } else if (bKind.isValue()) {
+                if (aKind.isDerivedReference()) {
+                    resultKind = aKind;
+                } else {
+                    AllocatableValue allocatable = getLIRGen().asAllocatable(a);
+                    resultKind = aKind.makeDerivedReference(allocatable);
+                    a = allocatable;
+                }
+            } else {
+                resultKind = aKind.makeUnknownReference();
+            }
+        } else {
+            resultKind = LIRKind.combine(a, b);
+        }
 
-    Value emitOr(Value a, Value b);
-
-    Value emitXor(Value a, Value b);
+        return emitAdd(resultKind, a, b, setFlags);
+    }
 
-    Value emitShl(Value a, Value b);
-
-    Value emitShr(Value a, Value b);
+    protected abstract Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags);
 
-    Value emitUShr(Value a, Value b);
-
-    Value emitFloatConvert(FloatConvert op, Value inputVal);
+    @Override
+    public final Variable emitSub(Value aVal, Value bVal, boolean setFlags) {
+        LIRKind resultKind;
+        Value a = aVal;
+        Value b = bVal;
 
-    Value emitReinterpret(LIRKind to, Value inputVal);
+        if (isNumericInteger(a.getPlatformKind())) {
+            LIRKind aKind = a.getLIRKind();
+            LIRKind bKind = b.getLIRKind();
+            assert a.getPlatformKind() == b.getPlatformKind();
 
-    Value emitNarrow(Value inputVal, int bits);
+            if (aKind.isUnknownReference()) {
+                resultKind = aKind;
+            } else if (bKind.isUnknownReference()) {
+                resultKind = bKind;
+            }
 
-    Value emitSignExtend(Value inputVal, int fromBits, int toBits);
-
-    Value emitZeroExtend(Value inputVal, int fromBits, int toBits);
+            if (aKind.isValue() && bKind.isValue()) {
+                resultKind = aKind;
+            } else if (bKind.isValue()) {
+                if (aKind.isDerivedReference()) {
+                    resultKind = aKind;
+                } else {
+                    AllocatableValue allocatable = getLIRGen().asAllocatable(a);
+                    resultKind = aKind.makeDerivedReference(allocatable);
+                    a = allocatable;
+                }
+            } else if (aKind.isDerivedReference() && bKind.isDerivedReference() && aKind.getDerivedReferenceBase().equals(bKind.getDerivedReferenceBase())) {
+                resultKind = LIRKind.value(a.getPlatformKind());
+            } else {
+                resultKind = aKind.makeUnknownReference();
+            }
+        } else {
+            resultKind = LIRKind.combine(a, b);
+        }
 
-    Value emitMathAbs(Value input);
-
-    Value emitMathSqrt(Value input);
+        return emitSub(resultKind, a, b, setFlags);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGeneratorTool.java	Thu Oct 08 15:58:13 2015 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, 2014, 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.gen;
+
+import jdk.internal.jvmci.meta.LIRKind;
+import jdk.internal.jvmci.meta.Value;
+
+import com.oracle.graal.compiler.common.calc.FloatConvert;
+import com.oracle.graal.lir.LIRFrameState;
+
+/**
+ * This interface can be used to generate LIR for arithmetic operations.
+ *
+ * The setFlags flag in emitAdd, emitSub and emitMul indicates, that the instruction must set the
+ * flags register to be used for a later branch. (On AMD64, the condition codes are set in every
+ * arithmetic instruction, but other architectures optionally set the flags register) If setFlags is
+ * set, the instruction must set the flags register; if false, the instruction may or may not set
+ * the flags register.
+ */
+public interface ArithmeticLIRGeneratorTool {
+
+    Value emitNegate(Value input);
+
+    Value emitAdd(Value a, Value b, boolean setFlags);
+
+    Value emitSub(Value a, Value b, boolean setFlags);
+
+    Value emitMul(Value a, Value b, boolean setFlags);
+
+    Value emitMulHigh(Value a, Value b);
+
+    Value emitUMulHigh(Value a, Value b);
+
+    Value emitDiv(Value a, Value b, LIRFrameState state);
+
+    Value emitRem(Value a, Value b, LIRFrameState state);
+
+    Value emitUDiv(Value a, Value b, LIRFrameState state);
+
+    Value emitURem(Value a, Value b, LIRFrameState state);
+
+    Value emitNot(Value input);
+
+    Value emitAnd(Value a, Value b);
+
+    Value emitOr(Value a, Value b);
+
+    Value emitXor(Value a, Value b);
+
+    Value emitShl(Value a, Value b);
+
+    Value emitShr(Value a, Value b);
+
+    Value emitUShr(Value a, Value b);
+
+    Value emitFloatConvert(FloatConvert op, Value inputVal);
+
+    Value emitReinterpret(LIRKind to, Value inputVal);
+
+    Value emitNarrow(Value inputVal, int bits);
+
+    Value emitSignExtend(Value inputVal, int fromBits, int toBits);
+
+    Value emitZeroExtend(Value inputVal, int fromBits, int toBits);
+
+    Value emitMathAbs(Value input);
+
+    Value emitMathSqrt(Value input);
+
+    Value emitBitCount(Value operand);
+
+    Value emitBitScanForward(Value operand);
+
+    Value emitBitScanReverse(Value operand);
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Thu Oct 08 15:58:13 2015 -0700
@@ -95,11 +95,22 @@
 
     private LIRGenerationResult res;
 
-    public LIRGenerator(LIRKindTool lirKindTool, CodeGenProviders providers, CallingConvention cc, LIRGenerationResult res) {
+    protected final ArithmeticLIRGenerator arithmeticLIRGen;
+
+    public LIRGenerator(LIRKindTool lirKindTool, ArithmeticLIRGenerator arithmeticLIRGen, CodeGenProviders providers, CallingConvention cc, LIRGenerationResult res) {
         this.lirKindTool = lirKindTool;
+        this.arithmeticLIRGen = arithmeticLIRGen;
         this.res = res;
         this.providers = providers;
         this.cc = cc;
+
+        assert arithmeticLIRGen.lirGen == null;
+        arithmeticLIRGen.lirGen = this;
+    }
+
+    @Override
+    public ArithmeticLIRGeneratorTool getArithmetic() {
+        return arithmeticLIRGen;
     }
 
     @Override
@@ -126,7 +137,7 @@
         return providers.getForeignCalls();
     }
 
-    protected LIRKindTool getLIRKindTool() {
+    public LIRKindTool getLIRKindTool() {
         return lirKindTool;
     }
 
@@ -194,7 +205,7 @@
      * @return True if the constant can be used directly, false if the constant needs to be in a
      *         register.
      */
-    protected abstract boolean canInlineConstant(JavaConstant c);
+    public abstract boolean canInlineConstant(JavaConstant c);
 
     public Value loadNonConst(Value value) {
         if (isJavaConstant(value) && !canInlineConstant(asJavaConstant(value))) {
@@ -426,92 +437,4 @@
     public LIRInstruction createMultiBenchmarkCounter(String[] names, String[] groups, Value[] increments) {
         throw JVMCIError.unimplemented();
     }
-
-    // automatic derived reference handling
-
-    protected abstract boolean isNumericInteger(PlatformKind kind);
-
-    protected abstract Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags);
-
-    public final Variable emitAdd(Value aVal, Value bVal, boolean setFlags) {
-        LIRKind resultKind;
-        Value a = aVal;
-        Value b = bVal;
-
-        if (isNumericInteger(a.getPlatformKind())) {
-            LIRKind aKind = a.getLIRKind();
-            LIRKind bKind = b.getLIRKind();
-            assert a.getPlatformKind() == b.getPlatformKind();
-
-            if (aKind.isUnknownReference()) {
-                resultKind = aKind;
-            } else if (bKind.isUnknownReference()) {
-                resultKind = bKind;
-            } else if (aKind.isValue() && bKind.isValue()) {
-                resultKind = aKind;
-            } else if (aKind.isValue()) {
-                if (bKind.isDerivedReference()) {
-                    resultKind = bKind;
-                } else {
-                    AllocatableValue allocatable = asAllocatable(b);
-                    resultKind = bKind.makeDerivedReference(allocatable);
-                    b = allocatable;
-                }
-            } else if (bKind.isValue()) {
-                if (aKind.isDerivedReference()) {
-                    resultKind = aKind;
-                } else {
-                    AllocatableValue allocatable = asAllocatable(a);
-                    resultKind = aKind.makeDerivedReference(allocatable);
-                    a = allocatable;
-                }
-            } else {
-                resultKind = aKind.makeUnknownReference();
-            }
-        } else {
-            resultKind = LIRKind.combine(a, b);
-        }
-
-        return emitAdd(resultKind, a, b, setFlags);
-    }
-
-    protected abstract Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags);
-
-    public final Variable emitSub(Value aVal, Value bVal, boolean setFlags) {
-        LIRKind resultKind;
-        Value a = aVal;
-        Value b = bVal;
-
-        if (isNumericInteger(a.getPlatformKind())) {
-            LIRKind aKind = a.getLIRKind();
-            LIRKind bKind = b.getLIRKind();
-            assert a.getPlatformKind() == b.getPlatformKind();
-
-            if (aKind.isUnknownReference()) {
-                resultKind = aKind;
-            } else if (bKind.isUnknownReference()) {
-                resultKind = bKind;
-            }
-
-            if (aKind.isValue() && bKind.isValue()) {
-                resultKind = aKind;
-            } else if (bKind.isValue()) {
-                if (aKind.isDerivedReference()) {
-                    resultKind = aKind;
-                } else {
-                    AllocatableValue allocatable = asAllocatable(a);
-                    resultKind = aKind.makeDerivedReference(allocatable);
-                    a = allocatable;
-                }
-            } else if (aKind.isDerivedReference() && bKind.isDerivedReference() && aKind.getDerivedReferenceBase().equals(bKind.getDerivedReferenceBase())) {
-                resultKind = LIRKind.value(a.getPlatformKind());
-            } else {
-                resultKind = aKind.makeUnknownReference();
-            }
-        } else {
-            resultKind = LIRKind.combine(a, b);
-        }
-
-        return emitSub(resultKind, a, b, setFlags);
-    }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Thu Oct 08 15:58:13 2015 -0700
@@ -43,13 +43,14 @@
 import com.oracle.graal.compiler.common.spi.CodeGenProviders;
 import com.oracle.graal.compiler.common.spi.ForeignCallLinkage;
 import com.oracle.graal.compiler.common.spi.ForeignCallsProvider;
+import com.oracle.graal.compiler.common.type.Stamp;
 import com.oracle.graal.lir.LIRFrameState;
 import com.oracle.graal.lir.LIRInstruction;
 import com.oracle.graal.lir.LabelRef;
 import com.oracle.graal.lir.SwitchStrategy;
 import com.oracle.graal.lir.Variable;
 
-public interface LIRGeneratorTool extends ArithmeticLIRGenerator, BenchmarkCounterFactory {
+public interface LIRGeneratorTool extends BenchmarkCounterFactory {
 
     /**
      * Factory for creating spill moves.
@@ -74,6 +75,8 @@
 
     }
 
+    ArithmeticLIRGeneratorTool getArithmetic();
+
     CodeGenProviders getProviders();
 
     TargetDescription target();
@@ -228,26 +231,11 @@
 
     CallingConvention getCallingConvention();
 
-    Variable emitBitCount(Value operand);
-
-    Variable emitBitScanForward(Value operand);
-
-    Variable emitBitScanReverse(Value operand);
-
     Variable emitByteSwap(Value operand);
 
     Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length);
 
     void emitBlackhole(Value operand);
 
-    @SuppressWarnings("unused")
-    default Value emitCountLeadingZeros(Value value) {
-        throw JVMCIError.unimplemented();
-    }
-
-    @SuppressWarnings("unused")
-    default Value emitCountTrailingZeros(Value value) {
-        throw JVMCIError.unimplemented();
-    }
-
+    LIRKind getLIRKind(Stamp stamp);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AbsNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -26,11 +26,11 @@
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Abs;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * Absolute value.
@@ -56,7 +56,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitMathAbs(nodeValueMap.operand(getValue())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -32,11 +32,11 @@
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 @NodeInfo(shortName = "+")
 public class AddNode extends BinaryArithmeticNode<Add> implements NarrowableArithmeticNode, BinaryCommutative<ValueNode> {
@@ -112,7 +112,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         Value op1 = nodeValueMap.operand(getX());
         assert op1 != null : getX() + ", this=" + this;
         Value op2 = nodeValueMap.operand(getY());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -35,11 +35,11 @@
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 import com.oracle.graal.nodes.util.GraphUtil;
 
 @NodeInfo(shortName = "&")
@@ -106,7 +106,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitAnd(nodeValueMap.operand(getX()), nodeValueMap.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -32,11 +32,11 @@
 import com.oracle.graal.compiler.common.type.Stamp;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 @NodeInfo(shortName = "/")
 public final class DivNode extends BinaryArithmeticNode<Div> {
@@ -94,7 +94,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitDiv(nodeValueMap.operand(getX()), nodeValueMap.operand(getY()), null));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -32,13 +32,13 @@
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
 import com.oracle.graal.nodes.spi.Lowerable;
 import com.oracle.graal.nodes.spi.LoweringTool;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * A {@code FloatConvert} converts between integers and floating point numbers according to Java
@@ -117,7 +117,8 @@
         tool.getLowerer().lower(this, tool);
     }
 
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    @Override
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitFloatConvert(getFloatConvert(), nodeValueMap.operand(getValue())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -119,7 +119,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
+        gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitDiv(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -79,7 +79,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
+        gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitRem(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -28,11 +28,11 @@
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp.Shl;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 @NodeInfo(shortName = "<<")
 public final class LeftShiftNode extends ShiftNode<Shl> {
@@ -86,7 +86,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitShl(nodeValueMap.operand(getX()), nodeValueMap.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -34,11 +34,11 @@
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 @NodeInfo(shortName = "*")
 public class MulNode extends BinaryArithmeticNode<Mul> implements NarrowableArithmeticNode, BinaryCommutative<ValueNode> {
@@ -97,7 +97,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         Value op1 = nodeValueMap.operand(getX());
         Value op2 = nodeValueMap.operand(getY());
         if (!getY().isConstant() && !BinaryArithmeticNode.livesLonger(this, getY(), nodeValueMap)) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -29,10 +29,10 @@
 import com.oracle.graal.compiler.common.type.PrimitiveStamp;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * The {@code NarrowNode} converts an integer to a narrower integer.
@@ -109,7 +109,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitNarrow(nodeValueMap.operand(getValue()), getResultBits()));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -26,10 +26,10 @@
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Neg;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * The {@code NegateNode} node negates its operand.
@@ -60,7 +60,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitNegate(nodeValueMap.operand(getValue())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -26,11 +26,11 @@
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Not;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * Binary negation of long or integer values.
@@ -57,7 +57,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitNot(nodeValueMap.operand(getValue())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -34,11 +34,11 @@
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 import com.oracle.graal.nodes.util.GraphUtil;
 
 @NodeInfo(shortName = "|")
@@ -93,7 +93,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitOr(nodeValueMap.operand(getX()), nodeValueMap.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -34,12 +34,12 @@
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * The {@code ReinterpretNode} class represents a reinterpreting conversion that changes the stamp
@@ -90,9 +90,9 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
-        LIRKind kind = gen.getLIRKind(stamp());
-        nodeValueMap.setResult(this, gen.emitReinterpret(kind, nodeValueMap.operand(getValue())));
+    public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) {
+        LIRKind kind = builder.getLIRGeneratorTool().getLIRKind(stamp());
+        builder.setResult(this, gen.emitReinterpret(kind, builder.operand(getValue())));
     }
 
     public static ValueNode reinterpret(JavaKind toKind, ValueNode value) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -25,12 +25,12 @@
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable;
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Rem;
 import com.oracle.graal.graph.NodeClass;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.spi.Lowerable;
 import com.oracle.graal.nodes.spi.LoweringTool;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 @NodeInfo(shortName = "%")
 public final class RemNode extends BinaryArithmeticNode<Rem> implements Lowerable {
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitRem(nodeValueMap.operand(getX()), nodeValueMap.operand(getY()), null));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -29,11 +29,11 @@
 import com.oracle.graal.compiler.common.type.IntegerStamp;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 @NodeInfo(shortName = ">>")
 public final class RightShiftNode extends ShiftNode<Shr> {
@@ -99,7 +99,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitShr(nodeValueMap.operand(getX()), nodeValueMap.operand(getY())));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -30,10 +30,10 @@
 import com.oracle.graal.compiler.common.type.PrimitiveStamp;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * The {@code SignExtendNode} converts an integer to a wider integer using sign extension.
@@ -105,7 +105,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitSignExtend(nodeValueMap.operand(getValue()), getInputBits(), getResultBits()));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SqrtNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -25,11 +25,11 @@
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable;
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Sqrt;
 import com.oracle.graal.graph.NodeClass;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * Square root.
@@ -44,7 +44,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitMathSqrt(nodeValueMap.operand(getValue())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -33,11 +33,11 @@
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 import com.oracle.graal.nodes.util.GraphUtil;
 
 @NodeInfo(shortName = "-")
@@ -156,7 +156,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitSub(nodeValueMap.operand(getX()), nodeValueMap.operand(getY()), false));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -76,7 +76,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
+        gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitUDiv(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -75,7 +75,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
+        gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitURem(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -29,11 +29,11 @@
 import com.oracle.graal.compiler.common.type.IntegerStamp;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 @NodeInfo(shortName = ">>>")
 public final class UnsignedRightShiftNode extends ShiftNode<UShr> {
@@ -87,7 +87,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitUShr(nodeValueMap.operand(getX()), nodeValueMap.operand(getY())));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -34,11 +34,11 @@
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 import com.oracle.graal.nodes.util.GraphUtil;
 
 @NodeInfo(shortName = "^")
@@ -94,7 +94,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitXor(nodeValueMap.operand(getX()), nodeValueMap.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -34,10 +34,10 @@
 import com.oracle.graal.compiler.common.type.Stamp;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * The {@code ZeroExtendNode} converts an integer to a wider integer using zero extension.
@@ -119,7 +119,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitZeroExtend(nodeValueMap.operand(getValue()), getInputBits(), getResultBits()));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java	Thu Oct 08 15:58:13 2015 -0700
@@ -22,10 +22,14 @@
  */
 package com.oracle.graal.nodes.spi;
 
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodes.ArithmeticOperation;
 
-public interface ArithmeticLIRLowerable extends ArithmeticOperation {
+public interface ArithmeticLIRLowerable extends ArithmeticOperation, LIRLowerable {
 
-    void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen);
+    default void generate(NodeLIRBuilderTool builder) {
+        generate(builder, builder.getLIRGeneratorTool().getArithmetic());
+    }
+
+    void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen);
 }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -25,25 +25,26 @@
 import jdk.internal.jvmci.code.CodeUtil;
 import jdk.internal.jvmci.meta.JavaConstant;
 import jdk.internal.jvmci.meta.JavaKind;
-import jdk.internal.jvmci.meta.Value;
 
 import com.oracle.graal.compiler.common.type.IntegerStamp;
 import com.oracle.graal.compiler.common.type.PrimitiveStamp;
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
+import com.oracle.graal.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.UnaryNode;
-import com.oracle.graal.nodes.spi.LIRLowerable;
+import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
 import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * Count the number of leading zeros using the {@code lzcntq} or {@code lzcntl} instructions.
  */
 @NodeInfo
-public final class AMD64CountLeadingZerosNode extends UnaryNode implements LIRLowerable {
+public final class AMD64CountLeadingZerosNode extends UnaryNode implements ArithmeticLIRLowerable {
     public static final NodeClass<AMD64CountLeadingZerosNode> TYPE = NodeClass.create(AMD64CountLeadingZerosNode.class);
 
     public AMD64CountLeadingZerosNode(ValueNode value) {
@@ -83,8 +84,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value result = gen.getLIRGeneratorTool().emitCountLeadingZeros(gen.operand(getValue()));
-        gen.setResult(this, result);
+    public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) {
+        builder.setResult(this, ((AMD64ArithmeticLIRGeneratorTool) gen).emitCountLeadingZeros(builder.operand(getValue())));
     }
 }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -25,25 +25,26 @@
 import jdk.internal.jvmci.code.CodeUtil;
 import jdk.internal.jvmci.meta.JavaConstant;
 import jdk.internal.jvmci.meta.JavaKind;
-import jdk.internal.jvmci.meta.Value;
 
 import com.oracle.graal.compiler.common.type.IntegerStamp;
 import com.oracle.graal.compiler.common.type.PrimitiveStamp;
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
+import com.oracle.graal.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.UnaryNode;
-import com.oracle.graal.nodes.spi.LIRLowerable;
+import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
 import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * Count the number of trailing zeros using the {@code tzcntq} or {@code tzcntl} instructions.
  */
 @NodeInfo
-public final class AMD64CountTrailingZerosNode extends UnaryNode implements LIRLowerable {
+public final class AMD64CountTrailingZerosNode extends UnaryNode implements ArithmeticLIRLowerable {
     public static final NodeClass<AMD64CountTrailingZerosNode> TYPE = NodeClass.create(AMD64CountTrailingZerosNode.class);
 
     public AMD64CountTrailingZerosNode(ValueNode value) {
@@ -79,8 +80,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value result = gen.getLIRGeneratorTool().emitCountTrailingZeros(gen.operand(getValue()));
-        gen.setResult(this, result);
+    public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) {
+        builder.setResult(this, ((AMD64ArithmeticLIRGeneratorTool) gen).emitCountTrailingZeros(builder.operand(getValue())));
     }
 }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -26,13 +26,13 @@
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.FloatConvertNode;
 import com.oracle.graal.nodes.calc.UnaryArithmeticNode;
 import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
  * This node has the semantics of the AMD64 floating point conversions. It is used in the lowering
@@ -56,7 +56,8 @@
         return this;
     }
 
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    @Override
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         nodeValueMap.setResult(this, gen.emitFloatConvert(op, nodeValueMap.operand(getValue())));
     }
 }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathIntrinsicNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathIntrinsicNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -31,14 +31,14 @@
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.amd64.AMD64ArithmeticLIRGenerator;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.UnaryNode;
 import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 @NodeInfo
 public final class AMD64MathIntrinsicNode extends UnaryNode implements ArithmeticLIRLowerable {
@@ -81,8 +81,8 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator lirGen) {
-        AMD64ArithmeticLIRGenerator gen = (AMD64ArithmeticLIRGenerator) lirGen;
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool lirGen) {
+        AMD64ArithmeticLIRGeneratorTool gen = (AMD64ArithmeticLIRGeneratorTool) lirGen;
         Value input = nodeValueMap.operand(getValue());
         Value result;
         switch (operation()) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -25,22 +25,22 @@
 import jdk.internal.jvmci.code.CodeUtil;
 import jdk.internal.jvmci.meta.JavaConstant;
 import jdk.internal.jvmci.meta.JavaKind;
-import jdk.internal.jvmci.meta.Value;
 
 import com.oracle.graal.compiler.common.type.IntegerStamp;
 import com.oracle.graal.compiler.common.type.PrimitiveStamp;
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.UnaryNode;
-import com.oracle.graal.nodes.spi.LIRLowerable;
+import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
 import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 @NodeInfo
-public final class BitCountNode extends UnaryNode implements LIRLowerable {
+public final class BitCountNode extends UnaryNode implements ArithmeticLIRLowerable {
 
     public static final NodeClass<BitCountNode> TYPE = NodeClass.create(BitCountNode.class);
 
@@ -67,8 +67,7 @@
     }
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value result = gen.getLIRGeneratorTool().emitBitCount(gen.operand(getValue()));
-        gen.setResult(this, result);
+    public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) {
+        builder.setResult(this, gen.emitBitCount(builder.operand(getValue())));
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -25,18 +25,18 @@
 import jdk.internal.jvmci.code.CodeUtil;
 import jdk.internal.jvmci.meta.JavaConstant;
 import jdk.internal.jvmci.meta.JavaKind;
-import jdk.internal.jvmci.meta.Value;
 
 import com.oracle.graal.compiler.common.type.IntegerStamp;
 import com.oracle.graal.compiler.common.type.PrimitiveStamp;
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.UnaryNode;
-import com.oracle.graal.nodes.spi.LIRLowerable;
+import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
 import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
@@ -44,7 +44,7 @@
  * input is zero.
  */
 @NodeInfo
-public final class BitScanForwardNode extends UnaryNode implements LIRLowerable {
+public final class BitScanForwardNode extends UnaryNode implements ArithmeticLIRLowerable {
 
     public static final NodeClass<BitScanForwardNode> TYPE = NodeClass.create(BitScanForwardNode.class);
 
@@ -125,8 +125,7 @@
     public static native int unsafeScan(int v);
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value result = gen.getLIRGeneratorTool().emitBitScanForward(gen.operand(getValue()));
-        gen.setResult(this, result);
+    public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) {
+        builder.setResult(this, gen.emitBitScanForward(builder.operand(getValue())));
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -25,18 +25,18 @@
 import jdk.internal.jvmci.code.CodeUtil;
 import jdk.internal.jvmci.meta.JavaConstant;
 import jdk.internal.jvmci.meta.JavaKind;
-import jdk.internal.jvmci.meta.Value;
 
 import com.oracle.graal.compiler.common.type.IntegerStamp;
 import com.oracle.graal.compiler.common.type.PrimitiveStamp;
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.UnaryNode;
-import com.oracle.graal.nodes.spi.LIRLowerable;
+import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
 import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 /**
@@ -44,7 +44,7 @@
  * input is zero.
  */
 @NodeInfo
-public final class BitScanReverseNode extends UnaryNode implements LIRLowerable {
+public final class BitScanReverseNode extends UnaryNode implements ArithmeticLIRLowerable {
 
     public static final NodeClass<BitScanReverseNode> TYPE = NodeClass.create(BitScanReverseNode.class);
 
@@ -121,9 +121,8 @@
     public static native int unsafeScan(long v);
 
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        Value result = gen.getLIRGeneratorTool().emitBitScanReverse(gen.operand(getValue()));
-        gen.setResult(this, result);
+    public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) {
+        builder.setResult(this, gen.emitBitScanReverse(builder.operand(getValue())));
     }
 
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.graph.NodeClass;
+import com.oracle.graal.lir.gen.LIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.FixedWithNextNode;
 import com.oracle.graal.nodes.StateSplit;
@@ -66,23 +67,24 @@
      * @see com.oracle.graal.replacements.DefaultJavaLoweringProvider#createUnsafeRead
      */
     @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        LIRKind kind = gen.getLIRGeneratorTool().target().getLIRKind(readKind);
-        Value loaded = gen.getLIRGeneratorTool().emitLoad(kind, gen.operand(address), null);
+    public void generate(NodeLIRBuilderTool builder) {
+        LIRGeneratorTool gen = builder.getLIRGeneratorTool();
+        LIRKind kind = gen.target().getLIRKind(readKind);
+        Value loaded = gen.emitLoad(kind, builder.operand(address), null);
         switch (readKind) {
             case Byte:
-                loaded = gen.getLIRGeneratorTool().emitSignExtend(loaded, 8, 32);
+                loaded = gen.getArithmetic().emitSignExtend(loaded, 8, 32);
                 break;
             case Short:
-                loaded = gen.getLIRGeneratorTool().emitSignExtend(loaded, 16, 32);
+                loaded = gen.getArithmetic().emitSignExtend(loaded, 16, 32);
                 break;
             case Boolean:
-                loaded = gen.getLIRGeneratorTool().emitZeroExtend(loaded, 8, 32);
+                loaded = gen.getArithmetic().emitZeroExtend(loaded, 8, 32);
                 break;
             case Char:
-                loaded = gen.getLIRGeneratorTool().emitZeroExtend(loaded, 16, 32);
+                loaded = gen.getArithmetic().emitZeroExtend(loaded, 16, 32);
                 break;
         }
-        gen.setResult(this, loaded);
+        builder.setResult(this, loaded);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerAddExactSplitNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerAddExactSplitNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -41,6 +41,6 @@
 
     @Override
     protected Value generateArithmetic(NodeLIRBuilderTool gen) {
-        return gen.getLIRGeneratorTool().emitAdd(gen.operand(getX()), gen.operand(getY()), true);
+        return gen.getLIRGeneratorTool().getArithmetic().emitAdd(gen.operand(getX()), gen.operand(getY()), true);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerMulExactSplitNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerMulExactSplitNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -41,6 +41,6 @@
 
     @Override
     protected Value generateArithmetic(NodeLIRBuilderTool gen) {
-        return gen.getLIRGeneratorTool().emitMul(gen.operand(getX()), gen.operand(getY()), true);
+        return gen.getLIRGeneratorTool().getArithmetic().emitMul(gen.operand(getX()), gen.operand(getY()), true);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerMulHighNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerMulHighNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -31,13 +31,13 @@
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.BinaryNode;
 import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 @NodeInfo(shortName = "*H")
 public final class IntegerMulHighNode extends BinaryNode implements ArithmeticLIRLowerable {
@@ -87,7 +87,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         Value a = nodeValueMap.operand(getX());
         Value b = nodeValueMap.operand(getY());
         nodeValueMap.setResult(this, gen.emitMulHigh(a, b));
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerSubExactSplitNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/IntegerSubExactSplitNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -41,6 +41,6 @@
 
     @Override
     protected Value generateArithmetic(NodeLIRBuilderTool gen) {
-        return gen.getLIRGeneratorTool().emitSub(gen.operand(getX()), gen.operand(getY()), true);
+        return gen.getLIRGeneratorTool().getArithmetic().emitSub(gen.operand(getX()), gen.operand(getY()), true);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/UnsignedMulHighNode.java	Thu Oct 08 14:58:22 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/arithmetic/UnsignedMulHighNode.java	Thu Oct 08 15:58:13 2015 -0700
@@ -31,13 +31,13 @@
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.CanonicalizerTool;
-import com.oracle.graal.lir.gen.ArithmeticLIRGenerator;
+import com.oracle.graal.lir.gen.ArithmeticLIRGeneratorTool;
 import com.oracle.graal.nodeinfo.NodeInfo;
 import com.oracle.graal.nodes.ConstantNode;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.BinaryNode;
 import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
-import com.oracle.graal.nodes.spi.NodeValueMap;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 
 @NodeInfo(shortName = "|*H|")
 public final class UnsignedMulHighNode extends BinaryNode implements ArithmeticLIRLowerable {
@@ -92,7 +92,7 @@
     }
 
     @Override
-    public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) {
+    public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
         Value a = nodeValueMap.operand(getX());
         Value b = nodeValueMap.operand(getY());
         nodeValueMap.setResult(this, gen.emitUMulHigh(a, b));