changeset 17146:2e4bd9de8682

Merge
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Wed, 17 Sep 2014 17:06:37 -0700
parents d75276c49399 (diff) 62d7d16b170b (current diff)
children 7a3f6543d383 5ecd1f298c64
files
diffstat 9 files changed, 253 insertions(+), 409 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Wed Sep 17 09:33:48 2014 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Wed Sep 17 17:06:37 2014 -0700
@@ -60,11 +60,13 @@
     public static abstract class Fmt00 {
 
         protected static final int OP_SHIFT = 30;
+        protected static final int CBCOND_SHIFT = 28;
         protected static final int OP2_SHIFT = 22;
 
         // @formatter:off
-        protected static final int OP_MASK  = 0b1100_0000_0000_0000_0000_0000_0000_0000;
-        protected static final int OP2_MASK = 0b0000_0001_1100_0000_0000_0000_0000_0000;
+        protected static final int OP_MASK     = 0b1100_0000_0000_0000_0000_0000_0000_0000;
+        protected static final int CBCOND_MASK = 0b0001_0000_0000_0000_0000_0000_0000_0000; // Used for distinguish CBcond and BPr instructions
+        protected static final int OP2_MASK    = 0b0000_0001_1100_0000_0000_0000_0000_0000;
         // @formatter:off
 
         private int op2;
@@ -86,7 +88,12 @@
                 case Bp:
                     return Fmt00c.read(masm, pos);
                 case Bpr:
-                    return Fmt00d.read(masm, pos);
+                    boolean isCBcond = (inst & CBCOND_MASK) != 0;
+                    if(isCBcond) {
+                        return Fmt00e.read(masm, pos);
+                    } else {
+                        return Fmt00d.read(masm, pos);
+                    }
                 default:
                     throw GraalInternalError.shouldNotReachHere("Unknown op2 " + op2);
             }
@@ -106,7 +113,7 @@
         }
 
         public void verify() {
-            assert ((op2 << OP2_SHIFT) & OP2_MASK) == (op2 << OP2_SHIFT);
+            assert ((op2 << OP2_SHIFT) & OP2_MASK) == (op2 << OP2_SHIFT) : Integer.toHexString(op2);
             assert Op2s.byValue(op2) != null : op2;
         }
         /**
@@ -520,7 +527,7 @@
             super(op2);
             this.annul = annul;
             this.rCondition = rCondition;
-            this.disp16 = d16;
+            setDisp16(d16);
             this.predictTaken = predictTaken;
             this.rs1 = rs1;
             this.label = label;
@@ -563,19 +570,20 @@
 
             // Make sure it's the right instruction:
             final int op = (inst & OP_MASK) >> OP_SHIFT;
-            assert op == Ops.BranchOp.getValue();
+            final int op2 = (inst & OP2_MASK) >> OP2_SHIFT;
+            final int condFlag = (inst & CBCOND_MASK) >> CBCOND_SHIFT;
+            assert op2 == Op2s.Bpr.getValue() && op == Ops.BranchOp.getValue() && condFlag == 0 : "0x" + Integer.toHexString(inst);
 
             // Get the instruction fields:
             final int a = (inst & A_MASK) >> A_SHIFT;
             final int cond = (inst & RCOND_MASK) >> RCOND_SHIFT;
-            final int op2 = (inst & OP2_MASK) >> OP2_SHIFT;
             final int p = (inst & P_MASK) >> P_SHIFT;
             final int rs1 = (inst & RS1_MASK) >> RS1_SHIFT;
             final int d16hi = (inst & D16HI_MASK) >> D16HI_SHIFT;
             assert (d16hi & ~0b11) == 0;
             final int d16lo = (inst & D16LO_MASK) >> D16LO_SHIFT;
             assert (d16lo & ~((1 << 14) - 1)) == 0;
-            final int d16 = (short) (((d16hi << 14) | d16lo) << 2); // sign extend
+            final int d16 = (short) (((d16hi << 14) | d16lo) << 2); // times 4 and sign extend
             Fmt00d fmt = new Fmt00d(op2, cond, p, a, d16, rs1, null);
             fmt.verify();
             return fmt;
@@ -592,18 +600,138 @@
         }
     }
 
-    public static class Fmt00e {
-
-        public Fmt00e(SPARCAssembler asm, int op, int c4lo, int cc2, int rs1, int d10lo, int regOrImmediate) {
-            assert op == 0;
-            assert (cc2 & 0xFFFFFFFE) == 0;
-            assert c4lo >= 0 && rs1 < 0x10;
-            assert rs1 >= 0 && rs1 < 0x20;
-            assert (regOrImmediate & 0x1F) < 0x20;
-            assert (regOrImmediate & 0xFFFFC000) == 0;
-            assert (d10lo & 0xFFFFFC00) == 0;
-
-            asm.emitInt(op << 30 | 1 << 28 | 3 << 22 | cc2 << 21 | (d10lo >> 8) << 19 | rs1 << 14 | (d10lo & 0xff) << 5 | regOrImmediate);
+    // @formatter:off
+    /**
+     * Instruction format CBcond
+     *
+     * |00   |chi|1 | clo | 011 |cc2|d10hi|rs1  |i |d10lo|rs2/simm5|
+     * |31 30|29 |28|27 25|24 22|21 |20 19|18 14|13|12  5|4       0|
+     */
+    // @formatter:on
+    public static class Fmt00e extends Fmt00 {
+        private static final int CHI_SHIFT = 29;
+        private static final int CLO_SHIFT = 25;
+        private static final int CC2_SHIFT = 21;
+        private static final int D10HI_SHIFT = 19;
+        private static final int RS1_SHIFT = 14;
+        private static final int I_SHIFT = 13;
+        private static final int D10LO_SHIFT = 5;
+        private static final int RS2_SHIFT = 0;
+
+        // @formatter:off
+        private static final int CHI_MASK      = 0b0010_0000_0000_0000_0000_0000_0000_0000;
+        private static final int CLO_MASK      = 0b0000_1110_0000_0000_0000_0000_0000_0000;
+        private static final int CC2_MASK      = 0b0000_0000_0010_0000_0000_0000_0000_0000;
+        private static final int D10HI_MASK    = 0b0000_0000_0001_1000_0000_0000_0000_0000;
+        private static final int RS1_MASK      = 0b0000_0000_0000_0111_1100_0000_0000_0000;
+        private static final int I_MASK        = 0b0000_0000_0000_0000_0010_0000_0000_0000;
+        private static final int D10LO_MASK    = 0b0000_0000_0000_0000_0001_1111_1110_0000;
+        private static final int RS2_MASK      = 0b0000_0000_0000_0000_0000_0000_0001_1111;
+        // @formatter:on
+
+        private int c;
+        private int cc2;
+        private int disp10;
+        private int rs1;
+        private int i;
+        private int regOrImmediate;
+        private Label label;
+
+        public Fmt00e(int c, int cc2, int rs1, int disp10, int i, int regOrImmediate, Label label) {
+            super(Op2s.Bpr.getValue());
+            this.c = c;
+            this.cc2 = cc2;
+            this.rs1 = rs1;
+            setDisp10(disp10);
+            this.i = i;
+            this.regOrImmediate = regOrImmediate;
+            this.label = label;
+        }
+
+        @Override
+        public void setImm(int imm) {
+            setDisp10(imm);
+        }
+
+        public void setDisp10(int disp10) {
+            this.disp10 = disp10 >> 2;
+        }
+
+        public void emit(SPARCAssembler masm) {
+            assert masm.hasFeature(CPUFeature.CBCOND);
+            if (label != null) {
+                final int pos = label.isBound() ? label.position() : patchUnbound(masm, label);
+                if (label.isBound()) {
+                    final int disp = pos - masm.position();
+                    setDisp10(disp);
+                } else {
+                    setDisp10(0);
+                }
+            }
+            verify();
+            masm.emitInt(getInstructionBits());
+        }
+
+        private static int patchUnbound(SPARCAssembler masm, Label label) {
+            label.addPatchAt(masm.position());
+            return 0;
+        }
+
+        @Override
+        protected int getInstructionBits() {
+            int cSplit = 0;
+            cSplit |= (c & 0b1000) << CHI_SHIFT - 3;
+            cSplit |= (c & 0b0111) << CLO_SHIFT;
+            int d10Split = 0;
+            d10Split |= (disp10 & 0b11_0000_0000) << D10HI_SHIFT - 8;
+            d10Split |= (disp10 & 0b00_1111_1111) << D10LO_SHIFT;
+            return super.getInstructionBits() | 1 << 28 | cSplit | cc2 << CC2_SHIFT | d10Split | rs1 << RS1_SHIFT | i << I_SHIFT | regOrImmediate << RS2_SHIFT;
+        }
+
+        public static Fmt00e read(SPARCAssembler masm, int pos) {
+            assert masm.hasFeature(CPUFeature.CBCOND);
+            final int inst = masm.getInt(pos);
+
+            // Make sure it's the right instruction:
+            final int op = (inst & OP_MASK) >> OP_SHIFT;
+            final int op2 = (inst & OP2_MASK) >> OP2_SHIFT;
+            final int condFlag = (inst & CBCOND_MASK) >> CBCOND_SHIFT;
+            assert op2 == Op2s.Bpr.getValue() && op == Ops.BranchOp.getValue() && condFlag == 1 : "0x" + Integer.toHexString(inst);
+
+            // @formatter:off
+            // Get the instruction fields:
+            final int chi =            (inst & CHI_MASK)   >> CHI_SHIFT;
+            final int clo =            (inst & CLO_MASK)   >> CLO_SHIFT;
+            final int cc2 =            (inst & CC2_MASK)   >> CC2_SHIFT;
+            final int d10hi =          (inst & D10HI_MASK) >> D10HI_SHIFT;
+            final int rs1 =            (inst & RS1_MASK)   >> RS1_SHIFT;
+            final int i =              (inst & I_MASK)     >> I_SHIFT;
+            final int d10lo =          (inst & D10LO_MASK) >> D10LO_SHIFT;
+            final int regOrImmediate = (inst & RS2_MASK)   >> RS2_SHIFT;
+            // @formatter:on
+
+            int c = chi << 3 | clo;
+
+            assert (d10lo & ~((1 << 8) - 1)) == 0;
+            final int d10 = ((short) (((d10hi << 8) | d10lo) << 6)) >> 4; // Times 4 and sign extend
+            Fmt00e fmt = new Fmt00e(c, cc2, rs1, d10, i, regOrImmediate, null);
+            fmt.verify();
+            return fmt;
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            assert (c & ~0b1111) == 0 : c;
+            assert (cc2 & ~1) == 0 : cc2;
+            assert isSimm(disp10, 10) : disp10;
+            assert (rs1 & ~0b1_1111) == 0 : rs1;
+            assert (i & ~1) == 0 : i;
+            if (i == 1) {
+                assert isSimm(regOrImmediate, 5) : regOrImmediate;
+            } else {
+                assert (regOrImmediate & ~0b1_1111) == 0 : regOrImmediate;
+            }
         }
     }
 
@@ -1869,6 +1997,10 @@
         }
     }
 
+    public boolean hasFeature(CPUFeature feature) {
+        return ((SPARC) this.target.arch).features.contains(feature);
+    }
+
     public static int getFloatEncoding(int reg) {
         assert reg < 32;
         return reg;
@@ -2426,353 +2558,23 @@
         }
     }
 
-    /**
-     * Compare and Branch if Carry Clear ( Greater not C Than or Equal, Unsigned )
-     */
-    public static class Cwbcc extends Fmt00e {
-
-        public Cwbcc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbcc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Carry Set (Less Than, Unsigned)
-     */
-    public static class Cwbcs extends Fmt00e {
-
-        public Cwbcs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbcs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Equal
-     */
-    public static class Cwbe extends Fmt00e {
-
-        public Cwbe(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbe(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Greater
-     */
-    public static class Cwbg extends Fmt00e {
-
-        public Cwbg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Greater or Equal
-     */
-    public static class Cwbge extends Fmt00e {
-
-        public Cwbge(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbge(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Greater Unsigned
-     */
-    public static class Cwbgu extends Fmt00e {
-
-        public Cwbgu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbgu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Less
-     */
-    public static class Cwbl extends Fmt00e {
-
-        public Cwbl(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbl(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Less or Equal
-     */
-    public static class Cwble extends Fmt00e {
-
-        public Cwble(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwble(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Less or Equal Unsigned
-     */
-    public static class Cwbleu extends Fmt00e {
-
-        public Cwbleu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbleu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Not Equal
-     */
-    public static class Cwbne extends Fmt00e {
-
-        public Cwbne(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbne(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Negative
-     */
-    public static class Cwbneg extends Fmt00e {
-
-        public Cwbneg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbneg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Positive
-     */
-    public static class Cwbpos extends Fmt00e {
-
-        public Cwbpos(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbpos(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Overflow Clear
-     */
-    public static class Cwbvc extends Fmt00e {
-
-        public Cwbvc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbvc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    /**
-     * Compare and Branch if Overflow Set
-     */
-    public static class Cwbvs extends Fmt00e {
-
-        public Cwbvs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 0, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cwbvs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbcc extends Fmt00e {
-
-        public Cxbcc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbcc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbcs extends Fmt00e {
-
-        public Cxbcs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbcs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbe extends Fmt00e {
-
-        public Cxbe(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbe(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbg extends Fmt00e {
-
-        public Cxbg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbge extends Fmt00e {
-
-        public Cxbge(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbge(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbgu extends Fmt00e {
-
-        public Cxbgu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbgu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbl extends Fmt00e {
-
-        public Cxbl(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbl(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxble extends Fmt00e {
-
-        public Cxble(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxble(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbleu extends Fmt00e {
-
-        public Cxbleu(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbleu(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbne extends Fmt00e {
-
-        public Cxbne(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbne(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbneg extends Fmt00e {
-
-        public Cxbneg(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbneg(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbpos extends Fmt00e {
-
-        public Cxbpos(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbpos(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbvc extends Fmt00e {
-
-        public Cxbvc(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbvc(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
-        }
-    }
-
-    public static class Cxbvs extends Fmt00e {
-
-        public Cxbvs(SPARCAssembler asm, Register src1, Register src2, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 1, src1.encoding(), simm10, src2.encoding());
-        }
-
-        public Cxbvs(SPARCAssembler asm, Register src1, int immed5, int simm10) {
-            super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue);
+    public static class CBcondw extends Fmt00e {
+        public CBcondw(ConditionFlag flag, Register src1, Register src2, Label label) {
+            super(flag.getValue(), 0, src1.encoding(), -1, 0, src2.encoding(), label);
+        }
+
+        public CBcondw(ConditionFlag flag, Register src1, int simm5, Label label) {
+            super(flag.getValue(), 0, src1.encoding(), -1, 1, simm5, label);
+        }
+    }
+
+    public static class CBcondx extends Fmt00e {
+        public CBcondx(ConditionFlag flag, Register src1, Register src2, Label label) {
+            super(flag.getValue(), 1, src1.encoding(), -1, 0, src2.encoding(), label);
+        }
+
+        public CBcondx(ConditionFlag flag, Register src1, int simm5, Label label) {
+            super(flag.getValue(), 1, src1.encoding(), -1, 1, simm5, label);
         }
     }
 
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Wed Sep 17 09:33:48 2014 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Wed Sep 17 17:06:37 2014 -0700
@@ -27,8 +27,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.*;
-import com.oracle.graal.sparc.*;
-import com.oracle.graal.sparc.SPARC.CPUFeature;
 
 public class SPARCMacroAssembler extends SPARCAssembler {
 
@@ -63,10 +61,6 @@
         fmt.write(this, branch);
     }
 
-    protected boolean hasFeature(CPUFeature feature) {
-        return ((SPARC) this.target.arch).features.contains(feature);
-    }
-
     @Override
     public AbstractAddress makeAddress(Register base, int displacement) {
         return new SPARCAddress(base, displacement);
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Sep 17 09:33:48 2014 -0700
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Sep 17 17:06:37 2014 -0700
@@ -179,9 +179,8 @@
 
         // If we don't have an index register we can use a displacement, otherwise load the
         // displacement into a register and add it to the base.
-        if (indexRegister.equals(Value.ILLEGAL)) {
+        if (indexRegister.equals(Value.ILLEGAL) && SPARCAssembler.isSimm13(finalDisp)) {
             displacementInt = (int) finalDisp;
-            assert SPARCAssembler.isSimm13(displacementInt) : displacementInt;
         } else {
             displacementInt = 0;
             if (baseRegister.equals(Value.ILLEGAL)) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Wed Sep 17 09:33:48 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Wed Sep 17 17:06:37 2014 -0700
@@ -85,6 +85,9 @@
         if ((config.sparcFeatures & config.vis3Instructions) != 0) {
             features.add(CPUFeature.VIS3);
         }
+        if ((config.sparcFeatures & config.cbcondInstructions) != 0) {
+            features.add(CPUFeature.CBCOND);
+        }
         return features;
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Sep 17 09:33:48 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Sep 17 17:06:37 2014 -0700
@@ -798,6 +798,7 @@
     @HotSpotVMConstant(name = "VM_Version::vis3_instructions_m", archs = {"sparc"}) @Stable public int vis3Instructions;
     @HotSpotVMConstant(name = "VM_Version::vis2_instructions_m", archs = {"sparc"}) @Stable public int vis2Instructions;
     @HotSpotVMConstant(name = "VM_Version::vis1_instructions_m", archs = {"sparc"}) @Stable public int vis1Instructions;
+    @HotSpotVMConstant(name = "VM_Version::cbcond_instructions_m", archs = {"sparc"}) @Stable public int cbcondInstructions;
 
     // offsets, ...
     @HotSpotVMFlag(name = "StackShadowPages") @Stable public int stackShadowPages;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java	Wed Sep 17 09:33:48 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java	Wed Sep 17 17:06:37 2014 -0700
@@ -129,16 +129,18 @@
     private void emit8ByteCompare(SPARCMacroAssembler masm, Register result, Register array1, Register array2, Register length, Label trueLabel, Label falseLabel) {
         Label loop = new Label();
         Label compareTail = new Label();
-        // new Ldx(new SPARCAddress(o6, 3), g0).emit(masm);
+        Label compareTailCorrectVectorEnd = new Label();
+
         Register tempReg1 = asRegister(temp4);
         Register tempReg2 = asRegister(temp5);
+
+        boolean hasCBcond = masm.hasFeature(CPUFeature.CBCOND);
+
         new And(result, VECTOR_SIZE - 1, result).emit(masm); // tail count (in bytes)
         new Andcc(length, ~(VECTOR_SIZE - 1), length).emit(masm);  // vector count (in bytes)
         new Bpe(CC.Xcc, compareTail).emit(masm);
-        new Nop().emit(masm);
 
-        Label compareTailCorrectVectorEnd = new Label();
-        new Sub(length, VECTOR_SIZE, length).emit(masm);
+        new Sub(length, VECTOR_SIZE, length).emit(masm); // Delay slot
         new Add(array1, length, array1).emit(masm);
         new Add(array2, length, array2).emit(masm);
         new Sub(g0, length, length).emit(masm);
@@ -146,11 +148,18 @@
         // Compare the last element first
         new Ldx(new SPARCAddress(array1, 0), tempReg1).emit(masm);
         new Ldx(new SPARCAddress(array2, 0), tempReg2).emit(masm);
-        new Cmp(tempReg1, tempReg2).emit(masm);
-        new Bpne(Xcc, true, false, falseLabel).emit(masm);
-        new Nop().emit(masm);
-        new Bpr(RCondition.Rc_z, false, false, length, compareTailCorrectVectorEnd).emit(masm);
-        new Nop().emit(masm);
+        if (hasCBcond) {
+            new CBcondx(ConditionFlag.NotEqual, tempReg1, tempReg2, falseLabel).emit(masm);
+            new Nop().emit(masm); // for optimal performance (see manual)
+            new CBcondx(ConditionFlag.Equal, length, 0, compareTailCorrectVectorEnd).emit(masm);
+            new Nop().emit(masm); // for optimal performance (see manual)
+        } else {
+            new Cmp(tempReg1, tempReg2).emit(masm);
+            new Bpne(Xcc, true, false, falseLabel).emit(masm);
+            new Nop().emit(masm);
+            new Bpr(RCondition.Rc_z, false, false, length, compareTailCorrectVectorEnd).emit(masm);
+            new Nop().emit(masm);
+        }
 
         // Load the first value from array 1 (Later done in back branch delay-slot)
         new Ldx(new SPARCAddress(array1, length), tempReg1).emit(masm);
@@ -164,8 +173,12 @@
         new Ldx(new SPARCAddress(array1, length), tempReg1).emit(masm); // Load in delay slot
 
         // Tail count zero, therefore we can go to the end
-        new Bpr(RCondition.Rc_z, true, true, result, trueLabel).emit(masm);
-        new Nop().emit(masm);
+        if (hasCBcond) {
+            new CBcondx(ConditionFlag.Equal, result, 0, trueLabel).emit(masm);
+        } else {
+            new Bpr(RCondition.Rc_z, true, true, result, trueLabel).emit(masm);
+            new Nop().emit(masm);
+        }
 
         masm.bind(compareTailCorrectVectorEnd);
         // Correct the array pointers
@@ -184,18 +197,28 @@
 
         Register tempReg1 = asRegister(temp3);
         Register tempReg2 = asRegister(temp4);
+        boolean hasCBcond = masm.hasFeature(CPUFeature.CBCOND);
 
         if (kind.getByteCount() <= 4) {
             // Compare trailing 4 bytes, if any.
-            new Cmp(result, 4).emit(masm);
-            new Bpl(Xcc, false, false, compare2Bytes).emit(masm);
-            new Nop().emit(masm);
+            if (hasCBcond) {
+                new CBcondx(ConditionFlag.Less, result, 4, compare2Bytes).emit(masm);
+            } else {
+                new Cmp(result, 4).emit(masm);
+                new Bpl(Xcc, false, false, compare2Bytes).emit(masm);
+                new Nop().emit(masm);
+            }
+
             new Lduw(new SPARCAddress(array1, 0), tempReg1).emit(masm);
             new Lduw(new SPARCAddress(array2, 0), tempReg2).emit(masm);
-            new Cmp(tempReg1, tempReg2).emit(masm);
 
-            new Bpne(Xcc, false, false, falseLabel).emit(masm);
-            new Nop().emit(masm);
+            if (hasCBcond) {
+                new CBcondx(ConditionFlag.NotEqual, tempReg1, tempReg2, falseLabel).emit(masm);
+            } else {
+                new Cmp(tempReg1, tempReg2).emit(masm);
+                new Bpne(Xcc, false, false, falseLabel).emit(masm);
+                new Nop().emit(masm);
+            }
 
             if (kind.getByteCount() <= 2) {
                 // Move array pointers forward.
@@ -206,14 +229,24 @@
                 // Compare trailing 2 bytes, if any.
                 masm.bind(compare2Bytes);
 
-                new Cmp(result, 2).emit(masm);
-                new Bpl(Xcc, false, true, compare1Byte).emit(masm);
-                new Nop().emit(masm);
+                if (hasCBcond) {
+                    new CBcondx(ConditionFlag.Less, result, 2, compare1Byte).emit(masm);
+                } else {
+                    new Cmp(result, 2).emit(masm);
+                    new Bpl(Xcc, false, true, compare1Byte).emit(masm);
+                    new Nop().emit(masm);
+                }
+
                 new Lduh(new SPARCAddress(array1, 0), tempReg1).emit(masm);
                 new Lduh(new SPARCAddress(array2, 0), tempReg2).emit(masm);
-                new Cmp(tempReg1, tempReg2).emit(masm);
-                new Bpne(Xcc, false, true, falseLabel).emit(masm);
-                new Nop().emit(masm);
+
+                if (hasCBcond) {
+                    new CBcondx(ConditionFlag.NotEqual, tempReg1, tempReg2, falseLabel).emit(masm);
+                } else {
+                    new Cmp(tempReg1, tempReg2).emit(masm);
+                    new Bpne(Xcc, false, true, falseLabel).emit(masm);
+                    new Nop().emit(masm);
+                }
 
                 // The one-byte tail compare is only required for boolean and byte arrays.
                 if (kind.getByteCount() <= 1) {
@@ -224,14 +257,23 @@
 
                     // Compare trailing byte, if any.
                     masm.bind(compare1Byte);
-                    new Cmp(result, 1).emit(masm);
-                    new Bpne(Xcc, trueLabel).emit(masm);
-                    new Nop().emit(masm);
+                    if (hasCBcond) {
+                        new CBcondx(ConditionFlag.NotEqual, result, 1, trueLabel).emit(masm);
+                    } else {
+                        new Cmp(result, 1).emit(masm);
+                        new Bpne(Xcc, trueLabel).emit(masm);
+                        new Nop().emit(masm);
+                    }
                     new Ldub(new SPARCAddress(array1, 0), tempReg1).emit(masm);
                     new Ldub(new SPARCAddress(array2, 0), tempReg2).emit(masm);
-                    new Cmp(tempReg1, tempReg2).emit(masm);
-                    new Bpne(Xcc, falseLabel).emit(masm);
-                    new Nop().emit(masm);
+                    if (hasCBcond) {
+                        // new SPARCAssembler.Ldx(new SPARCAddress(o7, 1), g3).emit(masm);
+                        new CBcondx(ConditionFlag.NotEqual, tempReg1, tempReg2, falseLabel).emit(masm);
+                    } else {
+                        new Cmp(tempReg1, tempReg2).emit(masm);
+                        new Bpne(Xcc, falseLabel).emit(masm);
+                        new Nop().emit(masm);
+                    }
                 } else {
                     masm.bind(compare1Byte);
                 }
--- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Wed Sep 17 09:33:48 2014 -0700
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Wed Sep 17 17:06:37 2014 -0700
@@ -291,9 +291,14 @@
         return features;
     }
 
+    public boolean hasFeature(CPUFeature feature) {
+        return features.contains(feature);
+    }
+
     public enum CPUFeature {
         VIS1,
         VIS2,
-        VIS3
+        VIS3,
+        CBCOND
     }
 }
--- a/src/cpu/sparc/vm/vmStructs_sparc.hpp	Wed Sep 17 09:33:48 2014 -0700
+++ b/src/cpu/sparc/vm/vmStructs_sparc.hpp	Wed Sep 17 17:06:37 2014 -0700
@@ -82,7 +82,8 @@
   declare_c2_constant(R_G7_num)                                           \
   declare_constant(VM_Version::vis1_instructions_m)                       \
   declare_constant(VM_Version::vis2_instructions_m)                       \
-  declare_constant(VM_Version::vis3_instructions_m)
+  declare_constant(VM_Version::vis3_instructions_m)                       \
+  declare_constant(VM_Version::cbcond_instructions_m)
 
 #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
 
--- a/test/blacklist_sparc.txt	Wed Sep 17 09:33:48 2014 -0700
+++ b/test/blacklist_sparc.txt	Wed Sep 17 17:06:37 2014 -0700
@@ -1,6 +1,3 @@
 com.oracle.graal.replacements.test.StandardMethodSubstitutionsTest
-com.oracle.graal.replacements.test.StringSubstitutionsTest
 com.oracle.graal.hotspot.amd64.test.CompressedNullCheckTest
-com.oracle.graal.replacements.test.ArraysSubstitutionsTest
-com.oracle.graal.compiler.test.CheckGraalInvariants
 com.oracle.graal.truffle.test.SLTruffleGraalTestSuite