changeset 18846:edbac8edc2e1

Merge.
author Doug Simon <doug.simon@oracle.com>
date Mon, 12 Jan 2015 20:39:26 +0100
parents f57d86eb036f (current diff) 5e80dd2f1783 (diff)
children cff8333119b4
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.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/SubNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java
diffstat 22 files changed, 218 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Jan 12 20:39:26 2015 +0100
@@ -53,6 +53,13 @@
         void emit(SPARCAssembler masm);
     }
 
+    public static final int CCR_ICC_SHIFT = 0;
+    public static final int CCR_XCC_SHIFT = 4;
+    public static final int CCR_C_SHIFT = 0;
+    public static final int CCR_V_SHIFT = 1;
+    public static final int CCR_Z_SHIFT = 2;
+    public static final int CCR_N_SHIFT = 3;
+
     // @formatter:off
     /**
      * Instruction format for Fmt00 instructions. This abstraction is needed as it
@@ -1468,19 +1475,6 @@
         }
     }
 
-    public static class Fmt4d {
-
-        public Fmt4d(SPARCAssembler masm, int op, int op3, int cond, int cc, int simm11, int rd) {
-            assert op == 2;
-            assert op3 >= 0 && op3 < 0x40;
-            assert cc >= 0 && cc < 0x8;
-            assert cond >= 0 && cond < 0x10;
-            assert rd >= 0 && rd < 0x20;
-
-            masm.emitInt(op << 30 | rd << 25 | op3 << 19 | ImmedTrue | ((cc << 15) & 0x00040000) | cond << 14 | ((cc << 11) & 0x3) | simm11 & 0x00004000);
-        }
-    }
-
     public static class Fmt5a {
 
         public Fmt5a(SPARCAssembler masm, int op, int op3, int op5, int rs1, int rs2, int rs3, int rd) {
@@ -1588,10 +1582,11 @@
         Orncc(0x16, "orncc"),
         Xnorcc(0x17, "xnorcc"),
         Addccc(0x18, "addccc"),
-        Mulxcc(0x19, "mulxcc"),
+        // dos not exist
+        // Mulxcc(0x19, "mulxcc"),
         Umulcc(0x1A, "umulcc"),
         Smulcc(0x1B, "smulcc"),
-        Subccc(0x1C0, "subccc"),
+        Subccc(0x1C, "subccc"),
         Udivcc(0x1E, "udivcc"),
         Sdivcc(0x1F, "sdivcc"),
 
@@ -1655,8 +1650,10 @@
         Stf   (0b10_0100, "stf"),
         Stfsr (0b10_0101, "stfsr"),
         Staf  (0x10_0110, "staf"),
+        Rd    (0b10_1000, "rd"),
         Stdf  (0b10_0111, "stdf"),
 
+        Wr    (0b11_0000, "wr"),
         Fcmp  (0b11_0101, "fcmp"),
 
         Ldxa  (0b01_1011, "ldxa"),
@@ -1814,6 +1811,7 @@
         Movxtod(0x118, "movxtod"),
         Movwtos(0b1_0001_1001, "movwtos"),
         UMulxhi(0b0_0001_0110, "umulxhi"),
+        Lzcnt  (0b0_0001_0111, "lzcnt"),
         // end VIS3
 
         // start CAMMELLIA
@@ -2395,6 +2393,14 @@
         }
     }
 
+    public static class Lzcnt extends Fmt3p {
+
+        public Lzcnt(Register src1, Register dst) {
+            /* VIS3 only */
+            super(Ops.ArithOp, Op3s.Impdep1, Opfs.Lzcnt, g0, src1, dst);
+        }
+    }
+
     public static class And extends Fmt10 {
 
         public And(Register src1, int simm13, Register dst) {
@@ -3993,6 +3999,17 @@
         }
     }
 
+    public static class SMulcc extends Fmt10 {
+
+        public SMulcc(Register src1, int simm13, Register dst) {
+            super(Op3s.Smulcc, src1, simm13, dst);
+        }
+
+        public SMulcc(Register src1, Register src2, Register dst) {
+            super(Op3s.Smulcc, src1, src2, dst);
+        }
+    }
+
     public static class Or extends Fmt10 {
 
         public Or(Register src1, int simm13, Register dst) {
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Mon Jan 12 20:39:26 2015 +0100
@@ -266,7 +266,7 @@
 
     @Override
     protected Value genIntegerAdd(Kind kind, Value x, Value y) {
-        return gen.emitAdd(x, y);
+        return gen.emitAdd(x, y, false);
     }
 
     @Override
@@ -277,7 +277,7 @@
 
     @Override
     protected Value genIntegerMul(Kind kind, Value x, Value y) {
-        return gen.emitMul(x, y);
+        return gen.emitMul(x, y, false);
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Jan 12 20:39:26 2015 +0100
@@ -155,7 +155,7 @@
                 if (CodeUtil.isPowerOf2(scale)) {
                     indexRegister = emitShl(longIndex, JavaConstant.forLong(CodeUtil.log2(scale)));
                 } else {
-                    indexRegister = emitMul(longIndex, JavaConstant.forLong(scale));
+                    indexRegister = emitMul(longIndex, JavaConstant.forLong(scale), false);
                 }
                 scaleEnum = Scale.Times1;
 
@@ -179,7 +179,7 @@
                 indexRegister = displacementRegister;
                 scaleEnum = Scale.Times1;
             } else {
-                baseRegister = emitAdd(baseRegister, displacementRegister);
+                baseRegister = emitAdd(baseRegister, displacementRegister, false);
             }
         }
 
@@ -231,7 +231,7 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpLIRKind, double overflowProbability) {
         append(new BranchOp(ConditionFlag.Overflow, overflow, noOverflow, overflowProbability));
     }
 
@@ -498,7 +498,7 @@
     }
 
     @Override
-    public Variable emitAdd(Value a, Value b) {
+    public Variable emitAdd(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
                 return emitBinary(IADD, true, a, b);
@@ -514,7 +514,7 @@
     }
 
     @Override
-    public Variable emitSub(Value a, Value b) {
+    public Variable emitSub(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
                 return emitBinary(ISUB, false, a, b);
@@ -530,7 +530,7 @@
     }
 
     @Override
-    public Variable emitMul(Value a, Value b) {
+    public Variable emitMul(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
                 return emitBinary(IMUL, true, a, b);
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Mon Jan 12 20:39:26 2015 +0100
@@ -142,7 +142,7 @@
                 if (baseRegister.equals(Value.ILLEGAL)) {
                     baseRegister = asAllocatable(indexRegister);
                 } else {
-                    baseRegister = emitAdd(baseRegister, indexRegister);
+                    baseRegister = emitAdd(baseRegister, indexRegister, false);
                 }
             }
         }
@@ -201,7 +201,7 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpLIRKind, double overflowProbability) {
         throw GraalInternalError.unimplemented();
     }
 
@@ -321,7 +321,7 @@
     }
 
     @Override
-    public Variable emitAdd(Value a, Value b) {
+    public Variable emitAdd(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
@@ -346,7 +346,7 @@
     }
 
     @Override
-    public Variable emitSub(Value a, Value b) {
+    public Variable emitSub(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
@@ -368,7 +368,7 @@
     }
 
     @Override
-    public Variable emitMul(Value a, Value b) {
+    public Variable emitMul(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Jan 12 20:39:26 2015 +0100
@@ -171,7 +171,7 @@
                     if (CodeUtil.isPowerOf2(scale)) {
                         indexRegister = emitShl(convertedIndex, JavaConstant.forInt(CodeUtil.log2(scale)));
                     } else {
-                        indexRegister = emitMul(convertedIndex, JavaConstant.forInt(scale));
+                        indexRegister = emitMul(convertedIndex, JavaConstant.forInt(scale), false);
                     }
                 } else {
                     indexRegister = convertedIndex;
@@ -181,7 +181,7 @@
                 } else {
                     Variable longBaseRegister = newVariable(LIRKind.derivedReference(Kind.Long));
                     emitMove(longBaseRegister, baseRegister);
-                    baseRegister = emitAdd(longBaseRegister, indexRegister);
+                    baseRegister = emitAdd(longBaseRegister, indexRegister, false);
                 }
             }
         }
@@ -255,7 +255,7 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpLIRKind, double overflowProbability) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.emitOverflowCheckBranch()");
     }
 
@@ -391,7 +391,7 @@
     }
 
     @Override
-    public Variable emitAdd(Value a, Value b) {
+    public Variable emitAdd(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
@@ -413,7 +413,7 @@
     }
 
     @Override
-    public Variable emitSub(Value a, Value b) {
+    public Variable emitSub(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
@@ -435,7 +435,7 @@
     }
 
     @Override
-    public Variable emitMul(Value a, Value b) {
+    public Variable emitMul(Value a, Value b, boolean setFlags) {
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind()) {
             case Int:
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Jan 12 20:39:26 2015 +0100
@@ -145,7 +145,7 @@
                     if (CodeUtil.isPowerOf2(scale)) {
                         indexRegister = emitShl(longIndex, JavaConstant.forLong(CodeUtil.log2(scale)));
                     } else {
-                        indexRegister = emitMul(longIndex, JavaConstant.forLong(scale));
+                        indexRegister = emitMul(longIndex, JavaConstant.forLong(scale), false);
                     }
                 } else {
                     indexRegister = asAllocatable(index);
@@ -171,7 +171,7 @@
                 } else {
                     Variable longBaseRegister = newVariable(LIRKind.derivedReference(Kind.Long));
                     emitMove(longBaseRegister, baseRegister);
-                    baseRegister = emitAdd(longBaseRegister, JavaConstant.forLong(finalDisp));
+                    baseRegister = emitAdd(longBaseRegister, JavaConstant.forLong(finalDisp), false);
                 }
             }
         }
@@ -253,8 +253,9 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
-        append(new BranchOp(ConditionFlag.OverflowSet, overflow, noOverflow, Kind.Long));
+    public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpLIRKind, double overflowProbability) {
+        Kind cmpKind = (Kind) cmpLIRKind.getPlatformKind();
+        append(new BranchOp(ConditionFlag.OverflowSet, overflow, noOverflow, cmpKind));
     }
 
     @Override
@@ -584,12 +585,12 @@
     }
 
     @Override
-    public Variable emitAdd(Value a, Value b) {
+    public Variable emitAdd(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
-                return emitBinary(IADD, true, a, b);
+                return emitBinary(setFlags ? IADDCC : IADD, true, a, b);
             case Long:
-                return emitBinary(LADD, true, a, b);
+                return emitBinary(setFlags ? LADDCC : LADD, true, a, b);
             case Float:
                 return emitBinary(FADD, true, a, b);
             case Double:
@@ -600,12 +601,12 @@
     }
 
     @Override
-    public Variable emitSub(Value a, Value b) {
+    public Variable emitSub(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
-                return emitBinary(ISUB, false, a, b);
+                return emitBinary(setFlags ? ISUBCC : ISUB, false, a, b);
             case Long:
-                return emitBinary(LSUB, false, a, b);
+                return emitBinary(setFlags ? LSUBCC : LSUB, false, a, b);
             case Float:
                 return emitBinary(FSUB, false, a, b);
             case Double:
@@ -616,12 +617,18 @@
     }
 
     @Override
-    public Variable emitMul(Value a, Value b) {
+    public Variable emitMul(Value a, Value b, boolean setFlags) {
         switch (a.getKind().getStackKind()) {
             case Int:
-                return emitBinary(IMUL, true, a, b);
+                return emitBinary(setFlags ? IMULCC : IMUL, true, a, b);
             case Long:
-                return emitBinary(LMUL, true, a, b);
+                if (setFlags) {
+                    Variable result = newVariable(LIRKind.derive(a, b));
+                    append(new SPARCLMulccOp(result, a, b, this));
+                    return result;
+                } else {
+                    return emitBinary(LMUL, true, a, b);
+                }
             case Float:
                 return emitBinary(FMUL, true, a, b);
             case Double:
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Mon Jan 12 20:39:26 2015 +0100
@@ -598,8 +598,10 @@
         return getDebugInfoBuilder().build(state, exceptionEdge);
     }
 
-    public void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, double probability) {
-        gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), probability);
+    @Override
+    public void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, Stamp stamp, double probability) {
+        LIRKind cmpKind = getLIRGeneratorTool().getLIRKind(stamp);
+        gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), cmpKind, probability);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java	Mon Jan 12 20:39:26 2015 +0100
@@ -85,10 +85,10 @@
             assert !gen.getCodeCache().needsDataPatch(asConstant(offset));
             Variable longAddress = gen.newVariable(LIRKind.value(Kind.Long));
             gen.emitMove(longAddress, address);
-            address = getGen().emitAdd(longAddress, asConstant(offset));
+            address = getGen().emitAdd(longAddress, asConstant(offset), false);
         } else {
             if (isLegal(offset)) {
-                address = getGen().emitAdd(address, offset);
+                address = getGen().emitAdd(address, offset, false);
             }
         }
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Jan 12 20:39:26 2015 +0100
@@ -26,6 +26,7 @@
 import static com.oracle.graal.asm.sparc.SPARCAssembler.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
@@ -34,11 +35,15 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.sparc.SPARC.CPUFeature;
+import com.oracle.graal.sparc.*;
 
 public enum SPARCArithmetic {
     // @formatter:off
     IADD, ISUB, IMUL, IUMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
     LADD, LSUB, LMUL, LUMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
+    IADDCC, ISUBCC, IMULCC,
+    LADDCC, LSUBCC, LMULCC,
     FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
     DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
     INEG, LNEG, FNEG, DNEG, INOT, LNOT,
@@ -175,6 +180,49 @@
         }
     }
 
+    /**
+     * Calculates the product and condition code for long multiplication of long values.
+     */
+    public static class SPARCLMulccOp extends SPARCLIRInstruction {
+        @Def({REG}) protected Value result;
+        @Alive({REG}) protected Value x;
+        @Alive({REG}) protected Value y;
+        @Temp({REG}) protected Value scratch1;
+        @Temp({REG}) protected Value scratch2;
+
+        public SPARCLMulccOp(Value result, Value x, Value y, LIRGeneratorTool gen) {
+            this.result = result;
+            this.x = x;
+            this.y = y;
+            this.scratch1 = gen.newVariable(LIRKind.derive(x, y));
+            this.scratch2 = gen.newVariable(LIRKind.derive(x, y));
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            Label noOverflow = new Label();
+            new Mulx(asLongReg(x), asLongReg(y), asLongReg(result)).emit(masm);
+
+            // Calculate the upper 64 bit signed := (umulxhi product - (x{63}&y + y{63}&x))
+            new Umulxhi(asLongReg(x), asLongReg(y), asLongReg(scratch1)).emit(masm);
+            new Srax(asLongReg(x), 63, asLongReg(scratch2)).emit(masm);
+            new And(asLongReg(scratch2), asLongReg(y), asLongReg(scratch2)).emit(masm);
+            new Sub(asLongReg(scratch1), asLongReg(scratch2), asLongReg(scratch1)).emit(masm);
+
+            new Srax(asLongReg(y), 63, asLongReg(scratch2)).emit(masm);
+            new And(asLongReg(scratch2), asLongReg(x), asLongReg(scratch2)).emit(masm);
+            new Sub(asLongReg(scratch1), asLongReg(scratch2), asLongReg(scratch1)).emit(masm);
+
+            // Now construct the lower half and compare
+            new Srax(asLongReg(result), 63, asLongReg(scratch2)).emit(masm);
+            new Cmp(asLongReg(scratch1), asLongReg(scratch2)).emit(masm);
+            new Bpe(CC.Xcc, false, true, noOverflow).emit(masm);
+            new Nop().emit(masm);
+            new Wrccr(SPARC.g0, 1 << (CCR_XCC_SHIFT + CCR_V_SHIFT)).emit(masm);
+            masm.bind(noOverflow);
+        }
+    }
+
     private static void emitRegConstant(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, JavaConstant src2, LIRFrameState info,
                     SPARCDelayedControlTransfer delaySlotLir) {
         assert isSimm13(crb.asIntConst(src2)) : src2;
@@ -185,12 +233,20 @@
             case IADD:
                 new Add(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
                 break;
+            case IADDCC:
+                new Addcc(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
+                break;
             case ISUB:
                 new Sub(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
                 break;
+            case ISUBCC:
+                new Subcc(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
+                break;
             case IMUL:
                 new Mulx(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
                 break;
+            case IMULCC:
+                throw GraalInternalError.unimplemented();
             case IDIV:
                 new Sdivx(asIntReg(src1), constant, asIntReg(dst)).emit(masm);
                 break;
@@ -218,9 +274,15 @@
             case LADD:
                 new Add(asLongReg(src1), constant, asLongReg(dst)).emit(masm);
                 break;
+            case LADDCC:
+                new Addcc(asLongReg(src1), constant, asLongReg(dst)).emit(masm);
+                break;
             case LSUB:
                 new Sub(asLongReg(src1), constant, asLongReg(dst)).emit(masm);
                 break;
+            case LSUBCC:
+                new Subcc(asLongReg(src1), constant, asLongReg(dst)).emit(masm);
+                break;
             case LMUL:
                 new Mulx(asLongReg(src1), constant, asLongReg(dst)).emit(masm);
                 break;
@@ -276,14 +338,42 @@
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Add(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                 break;
+            case IADDCC:
+                delaySlotLir.emitControlTransfer(crb, masm);
+                new Addcc(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
+                break;
             case ISUB:
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Sub(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                 break;
+            case ISUBCC:
+                delaySlotLir.emitControlTransfer(crb, masm);
+                new Subcc(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
+                break;
             case IMUL:
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Mulx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                 break;
+            case IMULCC:
+                try (SPARCScratchRegister tmpScratch = SPARCScratchRegister.get()) {
+                    Register tmp = tmpScratch.getRegister();
+                    new Mulx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
+                    Label noOverflow = new Label();
+                    new Sra(asIntReg(dst), 0, tmp).emit(masm);
+                    new Xorcc(SPARC.g0, SPARC.g0, SPARC.g0).emit(masm);
+                    if (masm.hasFeature(CPUFeature.CBCOND)) {
+                        new CBcondx(ConditionFlag.Equal, tmp, asIntReg(dst), noOverflow).emit(masm);
+                        // Is necessary, otherwise we will have a penalty of 5 cycles in S3
+                        new Nop().emit(masm);
+                    } else {
+                        new Cmp(tmp, asIntReg(dst)).emit(masm);
+                        new Bpe(CC.Xcc, noOverflow).emit(masm);
+                        new Nop().emit(masm);
+                    }
+                    new Wrccr(SPARC.g0, 1 << (SPARCAssembler.CCR_ICC_SHIFT + SPARCAssembler.CCR_V_SHIFT)).emit(masm);
+                    masm.bind(noOverflow);
+                }
+                break;
             case IDIV:
                 new Signx(asIntReg(src1), asIntReg(src1)).emit(masm);
                 new Signx(asIntReg(src2), asIntReg(src2)).emit(masm);
@@ -328,14 +418,24 @@
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Add(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                 break;
+            case LADDCC:
+                delaySlotLir.emitControlTransfer(crb, masm);
+                new Addcc(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
+                break;
             case LSUB:
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Sub(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                 break;
+            case LSUBCC:
+                delaySlotLir.emitControlTransfer(crb, masm);
+                new Subcc(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
+                break;
             case LMUL:
                 delaySlotLir.emitControlTransfer(crb, masm);
                 new Mulx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                 break;
+            case LMULCC:
+                throw GraalInternalError.unimplemented();
             case LDIV:
                 delaySlotLir.emitControlTransfer(crb, masm);
                 exceptionOffset = masm.position();
@@ -659,8 +759,11 @@
 
         switch (opcode) {
             case IADD:
+            case IADDCC:
             case ISUB:
+            case ISUBCC:
             case IMUL:
+            case IMULCC:
             case IDIV:
             case IREM:
             case IAND:
@@ -681,8 +784,11 @@
                 assert valid : "rk: " + rk + " xsk: " + xsk + " ysk: " + ysk;
                 break;
             case LADD:
+            case LADDCC:
             case LSUB:
+            case LSUBCC:
             case LMUL:
+            case LMULCC:
             case LDIV:
             case LREM:
             case LAND:
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Jan 12 20:39:26 2015 +0100
@@ -413,7 +413,7 @@
                 if (actualCondition != null) {
                     emitBranch(masm, actualTarget, actualCondition, cc, false);
                 } else if (actualConditionFlag != null) {
-                    emitBranch(masm, actualTarget, actualConditionFlag);
+                    emitBranch(masm, actualTarget, actualConditionFlag, cc);
                 } else {
                     GraalInternalError.shouldNotReachHere();
                 }
@@ -475,8 +475,8 @@
         }
     }
 
-    private static void emitBranch(SPARCMacroAssembler masm, Label target, ConditionFlag actualCondition) {
-        new Fmt00b(false, actualCondition, Op2s.Br, target).emit(masm);
+    private static void emitBranch(SPARCMacroAssembler masm, Label target, ConditionFlag actualCondition, CC cc) {
+        new Fmt00c(0, actualCondition, Op2s.Bp, cc, 0, target).emit(masm);
     }
 
     private static void emitBranch(SPARCMacroAssembler masm, Label target, Condition actualCondition, CC cc, boolean predictTaken) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Mon Jan 12 20:39:26 2015 +0100
@@ -29,6 +29,12 @@
 
 /**
  * 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 ArithmeticLIRGenerator {
 
@@ -36,11 +42,11 @@
 
     Value emitNegate(Value input);
 
-    Value emitAdd(Value a, Value b);
+    Value emitAdd(Value a, Value b, boolean setFlags);
 
-    Value emitSub(Value a, Value b);
+    Value emitSub(Value a, Value b, boolean setFlags);
 
-    Value emitMul(Value a, Value b);
+    Value emitMul(Value a, Value b, boolean setFlags);
 
     Value emitMulHigh(Value a, Value b);
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Mon Jan 12 20:39:26 2015 +0100
@@ -241,7 +241,7 @@
     public abstract void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
                     double trueDestinationProbability);
 
-    public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability);
+    public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpKind, double overflowProbability);
 
     public abstract void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Mon Jan 12 20:39:26 2015 +0100
@@ -165,7 +165,7 @@
     void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
                     double trueDestinationProbability);
 
-    void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability);
+    void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, LIRKind cmpKind, double overflowProbability);
 
     void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, LabelRef falseDestination, double trueSuccessorProbability);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Mon Jan 12 20:39:26 2015 +0100
@@ -98,6 +98,6 @@
             op1 = op2;
             op2 = tmp;
         }
-        builder.setResult(this, gen.emitAdd(op1, op2));
+        builder.setResult(this, gen.emitAdd(op1, op2, false));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Mon Jan 12 20:39:26 2015 +0100
@@ -106,6 +106,6 @@
             op1 = op2;
             op2 = tmp;
         }
-        builder.setResult(this, gen.emitMul(op1, op2));
+        builder.setResult(this, gen.emitMul(op1, op2, false));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Mon Jan 12 20:39:26 2015 +0100
@@ -133,6 +133,6 @@
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitSub(builder.operand(getX()), builder.operand(getY())));
+        builder.setResult(this, gen.emitSub(builder.operand(getX()), builder.operand(getY()), false));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Mon Jan 12 20:39:26 2015 +0100
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
@@ -66,7 +67,7 @@
 
     LIRGeneratorTool getLIRGeneratorTool();
 
-    void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, double probability);
+    void emitOverflowCheckBranch(BeginNode overflowSuccessor, BeginNode next, Stamp compareStamp, double probability);
 
     Value[] visitInvokeArguments(CallingConvention cc, Collection<ValueNode> arguments);
 
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Mon Jan 12 20:39:26 2015 +0100
@@ -47,12 +47,20 @@
     public void testAdd() {
         test("add", 1, 2);
         test("add", Integer.MAX_VALUE, 2);
+        test("add", Integer.MIN_VALUE, -1);
+        test("add", -1, 2);
     }
 
     @Test
     public void testMul() {
         test("mul", 1, 2);
+        test("mul", -1, 2);
+        test("mul", Integer.MIN_VALUE, 1);
+        test("mul", Integer.MIN_VALUE, 2);
+        test("mul", Integer.MIN_VALUE, Integer.MIN_VALUE);
+        test("mul", Integer.MAX_VALUE, 1);
         test("mul", Integer.MAX_VALUE, 2);
+        test("mul", Integer.MAX_VALUE, Integer.MAX_VALUE);
     }
 
     @Test
@@ -90,6 +98,10 @@
         test("longMul", (long) Integer.MAX_VALUE, 2L);
         test("longMul", (long) Integer.MIN_VALUE, 2L);
         test("longMul", Long.MAX_VALUE, 2L);
+        test("longMul", Long.MAX_VALUE, 1L);
+        test("longMul", Long.MAX_VALUE, Long.MAX_VALUE);
+        test("longMul", Long.MIN_VALUE, Long.MIN_VALUE);
+        test("longMul", Long.MIN_VALUE, Long.MAX_VALUE);
     }
 
     @Test
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java	Mon Jan 12 20:39:26 2015 +0100
@@ -37,6 +37,6 @@
 
     @Override
     protected Value generateArithmetic(NodeLIRBuilderTool gen) {
-        return gen.getLIRGeneratorTool().emitAdd(gen.operand(getX()), gen.operand(getY()));
+        return gen.getLIRGeneratorTool().emitAdd(gen.operand(getX()), gen.operand(getY()), true);
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java	Mon Jan 12 20:39:26 2015 +0100
@@ -69,7 +69,7 @@
     @Override
     public void generate(NodeLIRBuilderTool generator) {
         generator.setResult(this, generateArithmetic(generator));
-        generator.emitOverflowCheckBranch(getOverflowSuccessor(), getNext(), probability(getOverflowSuccessor()));
+        generator.emitOverflowCheckBranch(getOverflowSuccessor(), getNext(), stamp, probability(getOverflowSuccessor()));
     }
 
     protected abstract Value generateArithmetic(NodeLIRBuilderTool generator);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java	Mon Jan 12 20:39:26 2015 +0100
@@ -37,6 +37,6 @@
 
     @Override
     protected Value generateArithmetic(NodeLIRBuilderTool gen) {
-        return gen.getLIRGeneratorTool().emitMul(gen.operand(getX()), gen.operand(getY()));
+        return gen.getLIRGeneratorTool().emitMul(gen.operand(getX()), gen.operand(getY()), true);
     }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Mon Jan 12 20:39:04 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java	Mon Jan 12 20:39:26 2015 +0100
@@ -37,6 +37,6 @@
 
     @Override
     protected Value generateArithmetic(NodeLIRBuilderTool gen) {
-        return gen.getLIRGeneratorTool().emitSub(gen.operand(getX()), gen.operand(getY()));
+        return gen.getLIRGeneratorTool().emitSub(gen.operand(getX()), gen.operand(getY()), true);
     }
 }