changeset 10792:7a8d6ba83a04

SPARC: fixes and more stuff works
author twisti
date Tue, 16 Jul 2013 17:41:21 -0700
parents e2786e2c491a
children 6e12e0ace0d5
files 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/SPARCHotSpotBackend.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/SPARCSafepointOp.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/SPARCCompare.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp
diffstat 17 files changed, 500 insertions(+), 192 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Tue Jul 16 17:41:21 2013 -0700
@@ -116,7 +116,7 @@
         public void verify() {
             assert ((rd << RD_SHIFT) & RD_MASK) == (rd << RD_SHIFT);
             assert ((op2 << OP2_SHIFT) & OP2_MASK) == (op2 << OP2_SHIFT);
-            assert ((imm22 << IMM22_SHIFT) & IMM22_MASK) == (imm22 << IMM22_SHIFT);
+            assert ((imm22 << IMM22_SHIFT) & IMM22_MASK) == (imm22 << IMM22_SHIFT) : String.format("imm22: %d (%x)", imm22, imm22);
         }
     }
 
@@ -287,6 +287,11 @@
             masm.emitInt(getInstructionBits());
         }
 
+        private static int patchUnbound(SPARCAssembler masm, Label label) {
+            label.addPatchAt(masm.codeBuffer.position());
+            return 0;
+        }
+
         public void verify() {
             assert p < 2;
             assert cond < 0x10;
@@ -625,6 +630,28 @@
             this(rd.encoding(), op3.getValue(), rs1.encoding(), 0, 0, 0, 0);
         }
 
+        /**
+         * Special constructor for Casa and Casxa.
+         */
+        public Fmt11(Op3s op3, Register rs1, Register rs2, Register rd, Asi asi) {
+            this(rd.encoding(), op3.getValue(), rs1.encoding(), asi.isValid() ? 0 : 1, asi.isValid() ? asi.getValue() : 0, rs2.encoding(), 0);
+            assert asi.isValid() : "default asi is not supported yet";
+        }
+
+        /**
+         * Special constructor for loads and stores.
+         */
+        public Fmt11(Op3s op3, SPARCAddress addr, Register rd) {
+            this(rd.encoding(), op3.getValue(), addr.getBase().encoding(), 0, 0, 0, 0);
+            if (!addr.getIndex().equals(Register.None)) {
+                this.rs2 = addr.getIndex().encoding();
+            } else {
+                this.simm13 = addr.getDisplacement();
+                this.i = 1;
+            }
+            verify();
+        }
+
         private int getInstructionBits() {
             if (i == 0) {
                 return Ops.LdstOp.getValue() << OP_SHIFT | rd << RD_SHIFT | op3 << OP3_SHIFT | rs1 << RS1_SHIFT | i << I_SHIFT | immAsi << IMM_ASI_SHIFT | rs2 << RS2_SHIFT;
@@ -913,6 +940,8 @@
         Restore(0x3d, "restore"),
         Done(0x3e, "done"),
         Retry(0x3e, "retry"),
+        Casa(0b111100, "casa"),
+        Casxa(0b111110, "casxa"),
 
         Lduw(0x00, "lduw"),
         Ldub(0x01, "ldub"),
@@ -1241,6 +1270,28 @@
         }
     }
 
+    public enum Asi {
+        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);
+
+        private final int value;
+
+        private Asi(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+
+        public boolean isValid() {
+            return value != INVALID.getValue();
+        }
+    }
+
     public static int getFloatEncoding(int reg) {
         assert reg < 32;
         return reg;
@@ -1277,7 +1328,7 @@
     }
 
     public static final int hi22(int x) {
-        return x >> 10;
+        return x >>> 10;
     }
 
     public static final int lo10(int x) {
@@ -1643,9 +1694,18 @@
         }
     }
 
-    private static int patchUnbound(SPARCAssembler masm, Label label) {
-        label.addPatchAt(masm.codeBuffer.position());
-        return 0;
+    public static class Casa extends Fmt11 {
+
+        public Casa(Register src1, Register src2, Register dst, Asi asi) {
+            super(Op3s.Casa, src1, src2, dst, asi);
+        }
+    }
+
+    public static class Casxa extends Fmt11 {
+
+        public Casxa(Register src1, Register src2, Register dst, Asi asi) {
+            super(Op3s.Casxa, src1, src2, dst, asi);
+        }
     }
 
     public static class Cmask8 extends Fmt3n {
@@ -2536,51 +2596,50 @@
 
     public static class Lddf extends Fmt11 {
 
-        // TODO remove address
         public Lddf(SPARCAddress src, Register dst) {
-            super(Op3s.Lddf, src.getBase(), src.getDisplacement(), dst);
+            super(Op3s.Lddf, src, dst);
         }
     }
 
     public static class Ldf extends Fmt11 {
 
         public Ldf(SPARCAddress src, Register dst) {
-            super(Op3s.Ldf, src.getBase(), src.getDisplacement(), dst);
+            super(Op3s.Ldf, src, dst);
         }
     }
 
     public static class Ldsb extends Fmt11 {
 
         public Ldsb(SPARCAddress src, Register dst) {
-            super(Op3s.Ldsb, src.getBase(), src.getDisplacement(), dst);
+            super(Op3s.Ldsb, src, dst);
         }
     }
 
     public static class Ldsh extends Fmt11 {
 
         public Ldsh(SPARCAddress src, Register dst) {
-            super(Op3s.Ldsh, src.getBase(), src.getDisplacement(), dst);
+            super(Op3s.Ldsh, src, dst);
         }
     }
 
     public static class Ldsw extends Fmt11 {
 
         public Ldsw(SPARCAddress src, Register dst) {
-            super(Op3s.Ldsw, src.getBase(), src.getDisplacement(), dst);
+            super(Op3s.Ldsw, src, dst);
         }
     }
 
     public static class Lduw extends Fmt11 {
 
         public Lduw(SPARCAddress src, Register dst) {
-            super(Op3s.Lduw, src.getBase(), src.getDisplacement(), dst);
+            super(Op3s.Lduw, src, dst);
         }
     }
 
     public static class Ldx extends Fmt11 {
 
         public Ldx(SPARCAddress src, Register dst) {
-            super(Op3s.Ldx, src.getBase(), src.getDisplacement(), dst);
+            super(Op3s.Ldx, src, dst);
         }
     }
 
@@ -2822,8 +2881,8 @@
 
     public static class Sethi extends Fmt00a {
 
-        public Sethi(int simm22, Register dst) {
-            super(Op2s.Sethi, simm22, dst);
+        public Sethi(int imm22, Register dst) {
+            super(Op2s.Sethi, imm22, dst);
         }
     }
 
@@ -2903,44 +2962,28 @@
     public static class Stb extends Fmt11 {
 
         public Stb(Register dst, SPARCAddress addr) {
-            super(Op3s.Stb, addr.getBase(), addr.getDisplacement(), dst);
+            super(Op3s.Stb, addr, dst);
         }
     }
 
     public static class Sth extends Fmt11 {
 
         public Sth(Register dst, SPARCAddress addr) {
-            super(Op3s.Sth, addr.getBase(), addr.getDisplacement(), dst);
+            super(Op3s.Sth, addr, dst);
         }
     }
 
     public static class Stw extends Fmt11 {
 
-        public Stw(Register dst, Register src1, Register src2) {
-            super(Op3s.Stw, src1, src2, dst);
-        }
-
-        public Stw(Register dst, Register src1, int simm13) {
-            super(Op3s.Stw, src1, simm13, dst);
-        }
-
         public Stw(Register dst, SPARCAddress addr) {
-            this(dst, addr.getBase(), addr.getDisplacement());
+            super(Op3s.Stw, addr, dst);
         }
     }
 
     public static class Stx extends Fmt11 {
 
-        public Stx(Register dst, Register src1, Register src2) {
-            super(Op3s.Stx, src1, src2, dst);
-        }
-
-        public Stx(Register dst, Register src1, int simm13) {
-            super(Op3s.Stx, src1, simm13, dst);
-        }
-
         public Stx(Register dst, SPARCAddress addr) {
-            this(dst, addr.getBase(), addr.getDisplacement());
+            super(Op3s.Stx, addr, dst);
         }
     }
 
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Tue Jul 16 17:41:21 2013 -0700
@@ -85,6 +85,17 @@
         }
     }
 
+    public static class Bpgeu extends Bpcc {
+
+        public Bpgeu(CC cc, int simm19) {
+            super(cc, simm19);
+        }
+
+        public Bpgeu(CC cc, Label label) {
+            super(cc, label);
+        }
+    }
+
     public static class Bset extends Or {
 
         public Bset(Register src, Register dst) {
@@ -107,6 +118,20 @@
         }
     }
 
+    public static class Cas extends Casa {
+
+        public Cas(Register src1, Register src2, Register dst) {
+            super(src1, src2, dst, Asi.ASI_PRIMARY);
+        }
+    }
+
+    public static class Casx extends Casxa {
+
+        public Casx(Register src1, Register src2, Register dst) {
+            super(src1, src2, dst, Asi.ASI_PRIMARY);
+        }
+    }
+
     public static class Clr extends Or {
 
         public Clr(Register dst) {
@@ -302,53 +327,87 @@
     public static class Setx {
 
         private long value;
-        private Register tmp;
         private Register dst;
+        private boolean forceRelocatable;
 
-        public Setx(long value, Register tmp, Register dst) {
+        public Setx(long value, Register dst, boolean forceRelocatable) {
             this.value = value;
-            this.tmp = tmp;
             this.dst = dst;
+            this.forceRelocatable = forceRelocatable;
+        }
+
+        public Setx(long value, Register dst) {
+            this(value, dst, false);
         }
 
         public void emit(SPARCMacroAssembler masm) {
             int hi = (int) (value >> 32);
             int lo = (int) (value & ~0);
 
-            if (isSimm13(lo) && value == lo) {
-                new Or(g0, lo, dst).emit(masm);
-            } else if (hi == 0) {
-                new Sethi(lo, dst).emit(masm);   // hardware version zero-extends to upper 32
-                if (lo10(lo) != 0) {
-                    new Or(dst, lo10(lo), dst).emit(masm);
+// if (isSimm13(lo) && value == lo) {
+// new Or(g0, lo, dst).emit(masm);
+// } else if (hi == 0) {
+// new Sethi(lo, dst).emit(masm); // hardware version zero-extends to upper 32
+// if (lo10(lo) != 0) {
+// new Or(dst, lo10(lo), dst).emit(masm);
+// }
+// } else if (hi == -1) {
+// new Sethi(~lo, dst).emit(masm); // hardware version zero-extends to upper 32
+// new Xor(dst, ~lo10(~0), dst).emit(masm);
+// new Add(dst, lo10(lo), dst).emit(masm);
+// } else if (lo == 0) {
+// if (isSimm13(hi)) {
+// new Or(g0, hi, dst).emit(masm);
+// } else {
+// new Sethi(hi, dst).emit(masm); // hardware version zero-extends to upper 32
+// if (lo10(hi) != 0) {
+// new Or(dst, lo10(hi), dst).emit(masm);
+// }
+// }
+// new Sllx(dst, 32, dst).emit(masm);
+
+            // This is the same logic as MacroAssembler::internal_set.
+            final int startPc = masm.codeBuffer.position();
+
+            if (hi == 0 && lo >= 0) {
+                new Sethi(lo, dst).emit(masm);
+            } else if (hi == -1) {
+                new Sethi(~lo, dst).emit(masm);
+                new Xor(dst, ~lo10(~0), dst).emit(masm);
+            } else {
+                int shiftcnt = 0;
+                new Sethi(hi, dst).emit(masm);
+                if ((hi & 0x3ff) != 0) {                                       // Any bits?
+                    new Or(dst, hi & 0x3ff, dst).emit(masm);                   // msb 32-bits are now in lsb 32
                 }
-            } else if (hi == -1) {
-                new Sethi(~lo, dst).emit(masm);  // hardware version zero-extends to upper 32
-                new Xor(dst, ~lo10(~0), dst).emit(masm);
-                new Add(dst, lo10(lo), dst).emit(masm);
-            } else if (lo == 0) {
-                if (isSimm13(hi)) {
-                    new Or(g0, hi, dst).emit(masm);
+                if ((lo & 0xFFFFFC00) != 0) {                                  // done?
+                    if (((lo >> 20) & 0xfff) != 0) {                           // Any bits set?
+                        new Sllx(dst, 12, dst).emit(masm);                     // Make room for next 12 bits
+                        new Or(dst, (lo >> 20) & 0xfff, dst).emit(masm);       // Or in next 12
+                        shiftcnt = 0;                                          // We already shifted
+                    } else {
+                        shiftcnt = 12;
+                    }
+                    if (((lo >> 10) & 0x3ff) != 0) {
+                        new Sllx(dst, shiftcnt + 10, dst).emit(masm);          // Make room for last 10 bits
+                        new Or(dst, (lo >> 10) & 0x3ff, dst).emit(masm);       // Or in next 10
+                        shiftcnt = 0;
+                    } else {
+                        shiftcnt = 10;
+                    }
+                    new Sllx(dst, shiftcnt + 10, dst).emit(masm);              // Shift leaving disp field 0'd
                 } else {
-                    new Sethi(hi, dst).emit(masm);   // hardware version zero-extends to upper 32
-                    if (lo10(hi) != 0) {
-                        new Or(dst, lo10(hi), dst).emit(masm);
-                    }
+                    new Sllx(dst, 32, dst).emit(masm);
                 }
-                new Sllx(dst, 32, dst).emit(masm);
-            } else {
-                // TODO Use the same logic as in MacroAssembler::internal_sethi, which doesn't need
-// a scratch register.
-                new Sethi(hi, tmp).emit(masm);
-                new Sethi(lo, dst).emit(masm); // macro assembler version sign-extends
-                if (lo10(hi) != 0) {
-                    new Or(tmp, lo10(hi), tmp).emit(masm);
+            }
+            // Pad out the instruction sequence so it can be patched later.
+            if (forceRelocatable) {
+                while (masm.codeBuffer.position() < (startPc + (7 * 4))) {
+                    new Nop().emit(masm);
                 }
-                if (lo10(lo) != 0) {
-                    new Or(dst, lo10(lo), dst).emit(masm);
-                }
-                new Sllx(tmp, 32, tmp).emit(masm);
-                new Or(dst, tmp, dst).emit(masm);
+            }
+            if (lo10(lo) != 0 || forceRelocatable) {
+                new Add(dst, lo10(lo), dst).emit(masm);
             }
         }
     }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Jul 16 17:41:21 2013 -0700
@@ -389,31 +389,53 @@
             baseRegister = asAllocatable(base);
         }
 
+        AllocatableValue indexRegister;
         if (!index.equals(Value.ILLEGAL) && scale != 0) {
             if (isConstant(index)) {
                 finalDisp += asConstant(index).asLong() * scale;
+                indexRegister = Value.ILLEGAL;
             } else {
-                Value indexRegister;
                 if (scale != 1) {
                     Variable longIndex = newVariable(Kind.Long);
                     emitMove(longIndex, index);
                     indexRegister = emitMul(longIndex, Constant.forLong(scale));
                 } else {
-                    indexRegister = index;
+                    indexRegister = asAllocatable(index);
                 }
 
-                if (baseRegister.equals(Value.ILLEGAL)) {
-                    baseRegister = asAllocatable(indexRegister);
-                } else {
-                    Variable newBase = newVariable(Kind.Long);
-                    emitMove(newBase, baseRegister);
-                    baseRegister = newBase;
-                    baseRegister = emitAdd(baseRegister, indexRegister);
-                }
+// if (baseRegister.equals(Value.ILLEGAL)) {
+// baseRegister = asAllocatable(indexRegister);
+// } else {
+// Variable newBase = newVariable(Kind.Long);
+// emitMove(newBase, baseRegister);
+// baseRegister = newBase;
+// baseRegister = emitAdd(baseRegister, indexRegister);
+// }
+            }
+        } else {
+            indexRegister = Value.ILLEGAL;
+        }
+
+        int displacementInt;
+
+        // If we don't have an index register we can use a displacement, otherwise load the
+        // displacement into a register and add it to the base.
+        if (indexRegister.equals(Value.ILLEGAL)) {
+            // TODO What if displacement if too big?
+            displacementInt = (int) finalDisp;
+        } else {
+            displacementInt = 0;
+            AllocatableValue displacementRegister = load(Constant.forLong(finalDisp));
+            if (baseRegister.equals(Value.ILLEGAL)) {
+                baseRegister = displacementRegister;
+            } else {
+                Variable longBase = newVariable(Kind.Long);
+                emitMove(longBase, baseRegister);
+                baseRegister = emitAdd(longBase, displacementRegister);
             }
         }
 
-        return new SPARCAddressValue(target().wordKind, baseRegister, (int) finalDisp);
+        return new SPARCAddressValue(target().wordKind, baseRegister, indexRegister, displacementInt);
     }
 
     private SPARCAddressValue asAddress(Value address) {
@@ -488,7 +510,7 @@
     }
 
     @Override
-    public Value emitSub(Value a, Value b) {
+    public Variable emitSub(Value a, Value b) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -510,7 +532,7 @@
     }
 
     @Override
-    public Value emitMul(Value a, Value b) {
+    public Variable emitMul(Value a, Value b) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -602,7 +624,7 @@
     }
 
     @Override
-    public Value emitAnd(Value a, Value b) {
+    public Variable emitAnd(Value a, Value b) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -619,7 +641,7 @@
     }
 
     @Override
-    public Value emitOr(Value a, Value b) {
+    public Variable emitOr(Value a, Value b) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -635,7 +657,7 @@
     }
 
     @Override
-    public Value emitXor(Value a, Value b) {
+    public Variable emitXor(Value a, Value b) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -651,7 +673,7 @@
     }
 
     @Override
-    public Value emitShl(Value a, Value b) {
+    public Variable emitShl(Value a, Value b) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -667,7 +689,7 @@
     }
 
     @Override
-    public Value emitShr(Value a, Value b) {
+    public Variable emitShr(Value a, Value b) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -683,7 +705,7 @@
     }
 
     @Override
-    public Value emitUShr(Value a, Value b) {
+    public Variable emitUShr(Value a, Value b) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
@@ -699,7 +721,7 @@
     }
 
     @Override
-    public Value emitConvert(Op opcode, Value inputVal) {
+    public Variable emitConvert(Op opcode, Value inputVal) {
         Variable input = load(inputVal);
         Variable result = newVariable(opcode.to);
         switch (opcode) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Tue Jul 16 17:41:21 2013 -0700
@@ -85,9 +85,8 @@
                     if (SPARCAssembler.isSimm13(address.getDisplacement())) {
                         new Stx(g0, address).emit(masm);
                     } else {
-                        // TODO Can't use g3 as scratch here.
-                        new Setx(address.getDisplacement(), g3, g3).emit(masm);
-                        new Stx(g0, sp, g3).emit(masm);
+                        new Setx(address.getDisplacement(), g3).emit(masm);
+                        new Stx(g0, new SPARCAddress(sp, g3)).emit(masm);
                     }
                 }
             }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java	Tue Jul 16 17:41:21 2013 -0700
@@ -53,7 +53,8 @@
     protected TargetDescription createTarget() {
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
-        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, true);
+        final boolean inlineObjects = false;  // TODO We might want to change this later.
+        return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Tue Jul 16 17:41:21 2013 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
+import static com.oracle.graal.api.code.ValueUtil.*;
+
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.*;
@@ -32,6 +34,7 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.SPARCMove.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
@@ -60,16 +63,14 @@
 
     @Override
     public void emitTailcall(Value[] args, Value address) {
-        // TODO Auto-generated method stub
+        throw new InternalError("NYI");
     }
 
     @Override
     protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
         InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind();
         if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
-// append(new SPARCHotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps,
-// callState, invokeKind));
-            throw new InternalError("NYI");
+            append(new SPARCHotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
         } else {
             assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
             HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
@@ -93,33 +94,52 @@
 
     @Override
     public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
-        // TODO Auto-generated method stub
+        throw new InternalError("NYI");
     }
 
     @Override
     public void emitPatchReturnAddress(ValueNode address) {
-        // TODO Auto-generated method stub
+        throw new InternalError("NYI");
     }
 
     @Override
     public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
-        // TODO Auto-generated method stub
+        throw new InternalError("NYI");
     }
 
     @Override
     public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
-        // TODO Auto-generated method stub
+        Kind kind = x.newValue().kind();
+        assert kind == x.expectedValue().kind();
+
+        Variable address = load(operand(x.object()));
+        Value offset = operand(x.offset());
+        Variable cmpValue = (Variable) loadNonConst(operand(x.expectedValue()));
+        Variable newValue = load(operand(x.newValue()));
+
+        if (ValueUtil.isConstant(offset)) {
+            assert !runtime.needsDataPatch(asConstant(offset));
+            address = emitAdd(address, asConstant(offset));
+        } else {
+            if (isLegal(offset)) {
+                address = emitAdd(address, offset);
+            }
+        }
+
+        append(new CompareAndSwapOp(address, cmpValue, newValue));
+
+        Variable result = newVariable(x.kind());
+        emitMove(result, newValue);
+        setResult(x, result);
     }
 
     @Override
     public StackSlot getLockSlot(int lockDepth) {
-        // TODO Auto-generated method stub
-        return null;
+        throw new InternalError("NYI");
     }
 
     public Stub getStub() {
-        // TODO Auto-generated method stub
-        return null;
+        throw new InternalError("NYI");
     }
 
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Tue Jul 16 17:41:21 2013 -0700
@@ -71,8 +71,9 @@
         return attributesMap.clone();
     }
 
-    private final Register[] javaGeneralParameterRegisters;
-    private final Register[] nativeGeneralParameterRegisters;
+    private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5};
+    private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5};
+
     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};
@@ -124,9 +125,6 @@
     public SPARCHotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) {
         this.architecture = architecture;
 
-        javaGeneralParameterRegisters = new Register[]{i0, i1, i2, i3, i4, i5};
-        nativeGeneralParameterRegisters = new Register[]{i0, i1, i2, i3, i4, i5};
-
         csl = new CalleeSaveLayout(architecture, -1, -1, architecture.getWordSize(), calleeSaveRegisters);
         allocatable = initAllocatable(config.useCompressedOops);
         attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
@@ -144,12 +142,13 @@
 
     @Override
     public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
-        if (type == Type.NativeCall) {
-            return callingConvention(nativeGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
+        if (type == Type.JavaCall || type == Type.NativeCall) {
+            return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
         }
-        // On x64, parameter locations are the same whether viewed
-        // from the caller or callee perspective
-        return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
+        if (type == Type.JavaCallee) {
+            return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
+        }
+        throw GraalInternalError.shouldNotReachHere();
     }
 
     public Register[] getCallingConventionRegisters(Type type, Kind kind) {
@@ -157,7 +156,7 @@
             return fpuParameterRegisters;
         }
         assert architecture.canStoreValue(CPU, kind);
-        return type == Type.NativeCall ? nativeGeneralParameterRegisters : javaGeneralParameterRegisters;
+        return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters;
     }
 
     private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Tue Jul 16 17:41:21 2013 -0700
@@ -27,23 +27,21 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 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;
 
 /**
  * A direct call that complies with the conventions for such calls in HotSpot. In particular, for
  * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call.
- * This instruction (which moves 0L in G3) is patched by the C++ Graal code to replace the 0L
- * constant with Universe::non_oop_word(), a special sentinel used for the initial value of the
- * Klass in an inline cache. It puts the called method into G5 before calling.
  */
 @Opcode("CALL_DIRECT")
 final class SPARCHotspotDirectStaticCallOp extends DirectCallOp {
 
+    private static final long nonOopBits = HotSpotGraalRuntime.graalRuntime().getConfig().nonOopBits;
     private final Constant metaspaceMethod;
     private final InvokeKind invokeKind;
 
@@ -57,22 +55,15 @@
     @Override
     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 so that the C++ code can find it
-        // and replace the inline 0L value with Universe::non_oop_word()
+        // 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);
         tasm.recordMark(invokeKind == InvokeKind.Static ? Marks.MARK_INVOKESTATIC : Marks.MARK_INVOKESPECIAL);
-        // XXX move must be patchable!
-        SPARCMove.move(tasm, masm, g3.asValue(Kind.Long), Constant.LONG_0);
-        new Nop().emit(masm);
-        new Nop().emit(masm);
-        new Nop().emit(masm);
-        new Nop().emit(masm);
-        new Nop().emit(masm);
-        new Nop().emit(masm);
+        // SPARCMove.move(tasm, masm, g3.asValue(Kind.Long), Constant.LONG_0);
+        new Setx(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/SPARCHotspotDirectVirtualCallOp.java	Tue Jul 16 17:41:21 2013 -0700
@@ -0,0 +1,68 @@
+/*
+ * 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.nodes.java.MethodCallTargetNode.InvokeKind.*;
+import static com.oracle.graal.sparc.SPARC.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.bridge.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.SPARCCall.DirectCallOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+
+/**
+ * A direct call that complies with the conventions for such calls in HotSpot. In particular, for
+ * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call.
+ */
+@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) {
+        super(target, result, parameters, temps, state);
+        this.invokeKind = invokeKind;
+        assert invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual;
+    }
+
+    @Override
+    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);
+        super.emitCode(tasm, masm);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCSafepointOp.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCSafepointOp.java	Tue Jul 16 17:41:21 2013 -0700
@@ -61,7 +61,7 @@
         final int pos = masm.codeBuffer.position();
         final int offset = SafepointPollOffset.getValue() % unsafe.pageSize();
         Register scratch = ((RegisterValue) temp).getRegister();
-        new Setx(config.safepointPollingAddress + offset, scratch, scratch).emit(masm);
+        new Setx(config.safepointPollingAddress + offset, scratch).emit(masm);
         tasm.recordMark(config.isPollingPageFar ? Marks.MARK_POLL_FAR : Marks.MARK_POLL_NEAR);
         tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
         new Ldx(new SPARCAddress(scratch, 0), g0).emit(masm);
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java	Tue Jul 16 17:41:21 2013 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.lir.sparc;
 
+import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.code.*;
@@ -35,16 +36,22 @@
     private static final long serialVersionUID = -3583286416638228207L;
 
     @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue base;
+    @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue index;
     protected final int displacement;
 
-    public SPARCAddressValue(PlatformKind kind, AllocatableValue baseRegister, int finalDisp) {
+    public SPARCAddressValue(PlatformKind kind, AllocatableValue base, int displacement) {
+        this(kind, base, Value.ILLEGAL, displacement);
+    }
+
+    public SPARCAddressValue(PlatformKind kind, AllocatableValue base, AllocatableValue index, int displacement) {
         super(kind);
-        this.base = baseRegister;
-        this.displacement = finalDisp;
+        this.base = base;
+        this.index = index;
+        this.displacement = displacement;
     }
 
     private static Register toRegister(AllocatableValue value) {
-        if (value.equals(Value.ILLEGAL)) {
+        if (isIllegal(value)) {
             return Register.None;
         } else {
             RegisterValue reg = (RegisterValue) value;
@@ -53,7 +60,46 @@
     }
 
     public SPARCAddress toAddress() {
-        return new SPARCAddress(toRegister(base), displacement);
+        if (isLegal(index)) {
+            return new SPARCAddress(toRegister(base), toRegister(index));
+        } else {
+            return new SPARCAddress(toRegister(base), displacement);
+        }
     }
 
+    @Override
+    public String toString() {
+        StringBuilder s = new StringBuilder("[");
+        String sep = "";
+        if (isLegal(base)) {
+            s.append(base);
+            sep = " + ";
+        }
+        if (isLegal(index)) {
+            s.append(sep).append(index);
+            sep = " + ";
+        } else {
+            if (displacement < 0) {
+                s.append(" - ").append(-displacement);
+            } else if (displacement > 0) {
+                s.append(sep).append(displacement);
+            }
+        }
+        s.append("]");
+        return s.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof SPARCAddressValue) {
+            SPARCAddressValue addr = (SPARCAddressValue) obj;
+            return getPlatformKind() == addr.getPlatformKind() && displacement == addr.displacement && base.equals(addr.base) && index.equals(addr.index);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return base.hashCode() ^ index.hashCode() ^ (displacement << 4) ^ getPlatformKind().hashCode();
+    }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Tue Jul 16 17:41:21 2013 -0700
@@ -271,13 +271,9 @@
                     // new Sdivx(masm, asIntReg(src1), asIntReg(src2),
                     // asIntReg(dst));
                 case FSUB:
-                    throw new InternalError("NYI");
                 case FDIV:
-                    throw new InternalError("NYI");
                 case DSUB:
-                    throw new InternalError("NYI");
                 case DDIV:
-                    throw new InternalError("NYI");
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
@@ -305,34 +301,34 @@
                     break;
                 case ISHR:
                     assert isSimm13(tasm.asIntConst(src2));
-                    new Srl(asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst)).emit(masm);
+                    new Sra(asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst)).emit(masm);
                     break;
                 case IUSHR:
                     assert isSimm13(tasm.asIntConst(src2));
-                    new Sra(asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst)).emit(masm);
+                    new Srl(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);
                     break;
+                case LMUL:
+                    assert isSimm13(tasm.asIntConst(src2));
+                    new Mulx(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
+                    break;
                 case LXOR:
                     assert isSimm13(tasm.asIntConst(src2));
                     new Add(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
                     break;
                 case LUSHR:
-                    throw new InternalError("NYI");
+                    assert isSimm13(tasm.asIntConst(src2));
+                    new Srl(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
+                    break;
                 case FADD:
-                    throw new InternalError("NYI");
                 case FMUL:
-                    throw new InternalError("NYI");
                 case FDIV:
-                    throw new InternalError("NYI");
                 case DADD:
-                    throw new InternalError("NYI");
                 case DMUL:
-                    throw new InternalError("NYI");
                 case DDIV:
-                    throw new InternalError("NYI");
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
@@ -453,8 +449,8 @@
                     new Sra(asIntReg(src), 0, asLongReg(dst)).emit(masm);
                     break;
                 case I2B:
-                    new Sll(asIntReg(src), 24, asIntReg(src)).emit(masm);
-                    new Srl(asIntReg(dst), 24, asIntReg(src)).emit(masm);
+                    new Sll(asIntReg(src), 24, asIntReg(dst)).emit(masm);
+                    new Srl(asIntReg(dst), 24, asIntReg(dst)).emit(masm);
                     break;
                 case I2F:
                     new Fstoi(masm, asIntReg(src), asFloatReg(dst));
@@ -468,12 +464,6 @@
                 case DNEG:
                     new Fnegd(masm, asDoubleReg(src), asDoubleReg(dst));
                     break;
-                case LSHL:
-                    new Sllx(asLongReg(dst), asIntReg(src), asLongReg(dst)).emit(masm);
-                    break;
-                case LSHR:
-                    new Srlx(asLongReg(dst), asIntReg(src), asLongReg(dst)).emit(masm);
-                    break;
                 default:
                     throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
             }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Tue Jul 16 17:41:21 2013 -0700
@@ -72,8 +72,8 @@
                     new Cmp(asLongReg(x), asLongReg(y)).emit(masm);
                     break;
                 case ACMP:
-// new Cmp(asObjectReg(x), asObjectReg(y)).emit(masm);
-// break;
+                    new Cmp(asObjectReg(x), asObjectReg(y)).emit(masm);
+                    break;
                 case FCMP:
                     // masm.ucomiss(asFloatReg(x), asFloatReg(y));
                     // break;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Tue Jul 16 17:41:21 2013 -0700
@@ -58,6 +58,18 @@
                 case EQ:
                     new Bpe(CC.Xcc, destination.label()).emit(masm);
                     break;
+                case NE:
+                    new Bpne(CC.Xcc, destination.label()).emit(masm);
+                    break;
+                case BE:
+                    new Bpleu(CC.Xcc, destination.label()).emit(masm);
+                    break;
+                case LE:
+                    new Bple(CC.Xcc, destination.label()).emit(masm);
+                    break;
+                case AE:
+                    new Bpgeu(CC.Xcc, destination.label()).emit(masm);
+                    break;
                 case GT:
                     new Bpg(CC.Xcc, destination.label()).emit(masm);
                     break;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue Jul 16 17:41:21 2013 -0700
@@ -127,6 +127,7 @@
         public void emitMemAccess(SPARCMacroAssembler masm) {
             SPARCAddress addr = address.toAddress();
             switch (kind) {
+                case Boolean:
                 case Byte:
                     new Ldsb(addr, asRegister(result)).emit(masm);
                     break;
@@ -189,6 +190,26 @@
         }
     }
 
+    @Opcode("CAS")
+    public static class CompareAndSwapOp extends SPARCLIRInstruction {
+
+// @Def protected AllocatableValue result;
+        @Use protected AllocatableValue address;
+        @Use protected AllocatableValue cmpValue;
+        @Use protected AllocatableValue newValue;
+
+        public CompareAndSwapOp(AllocatableValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+            this.address = address;
+            this.cmpValue = cmpValue;
+            this.newValue = newValue;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+            compareAndSwap(masm, address, cmpValue, newValue);
+        }
+    }
+
     public static class StackLoadAddressOp extends SPARCLIRInstruction {
 
         @Def({REG}) protected AllocatableValue result;
@@ -219,6 +240,7 @@
             assert isRegister(input);
             SPARCAddress addr = address.toAddress();
             switch (kind) {
+                case Boolean:
                 case Byte:
                     new Stb(asRegister(input), addr).emit(masm);
                     break;
@@ -274,14 +296,12 @@
         }
         switch (input.getKind()) {
             case Int:
-                new Mov(asRegister(input), asRegister(result)).emit(masm);
-                break;
             case Long:
+            case Object:
                 new Mov(asRegister(input), asRegister(result)).emit(masm);
                 break;
             case Float:
             case Double:
-            case Object:
             default:
                 throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
         }
@@ -325,24 +345,52 @@
                 }
                 new Setuw(input.asInt(), asRegister(result)).emit(masm);
                 break;
-            case Long:
+            case Long: {
                 if (tasm.runtime.needsDataPatch(input)) {
+                    new Nop().emit(masm);
                     tasm.recordDataReferenceInCode(input, 0, true);
+                    new Setx(input.asLong(), asRegister(result), true).emit(masm);
+                    new Nop().emit(masm);
+                } else {
+                    new Nop().emit(masm);
+                    new Nop().emit(masm);
+                    new Setx(input.asLong(), asRegister(result)).emit(masm);
+                    new Nop().emit(masm);
+                    new Nop().emit(masm);
                 }
-                new Setx(input.asLong(), null, asRegister(result)).emit(masm);
                 break;
-            case Object:
+            }
+            case Object: {
                 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);
+// tasm.recordDataReferenceInCode(input, 0, true);
+// new Setx(0xDEADDEADDEADDEADL, null, asRegister(result)).emit(masm);
+                    throw GraalInternalError.shouldNotReachHere();
                 } else {
-                    throw new InternalError("NYI");
+                    Register dst = asRegister(result);
+                    new Rdpc(dst).emit(masm);
+                    tasm.asObjectConstRef(input);
+                    new Ldx(new SPARCAddress(dst, 0), dst).emit(masm);
                 }
                 break;
+            }
             default:
                 throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
         }
     }
+
+    protected static void compareAndSwap(SPARCMacroAssembler masm, AllocatableValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+        switch (cmpValue.getKind()) {
+            case Int:
+                new Cas(asRegister(address), asRegister(cmpValue), asRegister(newValue)).emit(masm);
+                break;
+            case Long:
+            case Object:
+                new Casx(asRegister(address), asRegister(cmpValue), asRegister(newValue)).emit(masm);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Tue Jul 16 18:30:45 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Tue Jul 16 17:41:21 2013 -0700
@@ -211,7 +211,7 @@
     }
 
     /**
-     * Returns the address of a float constant that is embedded as a data references into the code.
+     * Returns the address of a float constant that is embedded as a data reference into the code.
      */
     public AbstractAddress asFloatConstRef(Value value) {
         return asFloatConstRef(value, 4);
@@ -223,7 +223,7 @@
     }
 
     /**
-     * Returns the address of a double constant that is embedded as a data references into the code.
+     * Returns the address of a double constant that is embedded as a data reference into the code.
      */
     public AbstractAddress asDoubleConstRef(Value value) {
         return asDoubleConstRef(value, 8);
@@ -235,13 +235,21 @@
     }
 
     /**
-     * Returns the address of a long constant that is embedded as a data references into the code.
+     * Returns the address of a long constant that is embedded as a data reference into the code.
      */
     public AbstractAddress asLongConstRef(Value value) {
         assert value.getKind() == Kind.Long && isConstant(value);
         return recordDataReferenceInCode((Constant) value, 8, false);
     }
 
+    /**
+     * Returns the address of an object constant that is embedded as a data reference into the code.
+     */
+    public AbstractAddress asObjectConstRef(Value value) {
+        assert value.getKind() == Kind.Object && isConstant(value);
+        return recordDataReferenceInCode((Constant) value, 8, false);
+    }
+
     public AbstractAddress asIntAddr(Value value) {
         assert value.getKind() == Kind.Int;
         return asAddress(value);
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Tue Jul 16 18:30:45 2013 +0200
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Tue Jul 16 17:41:21 2013 -0700
@@ -43,8 +43,6 @@
 
   address pc = _instructions->start() + pc_offset;
 
-  tty->print_cr("CodeInstaller::pd_site_DataPatch: typeChar=%c, inlined=%d", typeChar, inlined);
-
   switch (typeChar) {
     case 'z':
     case 'b':
@@ -57,7 +55,9 @@
     case 'j':
     case 'd': {
       if (inlined) {
-        fatal(err_msg("inlined: type=%c, constant=%lx", inlined, Constant::primitive(constant)));
+        NativeMovConstReg* move = nativeMovConstReg_at(pc);
+        uint64_t value = Constant::primitive(constant);
+        move->set_data(value);
       } else {
         int size = _constants->size();
         if (alignment > 0) {
@@ -73,23 +73,27 @@
         NativeMovRegMem* load = nativeMovRegMem_at(pc);
         int disp = _constants_size + pc_offset - size - BytesPerInstWord;
         load->set_offset(-disp);
-
-//        assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
-//        *((jint*) operand) = (jint) disp;
-
-//        _instructions->relocate(instruction, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS) /*, Assembler::disp32_operand*/);
-//        TRACE_graal_3("relocating (%c) at %p/%p with destination at %p (%d)", typeChar, instruction, operand, dest, size);
       }
       break;
     }
     case 'a': {
-//      address operand = Assembler::locate_operand(instruction, Assembler::imm_operand);
-//      Handle obj = Constant::object(constant);
-//
-//      jobject value = JNIHandles::make_local(obj());
-//      *((jobject*) operand) = value;
-//      _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
-//      TRACE_graal_3("relocating (oop constant) at %p/%p", instruction, operand);
+      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));
       break;
     }
     default:
@@ -122,18 +126,16 @@
       assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
       NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
       call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
-//      _instructions->relocate(call->instruction_address(),
-//                                             virtual_call_Relocation::spec(_invoke_mark_pc),
-//                                             Assembler::call32_operand);
-      fatal("NYI");
+      _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc));
+      /*, Assembler::call32_operand); */
       break;
     }
     case MARK_INVOKESTATIC: {
       assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
       NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
       call->set_destination(SharedRuntime::get_resolve_static_call_stub());
-      _instructions->relocate(call->instruction_address(),
-                                             relocInfo::static_call_type /*, Assembler::call32_operand*/);
+      _instructions->relocate(call->instruction_address(), relocInfo::static_call_type);
+      /*, Assembler::call32_operand); */
       break;
     }
     case MARK_INVOKESPECIAL: {