changeset 9828:5aedcaed6ccf

Initial SPARC control instructions
author Morris Meyer <morris.meyer@oracle.com>
date Sun, 26 May 2013 18:16:28 -0400
parents 26a4433252a3
children 04911dff1c66 6e0c6526334b
files graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/AbstractSPARCAssembler.java graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/ControlSPARCTest.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.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 make/build-graal.xml mx/projects
diffstat 10 files changed, 587 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/AbstractSPARCAssembler.java	Sun May 26 22:49:23 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/AbstractSPARCAssembler.java	Sun May 26 18:16:28 2013 -0400
@@ -26,10 +26,11 @@
 import com.oracle.graal.api.code.Register;
 import com.oracle.graal.api.code.TargetDescription;
 import com.oracle.graal.asm.AbstractAssembler;
-import com.oracle.graal.asm.Label;
 
 public abstract class AbstractSPARCAssembler extends AbstractAssembler {
 
+    public static final String UNBOUND_TARGET = "L" + Integer.MAX_VALUE;
+
     public AbstractSPARCAssembler(TargetDescription target) {
         super(target);
     }
@@ -40,11 +41,6 @@
     }
 
     @Override
-    public void jmp(Label l) {
-        // SPARC: Implement jump.
-    }
-
-    @Override
     protected void patchJumpTarget(int branch, int jumpTarget) {
         // SPARC: Implement patching of jump target.
     }
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Sun May 26 22:49:23 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Sun May 26 18:16:28 2013 -0400
@@ -32,15 +32,6 @@
     private final int displacement;
 
     /**
-     * Creates an {@link SPARCAddress} with given base register,and no displacement.
-     * 
-     * @param base the base register
-     */
-    public SPARCAddress(Register base) {
-        this(base, Register.None, 0);
-    }
-
-    /**
      * Creates an {@link SPARCAddress} with given base register, no scaling and a given
      * displacement.
      * 
@@ -48,7 +39,9 @@
      * @param displacement the displacement
      */
     public SPARCAddress(Register base, int displacement) {
-        this(base, Register.None, displacement);
+        this.base = base;
+        this.displacement = displacement;
+        this.index = null;
     }
 
     /**
@@ -57,12 +50,11 @@
      * 
      * @param base the base register
      * @param index the index register
-     * @param displacement the displacement
      */
-    public SPARCAddress(Register base, Register index, int displacement) {
+    public SPARCAddress(Register base, Register index, int disp) {
         this.base = base;
         this.index = index;
-        this.displacement = displacement;
+        this.displacement = disp;
     }
 
     @Override
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Sun May 26 22:49:23 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Sun May 26 18:16:28 2013 -0400
@@ -26,6 +26,7 @@
 import com.oracle.graal.api.code.RegisterConfig;
 import com.oracle.graal.api.code.TargetDescription;
 import com.oracle.graal.api.meta.Kind;
+import com.oracle.graal.asm.*;
 import com.oracle.graal.hotspot.HotSpotGraalRuntime;
 
 /**
@@ -236,6 +237,26 @@
         }
     }
 
+    public enum Op2s {
+        Bpr(3),
+        Fb(6),
+        Fbp(5),
+        Br(2),
+        Bp(1),
+        Cb(7),
+        Sethi(4);
+
+        private final int value;
+
+        private Op2s(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
     public enum Op3s {
         Add(0x00, "add"),
         And(0x01, "and"),
@@ -623,6 +644,59 @@
         }
     }
 
+    public static class Bpa extends Fmt2c {
+        public Bpa(SPARCAssembler masm, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, Condition.Always.getValue(),
+                            Op2s.Bp.getValue(), CC.Icc.getValue(), 1, simmm19);
+        }
+        public Bpa(SPARCAssembler masm, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, Condition.Always.getValue(),
+                            Op2s.Bp.getValue(), CC.Icc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
+    }
+
+    public static class Bpe extends Fmt2c {
+        public Bpe(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, Condition.Equal.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpe(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, Condition.Equal.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
+    }
+
+    public static class Bpn extends Fmt2c {
+        public Bpn(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, Condition.Never.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpn(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, Condition.Never.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
+    }
+
+    public static class Bpne extends Fmt2c {
+        public Bpne(SPARCAssembler masm, CC cc, int simmm19) {
+            super(masm, Ops.BranchOp.getValue(), 0, Condition.NotZero.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1, simmm19);
+        }
+        public Bpne(SPARCAssembler masm, CC cc, Label label) {
+            super(masm, Ops.BranchOp.getValue(), 0, Condition.NotZero.getValue(),
+                            Op2s.Bp.getValue(), cc.getValue(), 1,
+                            label.isBound() ? label.position() : patchUnbound(masm, label));
+        }
+    }
+
+    private static int patchUnbound(SPARCAssembler masm, Label label) {
+        label.addPatchAt(masm.codeBuffer.position());
+        return 0;
+    }
+
     public static class Fadds extends Fmt3p {
         public Fadds(SPARCAssembler masm, Register src1, Register src2, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fadds.getValue(),
@@ -725,6 +799,13 @@
         }
     }
 
+    @Override
+    @SuppressWarnings("unused")
+    public void jmp(Label l) {
+        new Bpa(this, l);
+    }
+
+
     public static class Ld extends Fmt3b {
         public Ld(SPARCAssembler masm, SPARCAddress src, Register dst) {
             super(masm, Ops.ArithOp.getValue(), Op3s.Ldf.getValue(),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/ControlSPARCTest.java	Sun May 26 18:16:28 2013 -0400
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 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.compiler.sparc.test;
+
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+public class ControlSPARCTest extends SPARCTestBase {
+
+    @Test
+    public void testControl() {
+        compile("testSwitch1I");
+        // compile("testStatic");
+        compile("testCall");
+        compile("testLookupSwitch1I");
+    }
+
+    public static int testSwitch1I(int a) {
+        switch (a) {
+            case 1:
+                return 2;
+            case 2:
+                return 3;
+            default:
+                return 4;
+        }
+    }
+
+    public static int testLookupSwitch1I(int a) {
+        switch (a) {
+            case 0:
+                return 1;
+            case 1:
+                return 2;
+            case 2:
+                return 3;
+            case 3:
+                return 1;
+            case 4:
+                return 2;
+            case 5:
+                return 3;
+            case 6:
+                return 1;
+            case 7:
+                return 2;
+            case 8:
+                return 3;
+            case 9:
+                return 1;
+            case 10:
+                return 2;
+            case 11:
+                return 3;
+            default:
+                return -1;
+        }
+    }
+
+    @SuppressWarnings("unused") private static Object foo = null;
+
+    public static boolean testStatic(Object o) {
+        foo = o;
+        return true;
+    }
+
+    private static int method(int a, int b) {
+        return a + b;
+    }
+
+    public static int testCall(@SuppressWarnings("unused") Object o, int a, int b) {
+        return method(a, b);
+    }
+
+    public static void main(String[] args) {
+        ControlSPARCTest test = new ControlSPARCTest();
+        for (Method m : ControlSPARCTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Sun May 26 22:49:23 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Sun May 26 18:16:28 2013 -0400
@@ -23,8 +23,7 @@
 
 package com.oracle.graal.compiler.sparc;
 
-import static com.oracle.graal.api.code.ValueUtil.isRegister;
-import static com.oracle.graal.api.code.ValueUtil.isStackSlot;
+import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.sparc.SPARCArithmetic.*;
 
 import com.oracle.graal.api.code.CallingConvention;
@@ -47,9 +46,15 @@
 import com.oracle.graal.lir.LIRInstruction;
 import com.oracle.graal.lir.LabelRef;
 import com.oracle.graal.lir.Variable;
+import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.SequentialSwitchOp;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.TableSwitchOp;
+import com.oracle.graal.lir.sparc.SPARCMove.LoadOp;
 import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp;
 import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp;
+import com.oracle.graal.lir.sparc.SPARCMove.StoreOp;
 import com.oracle.graal.lir.sparc.SPARCArithmetic.Op1Stack;
 import com.oracle.graal.lir.sparc.SPARCArithmetic.Op2Stack;
 import com.oracle.graal.lir.sparc.SPARCArithmetic.Unary1Op;
@@ -122,7 +127,7 @@
 
     @Override
     public void emitJump(LabelRef label) {
-        throw new InternalError("NYI");
+        append(new JumpOp(label));
     }
 
     @Override
@@ -170,7 +175,14 @@
 
     @Override
     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
-        throw new InternalError("NYI");
+        // Making a copy of the switch value is necessary because jump table destroys the input
+        // value
+        if (key.getKind() == Kind.Int || key.getKind() == Kind.Long) {
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL));
+        } else {
+            assert key.getKind() == Kind.Object : key.getKind();
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object)));
+        }
     }
 
     @Override
@@ -180,7 +192,10 @@
 
     @Override
     protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
-        throw new InternalError("NYI");
+        // Making a copy of the switch value is necessary because jump table destroys the input
+        // value
+        Variable tmp = emitMove(key);
+        append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind)));
     }
 
     @Override
@@ -251,18 +266,68 @@
     }
 
     @Override
-    public Value emitAddress(Value base, long displacement, Value index, int scale) {
-        throw new InternalError("NYI");
+    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);
+        }
+
+        if (index != Value.ILLEGAL && scale != 0) {
+            if (isConstant(index)) {
+                finalDisp += asConstant(index).asLong() * scale;
+            } else {
+                Value indexRegister;
+                if (scale != 1) {
+                    indexRegister = emitMul(index, Constant.forInt(scale));
+                } else {
+                    indexRegister = index;
+                }
+
+                if (baseRegister == Value.ILLEGAL) {
+                    baseRegister = asAllocatable(indexRegister);
+                } else {
+                    Variable newBase = newVariable(Kind.Int);
+                    emitMove(newBase, baseRegister);
+                    baseRegister = newBase;
+                    baseRegister = emitAdd(baseRegister, indexRegister);
+                }
+            }
+        }
+
+        return new SPARCAddressValue(target().wordKind, baseRegister, (int) finalDisp);
+    }
+
+    private SPARCAddressValue asAddress(Value address) {
+        if (address instanceof SPARCAddressValue) {
+            return (SPARCAddressValue) address;
+        } else {
+            return emitAddress(address, 0, Value.ILLEGAL, 0);
+        }
     }
 
     @Override
-    public Value emitLoad(Kind kind, Value address, DeoptimizingNode canTrap) {
-        throw new InternalError("NYI");
+    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 input, DeoptimizingNode canTrap) {
-        throw new InternalError("NYI");
+    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
@@ -290,7 +355,7 @@
     }
 
     @Override
-    public Value emitAdd(Value a, Value b) {
+    public Variable emitAdd(Value a, Value b) {
         Variable result = newVariable(a.getKind());
         switch (a.getKind()) {
             case Int:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java	Sun May 26 18:16:28 2013 -0400
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 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.lir.sparc;
+
+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.LIRInstruction.*;
+
+public class SPARCAddressValue extends CompositeValue {
+
+    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) {
+        super(kind);
+        this.base = baseRegister;
+        this.displacement = finalDisp;
+    }
+
+    private static Register toRegister(AllocatableValue value) {
+        if (value.equals(Value.ILLEGAL)) {
+            return Register.None;
+        } else {
+            RegisterValue reg = (RegisterValue) value;
+            return reg.getRegister();
+        }
+    }
+
+    public SPARCAddress toAddress() {
+        return new SPARCAddress(toRegister(base), toRegister(index),
+                displacement);
+    }
+
+}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Sun May 26 22:49:23 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Sun May 26 18:16:28 2013 -0400
@@ -22,17 +22,29 @@
  */
 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.*;
+import com.oracle.graal.api.code.CompilationResult.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Bpe;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Subcc;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.sparc.SPARC;
 
 public class SPARCControlFlow {
 
     public static class ReturnOp extends SPARCLIRInstruction {
 
-        @Use({REG, ILLEGAL}) protected Value x;
+        @Use({ REG, ILLEGAL })
+        protected Value x;
 
         public ReturnOp(Value x) {
             this.x = x;
@@ -46,4 +58,140 @@
             // masm.return();
         }
     }
+
+    public static class SequentialSwitchOp extends SPARCLIRInstruction
+            implements FallThroughOp {
+
+        @Use({ CONST })
+        protected Constant[] keyConstants;
+        private final LabelRef[] keyTargets;
+        private LabelRef defaultTarget;
+        @Alive({ REG })
+        protected Value key;
+        @Temp({ REG, ILLEGAL })
+        protected Value scratch;
+
+        public SequentialSwitchOp(Constant[] keyConstants,
+                LabelRef[] keyTargets, LabelRef defaultTarget, Value key,
+                Value scratch) {
+            assert keyConstants.length == keyTargets.length;
+            this.keyConstants = keyConstants;
+            this.keyTargets = keyTargets;
+            this.defaultTarget = defaultTarget;
+            this.key = key;
+            this.scratch = scratch;
+        }
+
+        @Override
+        @SuppressWarnings("unused")
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            if (key.getKind() == Kind.Int) {
+                Register intKey = asIntReg(key);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    if (tasm.runtime.needsDataPatch(keyConstants[i])) {
+                        tasm.recordDataReferenceInCode(keyConstants[i], 0, true);
+                    }
+                    long lc = keyConstants[i].asLong();
+                    assert NumUtil.isInt(lc);
+                    new Subcc(masm, intKey, (int) lc, SPARC.r0); // CMP
+                    Label l = keyTargets[i].label();
+                    l.addPatchAt(tasm.asm.codeBuffer.position());
+                    new Bpe(masm, CC.Icc, l);
+                }
+            } else if (key.getKind() == Kind.Long) {
+                Register longKey = asLongReg(key);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    // masm.setp_eq_s64(tasm.asLongConst(keyConstants[i]),
+                    // longKey);
+                    // masm.at();
+                    Label l = keyTargets[i].label();
+                    l.addPatchAt(tasm.asm.codeBuffer.position());
+                    new Bpe(masm, CC.Xcc, l);
+                }
+            } else if (key.getKind() == Kind.Object) {
+                Register intKey = asObjectReg(key);
+                Register temp = asObjectReg(scratch);
+                for (int i = 0; i < keyConstants.length; i++) {
+                    SPARCMove.move(tasm, masm, temp.asValue(Kind.Object),
+                            keyConstants[i]);
+                    new Subcc(masm, intKey, temp, SPARC.r0); // CMP
+                    new Bpe(masm, CC.Icc, keyTargets[i].label());
+                }
+            } else {
+                throw new GraalInternalError(
+                        "sequential switch only supported for int, long and object");
+            }
+            if (defaultTarget != null) {
+                masm.jmp(defaultTarget.label());
+            } else {
+                // masm.hlt();
+            }
+        }
+
+        @Override
+        public LabelRef fallThroughTarget() {
+            return defaultTarget;
+        }
+
+        @Override
+        public void setFallThroughTarget(LabelRef target) {
+            defaultTarget = target;
+        }
+    }
+
+    public static class TableSwitchOp extends SPARCLIRInstruction {
+
+        private final int lowKey;
+        private final LabelRef defaultTarget;
+        private final LabelRef[] targets;
+        @Alive
+        protected Value index;
+        @Temp
+        protected Value scratch;
+
+        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget,
+                final LabelRef[] targets, Variable index, Variable scratch) {
+            this.lowKey = lowKey;
+            this.defaultTarget = defaultTarget;
+            this.targets = targets;
+            this.index = index;
+            this.scratch = scratch;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            tableswitch(tasm, masm, lowKey, defaultTarget, targets,
+                    asIntReg(index), asLongReg(scratch));
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static void tableswitch(TargetMethodAssembler tasm,
+            SPARCAssembler masm, int lowKey, LabelRef defaultTarget,
+            LabelRef[] targets, Register value, Register scratch) {
+        Buffer buf = masm.codeBuffer;
+        // Compare index against jump table bounds
+        int highKey = lowKey + targets.length - 1;
+        if (lowKey != 0) {
+            // subtract the low value from the switch value
+            // masm.sub_s32(value, value, lowKey);
+            // masm.setp_gt_s32(value, highKey - lowKey);
+        } else {
+            // masm.setp_gt_s32(value, highKey);
+        }
+
+        // Jump to default target if index is not within the jump table
+        if (defaultTarget != null) {
+            // masm.at();
+            // masm.bra(defaultTarget.label().toString());
+        }
+
+        // address of jump table
+        int tablePos = buf.position();
+
+        JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4);
+        tasm.compilationResult.addAnnotation(jt);
+
+        // SPARC: unimp: tableswitch extract
+    }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Sun May 26 22:49:23 2013 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Sun May 26 18:16:28 2013 -0400
@@ -25,22 +25,112 @@
 import static com.oracle.graal.api.code.ValueUtil.asRegister;
 import static com.oracle.graal.api.code.ValueUtil.isConstant;
 import static com.oracle.graal.api.code.ValueUtil.isRegister;
-import static com.oracle.graal.lir.LIRInstruction.OperandFlag.CONST;
-import static com.oracle.graal.lir.LIRInstruction.OperandFlag.HINT;
-import static com.oracle.graal.lir.LIRInstruction.OperandFlag.REG;
-import static com.oracle.graal.lir.LIRInstruction.OperandFlag.STACK;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import com.oracle.graal.api.meta.AllocatableValue;
-import com.oracle.graal.api.meta.Constant;
-import com.oracle.graal.api.meta.Value;
-import com.oracle.graal.asm.sparc.SPARCAssembler;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.graph.GraalInternalError;
-import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.*;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.TargetMethodAssembler;
 
 public class SPARCMove {
 
+    public static class LoadOp extends SPARCLIRInstruction {
+
+        private final Kind kind;
+        @Def({REG}) protected AllocatableValue result;
+        @Use({COMPOSITE}) protected SPARCAddressValue address;
+        @State protected LIRFrameState state;
+
+        public LoadOp(Kind kind, AllocatableValue result, SPARCAddressValue address, LIRFrameState state) {
+            this.kind = kind;
+            this.result = result;
+            this.address = address;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            @SuppressWarnings("unused") SPARCAddress addr = address.toAddress();
+            switch (kind) {
+                case Byte:
+                    // masm.ld_global_s8(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Short:
+                    // masm.ld_global_s16(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Char:
+                    // masm.ld_global_u16(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Int:
+                    // masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Long:
+                    // masm.ld_global_s64(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Float:
+                    // masm.ld_global_f32(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Double:
+                    // masm.ld_global_f64(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                case Object:
+                    // masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    public static class StoreOp extends SPARCLIRInstruction {
+
+        private final Kind kind;
+        @Use({COMPOSITE}) protected SPARCAddressValue address;
+        @Use({REG}) protected AllocatableValue input;
+        @State protected LIRFrameState state;
+
+        public StoreOp(Kind kind, SPARCAddressValue address, AllocatableValue input, LIRFrameState state) {
+            this.kind = kind;
+            this.address = address;
+            this.input = input;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm) {
+            assert isRegister(input);
+            @SuppressWarnings("unused") SPARCAddress addr = address.toAddress();
+            switch (kind) {
+                case Byte:
+                    // masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Short:
+                    // masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Int:
+                    // masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Long:
+                    // masm.st_global_s64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Float:
+                    // masm.st_global_f32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Double:
+                    // masm.st_global_f64(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                case Object:
+                    // masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind());
+            }
+        }
+    }
+
     @Opcode("MOVE")
     public static class MoveToRegOp extends SPARCLIRInstruction implements MoveOp {
 
--- a/make/build-graal.xml	Sun May 26 22:49:23 2013 +0200
+++ b/make/build-graal.xml	Sun May 26 18:16:28 2013 -0400
@@ -60,6 +60,7 @@
       <src path="${src.dir}/com.oracle.graal.replacements.amd64"/>
       <src path="${src.dir}/com.oracle.graal.hotspot.amd64"/>
       <src path="${src.dir}/com.oracle.graal.asm.sparc"/>
+      <src path="${src.dir}/com.oracle.graal.sparc"/>
       <src path="${src.dir}/com.oracle.graal.lir.sparc"/>
       <src path="${src.dir}/com.oracle.graal.compiler.sparc"/>
       <src path="${src.dir}/com.oracle.graal.hotspot.sparc"/>
--- a/mx/projects	Sun May 26 22:49:23 2013 +0200
+++ b/mx/projects	Sun May 26 18:16:28 2013 -0400
@@ -188,7 +188,7 @@
 # graal.lir.sparc
 project@com.oracle.graal.lir.sparc@subDir=graal
 project@com.oracle.graal.lir.sparc@sourceDirs=src
-project@com.oracle.graal.lir.sparc@dependencies=com.oracle.graal.asm.sparc
+project@com.oracle.graal.lir.sparc@dependencies=com.oracle.graal.asm.sparc,com.oracle.graal.sparc
 project@com.oracle.graal.lir.sparc@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.lir.sparc@javaCompliance=1.7
 
@@ -316,7 +316,7 @@
 # graal.compiler.sparc.test
 project@com.oracle.graal.compiler.sparc.test@subDir=graal
 project@com.oracle.graal.compiler.sparc.test@sourceDirs=src
-project@com.oracle.graal.compiler.sparc.test@dependencies=com.oracle.graal.compiler.sparc,com.oracle.graal.compiler.test,com.oracle.graal.sparc
+project@com.oracle.graal.compiler.sparc.test@dependencies=com.oracle.graal.compiler.sparc,com.oracle.graal.compiler.test
 project@com.oracle.graal.compiler.sparc.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.sparc.test@javaCompliance=1.7