changeset 22692:f87ae6a74d88

[SPARC] Introduce LIR instruction for Op3 and Opf instructions
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Mon, 21 Sep 2015 14:35:30 +0200
parents 54d85a1b4188
children f04f2d2b2c42
files graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFloatCompareOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCOP3Op.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCOPFOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java
diffstat 8 files changed, 480 insertions(+), 499 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Fri Sep 18 12:18:41 2015 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Sep 21 14:35:30 2015 +0200
@@ -33,7 +33,6 @@
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Andncc;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Casa;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Casxa;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Fcmp;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Flushw;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Fpop1;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Fpop2;
@@ -83,7 +82,6 @@
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fabsd;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fabss;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Faddd;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Faddq;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fadds;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fandd;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.Fdivd;
@@ -202,7 +200,7 @@
         }
     }
 
-    public enum Ops {
+    public static enum Ops {
         // @formatter:off
         BranchOp(0b00),
         CallOp(0b01),
@@ -226,7 +224,7 @@
         }
     }
 
-    public enum Op2s {
+    public static enum Op2s {
         // @formatter:off
         Illtrap(0b000),
         Bpr    (0b011),
@@ -253,7 +251,7 @@
         }
     }
 
-    public enum Op3s {
+    public static enum Op3s {
         // @formatter:off
 
         Add(0x00, "add", ArithOp),
@@ -363,7 +361,6 @@
 
         Rd    (0b10_1000, "rd", ArithOp),
         Wr    (0b11_0000, "wr", ArithOp),
-        Fcmp  (0b11_0101, "fcmp", ArithOp),
 
         Tcc(0b11_1010, "tcc", ArithOp);
 
@@ -374,7 +371,6 @@
         private final Ops op;
 
         private Op3s(int value, String name, Ops op) {
-            assert isImm(value, 6);
             this.value = value;
             this.operator = name;
             this.op = op;
@@ -406,183 +402,80 @@
         }
     }
 
-    public enum Opfs {
+    public static enum Opfs {
         // @formatter:off
 
-        Fmovs(0b0_0000_0001, "fmovs"),
-        Fmovd(0b0_0000_0010, "fmovd"),
-        Fmovq(0b0_0000_0011, "fmovq"),
-        Fmovscc(0b00_0001, "fmovscc"),
-        Fmovdcc(0b00_0010, "fmovdcc"),
-        Fnegs(0x05, "fnegs"),
-        Fnegd(0x06, "fnegd"),
-        Fnegq(0x07, "fnegq"),
-        Fabss(0x09, "fabss"),
-        Fabsd(0x0A, "fabsd"),
-        Fabsq(0x0B, "fabsq"),
+        Fmovs(0b0_0000_0001, "fmovs", Fpop1),
+        Fmovd(0b0_0000_0010, "fmovd", Fpop1),
+        Fmovq(0b0_0000_0011, "fmovq", Fpop1),
+        Fmovscc(0b00_0001, "fmovscc", Fpop2),
+        Fmovdcc(0b00_0010, "fmovdcc", Fpop2),
+        Fnegs(0x05, "fnegs", Fpop1),
+        Fnegd(0x06, "fnegd", Fpop1),
+        Fnegq(0x07, "fnegq", Fpop1),
+        Fabss(0x09, "fabss", Fpop1),
+        Fabsd(0x0A, "fabsd", Fpop1),
+        Fabsq(0x0B, "fabsq", Fpop1),
 
         // start VIS1
-        Edge8cc(0x0, "edge8cc"),
-        Edge8n(0x1, "edge8n"),
-        Edge8lcc(0x2, "edge8lcc"),
-        Edge8ln(0x3, "edge8ln"),
-        Edge16cc(0x4, "edge16cc"),
-        Edge16n(0x5, "edge16n"),
-        Edge16lcc(0x6, "edge16lcc"),
-        Edge16ln(0x7, "edge16ln"),
-        Edge32cc(0x8, "edge32cc"),
-        Edge32n(0x9, "edge32n"),
-        Edge32lcc(0xA, "edge32lcc"),
-        Edge32ln(0xB, "edge32ln"),
-        Array8(0x10, "array8"),
-        Array16(0x12, "array16"),
-        Array32(0x14, "array32"),
-        AlignAddress(0x18, "alignaddress"),
-        AlignAddressLittle(0x1A, "alignaddress_little"),
-        Fpcmple16(0x20, "fpcmple16"),
-        Fpcmpne16(0x22, "fpcmpne16"),
-        Fpcmple32(0x24, "fpcmple32"),
-        Fpcmpne32(0x26, "fpcmpne32"),
-        Fpcmpgt16(0x28, "fpcmpgt16"),
-        Fpcmpeq16(0x2A, "fpcmpeq16"),
-        Fpcmpgt32(0x2C, "fpcmpgt32"),
-        Fpcmpeq32(0x2E, "fpcmpeq32"),
-        Fmul8x16(0x31, "fmul8x16"),
-        Fmul8x16au(0x33, "fmul8x16au"),
-        Fmul8x16al(0x35, "fmul8x16al"),
-        Fmul8sux16(0x36, "fmul8sux16"),
-        Fmul8ulx16(0x37, "fmul8ulx16"),
-        Fmuld8sux16(0x38, "fmuld8sux16"),
-        Fmuld8ulx16(0x39, "fmuld8ulx16"),
-        Fpack32(0x3A, "fpack32"),
-        Fpack16(0x3B, "fpack16"),
-        Fpackfix(0x3D, "fpackfix"),
-        Faligndatag(0x48, "faligndata"),
-        Fpmerge(0x4B, "fpmerge"),
-        Fpadd16(0x50, "fpadd16"),
-        Fpadd16s(0x51, "fpadd16s"),
-        Fpadd32(0x52, "fpadd32"),
-        Fpadd32s(0x53, "fpadd32s"),
-        Fpsub16(0x54, "fpadd16"),
-        Fpsub16s(0x55, "fpadd16s"),
-        Fpsub32(0x56, "fpadd32"),
-        Fpsub32s(0x57, "fpadd32s"),
-        Fzerod(0x60, "fzerod"),
-        Fzeros(0x61, "fzeros"),
-        Fnot2d(0x66, "fnot1d"),
-        Fnot2s(0x67, "fnot1s"),
-        Fnot1d(0x6A, "fnot1d"),
-        Fnot1s(0x6B, "fnot1s"),
-        Fsrc1d(0x74, "fsrc1d"),
-        Fsrc1s(0x75, "fsrc1s"),
-        Fsrc2d(0x78, "fsrc2d"),
-        Fsrc2s(0x79, "fsrc2s"),
-        Foned(0x7E, "foned"),
-        Fones(0x7F, "fones"),
-        Fandd(0b0_0111_0000, "fandd"),
-        Fands(0b0_0111_0001, "fands"),
-        Fxord(0b0_0110_1100, "fxord"),
-        Fxors(0b0_0110_1101, "fxors"),
+        Fpadd32(0x52, "fpadd32", Impdep1),
+        Fzerod(0x60, "fzerod", Impdep1),
+        Fzeros(0x61, "fzeros", Impdep1),
+        Fnot2d(0x66, "fnot1d", Impdep1),
+        Fsrc2d(0x78, "fsrc2d", Impdep1),
+        Fsrc2s(0x79, "fsrc2s", Impdep1),
+        Fandd(0b0_0111_0000, "fandd", Impdep1),
+        Fands(0b0_0111_0001, "fands", Impdep1),
         // end VIS1
 
-        // start VIS2
-        Bmask(0x19, "bmask"),
-        Bshuffle(0x4c, "bshuffle"),
-        // end VIS2 only
-
         // start VIS3
-        Addxc(0x11, "addxc"),
-        Addxccc(0x13, "addxccc"),
-        Cmask8(0x1B, "cmask8"),
-        Cmask16(0x1D, "cmask16"),
-        Cmask32(0x1F, "cmask32"),
-        Fmean16(0x40, "fmean16"),
-        Fnadds(0x51, "fnadds"),
-        Fnaddd(0x52, "fnaddd"),
-        Fnmuls(0x59, "fnmuls"),
-        Fnmuld(0x5A, "fnmuld"),
-        Fnsmuld(0x79, "fnsmuld"),
-        Fnhadds(0x71, "fnhadds"),
-        Fnhaddd(0x72, "fnhaddd"),
-        Movdtox(0x110, "movdtox"),
-        Movstouw(0x111, "movstouw"),
-        Movstosw(0x113, "movstosw"),
-        Movxtod(0x118, "movxtod"),
-        Movwtos(0b1_0001_1001, "movwtos"),
-        UMulxhi(0b0_0001_0110, "umulxhi"),
-        Lzcnt  (0b0_0001_0111, "lzcnt"),
+        Movdtox(0x110, "movdtox", Impdep1),
+        Movstouw(0x111, "movstouw", Impdep1),
+        Movstosw(0x113, "movstosw", Impdep1),
+        Movxtod(0x118, "movxtod", Impdep1),
+        Movwtos(0b1_0001_1001, "movwtos", Impdep1),
+        UMulxhi(0b0_0001_0110, "umulxhi", Impdep1),
         // end VIS3
 
-        // start CAMMELLIA
-        CammelliaFl(0x13C, "cammelia_fl"),
-        CammelliaFli(0x13D, "cammellia_fli"),
-        // end CAMMELLIA
-
-        // start CRYPTO
-        Crc32c(0x147, "crc32c"),
-        // end CRYPTO
+        Fadds(0x41, "fadds", Fpop1),
+        Faddd(0x42, "faddd", Fpop1),
+        Fsubs(0x45, "fsubs", Fpop1),
+        Fsubd(0x46, "fsubd", Fpop1),
+        Fmuls(0x49, "fmuls", Fpop1),
+        Fmuld(0x4A, "fmuld", Fpop1),
+        Fdivs(0x4D, "fdivs", Fpop1),
+        Fdivd(0x4E, "fdivd", Fpop1),
 
-        // start OSA 2011
-        Fpadd64(0x44, "fpadd64"),
-        Fpsub64(0x46, "fpsub64"),
-        Fpadds16(0x58, "fpadds16"),
-        Fpadds16s(0x59, "fpadds16"),
-        Fpadds32(0x5A, "fpadds32"),
-        Fpadds32s(0x5B, "fpadds32s"),
-        Fpsubs16(0x5C, "fpsubs16"),
-        Fpsubs16s(0x5D, "fpsubs16s"),
-        Fpsubs32(0x5E, "fpsubs32"),
-        Fpsubs32s(0x5F, "fpsubs32s"),
-        Fpcmpne8(0x122, "fpcmpne8"),
-        Fpcmpeq8(0x12C, "fpcmpeq8"),
-        // end OSA 2011
+        Fsqrts(0x29, "fsqrts", Fpop1),
+        Fsqrtd(0x2A, "fsqrtd", Fpop1),
 
-        Fadds(0x41, "fadds"),
-        Faddd(0x42, "faddd"),
-        Faddq(0x43, "faddq"),
-        Fsubs(0x45, "fsubs"),
-        Fsubd(0x46, "fsubd"),
-        Fsubq(0x47, "fsubq"),
-        Fmuls(0x49, "fmuls"),
-        Fmuld(0x4A, "fmuld"),
-        Fdivs(0x4D, "fdivs"),
-        Fdivd(0x4E, "fdivd"),
-        Fdivq(0x4F, "fdivq"),
-
-        Fsqrts(0x29, "fsqrts"),
-        Fsqrtd(0x2A, "fsqrtd"),
-        Fsqrtq(0x2B, "fsqrtq"),
+        Fsmuld(0x69, "fsmuld", Fpop1),
 
-        Fsmuld(0x69, "fsmuld"),
-        Fmulq(0x6B, "fmulq"),
-        Fdmuldq(0x6E, "fdmulq"),
-
-        Fstoi(0xD1, "fstoi"),
-        Fdtoi(0xD2, "fdtoi"),
-        Fstox(0x81, "fstox"),
-        Fdtox(0x82, "fdtox"),
-        Fxtos(0x84, "fxtos"),
-        Fxtod(0x88, "fxtod"),
-        Fxtoq(0x8C, "fxtoq"),
-        Fitos(0xC4, "fitos"),
-        Fdtos(0xC6, "fdtos"),
-        Fitod(0xC8, "fitod"),
-        Fstod(0xC9, "fstod"),
-        Fitoq(0xCC, "fitoq"),
+        Fstoi(0xD1, "fstoi", Fpop1),
+        Fdtoi(0xD2, "fdtoi", Fpop1),
+        Fstox(0x81, "fstox", Fpop1),
+        Fdtox(0x82, "fdtox", Fpop1),
+        Fxtos(0x84, "fxtos", Fpop1),
+        Fxtod(0x88, "fxtod", Fpop1),
+        Fitos(0xC4, "fitos", Fpop1),
+        Fdtos(0xC6, "fdtos", Fpop1),
+        Fitod(0xC8, "fitod", Fpop1),
+        Fstod(0xC9, "fstod", Fpop1),
 
 
-        Fcmps(0x51, "fcmps"),
-        Fcmpd(0x52, "fcmpd"),
-        Fcmpq(0x53, "fcmpq");
+        Fcmps(0x51, "fcmps", Fpop2),
+        Fcmpd(0x52, "fcmpd", Fpop2);
 
         // @formatter:on
 
         private final int value;
         private final String operator;
+        private final Op3s op3;
 
-        private Opfs(int value, String op) {
+        private Opfs(int value, String op, Op3s op3) {
             this.value = value;
             this.operator = op;
+            this.op3 = op3;
         }
 
         public int getValue() {
@@ -935,10 +828,11 @@
         private static final BitSpec op = new ContinousBitSpec(31, 30, "op");
         private static final BitSpec op2 = new ContinousBitSpec(24, 22, "op2");
         private static final BitSpec op3 = new ContinousBitSpec(24, 19, "op3");
+        private static final BitSpec opf = new ContinousBitSpec(13, 5, "opf");
         private static final BitSpec rd = new ContinousBitSpec(29, 25, "rd");
         private static final BitSpec rs1 = new ContinousBitSpec(18, 14, "rs1");
         private static final BitSpec rs2 = new ContinousBitSpec(4, 0, "rs2");
-        private static final BitSpec simm13 = new ContinousBitSpec(12, 0, "simm13");
+        private static final BitSpec simm13 = new ContinousBitSpec(12, 0, true, "simm13");
         private static final BitSpec imm22 = new ContinousBitSpec(21, 0, "imm22");
         private static final BitSpec immAsi = new ContinousBitSpec(12, 5, "immASI");
         private static final BitSpec i = new ContinousBitSpec(13, 13, "i");
@@ -950,6 +844,7 @@
         private static final BitSpec cond = new ContinousBitSpec(28, 25, "cond");
         private static final BitSpec rcond = new ContinousBitSpec(27, 25, "rcond");
         private static final BitSpec cc = new ContinousBitSpec(21, 20, "cc");
+        private static final BitSpec fcc = new ContinousBitSpec(26, 25, "cc");
         private static final BitSpec d16hi = new ContinousBitSpec(21, 20, "d16hi");
         private static final BitSpec d16lo = new ContinousBitSpec(13, 0, "d16lo");
         private static final BitSpec d16 = new CompositeBitSpec(d16hi, d16lo);
@@ -1126,28 +1021,34 @@
          * @param keys Ordered by the importance
          * @param operation Operation represented by this list of keys
          */
-        private void addOp(List<BitKey> keys, SPARCOp operation) {
+        private void addOp(List<BitKey[]> keys, SPARCOp operation) {
             assert keys.size() > 0;
-            BitKey first = keys.get(0);
-            assert first.spec.equals(spec) : first.spec + " " + spec;
-            BitKeyIndex node;
-            if (keys.size() == 1) {
-                if (nodes.containsKey(first.value)) {
-                    node = nodes.get(first.value);
-                    assert node.op == null : node + " " + keys;
-                    node.op = operation;
+            BitKey[] firstKeys = keys.get(0);
+            for (BitKey first : firstKeys) {
+                assert first.spec.equals(spec) : first.spec + " " + spec;
+                BitKeyIndex node;
+                if (keys.size() == 1) {
+                    if (nodes.containsKey(first.value)) {
+                        node = nodes.get(first.value);
+                        assert node.op == null : node + " " + keys;
+                        node.op = operation;
+                    } else {
+                        assert !nodes.containsKey(first.value) : "Index must be unique. Existing key: " + nodes.get(first.value);
+                        node = new BitKeyIndex(operation);
+                    }
                 } else {
-                    assert !nodes.containsKey(first.value) : "Index must be unique. Existing key: " + nodes.get(first.value);
-                    node = new BitKeyIndex(operation);
+                    node = nodes.get(first.value);
+                    BitKey[] next = keys.get(1);
+                    if (node == null) {
+                        for (int i = 1; i < next.length; i++) {
+                            assert next[i - 1].spec.equals(next[i].spec) : "All spec on this node must equal";
+                        }
+                        node = new BitKeyIndex(next[0].spec);
+                    }
+                    node.addOp(keys.subList(1, keys.size()), operation);
                 }
-            } else {
-                node = nodes.get(first.value);
-                if (node == null) {
-                    node = new BitKeyIndex(keys.get(1).spec);
-                }
-                node.addOp(keys.subList(1, keys.size()), operation);
+                nodes.put(first.value, node);
             }
-            nodes.put(first.value, node);
         }
 
         /**
@@ -1182,6 +1083,7 @@
     public static final Bpr BPR = new Bpr();
     public static final Br BR = new Br();
     public static final Sethi SETHI = new Sethi();
+    public static final OpfOp OPF = new OpfOp();
     public static final Op3Op OP3 = new Op3Op();
     public static final SPARCOp LDST = new SPARCOp(Ops.LdstOp);
     public static final SPARCOp BRANCH = new SPARCOp(Ops.BranchOp);
@@ -1204,7 +1106,7 @@
     public static class SPARCOp {
         private final Ops op;
         private final BitKey opKey;
-        private List<BitKey> keyFields;
+        private List<BitKey[]> keyFields;
         private static final List<SPARCOp> OPS = new ArrayList<>();
 
         public SPARCOp(Ops op) {
@@ -1219,18 +1121,20 @@
         }
 
         public boolean match(int inst) {
-            for (BitKey k : keyFields) {
-                if (k.spec.getBits(inst) != k.value) {
-                    return false;
+            for (BitKey[] keys : keyFields) {
+                for (BitKey k : keys) {
+                    if (k.spec.getBits(inst) != k.value) {
+                        return false;
+                    }
                 }
             }
             return true;
         }
 
-        protected List<BitKey> getKeys() {
+        protected List<BitKey[]> getKeys() {
             if (keyFields == null) {
                 keyFields = new ArrayList<>(4);
-                keyFields.add(opKey);
+                keyFields.add(new BitKey[]{opKey});
             }
             return keyFields;
         }
@@ -1254,14 +1158,14 @@
         private final Op2s op2;
         private final boolean delaySlot;
         private final BitSpec disp;
-        private final BitKey op2Key;
+        private final BitKey[] op2Key;
 
         private ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp) {
             super(op);
             this.op2 = op2;
             this.delaySlot = delaySlot;
             this.disp = disp;
-            this.op2Key = new BitKey(BitSpec.op2, op2.value);
+            this.op2Key = new BitKey[]{new BitKey(BitSpec.op2, op2.value)};
         }
 
         public boolean hasDelaySlot() {
@@ -1297,8 +1201,8 @@
         }
 
         @Override
-        protected List<BitKey> getKeys() {
-            List<BitKey> keys = super.getKeys();
+        protected List<BitKey[]> getKeys() {
+            List<BitKey[]> keys = super.getKeys();
             keys.add(op2Key);
             return keys;
         }
@@ -1372,9 +1276,9 @@
         }
 
         @Override
-        protected List<BitKey> getKeys() {
-            List<BitKey> keys = super.getKeys();
-            keys.add(CBCOND_KEY);
+        protected List<BitKey[]> getKeys() {
+            List<BitKey[]> keys = super.getKeys();
+            keys.add(new BitKey[]{CBCOND_KEY});
             return keys;
         }
 
@@ -1398,9 +1302,9 @@
         }
 
         @Override
-        protected List<BitKey> getKeys() {
-            List<BitKey> keys = super.getKeys();
-            keys.add(CBCOND_KEY);
+        protected List<BitKey[]> getKeys() {
+            List<BitKey[]> keys = super.getKeys();
+            keys.add(new BitKey[]{CBCOND_KEY});
             return keys;
         }
 
@@ -1460,9 +1364,9 @@
         }
 
         @Override
-        protected List<BitKey> getKeys() {
-            List<BitKey> keys = super.getKeys();
-            keys.add(op2Key);
+        protected List<BitKey[]> getKeys() {
+            List<BitKey[]> keys = super.getKeys();
+            keys.add(new BitKey[]{op2Key});
             return keys;
         }
     }
@@ -1495,6 +1399,69 @@
             assert match(inst);
             return OP3S[ArithOp.value & 1][BitSpec.op3.getBits(inst)];
         }
+
+        public void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, Register rs2, Register rd) {
+            int instruction = setBits(0, opcode, rs1, rd);
+            instruction = BitSpec.rs2.setBits(instruction, rs2.encoding);
+            instruction = BitSpec.i.setBits(instruction, 0);
+            masm.emitInt(instruction);
+        }
+
+        public void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, int simm13, Register rd) {
+            int instruction = setBits(0, opcode, rs1, rd);
+            instruction = BitSpec.i.setBits(instruction, 1);
+            instruction = BitSpec.simm13.setBits(instruction, simm13);
+            masm.emitInt(instruction);
+        }
+
+        private static int setBits(int instruction, Op3s op3, Register rs1, Register rd) {
+            assert op3.op.equals(ArithOp);
+            int tmp = BitSpec.op3.setBits(instruction, op3.value);
+            tmp = BitSpec.op.setBits(tmp, op3.op.value);
+            tmp = BitSpec.rd.setBits(tmp, rd.encoding);
+            return BitSpec.rs1.setBits(tmp, rs1.encoding);
+        }
+    }
+
+    public static class OpfOp extends SPARCOp {
+        public OpfOp() {
+            super(ArithOp);
+        }
+
+        public void emit(SPARCMacroAssembler masm, Opfs opf, Register rs1, Register rs2, Register rd) {
+            int instruction = setBits(0, opf, rs1, rs2);
+            instruction = BitSpec.rd.setBits(instruction, rd.encoding);
+            instruction = BitSpec.i.setBits(instruction, 0);
+            masm.emitInt(instruction);
+        }
+
+        public void emitFcmp(SPARCMacroAssembler masm, Opfs opf, CC cc, Register rs1, Register rs2) {
+            assert opf.equals(Opfs.Fcmpd) || opf.equals(Opfs.Fcmps) : opf;
+            int instruction = setBits(0, opf, rs1, rs2);
+            instruction = BitSpec.fcc.setBits(instruction, cc.value);
+            masm.emitInt(instruction);
+        }
+
+        private static int setBits(int instruction, Opfs opf, Register rs1, Register rs2) {
+            int tmp = BitSpec.op.setBits(instruction, opf.op3.op.value);
+            tmp = BitSpec.op3.setBits(tmp, opf.op3.value);
+            tmp = BitSpec.opf.setBits(tmp, opf.value);
+            tmp = BitSpec.rs1.setBits(tmp, rs1.encoding);
+            return BitSpec.rs2.setBits(tmp, rs2.encoding);
+        }
+
+        @Override
+        protected List<BitKey[]> getKeys() {
+            List<BitKey[]> keys = super.getKeys();
+            // @formatter:off
+            keys.add(new BitKey[]{
+                            new BitKey(BitSpec.op3, Op3s.Fpop1.value),
+                            new BitKey(BitSpec.op3, Op3s.Fpop2.value),
+                            new BitKey(BitSpec.op3, Op3s.Impdep1.value),
+                            new BitKey(BitSpec.op3, Op3s.Impdep2.value)});
+            // @formatter:on
+            return keys;
+        }
     }
 
     public boolean hasFeature(CPUFeature feature) {
@@ -1911,10 +1878,6 @@
         op3(Fpop1, Faddd, rs1, rs2, rd);
     }
 
-    public void faddq(Register rs1, Register rs2, Register rd) {
-        op3(Fpop1, Faddq, rs1, rs2, rd);
-    }
-
     public void fdivs(Register rs1, Register rs2, Register rd) {
         op3(Fpop1, Fdivs, rs1, rs2, rd);
     }
@@ -2058,7 +2021,7 @@
         int a = cc.value;
         int b = opf.value << 5 | rs2.encoding;
         delaySlotOptimizationPoints.add(position());
-        fmt10(a, Fcmp.value, rs1.encoding, b);
+        fmt10(a, Fpop2.value, rs1.encoding, b);
     }
 
     // @formatter:off
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Fri Sep 18 12:18:41 2015 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Sep 21 14:35:30 2015 +0200
@@ -23,6 +23,10 @@
 
 package com.oracle.graal.compiler.sparc;
 
+import static com.oracle.graal.asm.sparc.SPARCAssembler.CC.Fcc0;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Subcc;
+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.lir.LIRValueUtil.asConstantValue;
 import static com.oracle.graal.lir.LIRValueUtil.asJavaConstant;
 import static com.oracle.graal.lir.LIRValueUtil.isJavaConstant;
@@ -93,13 +97,10 @@
 import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.IPOPCNT;
 import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.LBSR;
 import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.LPOPCNT;
-import static com.oracle.graal.lir.sparc.SPARCCompare.DCMP;
-import static com.oracle.graal.lir.sparc.SPARCCompare.FCMP;
-import static com.oracle.graal.lir.sparc.SPARCCompare.ICMP;
-import static com.oracle.graal.lir.sparc.SPARCCompare.LCMP;
 import static com.oracle.graal.lir.sparc.SPARCMathIntrinsicOp.IntrinsicOpcode.ABS;
 import static com.oracle.graal.lir.sparc.SPARCMathIntrinsicOp.IntrinsicOpcode.SQRT;
 import static jdk.internal.jvmci.code.ValueUtil.isStackSlotValue;
+import static jdk.internal.jvmci.meta.JavaKind.Char;
 import jdk.internal.jvmci.code.CallingConvention;
 import jdk.internal.jvmci.code.CodeUtil;
 import jdk.internal.jvmci.code.StackSlotValue;
@@ -117,6 +118,8 @@
 import com.oracle.graal.asm.sparc.SPARCAssembler;
 import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
 import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
+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;
@@ -145,14 +148,13 @@
 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.SPARCCompare;
-import com.oracle.graal.lir.sparc.SPARCCompare.CompareOp;
 import com.oracle.graal.lir.sparc.SPARCControlFlow;
 import com.oracle.graal.lir.sparc.SPARCControlFlow.BranchOp;
 import com.oracle.graal.lir.sparc.SPARCControlFlow.CondMoveOp;
 import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp;
 import com.oracle.graal.lir.sparc.SPARCControlFlow.StrategySwitchOp;
 import com.oracle.graal.lir.sparc.SPARCControlFlow.TableSwitchOp;
+import com.oracle.graal.lir.sparc.SPARCFloatCompareOp;
 import com.oracle.graal.lir.sparc.SPARCImmediateAddressValue;
 import com.oracle.graal.lir.sparc.SPARCJumpOp;
 import com.oracle.graal.lir.sparc.SPARCLoadConstantTableBaseOp;
@@ -166,7 +168,7 @@
 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.SPARCTestOp;
+import com.oracle.graal.lir.sparc.SPARCOP3Op;
 import com.oracle.graal.phases.util.Providers;
 
 /**
@@ -327,37 +329,42 @@
             right = loadNonConst(y);
             actualCondition = cond;
         }
-        SPARCCompare opcode;
         JavaKind actualCmpKind = (JavaKind) cmpKind;
-        switch (actualCmpKind) {
-            case Byte:
-                left = emitSignExtend(left, 8, 32);
-                right = emitSignExtend(right, 8, 32);
-                actualCmpKind = JavaKind.Int;
-                opcode = ICMP;
-                break;
-            case Short:
-                left = emitSignExtend(left, 16, 32);
-                right = emitSignExtend(right, 16, 32);
-                actualCmpKind = JavaKind.Int;
-                opcode = ICMP;
-                break;
-            case Long:
-                opcode = LCMP;
-                break;
-            case Int:
-                opcode = ICMP;
-                break;
-            case Float:
-                opcode = FCMP;
-                break;
-            case Double:
-                opcode = DCMP;
-                break;
-            default:
-                throw JVMCIError.shouldNotReachHere(actualCmpKind.toString());
+        if (actualCmpKind.isNumericInteger()) {
+            actualCmpKind = toSPARCCmpKind(actualCmpKind);
+            append(new SPARCControlFlow.CompareBranchOp(canonicalizeForCompare(left, cmpKind, actualCmpKind), canonicalizeForCompare(right, cmpKind, actualCmpKind), actualCondition, trueDestination,
+                            falseDestination, actualCmpKind, unorderedIsTrue, trueDestinationProbability));
+        } else if (actualCmpKind.isNumericFloat()) {
+            emitFloatCompare(cmpKind, x, y, Fcc0);
+            ConditionFlag cf = SPARCControlFlow.fromCondition(Fcc0, cond, unorderedIsTrue);
+            append(new SPARCControlFlow.BranchOp(cf, trueDestination, falseDestination, actualCmpKind, trueDestinationProbability));
         }
-        append(new SPARCControlFlow.CompareBranchOp(opcode, left, right, actualCondition, trueDestination, falseDestination, actualCmpKind, unorderedIsTrue, trueDestinationProbability));
+    }
+
+    private static JavaKind toSPARCCmpKind(JavaKind actualCmpKind) {
+        // TODO: Change to PlatformKind
+        assert actualCmpKind.isNumericInteger();
+        if (actualCmpKind.getByteCount() <= 4) {
+            return JavaKind.Int;
+        } else {
+            return JavaKind.Long;
+        }
+    }
+
+    private Value canonicalizeForCompare(Value v, PlatformKind from, PlatformKind to) {
+        if (LIRValueUtil.isJavaConstant(v)) {
+            JavaConstant c = asJavaConstant(v);
+            return new ConstantValue(v.getLIRKind().changeType(to), c);
+        } else {
+            int fromBytes = from.getSizeInBytes() * 8;
+            int toBytes = to.getSizeInBytes() * 8;
+            assert from.getSizeInBytes() <= v.getPlatformKind().getSizeInBytes();
+            if (from == to && !v.getPlatformKind().equals(JavaKind.Char)) {
+                return v;
+            } else {
+                return emitSignExtend(v, fromBytes, toBytes);
+            }
+        }
     }
 
     @Override
@@ -375,9 +382,9 @@
     private void emitIntegerTest(Value a, Value b) {
         assert ((JavaKind) a.getPlatformKind()).isNumericInteger();
         if (LIRValueUtil.isVariable(b)) {
-            append(new SPARCTestOp(load(b), loadNonConst(a)));
+            append(new SPARCOP3Op(Op3s.Andcc, load(b), loadNonConst(a)));
         } else {
-            append(new SPARCTestOp(load(a), loadNonConst(b)));
+            append(new SPARCOP3Op(Op3s.Andcc, load(a), loadNonConst(b)));
         }
     }
 
@@ -438,9 +445,23 @@
      * @return true if the left and right operands were switched, false otherwise
      */
     protected boolean emitCompare(PlatformKind cmpKind, Value a, Value b) {
-        Variable left;
+        boolean mirrored;
+        JavaKind cmpJavaKind = (JavaKind) cmpKind;
+        if (cmpJavaKind.isNumericInteger()) { // Integer case
+            mirrored = emitIntegerCompare(cmpJavaKind, a, b);
+        } else if (cmpJavaKind.isNumericFloat()) { // Float case
+            mirrored = false; // No mirroring done on floats
+            emitFloatCompare(cmpJavaKind, a, b, Fcc0);
+        } else {
+            throw JVMCIError.shouldNotReachHere();
+        }
+        return mirrored;
+    }
+
+    private boolean emitIntegerCompare(JavaKind cmpJavaKind, Value a, Value b) {
+        boolean mirrored;
+        Value left;
         Value right;
-        boolean mirrored;
         if (LIRValueUtil.isVariable(b)) {
             left = load(b);
             right = loadNonConst(a);
@@ -450,30 +471,34 @@
             right = loadNonConst(b);
             mirrored = false;
         }
-        switch ((JavaKind) cmpKind) {
-            case Short:
-            case Char:
-                append(new CompareOp(ICMP, emitSignExtend(left, 16, 32), emitSignExtend(right, 16, 32)));
-                break;
-            case Byte:
-                append(new CompareOp(ICMP, emitSignExtend(left, 8, 32), emitSignExtend(right, 8, 32)));
-                break;
-            case Int:
-                append(new CompareOp(ICMP, left, right));
-                break;
-            case Long:
-                append(new CompareOp(LCMP, left, right));
+        int compareBits = cmpJavaKind.getBitCount();
+        // SPARC compares 32 or 64 bits
+        if (compareBits < JavaKind.Int.getBitCount()) {
+            if (cmpJavaKind.equals(Char)) { // Char needs zero extend
+                left = emitZeroExtend(left, compareBits, 32);
+                right = emitZeroExtend(right, compareBits, 32);
+            } else {
+                left = emitSignExtend(left, compareBits, 32);
+                right = emitSignExtend(right, compareBits, 32);
+            }
+        }
+        append(new SPARCOP3Op(Subcc, left, right));
+        return mirrored;
+    }
+
+    private void emitFloatCompare(PlatformKind cmpJavaKind, Value a, Value b, CC cc) {
+        Opfs floatCompareOpcode;
+        switch ((JavaKind) cmpJavaKind) {
+            case Double:
+                floatCompareOpcode = Fcmpd;
                 break;
             case Float:
-                append(new CompareOp(FCMP, left, right));
-                break;
-            case Double:
-                append(new CompareOp(DCMP, left, right));
+                floatCompareOpcode = Fcmps;
                 break;
             default:
                 throw JVMCIError.shouldNotReachHere();
         }
-        return mirrored;
+        append(new SPARCFloatCompareOp(floatCompareOpcode, cc, load(a), load(b)));
     }
 
     @Override
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Fri Sep 18 12:18:41 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2013, 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.lir.sparc;
-
-import static com.oracle.graal.asm.sparc.SPARCAssembler.isSimm13;
-import static com.oracle.graal.asm.sparc.SPARCAssembler.CC.Fcc0;
-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.lir.LIRInstruction.OperandFlag.CONST;
-import static com.oracle.graal.lir.LIRInstruction.OperandFlag.REG;
-import static com.oracle.graal.lir.LIRValueUtil.asJavaConstant;
-import static jdk.internal.jvmci.code.ValueUtil.asRegister;
-import static jdk.internal.jvmci.code.ValueUtil.isRegister;
-import jdk.internal.jvmci.common.JVMCIError;
-import jdk.internal.jvmci.meta.JavaConstant;
-import jdk.internal.jvmci.meta.JavaKind;
-import jdk.internal.jvmci.meta.Value;
-
-import com.oracle.graal.asm.NumUtil;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler;
-import com.oracle.graal.lir.LIRInstructionClass;
-import com.oracle.graal.lir.Opcode;
-import com.oracle.graal.lir.asm.CompilationResultBuilder;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.CompareBranchOp;
-
-public enum SPARCCompare {
-    ICMP,
-    LCMP,
-    FCMP,
-    DCMP;
-
-    public static final class CompareOp extends SPARCLIRInstruction {
-        public static final LIRInstructionClass<CompareOp> TYPE = LIRInstructionClass.create(CompareOp.class);
-        public static final SizeEstimate SIZE = SizeEstimate.create(1);
-
-        @Opcode private final SPARCCompare opcode;
-        @Use({REG}) protected Value x;
-        @Use({REG, CONST}) protected Value y;
-
-        public CompareOp(SPARCCompare opcode, Value x, Value y) {
-            super(TYPE, SIZE);
-            this.opcode = opcode;
-            this.x = x;
-            this.y = y;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            emit(crb, masm, opcode, x, y);
-        }
-
-        @Override
-        public void verify() {
-            super.verify();
-            assert CompareBranchOp.SUPPORTED_KINDS.contains(x.getPlatformKind()) : x.getPlatformKind();
-            assert x.getPlatformKind().equals(y.getPlatformKind()) : x + " " + y;
-            // @formatter:off
-            assert
-                    (name().startsWith("I") && x.getPlatformKind() == JavaKind.Int && ((JavaKind) y.getPlatformKind()).getStackKind() == JavaKind.Int) ||
-                    (name().startsWith("L") && x.getPlatformKind() == JavaKind.Long && y.getPlatformKind() == JavaKind.Long) ||
-                    (name().startsWith("A") && x.getPlatformKind() == JavaKind.Object && y.getPlatformKind() == JavaKind.Object) ||
-                    (name().startsWith("F") && x.getPlatformKind() == JavaKind.Float && y.getPlatformKind() == JavaKind.Float) ||
-                    (name().startsWith("D") && x.getPlatformKind() == JavaKind.Double && y.getPlatformKind() == JavaKind.Double)
-                    : "Name; " + name() + " x: " + x + " y: " + y;
-            // @formatter:on
-        }
-    }
-
-    public static void emit(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCCompare opcode, Value x, Value y) {
-        if (isRegister(y)) {
-            switch (opcode) {
-                case ICMP:
-                    masm.cmp(asRegister(x, JavaKind.Int), asRegister(y, JavaKind.Int));
-                    break;
-                case LCMP:
-                    masm.cmp(asRegister(x, JavaKind.Long), asRegister(y, JavaKind.Long));
-                    break;
-                case FCMP:
-                    masm.fcmp(Fcc0, Fcmps, asRegister(x, JavaKind.Float), asRegister(y, JavaKind.Float));
-                    break;
-                case DCMP:
-                    masm.fcmp(Fcc0, Fcmpd, asRegister(x, JavaKind.Double), asRegister(y, JavaKind.Double));
-                    break;
-                default:
-                    throw JVMCIError.shouldNotReachHere();
-            }
-        } else {
-            JavaConstant c = asJavaConstant(y);
-            int imm;
-            if (c.isNull()) {
-                imm = 0;
-            } else {
-                assert NumUtil.isInt(c.asLong());
-                imm = (int) c.asLong();
-            }
-
-            switch (opcode) {
-                case LCMP:
-                    assert isSimm13(imm);
-                    masm.cmp(asRegister(x, JavaKind.Long), imm);
-                    break;
-                case ICMP:
-                    assert isSimm13(imm);
-                    masm.cmp(asRegister(x, JavaKind.Int), imm);
-                    break;
-                default:
-                    throw JVMCIError.shouldNotReachHere();
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Fri Sep 18 12:18:41 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Sep 21 14:35:30 2015 +0200
@@ -54,13 +54,16 @@
 import static com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag.LessEqualUnsigned;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag.LessUnsigned;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.Subcc;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.CONST;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.HINT;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.ILLEGAL;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.REG;
 import static com.oracle.graal.lir.LIRValueUtil.asJavaConstant;
+import static com.oracle.graal.lir.LIRValueUtil.isConstantValue;
 import static com.oracle.graal.lir.LIRValueUtil.isJavaConstant;
 import static com.oracle.graal.lir.sparc.SPARCMove.const2reg;
+import static com.oracle.graal.lir.sparc.SPARCOP3Op.emitOp3;
 import static jdk.internal.jvmci.code.ValueUtil.asRegister;
 import static jdk.internal.jvmci.sparc.SPARC.g0;
 
@@ -92,7 +95,6 @@
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
 import com.oracle.graal.compiler.common.calc.Condition;
-import com.oracle.graal.lir.ConstantValue;
 import com.oracle.graal.lir.LIRInstructionClass;
 import com.oracle.graal.lir.LabelRef;
 import com.oracle.graal.lir.Opcode;
@@ -133,9 +135,8 @@
     public static final class CompareBranchOp extends SPARCBlockEndOp implements SPARCDelayedControlTransfer {
         public static final LIRInstructionClass<CompareBranchOp> TYPE = LIRInstructionClass.create(CompareBranchOp.class);
         public static final SizeEstimate SIZE = SizeEstimate.create(3);
-        static final EnumSet<JavaKind> SUPPORTED_KINDS = EnumSet.of(JavaKind.Long, JavaKind.Int, JavaKind.Object, JavaKind.Float, JavaKind.Double);
+        static final EnumSet<JavaKind> SUPPORTED_KINDS = EnumSet.of(JavaKind.Long, JavaKind.Int, JavaKind.Short, JavaKind.Char, JavaKind.Byte);
 
-        private final SPARCCompare opcode;
         @Use({REG}) protected Value x;
         @Use({REG, CONST}) protected Value y;
         private ConditionFlag conditionFlag;
@@ -149,10 +150,8 @@
         private int delaySlotPosition = -1;
         private double trueDestinationProbability;
 
-        public CompareBranchOp(SPARCCompare opcode, Value x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, JavaKind kind, boolean unorderedIsTrue,
-                        double trueDestinationProbability) {
+        public CompareBranchOp(Value x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, JavaKind kind, boolean unorderedIsTrue, double trueDestinationProbability) {
             super(TYPE, SIZE);
-            this.opcode = opcode;
             this.x = x;
             this.y = y;
             this.trueDestination = trueDestination;
@@ -176,13 +175,19 @@
                     emitted = emitShortCompareBranch(crb, masm);
                 }
                 if (!emitted) { // No short compare/branch was used, so we go into fallback
-                    SPARCCompare.emit(crb, masm, opcode, x, y);
-                    emitted = emitBranch(crb, masm, kind, conditionFlag, trueDestination, falseDestination, true, trueDestinationProbability);
+                    emitted = emitLongCompareBranch(crb, masm, true);
+                    masm.nop();
+                    emitted = true;
                 }
             }
             assert emitted;
         }
 
+        private boolean emitLongCompareBranch(CompilationResultBuilder crb, SPARCMacroAssembler masm, boolean withDelayedNop) {
+            emitOp3(masm, Subcc, x, y);
+            return emitBranch(crb, masm, kind, conditionFlag, trueDestination, falseDestination, withDelayedNop, trueDestinationProbability);
+        }
+
         private static int getTargetPosition(Assembler asm) {
             return asm.position() + maximumSelfOffsetInstructions * asm.target.wordSize;
         }
@@ -192,8 +197,7 @@
             // When we use short branches, no delay slot is available
             int targetPosition = getTargetPosition(masm);
             if (!canUseShortBranch(crb, masm, targetPosition)) {
-                SPARCCompare.emit(crb, masm, opcode, x, y);
-                emitted = emitBranch(crb, masm, kind, conditionFlag, trueDestination, falseDestination, false, trueDestinationProbability);
+                emitted = emitLongCompareBranch(crb, masm, false);
                 if (emitted) {
                     delaySlotPosition = masm.position();
                 }
@@ -335,7 +339,8 @@
         public void verify() {
             super.verify();
             assert SUPPORTED_KINDS.contains(kind) : kind;
-            assert x.getPlatformKind().equals(kind) && y.getPlatformKind().equals(kind) : x + " " + y;
+            assert !isConstantValue(x);
+            assert x.getPlatformKind().equals(kind) && (isConstantValue(y) || y.getPlatformKind().equals(kind)) : x + " " + y;
         }
     }
 
@@ -384,11 +389,6 @@
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
             emitBranch(crb, masm, kind, conditionFlag, trueDestination, falseDestination, true, trueDestinationProbability);
         }
-
-        @Override
-        public void verify() {
-            assert CompareBranchOp.SUPPORTED_KINDS.contains(kind);
-        }
     }
 
     private static boolean emitBranch(CompilationResultBuilder crb, SPARCMacroAssembler masm, JavaKind kind, ConditionFlag conditionFlag, LabelRef trueDestination, LabelRef falseDestination,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFloatCompareOp.java	Mon Sep 21 14:35:30 2015 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, 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.lir.sparc;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.REG;
+import static jdk.internal.jvmci.code.ValueUtil.asRegister;
+import jdk.internal.jvmci.meta.Value;
+
+import com.oracle.graal.asm.sparc.SPARCAssembler;
+import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Opfs;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler;
+import com.oracle.graal.lir.LIRInstructionClass;
+import com.oracle.graal.lir.Opcode;
+import com.oracle.graal.lir.asm.CompilationResultBuilder;
+
+public class SPARCFloatCompareOp extends SPARCLIRInstruction {
+    public static final LIRInstructionClass<SPARCFloatCompareOp> TYPE = LIRInstructionClass.create(SPARCFloatCompareOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(1);
+
+    private final CC cc;
+    @Opcode protected final Opfs opf;
+    @Use({REG}) protected Value a;
+    @Use({REG}) protected Value b;
+
+    public SPARCFloatCompareOp(Opfs opf, CC cc, Value a, Value b) {
+        super(TYPE, SIZE);
+        this.cc = cc;
+        this.opf = opf;
+        this.a = a;
+        this.b = b;
+    }
+
+    @Override
+    protected void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        SPARCAssembler.OPF.emitFcmp(masm, opf, cc, asRegister(a), asRegister(b));
+    }
+
+    @Override
+    public void verify() {
+        assert a.getPlatformKind().equals(b.getPlatformKind()) : "a: " + a + " b: " + b;
+        assert opf.equals(Opfs.Fcmpd) || opf.equals(Opfs.Fcmps) : opf;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCOP3Op.java	Mon Sep 21 14:35:30 2015 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, 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.lir.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCAssembler.OP3;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.isSimm13;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.CONST;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.REG;
+import static com.oracle.graal.lir.LIRValueUtil.asJavaConstant;
+import static com.oracle.graal.lir.LIRValueUtil.isJavaConstant;
+import static jdk.internal.jvmci.code.ValueUtil.asRegister;
+import static jdk.internal.jvmci.code.ValueUtil.isRegister;
+import static jdk.internal.jvmci.common.JVMCIError.shouldNotReachHere;
+import static jdk.internal.jvmci.sparc.SPARC.g0;
+import jdk.internal.jvmci.meta.JavaConstant;
+import jdk.internal.jvmci.meta.Value;
+
+import com.oracle.graal.asm.sparc.SPARCAssembler.Op3s;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler;
+import com.oracle.graal.lir.LIRInstructionClass;
+import com.oracle.graal.lir.Opcode;
+import com.oracle.graal.lir.asm.CompilationResultBuilder;
+
+public class SPARCOP3Op extends SPARCLIRInstruction {
+    public static final LIRInstructionClass<SPARCOP3Op> TYPE = LIRInstructionClass.create(SPARCOP3Op.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(1);
+
+    @Opcode private final Op3s op3;
+    @Use({REG}) protected Value a;
+    @Use({REG, CONST}) protected Value b;
+    @Use({REG}) protected Value result;
+
+    public SPARCOP3Op(Op3s op3, Value a, Value b) {
+        this(op3, a, b, g0.asValue());
+    }
+
+    public SPARCOP3Op(Op3s op3, Value a, Value b, Value result) {
+        super(TYPE, SIZE);
+        this.op3 = op3;
+        this.a = a;
+        this.b = b;
+        this.result = result;
+    }
+
+    @Override
+    protected void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        emitOp3(masm, op3, a, b, result);
+    }
+
+    public static void emitOp3(SPARCMacroAssembler masm, Op3s op3, Value a, Value b) {
+        emitOp3(masm, op3, a, b, g0.asValue());
+    }
+
+    public static void emitOp3(SPARCMacroAssembler masm, Op3s op3, Value a, Value b, Value result) {
+        assert isRegister(a);
+        if (isJavaConstant(b)) {
+            JavaConstant constant = asJavaConstant(b);
+            long simm13;
+            if (constant.isNull()) {
+                simm13 = 0;
+            } else {
+                simm13 = constant.asLong(); // Cast is safe, as isSimm13 assertion is done
+            }
+            assert isSimm13(constant);
+            OP3.emit(masm, op3, asRegister(a), (int) simm13, asRegister(result));
+        } else if (isRegister(b)) {
+            OP3.emit(masm, op3, asRegister(a), asRegister(b), asRegister(result));
+        } else {
+            throw shouldNotReachHere(String.format("Got values a: %s b: %s", a, b));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCOPFOp.java	Mon Sep 21 14:35:30 2015 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, 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.lir.sparc;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.REG;
+import static jdk.internal.jvmci.code.ValueUtil.asRegister;
+import jdk.internal.jvmci.meta.Value;
+
+import com.oracle.graal.asm.sparc.SPARCAssembler;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Opfs;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler;
+import com.oracle.graal.lir.LIRInstructionClass;
+import com.oracle.graal.lir.Opcode;
+import com.oracle.graal.lir.asm.CompilationResultBuilder;
+
+public class SPARCOPFOp extends SPARCLIRInstruction {
+    public static final LIRInstructionClass<SPARCOPFOp> TYPE = LIRInstructionClass.create(SPARCOPFOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(1);
+
+    @Opcode protected final Opfs opf;
+    @Use({REG}) protected Value a;
+    @Use({REG}) protected Value b;
+    @Use({REG}) protected Value result;
+
+    public SPARCOPFOp(Opfs opf, Value a, Value b, Value result) {
+        super(TYPE, SIZE);
+        this.opf = opf;
+        this.a = a;
+        this.b = b;
+        this.result = result;
+    }
+
+    @Override
+    protected void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        SPARCAssembler.OPF.emit(masm, opf, asRegister(a), asRegister(b), asRegister(result));
+    }
+}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Fri Sep 18 12:18:41 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2011, 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.lir.sparc;
-
-import static com.oracle.graal.lir.LIRInstruction.OperandFlag.CONST;
-import static com.oracle.graal.lir.LIRInstruction.OperandFlag.REG;
-import static com.oracle.graal.lir.LIRValueUtil.isJavaConstant;
-import static jdk.internal.jvmci.code.ValueUtil.asRegister;
-import static jdk.internal.jvmci.code.ValueUtil.isRegister;
-import static jdk.internal.jvmci.sparc.SPARC.g0;
-import jdk.internal.jvmci.common.JVMCIError;
-import jdk.internal.jvmci.meta.JavaKind;
-import jdk.internal.jvmci.meta.Value;
-
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler;
-import com.oracle.graal.lir.LIRInstructionClass;
-import com.oracle.graal.lir.asm.CompilationResultBuilder;
-
-public class SPARCTestOp extends SPARCLIRInstruction {
-    public static final LIRInstructionClass<SPARCTestOp> TYPE = LIRInstructionClass.create(SPARCTestOp.class);
-    public static final SizeEstimate SIZE = SizeEstimate.create(1);
-
-    @Use({REG}) protected Value x;
-    @Use({REG, CONST}) protected Value y;
-
-    public SPARCTestOp(Value x, Value y) {
-        super(TYPE, SIZE);
-        this.x = x;
-        this.y = y;
-    }
-
-    @Override
-    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-        if (isRegister(y)) {
-            switch ((JavaKind) x.getPlatformKind()) {
-                case Short:
-                case Byte:
-                case Char:
-                case Boolean:
-                case Int:
-                    masm.andcc(asRegister(x, JavaKind.Int), asRegister(y, JavaKind.Int), g0);
-                    break;
-                case Long:
-                    masm.andcc(asRegister(x, JavaKind.Long), asRegister(y, JavaKind.Long), g0);
-                    break;
-                default:
-                    throw JVMCIError.shouldNotReachHere();
-            }
-        } else if (isJavaConstant(y)) {
-            switch ((JavaKind) x.getPlatformKind()) {
-                case Short:
-                case Byte:
-                case Char:
-                case Boolean:
-                case Int:
-                    masm.andcc(asRegister(x, JavaKind.Int), crb.asIntConst(y), g0);
-                    break;
-                case Long:
-                    masm.andcc(asRegister(x, JavaKind.Long), crb.asIntConst(y), g0);
-                    break;
-                default:
-                    throw JVMCIError.shouldNotReachHere();
-            }
-        } else {
-            throw JVMCIError.shouldNotReachHere();
-        }
-    }
-
-}