changeset 11233:5a9d68c3a7d7

SPARC: a lot of fixes and more
author twisti
date Mon, 05 Aug 2013 22:23:00 -0700
parents 22d3ee2fcb97
children 73eb4d8a4015 3bc0b35218e7
files graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.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/SPARCMathIntrinsicOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp src/cpu/sparc/vm/nativeInst_sparc.hpp
diffstat 23 files changed, 833 insertions(+), 440 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Mon Aug 05 22:23:00 2013 -0700
@@ -104,13 +104,20 @@
     }
 
     /**
+     * @return true if this address has an index register
+     */
+    public boolean hasIndex() {
+        return !getIndex().equals(Register.None);
+    }
+
+    /**
      * This method adds the stack-bias to the displacement if the base register is either
      * {@link SPARC#sp} or {@link SPARC#fp}.
      * 
      * @return Optional additive displacement.
      */
     public int getDisplacement() {
-        if (!getIndex().equals(Register.None)) {
+        if (hasIndex()) {
             throw GraalInternalError.shouldNotReachHere("address has index register");
         }
         // TODO Should we also hide the register save area size here?
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Aug 05 22:23:00 2013 -0700
@@ -458,9 +458,12 @@
     /**
      * Instruction format for Arithmetic, Logical, Moves, Tcc, Prefetch, and Misc.
      * 
-     * | 10  |   rd   |   op3   |   rs1   | i|   imm_asi   |   rs2   |
-     * | 10  |   rd   |   op3   |   rs1   | i|        simm13         |
-     * |31 30|29    25|24     19|18     14|13|12          5|4       0|
+     * | 10  |   rd   |   op3   |   rs1   | i|     imm_asi   |   rs2   |
+     * | 10  |   rd   |   op3   |   rs1   | i|          simm13         |
+     * | 10  |   rd   |   op3   |   rs1   | i| x|            |   rs2   |
+     * | 10  |   rd   |   op3   |   rs1   | i| x|            | shcnt32 |
+     * | 10  |   rd   |   op3   |   rs1   | i| x|           |  shcnt64 |
+     * |31 30|29    25|24     19|18     14|13|12|11         5|4       0|
      */
     // @formatter:on
     public static class Fmt10 {
@@ -470,6 +473,7 @@
         private static final int OP3_SHIFT = 19;
         private static final int RS1_SHIFT = 14;
         private static final int I_SHIFT = 13;
+        private static final int X_SHIFT = 12;
         private static final int IMM_ASI_SHIFT = 5;
         private static final int RS2_SHIFT = 0;
         private static final int SIMM13_SHIFT = 0;
@@ -480,6 +484,7 @@
         private static final int OP3_MASK     = 0b00000001111110000000000000000000;
         private static final int RS1_MASK     = 0b00000000000001111100000000000000;
         private static final int I_MASK       = 0b00000000000000000010000000000000;
+        private static final int X_MASK       = 0b00000000000000000001000000000000;
         private static final int IMM_ASI_MASK = 0b00000000000000000001111111100000;
         private static final int RS2_MASK     = 0b00000000000000000000000000011111;
         private static final int SIMM13_MASK  = 0b00000000000000000001111111111111;
@@ -489,15 +494,17 @@
         private int op3;
         private int rs1;
         private int i;
+        private int x;
         private int immAsi;
         private int rs2;
         private int simm13;
 
-        private Fmt10(int rd, int op3, int rs1, int i, int immAsi, int rs2, int simm13) {
+        private Fmt10(int rd, int op3, int rs1, int i, int x, int immAsi, int rs2, int simm13) {
             this.rd = rd;
             this.op3 = op3;
             this.rs1 = rs1;
             this.i = i;
+            this.x = x;
             this.immAsi = immAsi;
             this.rs2 = rs2;
             this.simm13 = simm13;
@@ -505,26 +512,40 @@
         }
 
         public Fmt10(Op3s op3, Register rs1, Register rs2, Register rd) {
-            this(rd.encoding(), op3.getValue(), rs1.encoding(), 0, 0, rs2.encoding(), 0);
+            this(rd.encoding(), op3.getValue(), rs1.encoding(), 0, getXBit(op3), 0, rs2.encoding(), 0);
         }
 
         public Fmt10(Op3s op3, Register rs1, int simm13, Register rd) {
-            this(rd.encoding(), op3.getValue(), rs1.encoding(), 1, 0, 0, simm13);
+            this(rd.encoding(), op3.getValue(), rs1.encoding(), 1, getXBit(op3), 0, 0, simm13);
         }
 
         public Fmt10(Op3s op3) {
-            this(0, op3.getValue(), 0, 0, 0, 0, 0);
+            this(0, op3.getValue(), 0, 0, getXBit(op3), 0, 0, 0);
         }
 
         public Fmt10(Op3s op3, Register rs1, Register rd) {
-            this(rd.encoding(), op3.getValue(), rs1.encoding(), 0, 0, 0, 0);
+            this(rd.encoding(), op3.getValue(), rs1.encoding(), 0, getXBit(op3), 0, 0, 0);
+        }
+
+        /**
+         * Helper method to determine if the instruction needs the X bit set.
+         */
+        private static int getXBit(Op3s op3) {
+            switch (op3) {
+                case Sllx:
+                case Srax:
+                case Srlx:
+                    return 1;
+                default:
+                    return 0;
+            }
         }
 
         private int getInstructionBits() {
             if (i == 0) {
-                return Ops.ArithOp.getValue() << OP_SHIFT | rd << RD_SHIFT | op3 << OP3_SHIFT | rs1 << RS1_SHIFT | i << I_SHIFT | immAsi << IMM_ASI_SHIFT | rs2 << RS2_SHIFT;
+                return Ops.ArithOp.getValue() << OP_SHIFT | rd << RD_SHIFT | op3 << OP3_SHIFT | rs1 << RS1_SHIFT | i << I_SHIFT | x << X_SHIFT | immAsi << IMM_ASI_SHIFT | rs2 << RS2_SHIFT;
             } else {
-                return Ops.ArithOp.getValue() << OP_SHIFT | rd << RD_SHIFT | op3 << OP3_SHIFT | rs1 << RS1_SHIFT | i << I_SHIFT | ((simm13 << SIMM13_SHIFT) & SIMM13_MASK);
+                return Ops.ArithOp.getValue() << OP_SHIFT | rd << RD_SHIFT | op3 << OP3_SHIFT | rs1 << RS1_SHIFT | i << I_SHIFT | x << X_SHIFT | ((simm13 << SIMM13_SHIFT) & SIMM13_MASK);
             }
         }
 
@@ -540,11 +561,12 @@
             final int op3 = (inst & OP3_MASK) >> OP3_SHIFT;
             final int rs1 = (inst & RS1_MASK) >> RS1_SHIFT;
             final int i = (inst & I_MASK) >> I_SHIFT;
+            final int x = (inst & X_MASK) >> X_SHIFT;
             final int immAsi = (inst & IMM_ASI_MASK) >> IMM_ASI_SHIFT;
             final int rs2 = (inst & RS2_MASK) >> RS2_SHIFT;
             final int simm13 = (inst & SIMM13_MASK) >> SIMM13_SHIFT;
 
-            return new Fmt10(rd, op3, rs1, i, immAsi, rs2, simm13);
+            return new Fmt10(rd, op3, rs1, i, x, immAsi, rs2, simm13);
         }
 
         public void write(SPARCAssembler masm, int pos) {
@@ -562,6 +584,7 @@
             assert ((op3 << OP3_SHIFT) & OP3_MASK) == (op3 << OP3_SHIFT);
             assert ((rs1 << RS1_SHIFT) & RS1_MASK) == (rs1 << RS1_SHIFT);
             assert ((i << I_SHIFT) & I_MASK) == (i << I_SHIFT);
+            assert ((x << X_SHIFT) & X_MASK) == (x << X_SHIFT);
             assert ((immAsi << IMM_ASI_SHIFT) & IMM_ASI_MASK) == (immAsi << IMM_ASI_SHIFT);
             assert ((rs2 << RS2_SHIFT) & RS2_MASK) == (rs2 << RS2_SHIFT);
             assert isSimm13(simm13);
@@ -711,6 +734,15 @@
         }
     }
 
+    // @formatter:off
+    /**
+     * Instruction format for Movcc.
+     * 
+     * | 10  |   rd   |   op3   |cc2|   cond  | i|cc1|cc0|      -      |   rs2   |
+     * | 10  |   rd   |   op3   |cc2|   cond  | i|cc1|cc0|        simm11         |
+     * |31 30|29    25|24     19| 18|17     14|13| 12| 11|10          5|4       0|
+     */
+    // @formatter:on
     public static class Fmt10c {
 
         private static final int OP_SHIFT = 30;
@@ -719,7 +751,8 @@
         private static final int CC2_SHIFT = 18;
         private static final int COND_SHIFT = 14;
         private static final int I_SHIFT = 13;
-        private static final int CC_SHIFT = 11;
+        private static final int CC1_SHIFT = 12;
+        private static final int CC0_SHIFT = 11;
         private static final int RS2_SHIFT = 0;
         private static final int SIMM11_SHIFT = 0;
 
@@ -730,7 +763,8 @@
         private static final int CC2_MASK    = 0b00000000000001000000000000000000;
         private static final int COND_MASK   = 0b00000000000000111100000000000000;
         private static final int I_MASK      = 0b00000000000000000010000000000000;
-        private static final int CC_MASK     = 0b00000000000000000001100000000000;
+        private static final int CC1_MASK    = 0b00000000000000000001000000000000;
+        private static final int CC0_MASK    = 0b00000000000000000000100000000000;
         private static final int RS2_MASK    = 0b00000000000000000000000000011111;
         private static final int SIMM11_MASK = 0b00000000000000000000011111111111;
         // @formatter:on
@@ -755,20 +789,33 @@
         }
 
         public Fmt10c(Op3s op3, ConditionFlag cond, CC cc, Register rs2, Register rd) {
-            this(rd.encoding(), op3.getValue(), cond.getValue(), 0, cc.getValue(), rs2.encoding(), 0);
+            this(rd.encoding(), op3.getValue(), cond.getValue(), 0, getCC(cc), rs2.encoding(), 0);
         }
 
         public Fmt10c(Op3s op3, ConditionFlag cond, CC cc, int simm11, Register rd) {
-            this(rd.encoding(), op3.getValue(), cond.getValue(), 1, cc.getValue(), 0, simm11);
+            this(rd.encoding(), op3.getValue(), cond.getValue(), 1, getCC(cc), 0, simm11);
+        }
+
+        /**
+         * Converts regular CC codes to CC codes used by Movcc instructions.
+         */
+        private static int getCC(CC cc) {
+            switch (cc) {
+                case Icc:
+                case Xcc:
+                    return 0b100 + cc.getValue();
+                default:
+                    return cc.getValue();
+            }
         }
 
         private int getInstructionBits() {
             if (i == 0) {
-                return Ops.ArithOp.getValue() << OP_SHIFT | rd << RD_SHIFT | op3 << OP3_SHIFT | ((cc << CC2_SHIFT) & CC2_MASK) | cond << COND_SHIFT | i << I_SHIFT | ((cc << CC_SHIFT) & CC_MASK) |
-                                rs2 << RS2_SHIFT;
+                return Ops.ArithOp.getValue() << OP_SHIFT | rd << RD_SHIFT | op3 << OP3_SHIFT | ((cc << (CC2_SHIFT - 2)) & CC2_MASK) | cond << COND_SHIFT | i << I_SHIFT |
+                                ((cc << (CC1_SHIFT - 1)) & CC1_MASK) | ((cc << CC0_SHIFT) & CC0_MASK) | rs2 << RS2_SHIFT;
             } else {
-                return Ops.ArithOp.getValue() << OP_SHIFT | rd << RD_SHIFT | op3 << OP3_SHIFT | ((cc << CC2_SHIFT) & CC2_MASK) | cond << COND_SHIFT | i << I_SHIFT | ((cc << CC_SHIFT) & CC_MASK) |
-                                ((simm11 << SIMM11_SHIFT) & SIMM11_MASK);
+                return Ops.ArithOp.getValue() << OP_SHIFT | rd << RD_SHIFT | op3 << OP3_SHIFT | ((cc << (CC2_SHIFT - 2)) & CC2_MASK) | cond << COND_SHIFT | i << I_SHIFT |
+                                ((cc << (CC1_SHIFT - 1)) & CC1_MASK) | ((cc << CC0_SHIFT) & CC0_MASK) | ((simm11 << SIMM11_SHIFT) & SIMM11_MASK);
             }
         }
 
@@ -784,7 +831,7 @@
             final int op3 = (inst & OP3_MASK) >> OP3_SHIFT;
             final int cond = (inst & COND_MASK) >> COND_SHIFT;
             final int i = (inst & I_MASK) >> I_SHIFT;
-            final int cc = (inst & CC2_MASK) >> CC2_SHIFT | (inst & CC_MASK) >> CC_SHIFT;
+            final int cc = (inst & CC2_MASK) >> CC2_SHIFT | (inst & CC1_MASK) >> CC1_SHIFT | (inst & CC0_MASK) >> CC0_SHIFT;
             final int rs2 = (inst & RS2_MASK) >> RS2_SHIFT;
             final int simm11 = (inst & SIMM11_MASK) >> SIMM11_SHIFT;
 
@@ -808,7 +855,7 @@
             assert ((i << I_SHIFT) & I_MASK) == (i << I_SHIFT);
             // assert cc >= 0 && cc < 0x8;
             assert ((rs2 << RS2_SHIFT) & RS2_MASK) == (rs2 << RS2_SHIFT);
-            // assert isSimm11(simm11);
+            assert isSimm11(simm11);
         }
     }
 
@@ -843,7 +890,14 @@
     public static final int ImmedTrue = 0x00002000;
 
     public enum Ops {
-        BranchOp(0b00), CallOp(0b01), ArithOp(0b10), LdstOp(0b11);
+        // @formatter:off
+
+        BranchOp(0b00),
+        CallOp(0b01),
+        ArithOp(0b10),
+        LdstOp(0b11);
+
+        // @formatter:on
 
         private final int value;
 
@@ -857,7 +911,18 @@
     }
 
     public enum Op2s {
-        Bpr(3), Fb(6), Fbp(5), Br(2), Bp(1), Cb(7), Sethi(4);
+        // @formatter:off
+
+        Illtrap(0b000),
+        Bpr(3),
+        Fb(6),
+        Fbp(5),
+        Br(2),
+        Bp(1),
+        Cb(7),
+        Sethi(0b100);
+
+        // @formatter:on
 
         private final int value;
 
@@ -871,6 +936,8 @@
     }
 
     public enum Op3s {
+        // @formatter:off
+
         Add(0x00, "add"),
         And(0x01, "and"),
         Or(0x02, "or"),
@@ -943,17 +1010,15 @@
         Casa(0b111100, "casa"),
         Casxa(0b111110, "casxa"),
 
-        Lduw(0x00, "lduw"),
-        Ldub(0x01, "ldub"),
-        Lduh(0x02, "lduh"),
-        Ldd(0x03, "ldd"),
-        Stw(0x04, "stw"),
-        Stb(0x05, "stb"),
-        Sth(0x06, "sth"),
-        Std(0x07, "std"),
-        Ldsw(0x08, "ldsw"),
-        Ldsb(0x09, "ldsb"),
-        Ldsh(0x0A, "ldsh"),
+        Lduw(0b00000, "lduw"),
+        Ldub(0b00001, "ldub"),
+        Lduh(0b00010, "lduh"),
+        Stw(0b000100, "stw"),
+        Stb(0b000101, "stb"),
+        Sth(0b000110, "sth"),
+        Ldsw(0b001000, "ldsw"),
+        Ldsb(0b001001, "ldsb"),
+        Ldsh(0b001010, "ldsh"),
         Ldx(0b001011, "ldx"),
         Stx(0b001110, "stx"),
 
@@ -966,6 +1031,8 @@
         Staf(0x26, "staf"),
         Stdf(0x27, "stdf");
 
+        // @formatter:on
+
         private final int value;
         private final String operator;
 
@@ -984,7 +1051,18 @@
     }
 
     public enum Op5s {
-        Fmadds(0x1), Fmaddd(0x2), Fmsubs(0x5), Fmsubd(0x6), Fnmsubs(0x9), Fnmsubd(0xA), Fnmadds(0xD), Fnmaddd(0xE);
+        // @formatter:off
+
+        Fmadds(0x1),
+        Fmaddd(0x2),
+        Fmsubs(0x5),
+        Fmsubd(0x6),
+        Fnmsubs(0x9),
+        Fnmsubd(0xA),
+        Fnmadds(0xD),
+        Fnmaddd(0xE);
+
+        // @formatter:on
 
         private final int value;
 
@@ -998,9 +1076,17 @@
     }
 
     public enum Opfs {
-        Fmovs(0x01, "fmovs"), Fmovd(0x02, "fmovd"), Fmovq(0x03, "fmovq"), Fnegs(0x05, "fnegs"), Fnegd(0x06, "fnegd"), Fnegq(0x07, "fnegq"), Fabss(0x09, "fabss"), Fabsd(0x0A, "fabsd"), Fabsq(
-                        0x0B,
-                        "fabsq"),
+        // @formatter:off
+
+        Fmovs(0x01, "fmovs"),
+        Fmovd(0x02, "fmovd"),
+        Fmovq(0x03, "fmovq"),
+        Fnegs(0x05, "fnegs"),
+        Fnegd(0x06, "fnegd"),
+        Fnegq(0x07, "fnegq"),
+        Fabss(0x09, "fabss"),
+        Fabsd(0x0A, "fabsd"),
+        Fabsq(0x0B, "fabsq"),
 
         // start VIS1
         Edge8cc(0x0, "edge8cc"),
@@ -1129,6 +1215,7 @@
 
         Fstoi(0xD1, "fstoi"),
         Fdtoi(0xD2, "fdtoi");
+        // @formatter:on
 
         private final int value;
         private final String operator;
@@ -1148,9 +1235,17 @@
     }
 
     public enum MembarMask {
-        StoreStore(1 << 3, "storestore"), LoadStore(1 << 2, "loadstore"), StoreLoad(1 << 1, "storeload"), LoadLoad(1 << 0, "loadload"), Sync(1 << 6, "sync"), MemIssue(1 << 5, "memissue"), LookAside(
-                        1 << 4,
-                        "lookaside");
+        // @formatter:off
+
+        StoreStore(1 << 3, "storestore"),
+        LoadStore(1 << 2, "loadstore"),
+        StoreLoad(1 << 1, "storeload"),
+        LoadLoad(1 << 0, "loadload"),
+        Sync(1 << 6, "sync"),
+        MemIssue(1 << 5, "memissue"),
+        LookAside(1 << 4, "lookaside");
+
+        // @formatter:on
 
         private final int value;
         private final String operator;
@@ -1170,7 +1265,17 @@
     }
 
     public enum CC {
-        Icc(0, "icc"), Xcc(2, "xcc"), Ptrcc(HotSpotGraalRuntime.wordKind() == Kind.Long ? Xcc.getValue() : Icc.getValue(), "ptrcc"), Fcc0(0, "fcc0"), Fcc1(1, "fcc1"), Fcc2(2, "fcc2"), Fcc3(3, "fcc3");
+        // @formatter:off
+
+        Icc(0b00, "icc"),
+        Xcc(0b10, "xcc"),
+        Ptrcc(HotSpotGraalRuntime.wordKind() == Kind.Long ? Xcc.getValue() : Icc.getValue(), "ptrcc"),
+        Fcc0(0b00, "fcc0"),
+        Fcc1(0b01, "fcc1"),
+        Fcc2(0b10, "fcc2"),
+        Fcc3(0b11, "fcc3");
+
+        // @formatter:on
 
         private final int value;
         private final String operator;
@@ -1190,8 +1295,9 @@
     }
 
     public enum ConditionFlag {
+        // @formatter:off
+
         // for FBfcc & FBPfcc instruction
-
         F_Never(0, "f_never"),
         F_NotEqual(1, "f_notEqual"),
         F_NotZero(1, "f_notZero"),
@@ -1233,6 +1339,8 @@
         Positive(14, "positive"),
         OverflowClear(15, "overflowClear");
 
+        // @formatter:on
+
         private final int value;
         private final String operator;
 
@@ -1251,7 +1359,17 @@
     }
 
     public enum RCondition {
-        Rc_z(1, "rc_z"), Rc_lez(2, "rc_lez"), Rc_lz(3, "rc_lz"), Rc_nz(5, "rc_nz"), Rc_gz(6, "rc_gz"), Rc_gez(7, "rc_gez"), Rc_last(Rc_gez.getValue(), "rc_last");
+        // @formatter:off
+
+        Rc_z(1, "rc_z"),
+        Rc_lez(2, "rc_lez"),
+        Rc_lz(3, "rc_lz"),
+        Rc_nz(5, "rc_nz"),
+        Rc_gz(6, "rc_gz"),
+        Rc_gez(7, "rc_gez"),
+        Rc_last(Rc_gez.getValue(), "rc_last");
+
+        // @formatter:on
 
         private final int value;
         private final String operator;
@@ -1271,12 +1389,19 @@
     }
 
     public enum Asi {
-        INVALID(-1), ASI_PRIMARY(0x80), ASI_PRIMARY_NOFAULT(0x82), ASI_PRIMARY_LITTLE(0x88),
+        // @formatter:off
+
+        INVALID(-1),
+        ASI_PRIMARY(0x80),
+        ASI_PRIMARY_NOFAULT(0x82),
+        ASI_PRIMARY_LITTLE(0x88),
         // Block initializing store
         ASI_ST_BLKINIT_PRIMARY(0xE2),
         // Most-Recently-Used (MRU) BIS variant
         ASI_ST_BLKINIT_MRU_PRIMARY(0xF2);
 
+        // @formatter:on
+
         private final int value;
 
         private Asi(int value) {
@@ -1337,6 +1462,10 @@
         return minSimm(nbits) <= imm && imm <= maxSimm(nbits);
     }
 
+    public static boolean isSimm11(int imm) {
+        return isSimm(imm, 11);
+    }
+
     public static boolean isSimm13(int imm) {
         return isSimm(imm, 13);
     }
@@ -2613,6 +2742,13 @@
         }
     }
 
+    public static class Illtrap extends Fmt00a {
+
+        public Illtrap(int const22) {
+            super(Op2s.Illtrap, const22, g0);
+        }
+    }
+
     public static class Jmpl extends Fmt10 {
 
         public Jmpl(Register src, int simm13, Register dst) {
@@ -2648,6 +2784,13 @@
         }
     }
 
+    public static class Lduh extends Fmt11 {
+
+        public Lduh(SPARCAddress src, Register dst) {
+            super(Op3s.Lduh, src, dst);
+        }
+    }
+
     public static class Ldsw extends Fmt11 {
 
         public Ldsw(SPARCAddress src, Register dst) {
@@ -2921,8 +3064,8 @@
 
     public static class Sll extends Fmt10 {
 
-        public Sll(Register src1, int simm13, Register dst) {
-            super(Op3s.Sll, src1, simm13, dst);
+        public Sll(Register src1, int shcnt32, Register dst) {
+            super(Op3s.Sll, src1, shcnt32, dst);
         }
 
         public Sll(Register src1, Register src2, Register dst) {
@@ -2932,8 +3075,8 @@
 
     public static class Sllx extends Fmt10 {
 
-        public Sllx(Register src1, int simm13, Register dst) {
-            super(Op3s.Sllx, src1, simm13, dst);
+        public Sllx(Register src1, int shcnt64, Register dst) {
+            super(Op3s.Sllx, src1, shcnt64, dst);
         }
 
         public Sllx(Register src1, Register src2, Register dst) {
@@ -2943,8 +3086,8 @@
 
     public static class Sra extends Fmt10 {
 
-        public Sra(Register src1, int simm13, Register dst) {
-            super(Op3s.Sra, src1, simm13, dst);
+        public Sra(Register src1, int shcnt32, Register dst) {
+            super(Op3s.Sra, src1, shcnt32, dst);
         }
 
         public Sra(Register src1, Register src2, Register dst) {
@@ -2954,8 +3097,8 @@
 
     public static class Srax extends Fmt10 {
 
-        public Srax(Register src1, int simm13, Register dst) {
-            super(Op3s.Srax, src1, simm13, dst);
+        public Srax(Register src1, int shcnt64, Register dst) {
+            super(Op3s.Srax, src1, shcnt64, dst);
         }
 
         public Srax(Register src1, Register src2, Register dst) {
@@ -2965,8 +3108,8 @@
 
     public static class Srl extends Fmt10 {
 
-        public Srl(Register src1, int simm13, Register dst) {
-            super(Op3s.Srl, src1, simm13, dst);
+        public Srl(Register src1, int shcnt32, Register dst) {
+            super(Op3s.Srl, src1, shcnt32, dst);
         }
 
         public Srl(Register src1, Register src2, Register dst) {
@@ -2976,8 +3119,8 @@
 
     public static class Srlx extends Fmt10 {
 
-        public Srlx(Register src1, int simm13, Register dst) {
-            super(Op3s.Srlx, src1, simm13, dst);
+        public Srlx(Register src1, int shcnt64, Register dst) {
+            super(Op3s.Srlx, src1, shcnt64, dst);
         }
 
         public Srlx(Register src1, Register src2, Register dst) {
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Mon Aug 05 22:23:00 2013 -0700
@@ -53,7 +53,7 @@
     @Override
     public void jmp(Label l) {
         new Bpa(l).emit(this);
-        new Nop().emit(this);
+        new Nop().emit(this);  // delay slot
     }
 
     @Override
@@ -74,6 +74,10 @@
         return Placeholder;
     }
 
+    public final void ensureUniquePC() {
+        new Nop().emit(this);
+    }
+
     public static class Bclr extends Andn {
 
         public Bclr(Register src, Register dst) {
@@ -96,6 +100,17 @@
         }
     }
 
+    public static class Bplu extends Bpcs {
+
+        public Bplu(CC cc, int simm19) {
+            super(cc, simm19);
+        }
+
+        public Bplu(CC cc, Label label) {
+            super(cc, label);
+        }
+    }
+
     public static class Bset extends Or {
 
         public Bset(Register src, Register dst) {
@@ -240,7 +255,6 @@
 
         public Neg(Register src2, Register dst) {
             super(g0, src2, dst);
-            assert src2.encoding() != dst.encoding();
         }
 
         public Neg(Register dst) {
@@ -421,7 +435,6 @@
 
         public Signx(Register src1, Register dst) {
             super(src1, g0, dst);
-            assert src1.encoding() != dst.encoding();
         }
 
         public Signx(Register dst) {
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Aug 05 22:23:00 2013 -0700
@@ -24,7 +24,6 @@
 package com.oracle.graal.compiler.sparc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-import static com.oracle.graal.lir.LIRValueUtil.*;
 import static com.oracle.graal.lir.sparc.SPARCArithmetic.*;
 import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.*;
 import static com.oracle.graal.lir.sparc.SPARCCompare.*;
@@ -32,6 +31,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
@@ -39,26 +39,8 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegConst;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.Op1Stack;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.Op2Reg;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.Op2Stack;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.ShiftOp;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.Unary1Op;
-import com.oracle.graal.lir.sparc.SPARCArithmetic.Unary2Op;
-import com.oracle.graal.lir.sparc.SPARCCompare.CompareOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.BranchOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.CondMoveOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.FloatCondMoveOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.SequentialSwitchOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.SwitchRangesOp;
-import com.oracle.graal.lir.sparc.SPARCControlFlow.TableSwitchOp;
-import com.oracle.graal.lir.sparc.SPARCMove.MembarOp;
-import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp;
-import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp;
-import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp;
-import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.*;
+import com.oracle.graal.lir.sparc.SPARCMove.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.ConvertNode.Op;
@@ -99,7 +81,7 @@
             case Double:
                 return false;
             default:
-                return c.isNull();
+                return c.isDefaultForKind();
         }
     }
 
@@ -113,7 +95,7 @@
             case Object:
                 return c.isNull();
             default:
-                return true;
+                return false;
         }
     }
 
@@ -126,8 +108,7 @@
 
     protected SPARCLIRInstruction createMove(AllocatableValue dst, Value src) {
         if (src instanceof SPARCAddressValue) {
-            // return new LeaOp(dst, (AMD64AddressValue) src);
-            throw new InternalError("NYI");
+            return new LoadAddressOp(dst, (SPARCAddressValue) src);
         } else if (isRegister(src) || isStackSlot(dst)) {
             return new MoveFromRegOp(dst, src);
         } else {
@@ -164,9 +145,13 @@
                 indexRegister = Value.ILLEGAL;
             } else {
                 if (scale != 1) {
-                    Variable longIndex = newVariable(Kind.Long);
-                    emitMove(longIndex, index);
-                    indexRegister = emitMul(longIndex, Constant.forLong(scale));
+                    // Variable longIndex = newVariable(Kind.Long);
+                    Variable longIndex = emitConvert(Op.I2L, index);
+                    if (CodeUtil.isPowerOf2(scale)) {
+                        indexRegister = emitShl(longIndex, Constant.forLong(CodeUtil.log2(scale)));
+                    } else {
+                        indexRegister = emitMul(longIndex, Constant.forLong(scale));
+                    }
                 } else {
                     indexRegister = asAllocatable(index);
                 }
@@ -193,13 +178,12 @@
             displacementInt = (int) finalDisp;
         } else {
             displacementInt = 0;
-            AllocatableValue displacementRegister = load(Constant.forLong(finalDisp));
             if (baseRegister.equals(Value.ILLEGAL)) {
-                baseRegister = displacementRegister;
+                baseRegister = load(Constant.forLong(finalDisp));
             } else {
-                Variable longBase = newVariable(Kind.Long);
-                emitMove(longBase, baseRegister);
-                baseRegister = emitAdd(longBase, displacementRegister);
+                Variable longBaseRegister = newVariable(Kind.Long);
+                emitMove(longBaseRegister, baseRegister);  // FIXME get rid of this move
+                baseRegister = emitAdd(longBaseRegister, Constant.forLong(finalDisp));
             }
         }
 
@@ -241,11 +225,12 @@
     public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
-        switch (left.getKind().getStackKind()) {
+        Kind kind = left.getKind().getStackKind();
+        switch (kind) {
             case Int:
             case Long:
             case Object:
-                append(new BranchOp(finalCondition, label));
+                append(new BranchOp(finalCondition, label, kind));
                 break;
 // case Float:
 // append(new CompareOp(FCMP, x, y));
@@ -263,13 +248,13 @@
     @Override
     public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
         // append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, label));
-        throw GraalInternalError.shouldNotReachHere("emitOverflowCheckBranch: unimp");
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
         emitIntegerTest(left, right);
-        append(new BranchOp(negated ? Condition.NE : Condition.EQ, label));
+        append(new BranchOp(negated ? Condition.NE : Condition.EQ, label, left.getKind().getStackKind()));
     }
 
     private void emitIntegerTest(Value a, Value b) {
@@ -282,22 +267,6 @@
     }
 
     @Override
-    public Variable load(Value value) {
-        if (!isVariable(value)) {
-            return emitMove(value);
-        }
-        return (Variable) value;
-    }
-
-    @Override
-    public Value loadNonConst(Value value) {
-        if (isConstant(value) && !canInlineConstant((Constant) value)) {
-            return emitMove(value);
-        }
-        return value;
-    }
-
-    @Override
     public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
@@ -384,12 +353,8 @@
     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
         // Making a copy of the switch value is necessary because jump table destroys the input
         // value
-        if (key.getKind() == Kind.Int || key.getKind() == Kind.Long) {
-            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL));
-        } else {
-            assert key.getKind() == Kind.Object : key.getKind();
-            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object)));
-        }
+        assert key.getKind() == Kind.Int || key.getKind() == Kind.Long || key.getKind() == Kind.Object : key.getKind();
+        append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(key.getKind())));
     }
 
     @Override
@@ -408,23 +373,23 @@
     @Override
     public void emitBitCount(Variable result, Value operand) {
         if (operand.getKind().getStackKind() == Kind.Int) {
-            append(new SPARCBitManipulationOp(IPOPCNT, result, asAllocatable(operand)));
+            append(new SPARCBitManipulationOp(IPOPCNT, result, asAllocatable(operand), this));
         } else {
-            append(new SPARCBitManipulationOp(LPOPCNT, result, asAllocatable(operand)));
+            append(new SPARCBitManipulationOp(LPOPCNT, result, asAllocatable(operand), this));
         }
     }
 
     @Override
     public void emitBitScanForward(Variable result, Value operand) {
-        append(new SPARCBitManipulationOp(BSF, result, asAllocatable(operand)));
+        append(new SPARCBitManipulationOp(BSF, result, asAllocatable(operand), this));
     }
 
     @Override
     public void emitBitScanReverse(Variable result, Value operand) {
         if (operand.getKind().getStackKind() == Kind.Int) {
-            append(new SPARCBitManipulationOp(IBSR, result, asAllocatable(operand)));
+            append(new SPARCBitManipulationOp(IBSR, result, asAllocatable(operand), this));
         } else {
-            append(new SPARCBitManipulationOp(LBSR, result, asAllocatable(operand)));
+            append(new SPARCBitManipulationOp(LBSR, result, asAllocatable(operand), this));
         }
     }
 
@@ -466,7 +431,7 @@
     @Override
     public Value emitNegate(Value input) {
         Variable result = newVariable(input.getKind());
-        switch (input.getKind()) {
+        switch (input.getKind().getStackKind()) {
             case Int:
                 append(new Op1Stack(INEG, result, input));
                 break;
@@ -482,32 +447,71 @@
         return result;
     }
 
-    @Override
-    public Variable emitAdd(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
-            case Int:
-                append(new Op2Stack(IADD, result, a, loadNonConst(b)));
+    private Variable emitBinary(SPARCArithmetic op, boolean commutative, Value a, Value b) {
+        if (isConstant(b)) {
+            return emitBinaryConst(op, commutative, asAllocatable(a), asConstant(b));
+        } else if (commutative && isConstant(a)) {
+            return emitBinaryConst(op, commutative, asAllocatable(b), asConstant(a));
+        } else {
+            return emitBinaryVar(op, commutative, asAllocatable(a), asAllocatable(b));
+        }
+    }
+
+    private Variable emitBinaryConst(SPARCArithmetic op, boolean commutative, AllocatableValue a, Constant b) {
+        switch (op) {
+            case IADD:
+            case LADD:
+            case ISUB:
+            case LSUB:
+            case IAND:
+            case LAND:
+            case IOR:
+            case LOR:
+            case IXOR:
+            case LXOR:
+            case IMUL:
+            case LMUL:
+                if (NumUtil.isInt(b.asLong())) {
+                    Variable result = newVariable(a.getKind());
+                    append(new BinaryRegConst(op, result, a, b));
+                    return result;
+                }
                 break;
-            case Long:
-                append(new Op2Stack(LADD, result, a, loadNonConst(b)));
-                break;
-            case Float:
-                append(new Op2Stack(FADD, result, a, loadNonConst(b)));
-                break;
-            case Double:
-                append(new Op2Stack(DADD, result, a, loadNonConst(b)));
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind() + " prim: " + a.getKind().isPrimitive());
+        }
+
+        return emitBinaryVar(op, commutative, a, asAllocatable(b));
+    }
+
+    private Variable emitBinaryVar(SPARCArithmetic op, boolean commutative, AllocatableValue a, AllocatableValue b) {
+        Variable result = newVariable(a.getKind());
+        if (commutative) {
+            append(new BinaryCommutative(op, result, a, b));
+        } else {
+            append(new BinaryRegReg(op, result, a, b));
         }
         return result;
     }
 
     @Override
+    public Variable emitAdd(Value a, Value b) {
+        switch (a.getKind().getStackKind()) {
+            case Int:
+                return emitBinary(IADD, true, a, b);
+            case Long:
+                return emitBinary(LADD, true, a, b);
+            case Float:
+                return emitBinary(FADD, true, a, b);
+            case Double:
+                return emitBinary(DADD, true, a, b);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    @Override
     public Variable emitSub(Value a, Value b) {
         Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
+        switch (a.getKind().getStackKind()) {
             case Int:
                 append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
                 break;
@@ -529,12 +533,12 @@
     @Override
     public Variable emitMul(Value a, Value b) {
         Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
+        switch (a.getKind().getStackKind()) {
             case Int:
-                append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
+                append(new BinaryRegReg(IMUL, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op2Reg(LMUL, result, a, loadNonConst(b)));
+                append(new BinaryRegReg(LMUL, result, a, loadNonConst(b)));
                 break;
             case Float:
                 append(new Op2Stack(FMUL, result, a, loadNonConst(b)));
@@ -551,12 +555,12 @@
     @Override
     public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
         Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
+        switch (a.getKind().getStackKind()) {
             case Int:
-                append(new Op2Reg(IDIV, result, a, loadNonConst(b)));
+                append(new BinaryRegReg(IDIV, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op2Reg(LDIV, result, a, loadNonConst(b)));
+                append(new BinaryRegReg(LDIV, result, a, loadNonConst(b)));
                 break;
             case Float:
                 append(new Op2Stack(FDIV, result, a, loadNonConst(b)));
@@ -572,13 +576,14 @@
 
     @Override
     public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
+        LIRFrameState state = state(deopting);
         Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
+        switch (a.getKind().getStackKind()) {
             case Int:
-                append(new Op2Reg(IREM, result, a, loadNonConst(b)));
+                append(new RemOp(IREM, result, a, loadNonConst(b), state, this));
                 break;
             case Long:
-                append(new Op2Reg(LREM, result, a, loadNonConst(b)));
+                append(new RemOp(LREM, result, a, loadNonConst(b), state, this));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
@@ -588,9 +593,8 @@
 
     @Override
     public Value emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
-        @SuppressWarnings("unused")
-        LIRFrameState state = state(deopting);
-        switch (a.getKind()) {
+// LIRFrameState state = state(deopting);
+        switch (a.getKind().getStackKind()) {
             case Int:
                 // emitDivRem(IUDIV, a, b, state);
                 // return emitMove(RAX_I);
@@ -604,9 +608,8 @@
 
     @Override
     public Value emitURem(Value a, Value b, DeoptimizingNode deopting) {
-        @SuppressWarnings("unused")
-        LIRFrameState state = state(deopting);
-        switch (a.getKind()) {
+// LIRFrameState state = state(deopting);
+        switch (a.getKind().getStackKind()) {
             case Int:
                 // emitDivRem(IUREM, a, b, state);
                 // return emitMove(RDX_I);
@@ -621,7 +624,7 @@
     @Override
     public Variable emitAnd(Value a, Value b) {
         Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
+        switch (a.getKind().getStackKind()) {
             case Int:
                 append(new Op2Stack(IAND, result, a, loadNonConst(b)));
                 break;
@@ -638,7 +641,7 @@
     @Override
     public Variable emitOr(Value a, Value b) {
         Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
+        switch (a.getKind().getStackKind()) {
             case Int:
                 append(new Op2Stack(IOR, result, a, loadNonConst(b)));
                 break;
@@ -654,7 +657,7 @@
     @Override
     public Variable emitXor(Value a, Value b) {
         Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
+        switch (a.getKind().getStackKind()) {
             case Int:
                 append(new Op2Stack(IXOR, result, a, loadNonConst(b)));
                 break;
@@ -667,52 +670,51 @@
         return result;
     }
 
-    @Override
-    public Variable emitShl(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
-            case Int:
-                append(new Op2Stack(ISHL, result, a, loadNonConst(b)));
-                break;
-            case Long:
-                append(new Op2Stack(LSHL, result, a, loadNonConst(b)));
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
+    private Variable emitShift(SPARCArithmetic op, Value a, Value b) {
+        Variable result = newVariable(a.getPlatformKind());
+        AllocatableValue input = asAllocatable(a);
+        if (isConstant(b)) {
+            append(new BinaryRegConst(op, result, input, asConstant(b)));
+        } else {
+            append(new BinaryRegReg(op, result, input, b));
         }
         return result;
     }
 
     @Override
-    public Variable emitShr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
+    public Variable emitShl(Value a, Value b) {
+        switch (a.getKind().getStackKind()) {
             case Int:
-                append(new Op2Stack(ISHR, result, a, loadNonConst(b)));
-                break;
+                return emitShift(ISHL, a, b);
             case Long:
-                append(new Op2Stack(LSHR, result, a, loadNonConst(b)));
-                break;
+                return emitShift(LSHL, a, b);
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        return result;
+    }
+
+    @Override
+    public Variable emitShr(Value a, Value b) {
+        switch (a.getKind().getStackKind()) {
+            case Int:
+                return emitShift(ISHR, a, b);
+            case Long:
+                return emitShift(LSHR, a, b);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
     }
 
     @Override
     public Variable emitUShr(Value a, Value b) {
-        Variable result = newVariable(a.getKind());
-        switch (a.getKind()) {
+        switch (a.getKind().getStackKind()) {
             case Int:
-                append(new ShiftOp(IUSHR, result, a, b));
-                break;
+                return emitShift(IUSHR, a, b);
             case Long:
-                append(new ShiftOp(LUSHR, result, a, b));
-                break;
+                return emitShift(LUSHR, a, b);
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        return result;
     }
 
     @Override
@@ -724,13 +726,13 @@
                 append(new Unary2Op(I2L, result, input));
                 break;
             case L2I:
-                append(new Unary1Op(L2I, result, input));
+                append(new Unary2Op(L2I, result, input));
                 break;
             case I2B:
                 append(new Unary2Op(I2B, result, input));
                 break;
             case I2C:
-                append(new Unary1Op(I2C, result, input));
+                append(new Unary2Op(I2C, result, input));
                 break;
             case I2S:
                 append(new Unary2Op(I2S, result, input));
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java	Mon Aug 05 22:23:00 2013 -0700
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.asm.*;
@@ -38,11 +39,14 @@
     @Override
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
         Register thread = graalRuntime().getRuntime().threadRegister();
+        HotSpotVMConfig config = graalRuntime().getConfig();
 
         // Restore the thread register when coming back from the runtime.
         new Mov(l7, thread).emit(masm);
 
-        // Reset last Java frame.
-        new Stx(g0, new SPARCAddress(thread, graalRuntime().getConfig().threadLastJavaSpOffset)).emit(masm);
+        // Reset last Java frame, last Java PC and flags.
+        new Stx(g0, new SPARCAddress(thread, config.threadLastJavaSpOffset)).emit(masm);
+        new Stx(g0, new SPARCAddress(thread, config.threadLastJavaPcOffset)).emit(masm);
+        new Stw(g0, new SPARCAddress(thread, config.threadJavaFrameAnchorFlagsOffset)).emit(masm);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java	Mon Aug 05 22:23:00 2013 -0700
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.sparc.*;
@@ -39,12 +40,13 @@
     @Override
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
         HotSpotRuntime runtime = graalRuntime().getRuntime();
+        HotSpotVMConfig config = graalRuntime().getConfig();
         Register thread = runtime.threadRegister();
         Register stackPointer = runtime.stackPointerRegister();
 
         // Save last Java frame.
         new Add(stackPointer, new SPARCAddress(stackPointer, 0).getDisplacement(), g4).emit(masm);
-        new Stx(g4, new SPARCAddress(thread, graalRuntime().getConfig().threadLastJavaSpOffset)).emit(masm);
+        new Stx(g4, new SPARCAddress(thread, config.threadLastJavaSpOffset)).emit(masm);
 
         // Save the thread register when calling out to the runtime.
         new Mov(thread, l7).emit(masm);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Mon Aug 05 22:23:00 2013 -0700
@@ -53,7 +53,7 @@
     protected TargetDescription createTarget() {
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
-        final boolean inlineObjects = false;  // TODO We might want to change this later.
+        final boolean inlineObjects = true;
         return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
     }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Aug 05 22:23:00 2013 -0700
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.sparc.SPARC.*;
 
 import java.lang.reflect.*;
 
@@ -157,14 +158,11 @@
 
     @Override
     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-// AllocatableValue metaspaceMethod = AMD64.rbx.asValue();
-// emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode)
-// callTarget).metaspaceMethod()));
-// AllocatableValue targetAddress = AMD64.rax.asValue();
-// emitMove(targetAddress, operand(callTarget.computedAddress()));
-// append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod,
-// targetAddress, callState));
-        throw GraalInternalError.unimplemented();
+        AllocatableValue metaspaceMethod = g5.asValue();
+        emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()));
+        AllocatableValue targetAddress = g3.asValue();
+        emitMove(targetAddress, operand(callTarget.computedAddress()));
+        append(new SPARCIndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Mon Aug 05 22:23:00 2013 -0700
@@ -33,6 +33,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.*;
 
 public class SPARCHotSpotRegisterConfig implements RegisterConfig {
 
@@ -77,9 +78,12 @@
     private final Register[] fpuParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
 
     private final Register[] callerSaveRegisters = {g1, g3, g4, g5, o0, o1, o2, o3, o4, o5, o7};
-// private final Register[] calleeSaveRegisters = {l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3,
-// i4, i5, i6, i7};
-    private final Register[] calleeSaveRegisters = {l0, l1, l2, l3, l4, l5, l6, l7};
+
+    /**
+     * Registers saved by the callee. This lists all L and I registers which are saved in the
+     * register window. {@link FrameMap} uses this array to calculate the spill area size.
+     */
+    private final Register[] calleeSaveRegisters = {l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, i6, i7};
 
     private final CalleeSaveLayout csl;
 
@@ -100,7 +104,7 @@
                         // TODO this is not complete
                         o0, o1, o2, o3, o4, o5, /*o6,*/ o7,
                         l0, l1, l2, l3, l4, l5, l6, l7,
-                        i0, i1, i2, i3, i4, i5, /*i6,*/ i7,
+                        i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
                         f0, f1, f2, f3, f4, f5, f6, f7
                       };
         } else {
@@ -108,7 +112,7 @@
                         // TODO this is not complete
                         o0, o1, o2, o3, o4, o5, /*o6,*/ o7,
                         l0, l1, l2, l3, l4, l5, l6, l7,
-                        i0, i1, i2, i3, i4, i5, /*i6,*/ i7,
+                        i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
                         f0, f1, f2, f3, f4, f5, f6, f7
                       };
         }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Mon Aug 05 22:23:00 2013 -0700
@@ -32,6 +32,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.SPARCCall.DirectCallOp;
+import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
@@ -56,11 +57,7 @@
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
         // The mark for an invocation that uses an inline cache must be placed at the
         // instruction that loads the Klass from the inline cache.
-// SPARCMove.move(tasm, masm, g5.asValue(Kind.Long), tasm.asLongConstRef(metaspaceMethod));
-
-        new Rdpc(g5).emit(masm);
-        tasm.asLongConstRef(metaspaceMethod);
-        new Ldx(new SPARCAddress(g5, 0), g5).emit(masm);
+        SPARCMove.move(tasm, masm, g5.asValue(Kind.Long), metaspaceMethod);
         tasm.recordMark(invokeKind == InvokeKind.Static ? Marks.MARK_INVOKESTATIC : Marks.MARK_INVOKESPECIAL);
         // SPARCMove.move(tasm, masm, g3.asValue(Kind.Long), Constant.LONG_0);
         new Setx(nonOopBits, g3, true).emit(masm);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java	Mon Aug 05 22:23:00 2013 -0700
@@ -42,7 +42,6 @@
 @Opcode("CALL_DIRECT")
 final class SPARCHotspotDirectVirtualCallOp extends DirectCallOp {
 
-    private static final long nonOopBits = HotSpotGraalRuntime.graalRuntime().getConfig().nonOopBits;
     private final InvokeKind invokeKind;
 
     SPARCHotspotDirectVirtualCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind) {
@@ -55,14 +54,8 @@
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
         // The mark for an invocation that uses an inline cache must be placed at the
         // instruction that loads the Klass from the inline cache.
-// new Rdpc(g3).emit(masm);
-// tasm.asLongConstRef(nonOopBitsConstant);
-// tasm.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE);
-// new Ldx(new SPARCAddress(g3, 0), g3).emit(masm);
-
         tasm.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE);
-        // SPARCMove.move(tasm, masm, g3.asValue(Kind.Long), nonOopBitsConstant);
-        new Setx(nonOopBits, g3, true).emit(masm);
+        new Setx(HotSpotGraalRuntime.graalRuntime().getConfig().nonOopBits, g3, true).emit(masm);
         super.emitCode(tasm, masm);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java	Mon Aug 05 22:23:00 2013 -0700
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012, 2013, 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.hotspot.sparc;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.sparc.SPARC.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.sparc.SPARCCall.IndirectCallOp;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * A register indirect call that complies with the extra conventions for such calls in HotSpot. In
+ * particular, the metaspace Method of the callee must be in g5 for the case where a vtable entry's
+ * _from_compiled_entry is the address of an C2I adapter. Such adapters expect the target method to
+ * be in g5.
+ */
+@Opcode("CALL_INDIRECT")
+final class SPARCIndirectCallOp extends IndirectCallOp {
+
+    /**
+     * Vtable stubs expect the metaspace Method in g5.
+     */
+    public static final Register METHOD = g5;
+
+    @Use({REG}) protected Value metaspaceMethod;
+
+    SPARCIndirectCallOp(ResolvedJavaMethod targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state) {
+        super(targetMethod, result, parameters, temps, targetAddress, state);
+        this.metaspaceMethod = metaspaceMethod;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+        tasm.recordMark(Marks.MARK_INLINE_INVOKE);
+        Register callReg = asRegister(targetAddress);
+        assert !callReg.equals(METHOD);
+        SPARCCall.indirectCall(tasm, masm, callReg, callTarget, state);
+    }
+
+    @Override
+    protected void verify() {
+        super.verify();
+        assert asRegister(metaspaceMethod).equals(METHOD);
+    }
+}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java	Mon Aug 05 22:23:00 2013 -0700
@@ -45,6 +45,7 @@
 
     public SPARCAddressValue(PlatformKind kind, AllocatableValue base, AllocatableValue index, int displacement) {
         super(kind);
+        assert isIllegal(index) || displacement == 0;
         this.base = base;
         this.index = index;
         this.displacement = displacement;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Aug 05 22:23:00 2013 -0700
@@ -31,11 +31,12 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.spi.*;
 
 public enum SPARCArithmetic {
     // @formatter:off
-    IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
-    LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
+    IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
+    LADD, LSUB, LMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
     FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
     DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
     INEG, LNEG, FNEG, DNEG,
@@ -47,36 +48,6 @@
     // @formatter:on
 
     /**
-     * Binary operation with single source/destination operand and one constant.
-     */
-    public static class BinaryRegConst extends SPARCLIRInstruction {
-
-        @Opcode private final SPARCArithmetic opcode;
-        @Def({REG, HINT}) protected AllocatableValue result;
-        @Use({REG, STACK}) protected AllocatableValue x;
-        protected Constant y;
-
-        public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x, Constant y) {
-            this.opcode = opcode;
-            this.result = result;
-            this.x = x;
-            this.y = y;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-            SPARCMove.move(tasm, masm, result, x);
-            emit(tasm, masm, opcode, result, y, null);
-        }
-
-        @Override
-        public void verify() {
-            super.verify();
-            verifyKind(opcode, result, x, y);
-        }
-    }
-
-    /**
      * Unary operation with separate source and destination operand.
      */
     public static class Unary2Op extends SPARCLIRInstruction {
@@ -93,32 +64,10 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-            SPARCMove.move(tasm, masm, result, x);
             emit(tasm, masm, opcode, result, x, null);
         }
     }
 
-    /**
-     * Unary operation with single operand for source and destination.
-     */
-    public static class Unary1Op extends SPARCLIRInstruction {
-
-        @Opcode private final SPARCArithmetic opcode;
-        @Def({REG, HINT}) protected AllocatableValue result;
-        @Use({REG, STACK}) protected AllocatableValue x;
-
-        public Unary1Op(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x) {
-            this.opcode = opcode;
-            this.result = result;
-            this.x = x;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-            emit(masm, opcode, result);
-        }
-    }
-
     public static class Op1Stack extends SPARCLIRInstruction {
 
         @Opcode private final SPARCArithmetic opcode;
@@ -140,9 +89,9 @@
     public static class Op2Stack extends SPARCLIRInstruction {
 
         @Opcode private final SPARCArithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
-        @Alive({REG, STACK, CONST}) protected Value y;
+        @Def({REG}) protected Value result;
+        @Use({REG, CONST}) protected Value x;
+        @Alive({REG, CONST}) protected Value y;
 
         public Op2Stack(SPARCArithmetic opcode, Value result, Value x, Value y) {
             this.opcode = opcode;
@@ -163,14 +112,47 @@
         }
     }
 
-    public static class Op2Reg extends SPARCLIRInstruction {
+    /**
+     * Binary operation with two operands. The first source operand is combined with the
+     * destination. The second source operand must be a register.
+     */
+    public static class BinaryRegReg extends SPARCLIRInstruction {
 
         @Opcode private final SPARCArithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
+        @Def({REG}) protected Value result;
+        @Use({REG, CONST}) protected Value x;
         @Alive({REG, CONST}) protected Value y;
 
-        public Op2Reg(SPARCArithmetic opcode, Value result, Value x, Value y) {
+        public BinaryRegReg(SPARCArithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+            emit(tasm, masm, opcode, result, x, y, null);
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+    /**
+     * Binary operation with single source/destination operand and one constant.
+     */
+    public static class BinaryRegConst extends SPARCLIRInstruction {
+
+        @Opcode private final SPARCArithmetic opcode;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({REG}) protected AllocatableValue x;
+        protected Constant y;
+
+        public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x, Constant y) {
             this.opcode = opcode;
             this.result = result;
             this.x = x;
@@ -189,14 +171,17 @@
         }
     }
 
-    public static class ShiftOp extends SPARCLIRInstruction {
+    /**
+     * Commutative binary operation with two operands.
+     */
+    public static class BinaryCommutative extends SPARCLIRInstruction {
 
         @Opcode private final SPARCArithmetic opcode;
-        @Def({REG, HINT}) protected Value result;
-        @Use({REG, STACK, CONST}) protected Value x;
-        @Alive({REG, CONST}) protected Value y;
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG}) protected AllocatableValue x;
+        @Use({REG}) protected AllocatableValue y;
 
-        public ShiftOp(SPARCArithmetic opcode, Value result, Value x, Value y) {
+        public BinaryCommutative(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) {
             this.opcode = opcode;
             this.result = result;
             this.x = x;
@@ -209,6 +194,33 @@
         }
 
         @Override
+        protected void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+    public static class ShiftOp extends SPARCLIRInstruction {
+
+        @Opcode private final SPARCArithmetic opcode;
+        @Def({REG}) protected Value result;
+        @Use({REG, CONST}) protected Value x;
+        @Alive({REG, CONST}) protected Value y;
+
+        public ShiftOp(SPARCArithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+            assert !(x instanceof SPARCAddressValue);
+            emit(tasm, masm, opcode, result, x, y, null);
+        }
+
+        @Override
         public void verify() {
             super.verify();
             verifyKind(opcode, result, x, x);
@@ -216,17 +228,35 @@
         }
     }
 
-    protected static void emit(SPARCAssembler masm, SPARCArithmetic opcode, Value result) {
-        switch (opcode) {
-            case L2I:
-                new And(asIntReg(result), -1, asIntReg(result)).emit(masm);
-                break;
-            case I2C:
-                new Sll(asIntReg(result), 16, asIntReg(result)).emit(masm);
-                new Srl(asIntReg(result), 16, asIntReg(result)).emit(masm);
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
+    public static class RemOp extends SPARCLIRInstruction {
+
+        @Opcode private final SPARCArithmetic opcode;
+        @Def({REG}) protected Value result;
+        @Use({REG, CONST}) protected Value x;
+        @Alive({REG, CONST}) protected Value y;
+        @Def({REG}) protected Value scratch1;
+        @Def({REG}) protected Value scratch2;
+        @State protected LIRFrameState state;
+
+        public RemOp(SPARCArithmetic opcode, Value result, Value x, Value y, LIRFrameState state, LIRGeneratorTool gen) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+            this.scratch1 = gen.newVariable(x.getKind());
+            this.scratch2 = gen.newVariable(x.getKind());
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+            emit(tasm, masm, opcode, result, x, y, scratch1, scratch2, state);
+        }
+
+        @Override
+        protected void verify() {
+            super.verify();
+            verifyKind(opcode, result, x, y);
         }
     }
 
@@ -266,6 +296,11 @@
                     assert isSimm13(tasm.asIntConst(src2));
                     new Mulx(asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst)).emit(masm);
                     break;
+                case IDIV:
+                    assert isSimm13(tasm.asIntConst(src2));
+                    new Signx(asIntReg(src1), asIntReg(src1)).emit(masm);
+                    new Sdivx(asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst)).emit(masm);
+                    break;
                 case IAND:
                     assert isSimm13(tasm.asIntConst(src2));
                     new And(asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst)).emit(masm);
@@ -282,6 +317,10 @@
                     assert isSimm13(tasm.asIntConst(src2));
                     new Srl(asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst)).emit(masm);
                     break;
+                case IOR:
+                    assert isSimm13(tasm.asIntConst(src2));
+                    new Or(asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst)).emit(masm);
+                    break;
                 case IXOR:
                     assert isSimm13(tasm.asIntConst(src2));
                     new Xor(asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst)).emit(masm);
@@ -298,6 +337,10 @@
                     assert isSimm13(tasm.asIntConst(src2));
                     new Mulx(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
                     break;
+                case LDIV:
+                    throw GraalInternalError.unimplemented();
+                case LUDIV:
+                    throw GraalInternalError.unimplemented();
                 case LAND:
                     assert isSimm13(tasm.asIntConst(src2));
                     new And(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
@@ -312,11 +355,15 @@
                     break;
                 case LSHL:
                     assert isSimm13(tasm.asIntConst(src2));
-                    new Sll(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
+                    new Sllx(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
+                    break;
+                case LSHR:
+                    assert isSimm13(tasm.asIntConst(src2));
+                    new Srax(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
                     break;
                 case LUSHR:
                     assert isSimm13(tasm.asIntConst(src2));
-                    new Srl(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
+                    new Srlx(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
                     break;
                 case FADD:
                 case FMUL:
@@ -339,6 +386,8 @@
                     new Mulx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                     break;
                 case IDIV:
+                    new Signx(asIntReg(src1), asIntReg(src1)).emit(masm);
+                    new Signx(asIntReg(src2), asIntReg(src2)).emit(masm);
                     new Sdivx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                     break;
                 case IAND:
@@ -373,6 +422,8 @@
                 case LDIV:
                     new Sdivx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                     break;
+                case LUDIV:
+                    throw GraalInternalError.unimplemented();
                 case LAND:
                     new And(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                     break;
@@ -383,19 +434,14 @@
                     new Xor(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                     break;
                 case LSHL:
-                    new Sllx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
+                    new Sllx(asLongReg(src1), asIntReg(src2), asLongReg(dst)).emit(masm);
                     break;
                 case LSHR:
-                    new Srlx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
+                    new Srax(asLongReg(src1), asIntReg(src2), asLongReg(dst)).emit(masm);
                     break;
                 case LUSHR:
-                    new Srax(asLongReg(src1), asIntReg(src2), asLongReg(dst)).emit(masm);
+                    new Srlx(asLongReg(src1), asIntReg(src2), asLongReg(dst)).emit(masm);
                     break;
-                case LDIVREM:
-                case LUDIV:
-                case LUREM:
-                case LREM:
-                    throw GraalInternalError.unimplemented();
                 case FADD:
                     new Fadds(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)).emit(masm);
                     break;
@@ -425,7 +471,43 @@
                 case DREM:
                     throw GraalInternalError.unimplemented();
                 default:
-                    throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        if (info != null) {
+            assert exceptionOffset != -1;
+            tasm.recordImplicitException(exceptionOffset, info);
+        }
+    }
+
+    public static void emit(TargetMethodAssembler tasm, SPARCAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, Value src2, Value scratch1, Value scratch2, LIRFrameState info) {
+        int exceptionOffset = -1;
+        if (isConstant(src1)) {
+            switch (opcode) {
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(src2)) {
+            switch (opcode) {
+                case LREM:
+                    assert isSimm13(tasm.asIntConst(src2));
+                    new Sdivx(asLongReg(src1), tasm.asIntConst(src2), asLongReg(scratch1)).emit(masm);
+                    new Mulx(asLongReg(scratch1), tasm.asIntConst(src2), asLongReg(scratch2)).emit(masm);
+                    new Sub(asLongReg(src1), asLongReg(scratch2), asLongReg(dst)).emit(masm);
+                    break;
+                case LUREM:
+                    throw GraalInternalError.unimplemented();
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            switch (opcode) {
+                case LREM:
+                case LUREM:
+                    throw GraalInternalError.unimplemented();
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
             }
         }
 
@@ -444,12 +526,19 @@
                     new Neg(asIntReg(src), asIntReg(dst)).emit(masm);
                     break;
                 case I2L:
-                    new Sra(asIntReg(src), 0, asLongReg(dst)).emit(masm);
+                    new Signx(asIntReg(src), asLongReg(dst)).emit(masm);
+                    break;
+                case L2I:
+                    new Signx(asLongReg(src), asIntReg(dst)).emit(masm);
                     break;
                 case I2B:
                     new Sll(asIntReg(src), 24, asIntReg(dst)).emit(masm);
                     new Srl(asIntReg(dst), 24, asIntReg(dst)).emit(masm);
                     break;
+                case I2C:
+                    new Sll(asIntReg(src), 16, asIntReg(dst)).emit(masm);
+                    new Srl(asIntReg(dst), 16, asIntReg(dst)).emit(masm);
+                    break;
                 case I2F:
                     new Fstoi(masm, asIntReg(src), asFloatReg(dst));
                     break;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Mon Aug 05 22:23:00 2013 -0700
@@ -22,8 +22,10 @@
  */
 package com.oracle.graal.lir.sparc;
 
+import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.*;
 import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
@@ -32,7 +34,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.sparc.SPARC;
+import com.oracle.graal.nodes.spi.*;
 
 public class SPARCBitManipulationOp extends SPARCLIRInstruction {
 
@@ -42,37 +44,38 @@
 
     @Opcode private final IntrinsicOpcode opcode;
     @Def protected AllocatableValue result;
-    @Use({OperandFlag.REG, OperandFlag.STACK}) protected AllocatableValue input;
+    @Use({REG}) protected AllocatableValue input;
+    @Def({REG}) protected Value scratch;
 
-    public SPARCBitManipulationOp(IntrinsicOpcode opcode, AllocatableValue result, AllocatableValue input) {
+    public SPARCBitManipulationOp(IntrinsicOpcode opcode, AllocatableValue result, AllocatableValue input, LIRGeneratorTool gen) {
         this.opcode = opcode;
         this.result = result;
         this.input = input;
+        if (opcode == IntrinsicOpcode.IBSR || opcode == IntrinsicOpcode.LBSR) {
+            scratch = gen.newVariable(input.getKind());
+        }
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-        Register dst = ValueUtil.asIntReg(result);
-        Register tmp = null;  // ??
-        if (ValueUtil.isRegister(input)) {
-            Register src = ValueUtil.asRegister(input);
+        Register dst = asIntReg(result);
+        if (isRegister(input)) {
+            Register src = asRegister(input);
             switch (opcode) {
                 case IPOPCNT:
                     // clear upper word for 64 bit POPC
-                    new Srl(src, SPARC.g0, dst).emit(masm);
+                    new Srl(src, g0, dst).emit(masm);
                     new Popc(src, dst).emit(masm);
                     break;
                 case LPOPCNT:
                     new Popc(src, dst).emit(masm);
                     break;
                 case BSF:
-                    // countTrailingZerosI - bsfl
-                    // countTrailingZerosL - masm.bsfq(dst, src);
                     Kind tkind = input.getKind();
                     if (tkind == Kind.Int) {
                         new Sub(src, 1, dst).emit(masm);
                         new Andn(dst, src, dst).emit(masm);
-                        new Srl(dst, SPARC.g0, dst).emit(masm);
+                        new Srl(dst, g0, dst).emit(masm);
                         new Popc(dst, dst).emit(masm);
                     } else if (tkind == Kind.Long) {
                         new Sub(src, 1, dst).emit(masm);
@@ -82,11 +85,10 @@
                         throw GraalInternalError.shouldNotReachHere("missing: " + tkind);
                     }
                     break;
-                case IBSR:
-                    // countLeadingZerosI_bsr masm.bsrq(dst, src);
-                    // masm.bsrl(dst, src);
+                case IBSR: {
                     Kind ikind = input.getKind();
                     assert ikind == Kind.Int;
+                    Register tmp = asRegister(scratch);
                     new Srl(src, 1, tmp).emit(masm);
                     new Srl(src, 0, dst).emit(masm);
                     new Or(src, tmp, dst).emit(masm);
@@ -102,11 +104,11 @@
                     new Mov(ikind.getBitCount(), tmp).emit(masm);
                     new Sub(tmp, dst, dst).emit(masm);
                     break;
-                case LBSR:
-                    // countLeadingZerosL_bsr masm.bsrq(dst, src);
-                    // masm.bsrq(dst, src);
+                }
+                case LBSR: {
                     Kind lkind = input.getKind();
                     assert lkind == Kind.Int;
+                    Register tmp = asRegister(scratch);
                     new Srlx(src, 1, tmp).emit(masm);
                     new Or(src, tmp, dst).emit(masm);
                     new Srlx(dst, 2, tmp).emit(masm);
@@ -123,11 +125,12 @@
                     new Mov(lkind.getBitCount(), tmp).emit(masm);
                     new Sub(tmp, dst, dst).emit(masm);
                     break;
+                }
                 default:
-                    throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
+                    throw GraalInternalError.shouldNotReachHere();
 
             }
-        } else if (ValueUtil.isConstant(input) && isSimm13(tasm.asIntConst(input))) {
+        } else if (isConstant(input) && isSimm13(tasm.asIntConst(input))) {
             switch (opcode) {
                 case IPOPCNT:
                     new Popc(tasm.asIntConst(input), dst).emit(masm);
@@ -136,48 +139,49 @@
                     new Popc(tasm.asIntConst(input), dst).emit(masm);
                     break;
                 default:
-                    throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
+                    throw GraalInternalError.shouldNotReachHere();
             }
         } else {
-            SPARCAddress src = (SPARCAddress) tasm.asAddress(input);
-            switch (opcode) {
-                case IPOPCNT:
-                    new Ldsw(src, tmp).emit(masm);
-                    // clear upper word for 64 bit POPC
-                    new Srl(tmp, g0, dst).emit(masm);
-                    new Popc(tmp, dst).emit(masm);
-                    break;
-                case LPOPCNT:
-                    new Ldx(src, tmp).emit(masm);
-                    new Popc(tmp, dst).emit(masm);
-                    break;
-                case BSF:
-                    assert input.getKind() == Kind.Int;
-                    new Ldsw(src, tmp).emit(masm);
-                    new Srl(tmp, 1, tmp).emit(masm);
-                    new Srl(tmp, 0, dst).emit(masm);
-                    new Or(tmp, tmp, dst).emit(masm);
-                    new Srl(dst, 2, tmp).emit(masm);
-                    new Or(dst, tmp, dst).emit(masm);
-                    new Srl(dst, 4, tmp).emit(masm);
-                    new Or(dst, tmp, dst).emit(masm);
-                    new Srl(dst, 8, tmp).emit(masm);
-                    new Or(dst, tmp, dst).emit(masm);
-                    new Srl(dst, 16, tmp).emit(masm);
-                    new Or(dst, tmp, dst).emit(masm);
-                    new Popc(dst, dst).emit(masm);
-                    new Mov(Kind.Int.getBitCount(), tmp).emit(masm);
-                    new Sub(tmp, dst, dst).emit(masm);
-                    break;
-                case IBSR:
-                    // masm.bsrl(dst, src);
-                    // countLeadingZerosI_bsr masm.bsrq(dst, src);
-                    // masm.bsrl(dst, src);
-                case LBSR:
-                    // masm.bsrq(dst, src);
-                default:
-                    throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
-            }
+            throw GraalInternalError.shouldNotReachHere();
+// SPARCAddress src = (SPARCAddress) tasm.asAddress(input);
+// switch (opcode) {
+// case IPOPCNT:
+// new Ldsw(src, tmp).emit(masm);
+// // clear upper word for 64 bit POPC
+// new Srl(tmp, g0, dst).emit(masm);
+// new Popc(tmp, dst).emit(masm);
+// break;
+// case LPOPCNT:
+// new Ldx(src, tmp).emit(masm);
+// new Popc(tmp, dst).emit(masm);
+// break;
+// case BSF:
+// assert input.getKind() == Kind.Int;
+// new Ldsw(src, tmp).emit(masm);
+// new Srl(tmp, 1, tmp).emit(masm);
+// new Srl(tmp, 0, dst).emit(masm);
+// new Or(tmp, tmp, dst).emit(masm);
+// new Srl(dst, 2, tmp).emit(masm);
+// new Or(dst, tmp, dst).emit(masm);
+// new Srl(dst, 4, tmp).emit(masm);
+// new Or(dst, tmp, dst).emit(masm);
+// new Srl(dst, 8, tmp).emit(masm);
+// new Or(dst, tmp, dst).emit(masm);
+// new Srl(dst, 16, tmp).emit(masm);
+// new Or(dst, tmp, dst).emit(masm);
+// new Popc(dst, dst).emit(masm);
+// new Mov(Kind.Int.getBitCount(), tmp).emit(masm);
+// new Sub(tmp, dst, dst).emit(masm);
+// break;
+// case IBSR:
+// // masm.bsrl(dst, src);
+// // countLeadingZerosI_bsr masm.bsrq(dst, src);
+// // masm.bsrl(dst, src);
+// case LBSR:
+// // masm.bsrq(dst, src);
+// default:
+// throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
+// }
         }
     }
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Mon Aug 05 22:23:00 2013 -0700
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -42,10 +43,12 @@
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
         SPARCMove.move(tasm, masm, result, input);
         switch (input.getKind()) {
-        // case Int:
-        // masm.bswapl(ValueUtil.asIntReg(result));
-        // case Long:
-        // masm.bswapq(ValueUtil.asLongReg(result));
+            case Int:
+                // masm.bswapl(ValueUtil.asIntReg(result));
+            case Long:
+                // masm.bswapq(ValueUtil.asLongReg(result));
+            default:
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Mon Aug 05 22:23:00 2013 -0700
@@ -52,9 +52,7 @@
 
         @Override
         public boolean destroysCallerSavedRegisters() {
-            // On SPARC we never destroy caller saved registers since they are automatically saved
-            // in the register window.
-            return false;
+            return true;
         }
     }
 
@@ -115,9 +113,7 @@
 
         @Override
         public boolean destroysCallerSavedRegisters() {
-            // On SPARC we never destroy caller saved registers since they are automatically saved
-            // in the register window.
-            return false;
+            return callTarget.destroysRegisters();
         }
     }
 
@@ -164,6 +160,7 @@
         tasm.recordDirectCall(before, after, callTarget, info);
         tasm.recordExceptionHandlers(after, info);
         new Nop().emit(masm);  // delay slot
+        masm.ensureUniquePC();
     }
 
     public static void indirectJmp(TargetMethodAssembler tasm, SPARCMacroAssembler masm, Register dst, InvokeTarget target) {
@@ -173,6 +170,7 @@
         int after = masm.codeBuffer.position();
         tasm.recordIndirectCall(before, after, target, null);
         new Nop().emit(masm);  // delay slot
+        masm.ensureUniquePC();
     }
 
     public static void indirectCall(TargetMethodAssembler tasm, SPARCMacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) {
@@ -182,5 +180,6 @@
         tasm.recordIndirectCall(before, after, callTarget, info);
         tasm.recordExceptionHandlers(after, info);
         new Nop().emit(masm);  // delay slot
+        masm.ensureUniquePC();
     }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Aug 05 22:23:00 2013 -0700
@@ -45,39 +45,48 @@
 
         protected Condition condition;
         protected LabelRef destination;
+        protected final Kind kind;
 
-        public BranchOp(Condition condition, LabelRef destination) {
+        public BranchOp(Condition condition, LabelRef destination, Kind kind) {
             this.condition = condition;
             this.destination = destination;
+            this.kind = kind;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-            // FIXME Using xcc is wrong! It depends on the compare.
+            assert kind == Kind.Int || kind == Kind.Long || kind == Kind.Object;
+            CC cc = kind == Kind.Int ? CC.Icc : CC.Xcc;
             switch (condition) {
                 case EQ:
-                    new Bpe(CC.Xcc, destination.label()).emit(masm);
+                    new Bpe(cc, destination.label()).emit(masm);
                     break;
                 case NE:
-                    new Bpne(CC.Xcc, destination.label()).emit(masm);
+                    new Bpne(cc, destination.label()).emit(masm);
+                    break;
+                case BT:
+                    new Bplu(cc, destination.label()).emit(masm);
                     break;
                 case LT:
-                    new Bpl(CC.Xcc, destination.label()).emit(masm);
+                    new Bpl(cc, destination.label()).emit(masm);
                     break;
                 case BE:
-                    new Bpleu(CC.Xcc, destination.label()).emit(masm);
+                    new Bpleu(cc, destination.label()).emit(masm);
                     break;
                 case LE:
-                    new Bple(CC.Xcc, destination.label()).emit(masm);
+                    new Bple(cc, destination.label()).emit(masm);
+                    break;
+                case GE:
+                    new Bpge(cc, destination.label()).emit(masm);
                     break;
                 case AE:
-                    new Bpgeu(CC.Xcc, destination.label()).emit(masm);
+                    new Bpgeu(cc, destination.label()).emit(masm);
                     break;
                 case GT:
-                    new Bpg(CC.Xcc, destination.label()).emit(masm);
+                    new Bpg(cc, destination.label()).emit(masm);
                     break;
                 case AT:
-                    new Bpgu(CC.Xcc, destination.label()).emit(masm);
+                    new Bpgu(cc, destination.label()).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -152,8 +161,10 @@
         if (isFloat) {
             if (unorderedIsTrue && !trueOnUnordered(condition)) {
                 // cmove(tasm, masm, result, ConditionFlag.Parity, trueValue);
+                throw GraalInternalError.unimplemented();
             } else if (!unorderedIsTrue && trueOnUnordered(condition)) {
                 // cmove(tasm, masm, result, ConditionFlag.Parity, falseValue);
+                throw GraalInternalError.unimplemented();
             }
         }
     }
@@ -166,8 +177,9 @@
         assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move";
         switch (other.getKind()) {
             case Int:
+                // XXX CC depends on compare
                 new Movcc(cond, CC.Icc, asRegister(other), asRegister(result)).emit(masm);
-                throw new InternalError("check instruction");
+                break;
             case Long:
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -259,7 +271,6 @@
         }
 
         @Override
-        @SuppressWarnings("unused")
         public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
             if (key.getKind() == Kind.Int) {
                 Register intKey = asIntReg(key);
@@ -270,27 +281,26 @@
                     long lc = keyConstants[i].asLong();
                     assert NumUtil.isInt(lc);
                     new Cmp(intKey, (int) lc).emit(masm);
-                    Label l = keyTargets[i].label();
-                    l.addPatchAt(tasm.asm.codeBuffer.position());
-                    new Bpe(CC.Icc, l).emit(masm);
+                    new Bpe(CC.Icc, keyTargets[i].label()).emit(masm);
+                    new Nop().emit(masm);  // delay slot
                 }
             } else if (key.getKind() == Kind.Long) {
                 Register longKey = asLongReg(key);
+                Register temp = asLongReg(scratch);
                 for (int i = 0; i < keyConstants.length; i++) {
-                    // masm.setp_eq_s64(tasm.asLongConst(keyConstants[i]),
-                    // longKey);
-                    // masm.at();
-                    Label l = keyTargets[i].label();
-                    l.addPatchAt(tasm.asm.codeBuffer.position());
-                    new Bpe(CC.Xcc, l).emit(masm);
+                    SPARCMove.move(tasm, masm, temp.asValue(Kind.Long), keyConstants[i]);
+                    new Cmp(longKey, temp).emit(masm);
+                    new Bpe(CC.Xcc, keyTargets[i].label()).emit(masm);
+                    new Nop().emit(masm);  // delay slot
                 }
             } else if (key.getKind() == Kind.Object) {
-                Register intKey = asObjectReg(key);
+                Register objectKey = asObjectReg(key);
                 Register temp = asObjectReg(scratch);
                 for (int i = 0; i < keyConstants.length; i++) {
                     SPARCMove.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]);
-                    new Cmp(intKey, temp).emit(masm);
+                    new Cmp(objectKey, temp).emit(masm);
                     new Bpe(CC.Ptrcc, keyTargets[i].label()).emit(masm);
+                    new Nop().emit(masm);  // delay slot
                 }
             } else {
                 throw new GraalInternalError("sequential switch only supported for int, long and object");
@@ -298,7 +308,7 @@
             if (defaultTarget != null) {
                 masm.jmp(defaultTarget.label());
             } else {
-                // masm.hlt();
+                new Illtrap(0).emit(masm);
             }
         }
 
@@ -360,7 +370,7 @@
                 masm.bind(actualDefaultTarget);
                 // masm.hlt();
             }
-            throw new InternalError("NYI");
+            throw GraalInternalError.unimplemented();
         }
 
         @Override
@@ -444,6 +454,6 @@
         tasm.compilationResult.addAnnotation(jt);
 
         // SPARC: unimp: tableswitch extract
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
     }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Mon Aug 05 22:23:00 2013 -0700
@@ -51,7 +51,7 @@
     public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
         switch (opcode) {
             case SQRT:
-                new Fsqrtd(asDoubleReg(result), asDoubleReg(input)).emit(masm);
+                new Fsqrtd(asDoubleReg(input), asDoubleReg(result)).emit(masm);
                 break;
             case LOG:
             case LOG10:
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Mon Aug 05 22:23:00 2013 -0700
@@ -135,7 +135,7 @@
                     new Ldsh(addr, asRegister(result)).emit(masm);
                     break;
                 case Char:
-                    new Lduw(addr, asRegister(result)).emit(masm);
+                    new Lduh(addr, asRegister(result)).emit(masm);
                     break;
                 case Int:
                     new Ldsw(addr, asRegister(result)).emit(masm);
@@ -158,6 +158,27 @@
         }
     }
 
+    public static class LoadAddressOp extends SPARCLIRInstruction {
+
+        @Def({REG}) protected AllocatableValue result;
+        @Use({COMPOSITE, UNINITIALIZED}) protected SPARCAddressValue address;
+
+        public LoadAddressOp(AllocatableValue result, SPARCAddressValue address) {
+            this.result = result;
+            this.address = address;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+            SPARCAddress addr = address.toAddress();
+            if (addr.hasIndex()) {
+                new Add(addr.getBase(), addr.getIndex(), asLongReg(result)).emit(masm);
+            } else {
+                new Add(addr.getBase(), addr.getDisplacement(), asLongReg(result)).emit(masm);
+            }
+        }
+    }
+
     public static class MembarOp extends SPARCLIRInstruction {
 
         private final int barriers;
@@ -183,10 +204,9 @@
         }
 
         @Override
-        @SuppressWarnings("unused")
         public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
             tasm.recordImplicitException(masm.codeBuffer.position(), state);
-            new Ldx(new SPARCAddress(asRegister(input), 0), r0);
+            new Ldx(new SPARCAddress(asRegister(input), 0), r0).emit(masm);
         }
     }
 
@@ -222,7 +242,8 @@
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
-            new Ldx((SPARCAddress) tasm.asAddress(slot), asLongReg(result)).emit(masm);
+            SPARCAddress address = (SPARCAddress) tasm.asAddress(slot);
+            new Add(address.getBase(), address.getDisplacement(), asLongReg(result)).emit(masm);
         }
     }
 
@@ -245,6 +266,7 @@
                     new Stb(asRegister(input), addr).emit(masm);
                     break;
                 case Short:
+                case Char:
                     new Sth(asRegister(input), addr).emit(masm);
                     break;
                 case Int:
@@ -273,7 +295,7 @@
             super(kind, address, state);
             this.input = input;
             this.compress = compress;
-            if (input.isNonNull()) {
+            if (!input.isDefaultForKind()) {
                 throw GraalInternalError.shouldNotReachHere("Can only store null constants to memory");
             }
         }
@@ -285,8 +307,8 @@
                 case Byte:
                     new Stb(g0, address.toAddress()).emit(masm);
                     break;
+                case Short:
                 case Char:
-                case Short:
                     new Sth(g0, address.toAddress()).emit(masm);
                     break;
                 case Int:
@@ -353,14 +375,15 @@
     }
 
     private static void reg2stack(TargetMethodAssembler tasm, SPARCMacroAssembler masm, Value result, Value input) {
-        SPARCAddress dest = (SPARCAddress) tasm.asAddress(result);
+        SPARCAddress dst = (SPARCAddress) tasm.asAddress(result);
+        Register src = asRegister(input);
         switch (input.getKind()) {
             case Int:
-                new Stw(asRegister(input), dest).emit(masm);
+                new Stw(src, dst).emit(masm);
                 break;
             case Long:
             case Object:
-                new Stx(asRegister(input), dest).emit(masm);
+                new Stx(src, dst).emit(masm);
                 break;
             case Float:
             case Double:
@@ -371,14 +394,17 @@
 
     private static void stack2reg(TargetMethodAssembler tasm, SPARCMacroAssembler masm, Value result, Value input) {
         SPARCAddress src = (SPARCAddress) tasm.asAddress(input);
+        Register dst = asRegister(result);
         switch (input.getKind()) {
             case Int:
-                new Ldsw(src, asRegister(result)).emit(masm);
+                new Ldsw(src, dst).emit(masm);
                 break;
             case Long:
+            case Object:
+                new Ldx(src, dst).emit(masm);
+                break;
             case Float:
             case Double:
-            case Object:
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -415,14 +441,14 @@
                 if (input.isNull()) {
                     new Clr(asRegister(result)).emit(masm);
                 } else if (tasm.target.inlineObjects) {
-// tasm.recordDataReferenceInCode(input, 0, true);
-// new Setx(0xDEADDEADDEADDEADL, null, asRegister(result)).emit(masm);
-                    throw GraalInternalError.shouldNotReachHere();
+                    tasm.recordDataReferenceInCode(input, 0, true);
+                    new Setx(0xDEADDEADDEADDEADL, asRegister(result), true).emit(masm);
                 } else {
                     Register dst = asRegister(result);
                     new Rdpc(dst).emit(masm);
                     tasm.asObjectConstRef(input);
                     new Ldx(new SPARCAddress(dst, 0), dst).emit(masm);
+                    throw GraalInternalError.shouldNotReachHere("the patched offset might be too big for the load");
                 }
                 break;
             }
--- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Mon Aug 05 22:21:47 2013 -0700
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Mon Aug 05 22:23:00 2013 -0700
@@ -143,10 +143,7 @@
     // @formatter:on
 
     public SPARC() {
-        // The return address doesn't have an extra slot in the frame so we pass 0 for the return
-        // address size.
-        // XXX think about the return address size again
-        super("SPARC", 8, ByteOrder.BIG_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 1, r31.encoding + 1, 0);
+        super("SPARC", 8, ByteOrder.BIG_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 1, r31.encoding + 1, 8);
     }
 
     @Override
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Mon Aug 05 22:21:47 2013 -0700
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Mon Aug 05 22:23:00 2013 -0700
@@ -31,6 +31,8 @@
 inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
   if (inst->is_call() || inst->is_jump()) {
     return pc_offset + NativeCall::instruction_size;
+  } else if (inst->is_call_reg()) {
+    return pc_offset + NativeCallReg::instruction_size;
   } else if (inst->is_sethi()) {
     return pc_offset + NativeFarCall::instruction_size;
   } else {
@@ -83,23 +85,36 @@
       break;
     }
     case 'a': {
-      int size = _constants->size();
-      if (alignment > 0) {
-        guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
-        size = align_size_up(size, alignment);
+      if (inlined) {
+        NativeMovConstReg* move = nativeMovConstReg_at(pc);
+        Handle obj = Constant::object(constant);
+        jobject value = JNIHandles::make_local(obj());
+        move->set_data((intptr_t) value);
+
+        // We need two relocations:  one on the sethi and one on the add.
+        int oop_index = _oop_recorder->find_index(value);
+        RelocationHolder rspec = oop_Relocation::spec(oop_index);
+        _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec);
+        _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec);
+      } else {
+        int size = _constants->size();
+        if (alignment > 0) {
+          guarantee(alignment <= _constants->alignment(), "Alignment inside constants section is restricted by alignment of section begin");
+          size = align_size_up(size, alignment);
+        }
+        address dest = _constants->start() + size;
+        _constants->set_end(dest);
+        Handle obj = Constant::object(constant);
+        jobject value = JNIHandles::make_local(obj());
+        _constants->emit_address((address) value);
+
+        NativeMovRegMem* load = nativeMovRegMem_at(pc);
+        int disp = _constants_size + pc_offset - size - BytesPerInstWord;
+        load->set_offset(-disp);
+
+        int oop_index = _oop_recorder->find_index(value);
+        _constants->relocate(dest, oop_Relocation::spec(oop_index));
       }
-      address dest = _constants->start() + size;
-      _constants->set_end(dest);
-      Handle obj = Constant::object(constant);
-      jobject value = JNIHandles::make_local(obj());
-      _constants->emit_address((address) value);
-
-      NativeMovRegMem* load = nativeMovRegMem_at(pc);
-      int disp = _constants_size + pc_offset - size - BytesPerInstWord;
-      load->set_offset(-disp);
-
-      int oop_index = _oop_recorder->find_index(value);
-      _constants->relocate(dest, oop_Relocation::spec(oop_index));
       break;
     }
     default:
--- a/src/cpu/sparc/vm/nativeInst_sparc.hpp	Mon Aug 05 22:21:47 2013 -0700
+++ b/src/cpu/sparc/vm/nativeInst_sparc.hpp	Mon Aug 05 22:23:00 2013 -0700
@@ -55,6 +55,7 @@
   bool is_dtrace_trap();
   bool is_nop()                        { return long_at(0) == nop_instruction(); }
   bool is_call()                       { return is_op(long_at(0), Assembler::call_op); }
+  bool is_call_reg()                   { return is_op(long_at(0), Assembler::arith_op); }
   bool is_sethi()                      { return (is_op2(long_at(0), Assembler::sethi_op2)
                                           && inv_rd(long_at(0)) != G0); }
 
@@ -417,6 +418,19 @@
   return call;
 }
 
+class NativeCallReg: public NativeInstruction {
+ public:
+  enum Sparc_specific_constants {
+    instruction_size      = 8,
+    return_address_offset = 8,
+    instruction_offset    = 0
+  };
+
+  address next_instruction_address() const {
+    return addr_at(instruction_size);
+  }
+};
+
 // The NativeFarCall is an abstraction for accessing/manipulating native call-anywhere
 // instructions in the sparcv9 vm.  Used to call native methods which may be loaded
 // anywhere in the address space, possibly out of reach of a call instruction.