changeset 10854:e1fcdda22831

SPARC: can compile some stubs now but they don't work yet
author twisti
date Mon, 22 Jul 2013 22:26:49 -0700
parents 22baf2a69f6d
children d7f8a08c37c2
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/SPARCHotSpotDeoptimizeCallerOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.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/SPARCHotSpotPatchReturnAddressOp.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/SPARCHotSpotRuntime.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.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/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/SPARCMove.java graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp src/share/vm/graal/graalCodeInstaller.cpp
diffstat 19 files changed, 822 insertions(+), 276 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Jul 22 22:26:49 2013 -0700
@@ -395,7 +395,7 @@
         }
 
         public void verify() {
-            assert (disp30 & DISP30_MASK) == 0;
+            assert isDisp30(disp30) : disp30;
         }
     }
 
@@ -1316,15 +1316,41 @@
         return x & ((1 << nbits) - 1);
     }
 
-    private static final int max13 = ((1 << 12) - 1);
-    private static final int min13 = -(1 << 12);
-
-    public static boolean isSimm13(int src) {
-        return min13 <= src && src <= max13;
+    /**
+     * Minimum value for signed immediate ranges.
+     */
+    public static long minSimm(long nbits) {
+        return -(1L << (nbits - 1));
+    }
+
+    /**
+     * Maximum value for signed immediate ranges.
+     */
+    public static long maxSimm(long nbits) {
+        return (1L << (nbits - 1)) - 1;
     }
 
-    public static boolean isSimm13(long src) {
-        return NumUtil.isInt(src) && min13 <= src && src <= max13;
+    /**
+     * Test if imm is within signed immediate range for nbits.
+     */
+    public static boolean isSimm(long imm, int nbits) {
+        return minSimm(nbits) <= imm && imm <= maxSimm(nbits);
+    }
+
+    public static boolean isSimm13(int imm) {
+        return isSimm(imm, 13);
+    }
+
+    public static boolean isSimm13(long imm) {
+        return NumUtil.isInt(imm) && isSimm(imm, 13);
+    }
+
+    public static boolean isDisp30(long imm) {
+        return isSimm(imm, 30);
+    }
+
+    public static boolean isWordDisp30(long imm) {
+        return isSimm(imm, 30 + 2);
     }
 
     public static final int hi22(int x) {
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Mon Jul 22 22:26:49 2013 -0700
@@ -324,19 +324,24 @@
         }
     }
 
-    public static class Setx {
+    /**
+     * This instruction is like sethi but for 64-bit values.
+     */
+    public static class Sethix {
+
+        private static final int INSTRUCTION_SIZE = 7;
 
         private long value;
         private Register dst;
         private boolean forceRelocatable;
 
-        public Setx(long value, Register dst, boolean forceRelocatable) {
+        public Sethix(long value, Register dst, boolean forceRelocatable) {
             this.value = value;
             this.dst = dst;
             this.forceRelocatable = forceRelocatable;
         }
 
-        public Setx(long value, Register dst) {
+        public Sethix(long value, Register dst) {
             this(value, dst, false);
         }
 
@@ -344,28 +349,6 @@
             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);
-// }
-// } 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();
 
@@ -402,10 +385,32 @@
             }
             // Pad out the instruction sequence so it can be patched later.
             if (forceRelocatable) {
-                while (masm.codeBuffer.position() < (startPc + (7 * 4))) {
+                while (masm.codeBuffer.position() < (startPc + (INSTRUCTION_SIZE * 4))) {
                     new Nop().emit(masm);
                 }
             }
+        }
+    }
+
+    public static class Setx {
+
+        private long value;
+        private Register dst;
+        private boolean forceRelocatable;
+
+        public Setx(long value, Register dst, boolean forceRelocatable) {
+            this.value = value;
+            this.dst = dst;
+            this.forceRelocatable = forceRelocatable;
+        }
+
+        public Setx(long value, Register dst) {
+            this(value, dst, false);
+        }
+
+        public void emit(SPARCMacroAssembler masm) {
+            new Sethix(value, dst, forceRelocatable).emit(masm);
+            int lo = (int) (value & ~0);
             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	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Jul 22 22:26:49 2013 -0700
@@ -54,13 +54,11 @@
 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.LoadOp;
 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.SPARCMove.StoreOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.calc.ConvertNode.Op;
@@ -94,6 +92,32 @@
     }
 
     @Override
+    public boolean canStoreConstant(Constant c) {
+        // SPARC can only store integer null constants (via g0)
+        switch (c.getKind()) {
+            case Float:
+            case Double:
+                return false;
+            default:
+                return c.isNull();
+        }
+    }
+
+    @Override
+    public boolean canInlineConstant(Constant c) {
+        switch (c.getKind()) {
+            case Int:
+                return SPARCAssembler.isSimm13(c.asInt()) && !runtime.needsDataPatch(c);
+            case Long:
+                return SPARCAssembler.isSimm13(c.asLong()) && !runtime.needsDataPatch(c);
+            case Object:
+                return c.isNull();
+            default:
+                return true;
+        }
+    }
+
+    @Override
     public Variable emitMove(Value input) {
         Variable result = newVariable(input.getKind());
         emitMove(result, input);
@@ -117,6 +141,87 @@
     }
 
     @Override
+    public SPARCAddressValue emitAddress(Value base, long displacement, Value index, int scale) {
+        AllocatableValue baseRegister;
+        long finalDisp = displacement;
+        if (isConstant(base)) {
+            if (asConstant(base).isNull()) {
+                baseRegister = Value.ILLEGAL;
+            } else if (asConstant(base).getKind() != Kind.Object) {
+                finalDisp += asConstant(base).asLong();
+                baseRegister = Value.ILLEGAL;
+            } else {
+                baseRegister = load(base);
+            }
+        } else {
+            baseRegister = asAllocatable(base);
+        }
+
+        AllocatableValue indexRegister;
+        if (!index.equals(Value.ILLEGAL) && scale != 0) {
+            if (isConstant(index)) {
+                finalDisp += asConstant(index).asLong() * scale;
+                indexRegister = Value.ILLEGAL;
+            } else {
+                if (scale != 1) {
+                    Variable longIndex = newVariable(Kind.Long);
+                    emitMove(longIndex, index);
+                    indexRegister = emitMul(longIndex, Constant.forLong(scale));
+                } else {
+                    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);
+                // }
+            }
+        } 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, indexRegister, displacementInt);
+    }
+
+    protected SPARCAddressValue asAddressValue(Value address) {
+        if (address instanceof SPARCAddressValue) {
+            return (SPARCAddressValue) address;
+        } else {
+            return emitAddress(address, 0, Value.ILLEGAL, 0);
+        }
+    }
+
+    @Override
+    public Value emitAddress(StackSlot address) {
+        Variable result = newVariable(target().wordKind);
+        append(new StackLoadAddressOp(result, address));
+        return result;
+    }
+
+    @Override
     protected boolean peephole(ValueNode valueNode) {
         // No peephole optimizations for now
         return false;
@@ -267,7 +372,12 @@
 
     @Override
     protected void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
-        throw new InternalError("NYI");
+        long maxOffset = linkage.getMaxCallTargetOffset();
+        if (SPARCAssembler.isWordDisp30(maxOffset)) {
+            append(new SPARCCall.DirectNearForeignCallOp(linkage, result, arguments, temps, info));
+        } else {
+            append(new SPARCCall.DirectFarForeignCallOp(this, linkage, result, arguments, temps, info));
+        }
     }
 
     @Override
@@ -354,121 +464,6 @@
     }
 
     @Override
-    public boolean canInlineConstant(Constant c) {
-        switch (c.getKind()) {
-            case Int:
-                return SPARCAssembler.isSimm13(c.asInt()) && !runtime.needsDataPatch(c);
-            case Long:
-                return SPARCAssembler.isSimm13(c.asLong()) && !runtime.needsDataPatch(c);
-            case Object:
-                return c.isNull();
-            default:
-                return true;
-        }
-    }
-
-    @Override
-    public boolean canStoreConstant(Constant c) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
-    public SPARCAddressValue emitAddress(Value base, long displacement, Value index, int scale) {
-        AllocatableValue baseRegister;
-        long finalDisp = displacement;
-        if (isConstant(base)) {
-            if (asConstant(base).isNull()) {
-                baseRegister = Value.ILLEGAL;
-            } else if (asConstant(base).getKind() != Kind.Object) {
-                finalDisp += asConstant(base).asLong();
-                baseRegister = Value.ILLEGAL;
-            } else {
-                baseRegister = load(base);
-            }
-        } else {
-            baseRegister = asAllocatable(base);
-        }
-
-        AllocatableValue indexRegister;
-        if (!index.equals(Value.ILLEGAL) && scale != 0) {
-            if (isConstant(index)) {
-                finalDisp += asConstant(index).asLong() * scale;
-                indexRegister = Value.ILLEGAL;
-            } else {
-                if (scale != 1) {
-                    Variable longIndex = newVariable(Kind.Long);
-                    emitMove(longIndex, index);
-                    indexRegister = emitMul(longIndex, Constant.forLong(scale));
-                } else {
-                    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);
-// }
-            }
-        } 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, indexRegister, displacementInt);
-    }
-
-    private SPARCAddressValue asAddress(Value address) {
-        if (address instanceof SPARCAddressValue) {
-            return (SPARCAddressValue) address;
-        } else {
-            return emitAddress(address, 0, Value.ILLEGAL, 0);
-        }
-    }
-
-    @Override
-    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode deopting) {
-        SPARCAddressValue loadAddress = asAddress(address);
-        Variable result = newVariable(kind);
-        append(new LoadOp(kind, result, loadAddress, deopting != null ? state(deopting) : null));
-        return result;
-    }
-
-    @Override
-    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) {
-        SPARCAddressValue storeAddress = asAddress(address);
-        Variable input = load(inputVal);
-        append(new StoreOp(kind, storeAddress, input, deopting != null ? state(deopting) : null));
-    }
-
-    @Override
-    public Value emitAddress(StackSlot address) {
-        Variable result = newVariable(target().wordKind);
-        append(new StackLoadAddressOp(result, address));
-        return result;
-    }
-
-    @Override
     public Value emitNegate(Value input) {
         Variable result = newVariable(input.getKind());
         switch (input.getKind()) {
@@ -680,7 +675,7 @@
                 append(new Op2Stack(ISHL, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op1Stack(LSHL, result, loadNonConst(b)));
+                append(new Op2Stack(LSHL, result, a, loadNonConst(b)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -696,7 +691,7 @@
                 append(new Op2Stack(ISHR, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op1Stack(LSHR, result, loadNonConst(b)));
+                append(new Op2Stack(LSHR, result, a, loadNonConst(b)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Mon Jul 22 22:26:49 2013 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
+import java.util.*;
+
 import sun.misc.*;
 
 import com.oracle.graal.api.code.*;
@@ -36,6 +38,7 @@
 import com.oracle.graal.hotspot.stubs.Stub;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.nodes.*;
 
 import static com.oracle.graal.sparc.SPARC.*;
@@ -93,7 +96,7 @@
         }
     }
 
-    class HotSpotFrameContext implements FrameContext {
+    public class HotSpotFrameContext implements FrameContext {
 
         final boolean isStub;
 
@@ -138,6 +141,7 @@
     public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
         SPARCHotSpotLIRGenerator gen = (SPARCHotSpotLIRGenerator) lirGen;
         FrameMap frameMap = gen.frameMap;
+        assert gen.deoptimizationRescueSlot == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
 
         Stub stub = gen.getStub();
         AbstractAssembler masm = createAssembler(frameMap);
@@ -150,6 +154,12 @@
             tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot));
         }
 
+        if (stub != null) {
+            // SPARC stubs always enter a frame which saves the registers.
+            final Set<Register> definedRegisters = new HashSet<>();
+            stub.initDestroyedRegisters(definedRegisters);
+        }
+
         return tasm;
     }
 
@@ -165,13 +175,15 @@
 
         if (unverifiedStub != null) {
             tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY);
-            CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[]{runtime().lookupJavaType(Object.class)}, target, false);
+            // We need to use JavaCall here because we haven't entered the frame yet.
+            CallingConvention cc = regConfig.getCallingConvention(JavaCall, null, new JavaType[]{runtime().lookupJavaType(Object.class)}, target, false);
             Register inlineCacheKlass = g5; // see MacroAssembler::ic_call
+            Register scratch = g3;
             Register receiver = asRegister(cc.getArgument(0));
             SPARCAddress src = new SPARCAddress(receiver, config.hubOffset);
 
-            new Ldx(src, g0).emit(masm);
-            new Cmp(inlineCacheKlass, g0).emit(masm);
+            new Ldx(src, scratch).emit(masm);
+            new Cmp(scratch, inlineCacheKlass).emit(masm);
             new Bpne(CC.Xcc, unverifiedStub).emit(masm);
             new Nop().emit(masm);  // delay slot
         }
@@ -186,10 +198,9 @@
         HotSpotFrameContext frameContext = (HotSpotFrameContext) tasm.frameContext;
         if (frameContext != null && !frameContext.isStub) {
             tasm.recordMark(Marks.MARK_EXCEPTION_HANDLER_ENTRY);
-// SPARCCall.directCall(tasm, asm, runtime().lookupForeignCall(EXCEPTION_HANDLER), null, false,
-// null);
+            SPARCCall.directCall(tasm, masm, runtime().lookupForeignCall(EXCEPTION_HANDLER), null, false, null);
             tasm.recordMark(Marks.MARK_DEOPT_HANDLER_ENTRY);
-// SPARCCall.directCall(tasm, asm, runtime().lookupForeignCall(DEOPT_HANDLER), null, false, null);
+            SPARCCall.directCall(tasm, masm, runtime().lookupForeignCall(DEOPT_HANDLER), null, false, null);
         } else {
             // No need to emit the stubs for entries back into the method since
             // it has no calls that can cause such "return" entries
@@ -198,8 +209,8 @@
 
         if (unverifiedStub != null) {
             masm.bind(unverifiedStub);
-// SPARCCall.directJmp(tasm, asm, runtime().lookupForeignCall(IC_MISS_HANDLER));
-            // throw new InternalError("g0 must be scratch register");
+            Register scratch = g3;
+            SPARCCall.indirectJmp(tasm, masm, scratch, runtime().lookupForeignCall(IC_MISS_HANDLER));
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Mon Jul 22 22:26:49 2013 -0700
@@ -0,0 +1,73 @@
+/*
+ * 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.sparc.SPARC.*;
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+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.*;
+
+/**
+ * Removes the current frame and tail calls the uncommon trap routine.
+ */
+@Opcode("DEOPT_CALLER")
+final class SPARCHotSpotDeoptimizeCallerOp extends SPARCHotSpotEpilogueOp {
+
+    private final DeoptimizationAction action;
+    private final DeoptimizationReason reason;
+
+    SPARCHotSpotDeoptimizeCallerOp(DeoptimizationAction action, DeoptimizationReason reason) {
+        this.action = action;
+        this.reason = reason;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+        leaveFrame(tasm);
+
+// SPARCHotSpotBackend backend = (SPARCHotSpotBackend)
+// HotSpotGraalRuntime.graalRuntime().getBackend();
+// final boolean isStub = true;
+// HotSpotFrameContext frameContext = backend.new HotSpotFrameContext(isStub);
+// frameContext.enter(tasm);
+
+        HotSpotGraalRuntime runtime = graalRuntime();
+        Register thread = runtime.getRuntime().threadRegister();
+
+        Register scratch = g5;
+        new Mov(tasm.runtime.encodeDeoptActionAndReason(action, reason), scratch).emit(masm);
+        new Stw(scratch, new SPARCAddress(thread, runtime.getConfig().pendingDeoptimizationOffset)).emit(masm);
+
+        SPARCCall.indirectJmp(tasm, masm, scratch, tasm.runtime.lookupForeignCall(UNCOMMON_TRAP));
+
+// frameContext.leave(tasm);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java	Mon Jul 22 22:26:49 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * 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 com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Superclass for operations that leave a method's frame.
+ */
+abstract class SPARCHotSpotEpilogueOp extends SPARCLIRInstruction {
+
+    protected void leaveFrame(TargetMethodAssembler tasm) {
+        if (tasm.frameContext != null) {
+            tasm.frameContext.leave(tasm);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java	Mon Jul 22 22:26:49 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.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.sparc.SPARC.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Sets up the arguments for an exception handler in the callers frame, removes the current frame
+ * and jumps to the handler.
+ */
+@Opcode("JUMP_TO_EXCEPTION_HANDLER_IN_CALLER")
+final class SPARCHotSpotJumpToExceptionHandlerInCallerOp extends SPARCHotSpotEpilogueOp {
+
+    @Use(REG) AllocatableValue handlerInCallerPc;
+    @Use(REG) AllocatableValue exception;
+    @Use(REG) AllocatableValue exceptionPc;
+
+    SPARCHotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc) {
+        this.handlerInCallerPc = handlerInCallerPc;
+        this.exception = exception;
+        this.exceptionPc = exceptionPc;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+        leaveFrame(tasm);
+
+        // Restore SP from L7 if the exception PC is a method handle call site.
+        Register thread = graalRuntime().getRuntime().threadRegister();
+        int isMethodHandleReturnOffset = graalRuntime().getConfig().threadIsMethodHandleReturnOffset;
+        SPARCAddress dst = new SPARCAddress(thread, isMethodHandleReturnOffset);
+        new Lduw(dst, o7).emit(masm);
+        new Cmp(o7, o7).emit(masm);
+        new Movcc(ConditionFlag.NotZero, CC.Icc, l7, sp).emit(masm);
+
+        new Jmpl(asRegister(handlerInCallerPc), 0, g0).emit(masm);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Jul 22 22:26:49 2013 -0700
@@ -23,17 +23,21 @@
 package com.oracle.graal.hotspot.sparc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.HotSpotBackend.*;
 
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.sparc.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.sparc.SPARCMove.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
@@ -55,6 +59,32 @@
      */
     StackSlot deoptimizationRescueSlot;
 
+    @SuppressWarnings("hiding")
+    @Override
+    protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) {
+        assert runtime().config.basicLockSize == 8;
+        HotSpotLockStack lockStack = new HotSpotLockStack(frameMap, Kind.Long);
+        return new HotSpotDebugInfoBuilder(nodeOperands, lockStack);
+    }
+
+    @Override
+    public StackSlot getLockSlot(int lockDepth) {
+        return ((HotSpotDebugInfoBuilder) debugInfoBuilder).lockStack().makeLockSlot(lockDepth);
+    }
+
+    @Override
+    protected boolean needOnlyOopMaps() {
+        // Stubs only need oop maps
+        return graph.start() instanceof StubStartNode;
+    }
+
+    Stub getStub() {
+        if (graph.start() instanceof StubStartNode) {
+            return ((StubStartNode) graph.start()).getStub();
+        }
+        return null;
+    }
+
     @Override
     public void visitSafepointNode(SafepointNode i) {
         LIRFrameState info = state(i);
@@ -62,8 +92,37 @@
     }
 
     @Override
+    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
+        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));
+            Variable longAddress = newVariable(Kind.Long);
+            emitMove(longAddress, address);
+            address = emitAdd(longAddress, 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 void emitTailcall(Value[] args, Value address) {
-        throw new InternalError("NYI");
+// append(new AMD64TailcallOp(args, address));
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
@@ -89,57 +148,120 @@
 // emitMove(targetAddress, operand(callTarget.computedAddress()));
 // append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod,
 // targetAddress, callState));
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
+    public void emitUnwind(Value exception) {
+        ForeignCallLinkage linkage = getRuntime().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER);
+        CallingConvention linkageCc = linkage.getCallingConvention();
+        assert linkageCc.getArgumentCount() == 2;
+        RegisterValue exceptionParameter = (RegisterValue) linkageCc.getArgument(0);
+        emitMove(exceptionParameter, exception);
+        append(new SPARCHotSpotUnwindOp(exceptionParameter));
+        throw GraalInternalError.unimplemented();
+    }
+
+    @Override
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
+// append(new AMD64DeoptimizeOp(action, deopting.getDeoptimizationReason(), state(deopting)));
+        throw GraalInternalError.unimplemented();
     }
 
     @Override
     public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
-        throw new InternalError("NYI");
+        append(new SPARCHotSpotDeoptimizeCallerOp(action, reason));
     }
 
     @Override
     public void emitPatchReturnAddress(ValueNode address) {
-        throw new InternalError("NYI");
+        append(new SPARCHotSpotPatchReturnAddressOp(load(operand(address))));
     }
 
     @Override
     public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) {
-        throw new InternalError("NYI");
+        Variable handler = load(operand(handlerInCallerPc));
+        ForeignCallLinkage linkage = getRuntime().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER);
+        CallingConvention linkageCc = linkage.getCallingConvention();
+        assert linkageCc.getArgumentCount() == 2;
+        RegisterValue exceptionFixed = (RegisterValue) linkageCc.getArgument(0);
+        RegisterValue exceptionPcFixed = (RegisterValue) linkageCc.getArgument(1);
+        emitMove(exceptionFixed, operand(exception));
+        emitMove(exceptionPcFixed, operand(exceptionPc));
+        SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed);
+        append(op);
+    }
+
+    private static boolean isCompressCandidate(DeoptimizingNode access) {
+        return access != null && ((HeapAccess) access).isCompressible();
+    }
+
+    @Override
+    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode access) {
+        SPARCAddressValue loadAddress = asAddressValue(address);
+        Variable result = newVariable(kind);
+        assert access == null || access instanceof HeapAccess;
+        if (isCompressCandidate(access)) {
+            if (runtime().config.useCompressedOops && kind == Kind.Object) {
+// append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) :
+// null, runtime().config.narrowOopBase, runtime().config.narrowOopShift,
+// runtime().config.logMinObjAlignment));
+                throw GraalInternalError.unimplemented();
+            } else if (runtime().config.useCompressedKlassPointers && kind == Kind.Long) {
+// append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) :
+// null, runtime().config.narrowKlassBase, runtime().config.narrowKlassShift,
+// runtime().config.logKlassAlignment));
+                throw GraalInternalError.unimplemented();
+            } else {
+                append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null));
+            }
+        } else {
+            append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null));
+        }
+        return result;
     }
 
     @Override
-    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
-        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);
+    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode access) {
+        SPARCAddressValue storeAddress = asAddressValue(address);
+        LIRFrameState state = access != null ? state(access) : null;
+        if (isConstant(inputVal)) {
+            Constant c = asConstant(inputVal);
+            if (canStoreConstant(c)) {
+                if (inputVal.getKind() == Kind.Object) {
+                    append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedOops && isCompressCandidate(access)));
+                } else if (inputVal.getKind() == Kind.Long) {
+                    append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedKlassPointers && isCompressCandidate(access)));
+                } else {
+                    append(new StoreConstantOp(kind, storeAddress, c, state, false));
+                }
+                return;
             }
         }
-
-        append(new CompareAndSwapOp(address, cmpValue, newValue));
-
-        Variable result = newVariable(x.kind());
-        emitMove(result, newValue);
-        setResult(x, result);
+        Variable input = load(inputVal);
+        if (isCompressCandidate(access)) {
+            if (runtime().config.useCompressedOops && kind == Kind.Object) {
+// if (input.getKind() == Kind.Object) {
+// Variable scratch = newVariable(Kind.Long);
+// append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state,
+// runtime().config.narrowOopBase, runtime().config.narrowOopShift,
+// runtime().config.logMinObjAlignment));
+// } else {
+// // the input oop is already compressed
+// append(new StoreOp(input.getKind(), storeAddress, input, state));
+// }
+                throw GraalInternalError.unimplemented();
+            } else if (runtime().config.useCompressedKlassPointers && kind == Kind.Long) {
+// Variable scratch = newVariable(Kind.Long);
+// append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state,
+// runtime().config.narrowKlassBase, runtime().config.narrowKlassShift,
+// runtime().config.logKlassAlignment));
+                throw GraalInternalError.unimplemented();
+            } else {
+                append(new StoreOp(kind, storeAddress, input, state));
+            }
+        } else {
+            append(new StoreOp(kind, storeAddress, input, state));
+        }
     }
-
-    @Override
-    public StackSlot getLockSlot(int lockDepth) {
-        throw new InternalError("NYI");
-    }
-
-    public Stub getStub() {
-        throw new InternalError("NYI");
-    }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java	Mon Jul 22 22:26:49 2013 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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.sparc.SPARC.*;
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Patch the return address of the current frame.
+ */
+@Opcode("PATCH_RETURN")
+final class SPARCHotSpotPatchReturnAddressOp extends SPARCLIRInstruction {
+
+    @Use(REG) AllocatableValue address;
+
+    SPARCHotSpotPatchReturnAddressOp(AllocatableValue address) {
+        this.address = address;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+        // FIXME This is non-trivial. On SPARC we need to flush all register windows first before we
+        // can patch the return address (see: frame::patch_pc).
+        // int frameSize = tasm.frameMap.frameSize();
+        // new Stx(asRegister(address), new SPARCAddress(sp, frameSize));
+        new Ldx(new SPARCAddress(g0, g0), g0).emit(masm);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Mon Jul 22 22:26:49 2013 -0700
@@ -95,14 +95,16 @@
         // @formatter:off
         if (reserveForHeapBase) {
             registers = new Register[] {
-                    // TODO this is not complete
+                        // 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,
                         f0, f1, f2, f3, f4, f5, f6, f7
                       };
         } else {
             registers = new Register[] {
-                    // TODO this is not complete
+                        // 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,
                         f0, f1, f2, f3, f4, f5, f6, f7
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java	Mon Jul 22 22:26:49 2013 -0700
@@ -76,7 +76,7 @@
 
     @Override
     public Register stackPointerRegister() {
-        throw new InternalError("NYI: SPARC: Define stack pointer register.");
+        return sp;
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java	Mon Jul 22 22:26:49 2013 -0700
@@ -0,0 +1,66 @@
+/*
+ * 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.sparc.SPARC.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Removes the current frame and jumps to the {@link UnwindExceptionToCallerStub}.
+ */
+@Opcode("UNWIND")
+final class SPARCHotSpotUnwindOp extends SPARCHotSpotEpilogueOp {
+
+    @Use({REG}) protected RegisterValue exception;
+
+    SPARCHotSpotUnwindOp(RegisterValue exception) {
+        this.exception = exception;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) {
+        leaveFrame(tasm);
+
+        ForeignCallLinkage linkage = tasm.runtime.lookupForeignCall(UNWIND_EXCEPTION_TO_CALLER);
+        CallingConvention cc = linkage.getCallingConvention();
+        assert cc.getArgumentCount() == 2;
+        assert exception.equals(cc.getArgument(0));
+
+        // Get return address (is in o7 after leave).
+        Register returnAddress = asRegister(cc.getArgument(1));
+        new Mov(o7, returnAddress).emit(masm);
+
+        Register scratch = g5;
+        SPARCCall.indirectJmp(tasm, masm, scratch, linkage);
+    }
+}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Jul 22 22:26:49 2013 -0700
@@ -264,10 +264,10 @@
                     new Add(asIntReg(src2), -(tasm.asIntConst(src1)), asIntReg(dst)).emit(masm);
                     break;
                 case IAND:
-                    throw new InternalError("NYI");
+                    throw GraalInternalError.unimplemented();
                 case IDIV:
                     assert isSimm13(tasm.asIntConst(src1));
-                    throw new InternalError("NYI");
+                    throw GraalInternalError.unimplemented();
                     // new Sdivx(masm, asIntReg(src1), asIntReg(src2),
                     // asIntReg(dst));
                 case FSUB:
@@ -311,6 +311,14 @@
                     assert isSimm13(tasm.asIntConst(src2));
                     new Xor(asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst)).emit(masm);
                     break;
+                case LADD:
+                    assert isSimm13(tasm.asIntConst(src2));
+                    new Add(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
+                    break;
+                case LSUB:
+                    assert isSimm13(tasm.asIntConst(src2));
+                    new Sub(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
+                    break;
                 case LMUL:
                     assert isSimm13(tasm.asIntConst(src2));
                     new Mulx(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
@@ -319,6 +327,10 @@
                     assert isSimm13(tasm.asIntConst(src2));
                     new Add(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm);
                     break;
+                case LSHL:
+                    assert isSimm13(tasm.asIntConst(src2));
+                    new Sll(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);
@@ -365,7 +377,7 @@
                     new Sra(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                     break;
                 case IREM:
-                    throw new InternalError("NYI");
+                    throw GraalInternalError.unimplemented();
                 case LADD:
                     new Add(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                     break;
@@ -400,7 +412,7 @@
                 case LUDIV:
                 case LUREM:
                 case LREM:
-                    throw new InternalError("NYI");
+                    throw GraalInternalError.unimplemented();
                 case FADD:
                     new Fadds(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)).emit(masm);
                     break;
@@ -414,7 +426,7 @@
                     new Fdivs(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)).emit(masm);
                     break;
                 case FREM:
-                    throw new InternalError("NYI");
+                    throw GraalInternalError.unimplemented();
                 case DADD:
                     new Faddd(asDoubleReg(src1), asDoubleReg(src2), asDoubleReg(dst)).emit(masm);
                     break;
@@ -428,7 +440,7 @@
                     new Fdivd(asDoubleReg(src1), asDoubleReg(src2), asDoubleReg(dst)).emit(masm);
                     break;
                 case DREM:
-                    throw new InternalError("NYI");
+                    throw GraalInternalError.unimplemented();
                 default:
                     throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
             }
@@ -507,7 +519,7 @@
                 rk = result.getKind();
                 xsk = x.getKind().getStackKind();
                 ysk = y.getKind().getStackKind();
-                assert rk == Kind.Int && xsk == Kind.Int && ysk == Kind.Int : "opcode=" + opcode + ", rk=" + rk + ", xsk=" + xsk + ", ysk=" + ysk;
+                assert rk == Kind.Int && xsk == Kind.Int && ysk == Kind.Int;
                 break;
             case LADD:
             case LSUB:
@@ -517,13 +529,18 @@
             case LAND:
             case LOR:
             case LXOR:
+                rk = result.getKind();
+                xk = x.getKind();
+                yk = y.getKind();
+                assert rk == Kind.Long && xk == Kind.Long && yk == Kind.Long;
+                break;
             case LSHL:
             case LSHR:
             case LUSHR:
                 rk = result.getKind();
                 xk = x.getKind();
                 yk = y.getKind();
-                assert rk == Kind.Long && xk == Kind.Long && yk == Kind.Long;
+                assert rk == Kind.Long && xk == Kind.Long && (yk == Kind.Int || yk == Kind.Long);
                 break;
             case FADD:
             case FSUB:
@@ -543,10 +560,10 @@
                 rk = result.getKind();
                 xk = x.getKind();
                 yk = y.getKind();
-                assert rk == Kind.Double && xk == Kind.Double && yk == Kind.Double;
+                assert rk == Kind.Double && xk == Kind.Double && yk == Kind.Double : "opcode=" + opcode + ", result kind=" + rk + ", x kind=" + xk + ", y kind=" + yk;
                 break;
             default:
-                throw new InternalError("NYI: " + opcode);
+                throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
         }
     }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Mon Jul 22 22:26:49 2013 -0700
@@ -153,14 +153,13 @@
         }
         int before = masm.codeBuffer.position();
         if (scratch != null) {
-// // offset might not fit a 32-bit immediate, generate an
-// // indirect call with a 64-bit immediate
-// masm.movq(scratch, 0L);
-// masm.call(scratch);
-// } else {
-// masm.call();
+            // offset might not fit a 30-bit displacement, generate an
+            // indirect call with a 64-bit immediate
+            new Sethix(0L, scratch, true).emit(masm);
+            new Jmpl(scratch, 0, r15).emit(masm);
+        } else {
+            new Call(0).emit(masm);
         }
-        new Call(0).emit(masm);
         int after = masm.codeBuffer.position();
         tasm.recordDirectCall(before, after, callTarget, info);
         tasm.recordExceptionHandlers(after, info);
@@ -168,14 +167,14 @@
         new Nop().emit(masm);  // delay slot
     }
 
-    public static void directJmp(TargetMethodAssembler tasm, SPARCMacroAssembler masm, InvokeTarget target) {
+    public static void indirectJmp(TargetMethodAssembler tasm, SPARCMacroAssembler masm, Register dst, InvokeTarget target) {
         int before = masm.codeBuffer.position();
-// masm.jmp(0, true);
+        new Sethix(0L, dst, true).emit(masm);
+        new Jmp(new SPARCAddress(dst, 0)).emit(masm);
         int after = masm.codeBuffer.position();
-        tasm.recordDirectCall(before, after, target, null);
+        tasm.recordIndirectCall(before, after, target, null);
 // masm.ensureUniquePC();
         new Nop().emit(masm);  // delay slot
-        throw new InternalError("NYI");
     }
 
     public static void indirectCall(TargetMethodAssembler tasm, SPARCMacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) {
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Jul 22 22:26:49 2013 -0700
@@ -73,6 +73,9 @@
                 case GT:
                     new Bpg(CC.Xcc, destination.label()).emit(masm);
                     break;
+                case AT:
+                    new Bpgu(CC.Xcc, destination.label()).emit(masm);
+                    break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Mon Jul 22 22:26:49 2013 -0700
@@ -264,6 +264,51 @@
         }
     }
 
+    public static class StoreConstantOp extends MemOp {
+
+        protected final Constant input;
+        private final boolean compress;
+
+        public StoreConstantOp(Kind kind, SPARCAddressValue address, Constant input, LIRFrameState state, boolean compress) {
+            super(kind, address, state);
+            this.input = input;
+            this.compress = compress;
+            if (input.isNonNull()) {
+                throw GraalInternalError.shouldNotReachHere("Can only store null constants to memory");
+            }
+        }
+
+        @Override
+        public void emitMemAccess(SPARCMacroAssembler masm) {
+            switch (kind) {
+                case Boolean:
+                case Byte:
+                    new Stb(g0, address.toAddress()).emit(masm);
+                    break;
+                case Char:
+                case Short:
+                    new Sth(g0, address.toAddress()).emit(masm);
+                    break;
+                case Int:
+                    new Stw(g0, address.toAddress()).emit(masm);
+                    break;
+                case Long:
+                case Object:
+                    if (compress) {
+                        new Stw(g0, address.toAddress()).emit(masm);
+                    } else {
+                        new Stx(g0, address.toAddress()).emit(masm);
+                    }
+                    break;
+                case Float:
+                case Double:
+                    throw GraalInternalError.shouldNotReachHere("Cannot store float constants to memory");
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
     public static void move(TargetMethodAssembler tasm, SPARCMacroAssembler masm, Value result, Value input) {
         if (isRegister(input)) {
             if (isRegister(result)) {
@@ -314,9 +359,11 @@
                 new Stw(asRegister(input), dest).emit(masm);
                 break;
             case Long:
+            case Object:
+                new Stx(asRegister(input), dest).emit(masm);
+                break;
             case Float:
             case Double:
-            case Object:
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -342,21 +389,25 @@
             case Int:
                 if (tasm.runtime.needsDataPatch(input)) {
                     tasm.recordDataReferenceInCode(input, 0, true);
+                    new Setuw(input.asInt(), asRegister(result)).emit(masm);
+                } else {
+                    if (input.isDefaultForKind()) {
+                        new Clr(asRegister(result)).emit(masm);
+                    } else {
+                        new Setuw(input.asInt(), asRegister(result)).emit(masm);
+                    }
                 }
-                new Setuw(input.asInt(), asRegister(result)).emit(masm);
                 break;
             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);
+                    if (input.isDefaultForKind()) {
+                        new Clr(asRegister(result)).emit(masm);
+                    } else {
+                        new Setx(input.asLong(), asRegister(result)).emit(masm);
+                    }
                 }
                 break;
             }
--- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Mon Jul 22 21:43:31 2013 -0700
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Mon Jul 22 22:26:49 2013 -0700
@@ -41,38 +41,38 @@
     public static final RegisterCategory FPU = new RegisterCategory("FPU");
 
     // General purpose registers
-    public static final Register r0  = new Register(0, 0, "r0", CPU);
-    public static final Register r1  = new Register(1, 1, "r1", CPU);
-    public static final Register r2  = new Register(2, 2, "r2", CPU);
-    public static final Register r3  = new Register(3, 3, "r3", CPU);
-    public static final Register r4  = new Register(4, 4, "r4", CPU);
-    public static final Register r5  = new Register(5, 5, "r5", CPU);
-    public static final Register r6  = new Register(6, 6, "r6", CPU);
-    public static final Register r7  = new Register(7, 7, "r7", CPU);
-    public static final Register r8  = new Register(8, 8, "r8", CPU);
-    public static final Register r9  = new Register(9, 9, "r9", CPU);
-    public static final Register r10 = new Register(10, 10, "r10", CPU);
-    public static final Register r11 = new Register(11, 11, "r11", CPU);
-    public static final Register r12 = new Register(12, 12, "r12", CPU);
-    public static final Register r13 = new Register(13, 13, "r13", CPU);
-    public static final Register r14 = new Register(14, 14, "r14", CPU);
-    public static final Register r15 = new Register(15, 15, "r15", CPU);
-    public static final Register r16 = new Register(16, 16, "r16", CPU);
-    public static final Register r17 = new Register(17, 17, "r17", CPU);
-    public static final Register r18 = new Register(18, 18, "r18", CPU);
-    public static final Register r19 = new Register(19, 19, "r19", CPU);
-    public static final Register r20 = new Register(20, 20, "r20", CPU);
-    public static final Register r21 = new Register(21, 21, "r21", CPU);
-    public static final Register r22 = new Register(22, 22, "r22", CPU);
-    public static final Register r23 = new Register(23, 23, "r23", CPU);
-    public static final Register r24 = new Register(24, 24, "r24", CPU);
-    public static final Register r25 = new Register(25, 25, "r25", CPU);
-    public static final Register r26 = new Register(26, 26, "r26", CPU);
-    public static final Register r27 = new Register(27, 27, "r27", CPU);
-    public static final Register r28 = new Register(28, 28, "r28", CPU);
-    public static final Register r29 = new Register(29, 29, "r29", CPU);
-    public static final Register r30 = new Register(30, 30, "r30", CPU);
-    public static final Register r31 = new Register(31, 31, "r31", CPU);
+    public static final Register r0  = new Register(0, 0, "g0", CPU);
+    public static final Register r1  = new Register(1, 1, "g1", CPU);
+    public static final Register r2  = new Register(2, 2, "g2", CPU);
+    public static final Register r3  = new Register(3, 3, "g3", CPU);
+    public static final Register r4  = new Register(4, 4, "g4", CPU);
+    public static final Register r5  = new Register(5, 5, "g5", CPU);
+    public static final Register r6  = new Register(6, 6, "g6", CPU);
+    public static final Register r7  = new Register(7, 7, "g7", CPU);
+    public static final Register r8  = new Register(8, 8, "o0", CPU);
+    public static final Register r9  = new Register(9, 9, "o1", CPU);
+    public static final Register r10 = new Register(10, 10, "o2", CPU);
+    public static final Register r11 = new Register(11, 11, "o3", CPU);
+    public static final Register r12 = new Register(12, 12, "o4", CPU);
+    public static final Register r13 = new Register(13, 13, "o5", CPU);
+    public static final Register r14 = new Register(14, 14, "o6", CPU);
+    public static final Register r15 = new Register(15, 15, "o7", CPU);
+    public static final Register r16 = new Register(16, 16, "l0", CPU);
+    public static final Register r17 = new Register(17, 17, "l1", CPU);
+    public static final Register r18 = new Register(18, 18, "l2", CPU);
+    public static final Register r19 = new Register(19, 19, "l3", CPU);
+    public static final Register r20 = new Register(20, 20, "l4", CPU);
+    public static final Register r21 = new Register(21, 21, "l5", CPU);
+    public static final Register r22 = new Register(22, 22, "l6", CPU);
+    public static final Register r23 = new Register(23, 23, "l7", CPU);
+    public static final Register r24 = new Register(24, 24, "i0", CPU);
+    public static final Register r25 = new Register(25, 25, "i1", CPU);
+    public static final Register r26 = new Register(26, 26, "i2", CPU);
+    public static final Register r27 = new Register(27, 27, "i3", CPU);
+    public static final Register r28 = new Register(28, 28, "i4", CPU);
+    public static final Register r29 = new Register(29, 29, "i5", CPU);
+    public static final Register r30 = new Register(30, 30, "i6", CPU);
+    public static final Register r31 = new Register(31, 31, "i7", CPU);
 
     public static final Register g0 = r0;
     public static final Register g1 = r1;
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Mon Jul 22 21:43:31 2013 -0700
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp	Mon Jul 22 22:26:49 2013 -0700
@@ -29,8 +29,14 @@
 #include "graal/graalJavaAccess.hpp"
 
 inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
-  assert(inst->is_call() || inst->is_jump(), "sanity");
-  return pc_offset + NativeCall::instruction_size;
+  if (inst->is_call() || inst->is_jump()) {
+    return pc_offset + NativeCall::instruction_size;
+  } else if (inst->is_sethi()) {
+    return pc_offset + NativeFarCall::instruction_size;
+  } else {
+    fatal("unsupported type of instruction for call site");
+    return 0;
+  }
 }
 
 inline void CodeInstaller::pd_site_DataPatch(int pc_offset, oop site) {
@@ -107,7 +113,22 @@
 }
 
 inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
-  fatal("CodeInstaller::pd_relocate_ForeignCall - sparc unimp");
+  address pc = (address) inst;
+  if (inst->is_call()) {
+    NativeCall* call = nativeCall_at(pc);
+    call->set_destination((address) foreign_call_destination);
+    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
+  } else if (inst->is_sethi()) {
+    NativeFarCall* call = nativeFarCall_at(pc);
+    call->set_destination((address) foreign_call_destination);
+    _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
+  } else {
+    NativeJump* jump = nativeJump_at((address) (inst));
+    jump->set_jump_destination((address) foreign_call_destination);
+    _instructions->relocate((address)inst, runtime_call_Relocation::spec());
+    fatal("CodeInstaller::pd_relocate_ForeignCall - verify me!");
+  }
+  TRACE_graal_3("relocating (foreign call) at %p", inst);
 }
 
 inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
@@ -127,7 +148,6 @@
       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); */
       break;
     }
     case MARK_INVOKESTATIC: {
@@ -135,16 +155,13 @@
       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); */
       break;
     }
     case MARK_INVOKESPECIAL: {
       assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
       NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
       call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
-//      _instructions->relocate(call->instruction_address(),
-//                              relocInfo::opt_virtual_call_type, Assembler::call32_operand);
-      fatal("NYI");
+      _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type);
       break;
     }
     default:
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Mon Jul 22 21:43:31 2013 -0700
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Mon Jul 22 22:26:49 2013 -0700
@@ -734,12 +734,9 @@
   
   if (target->is_a(SystemDictionary::HotSpotInstalledCode_klass())) {
     assert(inst->is_jump(), "jump expected");
-
     CodeBlob* cb = (CodeBlob*) (address) HotSpotInstalledCode::codeBlob(target);
     assert(cb != NULL, "npe");
-    
     CodeInstaller::pd_relocate_CodeBlob(cb, inst);
-
     return;
   }
 
@@ -755,7 +752,6 @@
 
   if (foreign_call != NULL) {
     jlong foreign_call_destination = HotSpotForeignCallLinkage::address(foreign_call);
-
     CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination);
   } else { // method != NULL
     assert(hotspot_method != NULL, "unexpected JavaMethod");
@@ -764,7 +760,9 @@
     TRACE_graal_3("method call");
     CodeInstaller::pd_relocate_JavaMethod(hotspot_method, pc_offset);
   }
+
   _next_call_type = MARK_INVOKE_INVALID;
+
   if (debug_info != NULL) {
     _debug_recorder->end_safepoint(next_pc_offset);
   }