# HG changeset patch # User twisti # Date 1398301961 36000 # Node ID 109d6c7c40b53f9b2b1c156aa63d9bcd0820456d # Parent 8065d79ccd49ce249901f860c090b2e41ce5075e implement SPARC uncommon trap stub diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java Wed Apr 23 15:12:41 2014 -1000 @@ -30,11 +30,6 @@ public class SPARCAddress extends AbstractAddress { - /** - * Stack bias for stack and frame pointer loads. - */ - private static final int STACK_BIAS = 0x7ff; - private final Register base; private final Register index; private final int displacement; @@ -42,7 +37,7 @@ /** * Creates an {@link SPARCAddress} with given base register, no scaling and a given * displacement. - * + * * @param base the base register * @param displacement the displacement */ @@ -54,7 +49,7 @@ /** * Creates an {@link SPARCAddress} with given base register, no scaling and a given index. - * + * * @param base the base register * @param index the index register */ @@ -113,7 +108,7 @@ /** * This method adds the stack-bias to the displacement if the base register is either * {@link SPARC#sp} or {@link SPARC#fp}. - * + * * @return Optional additive displacement. */ public int getDisplacement() { diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Wed Apr 23 15:12:41 2014 -1000 @@ -37,7 +37,7 @@ /** * Constructs an assembler for the SPARC architecture. - * + * * @param registerConfig the register configuration used to bind {@link Register#Frame} and * {@link Register#CallerFrame} to physical registers. This value can be null if this * assembler instance will not be used to assemble instructions using these logical @@ -50,7 +50,7 @@ // @formatter:off /** * Instruction format for sethi. - * + * * | 00 | rd | op2 | imm22 | * |31 30|29 25|24 22|21 0| */ @@ -123,7 +123,7 @@ // @formatter:off /** * Instruction format for branches. - * + * * | 00 |a | cond | op2 | disp22 | * |31 30|29|28 25|24 22|21 0| */ @@ -142,7 +142,7 @@ // @formatter:off /** * Instruction format for conditional branches. - * + * * | 00 |a | cond | op2 |cc1|cc0|p | disp19 | * |31 30|29|28 25|24 22|21 |20 |19| 0| */ @@ -330,7 +330,7 @@ // @formatter:off /** * Instruction format for calls. - * + * * | 01 | disp30 | * |31 30|29 0| */ @@ -457,7 +457,7 @@ // @formatter:off /** * Instruction format for Arithmetic, Logical, Moves, Tcc, Prefetch, and Misc. - * + * * | 10 | rd | op3 | rs1 | i| imm_asi | rs2 | * | 10 | rd | op3 | rs1 | i| simm13 | * | 10 | rd | op3 | rs1 | i| x| | rs2 | @@ -594,7 +594,7 @@ // @formatter:off /** * Instruction format for Loads, Stores and Misc. - * + * * | 11 | rd | op3 | rs1 | i| imm_asi | rs2 | * | 11 | rd | op3 | rs1 | i| simm13 | * |31 30|29 25|24 19|18 14|13|12 5|4 0| @@ -749,7 +749,7 @@ // @formatter:off /** * Instruction format for Movcc. - * + * * | 10 | rd | op3 |cc2| cond | i|cc1|cc0| - | rs2 | * | 10 | rd | op3 |cc2| cond | i|cc1|cc0| simm11 | * |31 30|29 25|24 19| 18|17 14|13| 12| 11|10 5|4 0| @@ -1007,7 +1007,7 @@ Wrreg(0x30, "wrreg"), Saved(0x31, "saved"), - Fpop1(0x34, "fpop1"), + Fpop1(0b11_0100, "fpop1"), Fpop2(0x35, "fpop2"), Impdep1(0x36, "impdep1"), Impdep2(0x37, "impdep2"), @@ -1036,14 +1036,14 @@ Ldx(0b001011, "ldx"), Stx(0b001110, "stx"), - Ldf(0x20, "ldf"), + Ldf(0b100000, "ldf"), Ldfsr(0x21, "ldfsr"), Ldaf(0x22, "ldaf"), - Lddf(0x23, "lddf"), - Stf(0x24, "stf"), + Lddf(0b100011, "lddf"), + Stf(0b100100, "stf"), Stfsr(0x25, "stfsr"), Staf(0x26, "staf"), - Stdf(0x27, "stdf"); + Stdf(0b100111, "stdf"); // @formatter:on @@ -1092,9 +1092,9 @@ public enum Opfs { // @formatter:off - Fmovs(0x01, "fmovs"), - Fmovd(0x02, "fmovd"), - Fmovq(0x03, "fmovq"), + Fmovs(0b0_0000_0001, "fmovs"), + Fmovd(0b0_0000_0010, "fmovd"), + Fmovq(0b0_0000_0011, "fmovq"), Fnegs(0x05, "fnegs"), Fnegd(0x06, "fnegd"), Fnegq(0x07, "fnegq"), @@ -2376,6 +2376,20 @@ } } + public static class Fmovs extends Fmt3p { + + public Fmovs(Register src, Register dst) { + super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmovs, g0, src, dst); + } + } + + public static class Fmovd extends Fmt3p { + + public Fmovd(Register src, Register dst) { + super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fmovd, g0, src, dst); + } + } + public static class Fmuls extends Fmt3p { public Fmuls(Register src1, Register src2, Register dst) { @@ -3174,6 +3188,20 @@ } } + public static class Stdf extends Fmt11 { + + public Stdf(Register dst, SPARCAddress src) { + super(Op3s.Stdf, src, dst); + } + } + + public static class Stf extends Fmt11 { + + public Stf(Register dst, SPARCAddress src) { + super(Op3s.Stf, src, dst); + } + } + public static class Sth extends Fmt11 { public Sth(Register dst, SPARCAddress addr) { diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Wed Apr 23 15:12:41 2014 -1000 @@ -27,7 +27,9 @@ import static com.oracle.graal.lir.sparc.SPARCArithmetic.*; import static com.oracle.graal.lir.sparc.SPARCBitManipulationOp.IntrinsicOpcode.*; import static com.oracle.graal.lir.sparc.SPARCCompare.*; +import static com.oracle.graal.lir.sparc.SPARCControlFlow.*; import static com.oracle.graal.lir.sparc.SPARCMathIntrinsicOp.IntrinsicOpcode.*; +import static com.oracle.graal.lir.sparc.SPARCMove.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -40,25 +42,6 @@ import com.oracle.graal.lir.StandardOp.JumpOp; import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryCommutative; -import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegConst; -import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegReg; -import com.oracle.graal.lir.sparc.SPARCArithmetic.Op1Stack; -import com.oracle.graal.lir.sparc.SPARCArithmetic.Op2Stack; -import com.oracle.graal.lir.sparc.SPARCArithmetic.RemOp; -import com.oracle.graal.lir.sparc.SPARCArithmetic.Unary2Op; -import com.oracle.graal.lir.sparc.SPARCCompare.CompareOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.BranchOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.CondMoveOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.FloatCondMoveOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.StrategySwitchOp; -import com.oracle.graal.lir.sparc.SPARCControlFlow.TableSwitchOp; -import com.oracle.graal.lir.sparc.SPARCMove.LoadAddressOp; -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.StackLoadAddressOp; import com.oracle.graal.phases.util.*; /** @@ -129,7 +112,7 @@ @Override public void emitData(AllocatableValue dst, byte[] data) { - throw GraalInternalError.unimplemented(); + append(new LoadDataAddressOp(dst, data)); } @Override @@ -156,7 +139,7 @@ indexRegister = Value.ILLEGAL; } else { if (scale != 1) { - Value longIndex = emitSignExtend(index, 32, 64); + Value longIndex = index.getKind() == Kind.Long ? index : emitSignExtend(index, 32, 64); if (CodeUtil.isPowerOf2(scale)) { indexRegister = emitShl(longIndex, Constant.forLong(CodeUtil.log2(scale))); } else { @@ -184,16 +167,20 @@ // 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; + assert SPARCAssembler.isSimm13(displacementInt) : displacementInt; } else { displacementInt = 0; if (baseRegister.equals(Value.ILLEGAL)) { baseRegister = load(Constant.forLong(finalDisp)); } else { - Variable longBaseRegister = newVariable(Kind.Long); - emitMove(longBaseRegister, baseRegister); // FIXME get rid of this move - baseRegister = emitAdd(longBaseRegister, Constant.forLong(finalDisp)); + if (finalDisp == 0) { + // Nothing to do. Just use the base register. + } else { + Variable longBaseRegister = newVariable(Kind.Long); + emitMove(longBaseRegister, baseRegister); + baseRegister = emitAdd(longBaseRegister, Constant.forLong(finalDisp)); + } } } @@ -282,15 +269,16 @@ Condition finalCondition = mirrored ? cond.mirror() : cond; Variable result = newVariable(trueValue.getKind()); - switch (left.getKind().getStackKind()) { + Kind kind = left.getKind().getStackKind(); + switch (kind) { case Int: case Long: case Object: - append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue))); + append(new CondMoveOp(kind, result, finalCondition, load(trueValue), loadNonConst(falseValue))); break; case Float: case Double: - append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); + append(new FloatCondMoveOp(kind, result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); break; default: throw GraalInternalError.shouldNotReachHere("" + left.getKind()); @@ -345,7 +333,8 @@ public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { emitIntegerTest(left, right); Variable result = newVariable(trueValue.getKind()); - append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue))); + Kind kind = left.getKind().getStackKind(); + append(new CondMoveOp(kind, result, Condition.EQ, load(trueValue), loadNonConst(falseValue))); return result; } @@ -811,22 +800,23 @@ return inputVal; } else if (toBits > 32) { // sign extend to 64 bits - if (fromBits == 32) { - return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal)); - } else if (fromBits < 32) { - // TODO implement direct x2L sign extension conversions - Value intVal = emitSignExtend(inputVal, fromBits, 32); - return emitSignExtend(intVal, 32, toBits); - } else { - throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); + switch (fromBits) { + case 8: + return emitConvert2Op(Kind.Long, B2L, asAllocatable(inputVal)); + case 16: + return emitConvert2Op(Kind.Long, S2L, asAllocatable(inputVal)); + case 32: + return emitConvert2Op(Kind.Long, I2L, asAllocatable(inputVal)); + default: + throw GraalInternalError.unimplemented("unsupported sign extension (" + fromBits + " bit -> " + toBits + " bit)"); } } else { // sign extend to 32 bits (smaller values are internally represented as 32 bit values) switch (fromBits) { case 8: - return emitConvert2Op(Kind.Int, I2B, asAllocatable(inputVal)); + return emitConvert2Op(Kind.Int, B2I, asAllocatable(inputVal)); case 16: - return emitConvert2Op(Kind.Int, I2S, asAllocatable(inputVal)); + return emitConvert2Op(Kind.Int, S2I, asAllocatable(inputVal)); case 32: return inputVal; default: diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizationStub.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizationStub.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizationStub.java Wed Apr 23 15:12:41 2014 -1000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -35,11 +35,14 @@ public SPARCDeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { super(providers, target, linkage); - registerConfig = new SPARCHotSpotRegisterConfig(target, new Register[]{o0, o1, o2, o3, o4, o5, o7, l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, f0, f1, f2, f3, f4, f5, f6, f7}); + // This is basically the maximum we can spare. All other G and O register are used. + Register[] allocatable = new Register[]{g1, g3, g4, g5, o0, o1, o2, o3, o4}; + registerConfig = new SPARCHotSpotRegisterConfig(target, allocatable); } @Override public RegisterConfig getRegisterConfig() { return registerConfig; } + } diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Wed Apr 23 15:12:41 2014 -1000 @@ -83,6 +83,11 @@ } @Override + public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) { + return new SPARCHotSpotLIRGenerationResult(lir, frameMap, stub); + } + + @Override public NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen) { return new SPARCHotSpotNodeLIRBuilder(graph, lirGen); } @@ -190,11 +195,6 @@ } @Override - public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) { - return new LIRGenerationResultBase(lir, frameMap); - } - - @Override public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm; FrameMap frameMap = crb.frameMap; diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java Wed Apr 23 15:12:41 2014 -1000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -48,9 +48,8 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - // Save last Java frame. - new Add(stackPointer, new SPARCAddress(stackPointer, 0).getDisplacement(), g4).emit(masm); + new Add(stackPointer, STACK_BIAS, g4).emit(masm); new Stx(g4, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm); // Save the thread register when calling out to the runtime. diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java Wed Apr 23 15:12:41 2014 -1000 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, 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.asm.sparc.SPARCMacroAssembler.*; +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.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.asm.*; + +/** + * Emits code that enters a stack frame which is tailored to call the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") +final class SPARCHotSpotEnterUnpackFramesStackFrameOp extends SPARCLIRInstruction { + + private final Register thread; + private final int threadLastJavaSpOffset; + private final int threadLastJavaPcOffset; + @Alive(REG) AllocatableValue framePc; + @Alive(REG) AllocatableValue senderSp; + @Temp(REG) AllocatableValue scratch; + + SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch) { + this.thread = thread; + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.threadLastJavaPcOffset = threadLastJavaPcOffset; + this.framePc = framePc; + this.senderSp = senderSp; + this.scratch = scratch; + } + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + final int totalFrameSize = crb.frameMap.totalFrameSize(); + Register framePcRegister = asRegister(framePc); + Register senderSpRegister = asRegister(senderSp); + Register scratchRegister = asRegister(scratch); + + // Save final sender SP to O5_savedSP. + new Mov(senderSpRegister, o5).emit(masm); + + // Load final frame PC. + new Mov(framePcRegister, o7).emit(masm); + + // Allocate a full sized frame. + new Save(sp, -totalFrameSize, sp).emit(masm); + + new Mov(i0, o0).emit(masm); + new Mov(i1, o1).emit(masm); + new Mov(i2, o2).emit(masm); + new Mov(i3, o3).emit(masm); + new Mov(i4, o4).emit(masm); + + // Set up last Java values. + new Add(sp, STACK_BIAS, scratchRegister).emit(masm); + new Stx(scratchRegister, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm); + + // Clear last Java PC. + new Stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)).emit(masm); + + /* + * Safe thread register manually since we are not using LEAF_SP for {@link + * DeoptimizationStub#UNPACK_FRAMES}. + */ + new Mov(thread, l7).emit(masm); + } +} diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java Wed Apr 23 15:12:41 2014 -1000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -22,14 +22,49 @@ */ package com.oracle.graal.hotspot.sparc; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.gen.*; -public interface SPARCHotSpotLIRGenerationResult extends LIRGenerationResult { +public class SPARCHotSpotLIRGenerationResult extends LIRGenerationResultBase { + + /** + * The slot reserved for storing the original return address when a frame is marked for + * deoptimization. The return address slot in the callee is overwritten with the address of a + * deoptimization stub. + */ + private StackSlot deoptimizationRescueSlot; + private final Object stub; + + /** + * Map from debug infos that need to be updated with callee save information to the operations + * that provide the information. + */ + private Map calleeSaveInfo = new HashMap<>(); - StackSlot getDeoptimizationRescueSlot(); + public SPARCHotSpotLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) { + super(lir, frameMap); + this.stub = stub; + } + + StackSlot getDeoptimizationRescueSlot() { + return deoptimizationRescueSlot; + } - Stub getStub(); + public final void setDeoptimizationRescueSlot(StackSlot deoptimizationRescueSlot) { + this.deoptimizationRescueSlot = deoptimizationRescueSlot; + } + + Stub getStub() { + return (Stub) stub; + } + + Map getCalleeSaveInfo() { + return calleeSaveInfo; + } } diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Wed Apr 23 15:12:41 2014 -1000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -24,6 +24,8 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.nodes.UncommonTrapCallNode.*; +import static com.oracle.graal.sparc.SPARC.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -264,38 +266,78 @@ throw GraalInternalError.unimplemented(); } + /** + * @param savedRegisters the registers saved by this operation which may be subject to pruning + * @param savedRegisterLocations the slots to which the registers are saved + * @param supportsRemove determines if registers can be pruned + */ + protected SPARCSaveRegistersOp emitSaveRegisters(Register[] savedRegisters, StackSlot[] savedRegisterLocations, boolean supportsRemove) { + SPARCSaveRegistersOp save = new SPARCSaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove); + append(save); + return save; + } + public SaveRegistersOp emitSaveAllRegisters() { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + // We save all registers that were not saved by the save instruction. + // @formatter:off + Register[] savedRegisters = { + // CPU + g1, g3, g4, g5, + // FPU + f0, f1, f2, f3, f4, f5, f6, f7, + f8, f9, f10, f11, f12, f13, f14, f15, + f16, f17, f18, f19, f20, f21, f22, f23, + f24, f25, f26, f27, f28, f29, f30, f31 + }; + // @formatter:on + StackSlot[] savedRegisterLocations = new StackSlot[savedRegisters.length]; + for (int i = 0; i < savedRegisters.length; i++) { + PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); + assert kind != Kind.Illegal; + StackSlot spillSlot = getResult().getFrameMap().allocateSpillSlot(kind); + savedRegisterLocations[i] = spillSlot; + } + return emitSaveRegisters(savedRegisters, savedRegisterLocations, false); } public void emitLeaveCurrentStackFrame() { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + append(new SPARCHotSpotLeaveCurrentStackFrameOp()); } public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + append(new SPARCHotSpotLeaveDeoptimizedStackFrameOp()); } public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + Register thread = getProviders().getRegisters().getThreadRegister(); + Variable framePcVariable = load(framePc); + Variable senderSpVariable = load(senderSp); + Variable scratchVariable = newVariable(getHostWordKind()); + append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable)); } public void emitLeaveUnpackFramesStackFrame() { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + Register thread = getProviders().getRegisters().getThreadRegister(); + append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset())); } public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + Variable frameSizeVariable = load(frameSize); + Variable framePcVariable = load(framePc); + Variable senderSpVariable = load(senderSp); + Variable initialInfoVariable = load(initialInfo); + append(new SPARCHotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable)); } public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) { - // TODO Auto-generated method stub - throw GraalInternalError.unimplemented(); + ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); + + Register threadRegister = getProviders().getRegisters().getThreadRegister(); + Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); + append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister)); + Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(Kind.Long), trapRequest); + append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister)); + + return result; } } diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java Wed Apr 23 15:12:41 2014 -1000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, 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 com.oracle.graal.asm.sparc.*; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pops the current frame off the stack. + */ +@Opcode("LEAVE_CURRENT_STACK_FRAME") +final class SPARCHotSpotLeaveCurrentStackFrameOp extends SPARCHotSpotEpilogueOp { + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + // Save O registers over restore. + new Mov(o0, i0).emit(masm); + new Mov(o1, i1).emit(masm); + new Mov(o2, i2).emit(masm); + new Mov(o3, i3).emit(masm); + new Mov(o4, i4).emit(masm); + + leaveFrame(crb); + } +} diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java Wed Apr 23 15:12:41 2014 -1000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, 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 com.oracle.graal.asm.sparc.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pops the current frame off the stack including the return address. + */ +@Opcode("LEAVE_DEOPTIMIZED_STACK_FRAME") +final class SPARCHotSpotLeaveDeoptimizedStackFrameOp extends SPARCHotSpotEpilogueOp { + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + // Save O registers over restore. + new Mov(o0, i0).emit(masm); + new Mov(o1, i1).emit(masm); + new Mov(o2, i2).emit(masm); + new Mov(o3, i3).emit(masm); + new Mov(o4, i4).emit(masm); + + new RestoreWindow().emit(masm); + } +} diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java Wed Apr 23 15:12:41 2014 -1000 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014, 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 com.oracle.graal.api.code.*; +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.asm.*; + +/** + * Emits code that leaves a stack frame which is tailored to call the C++ method + * {@link DeoptimizationStub#UNPACK_FRAMES Deoptimization::unpack_frames}. + */ +@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") +final class SPARCHotSpotLeaveUnpackFramesStackFrameOp extends SPARCLIRInstruction { + + private final Register thread; + private final int threadLastJavaSpOffset; + private final int threadLastJavaPcOffset; + private final int threadJavaFrameAnchorFlagsOffset; + + SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset) { + this.thread = thread; + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.threadLastJavaPcOffset = threadLastJavaPcOffset; + this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset; + } + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + /* + * Safe thread register manually since we are not using LEAF_SP for {@link + * DeoptimizationStub#UNPACK_FRAMES}. + */ + new Mov(l7, thread).emit(masm); + + // Clear last Java frame values. + new Stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm); + new Stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)).emit(masm); + new Stw(g0, new SPARCAddress(thread, threadJavaFrameAnchorFlagsOffset)).emit(masm); + } +} diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPushInterpreterFrameOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPushInterpreterFrameOp.java Wed Apr 23 15:12:41 2014 -1000 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013, 2014, 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.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.sparc.*; +import com.oracle.graal.lir.asm.*; + +/** + * Pushes an interpreter frame to the stack. + */ +@Opcode("PUSH_INTERPRETER_FRAME") +final class SPARCHotSpotPushInterpreterFrameOp extends SPARCLIRInstruction { + + @Alive(REG) AllocatableValue frameSize; + @Alive(REG) AllocatableValue framePc; + @Alive(REG) AllocatableValue senderSp; + @Alive(REG) AllocatableValue initialInfo; + + SPARCHotSpotPushInterpreterFrameOp(AllocatableValue frameSize, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue initialInfo) { + this.frameSize = frameSize; + this.framePc = framePc; + this.senderSp = senderSp; + this.initialInfo = initialInfo; + } + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + final Register frameSizeRegister = asRegister(frameSize); + final Register framePcRegister = asRegister(framePc); + final Register senderSpRegister = asRegister(senderSp); + + // Save sender SP to O5_savedSP. + new Mov(senderSpRegister, o5).emit(masm); + + new Neg(frameSizeRegister).emit(masm); + new Save(sp, frameSizeRegister, sp).emit(masm); + + new Mov(i0, o0).emit(masm); + new Mov(i1, o1).emit(masm); + new Mov(i2, o2).emit(masm); + new Mov(i3, o3).emit(masm); + new Mov(i4, o4).emit(masm); + + // NOTE: Don't touch I5 as it contains valuable saved SP! + + // Move frame's new PC into i7 + new Mov(framePcRegister, i7).emit(masm); + } +} diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Wed Apr 23 15:12:41 2014 -1000 @@ -98,25 +98,27 @@ private static Register[] initAllocatable(boolean reserveForHeapBase) { Register[] registers = null; - // @formatter:off if (reserveForHeapBase) { - registers = new Register[] { + // @formatter:off + registers = new Register[]{ // 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 - }; + }; + // @formatter:on } else { - registers = new Register[] { + // @formatter:off + registers = new Register[]{ // 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 - }; + }; + // @formatter:on } - // @formatter:on if (RegisterPressure.getValue() != null) { String[] names = RegisterPressure.getValue().split(","); diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Apr 23 15:12:41 2014 -1000 @@ -794,6 +794,7 @@ // offsets, ... @HotSpotVMFlag(name = "StackShadowPages") @Stable public int stackShadowPages; @HotSpotVMFlag(name = "UseStackBanging") @Stable public boolean useStackBanging; + @HotSpotVMConstant(name = "STACK_BIAS") @Stable public int stackBias; @HotSpotVMField(name = "oopDesc::_mark", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int markOffset; @HotSpotVMField(name = "oopDesc::_metadata._klass", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int hubOffset; diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Wed Apr 23 15:12:41 2014 -1000 @@ -119,7 +119,14 @@ registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); registerForeignCall(UNCOMMON_TRAP, c.deoptimizationUncommonTrap, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + + /* + * We cannot use LEAF_SP here because on some architectures we have to align the stack + * manually before calling into the VM. See {@link + * AMD64HotSpotEnterUnpackFramesStackFrameOp#emitCode}. + */ registerForeignCall(UNPACK_FRAMES, c.deoptimizationUnpackFrames, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); link(new NewInstanceStub(providers, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Wed Apr 23 15:12:41 2014 -1000 @@ -126,8 +126,8 @@ // Pop all the frames we must move/replace. // // Frame picture (youngest to oldest) - // 1: self-frame (no frame link) - // 2: deoptimizing frame (no frame link) + // 1: self-frame + // 2: deoptimizing frame // 3: caller of deoptimizing frame (could be compiled/interpreted). // Pop self-frame. @@ -136,7 +136,7 @@ // Load the initial info we should save (e.g. frame pointer). final Word initialInfo = unrollBlock.readWord(deoptimizationUnrollBlockInitialInfoOffset()); - // Pop deoptimized frame + // Pop deoptimized frame. final int sizeOfDeoptimizedFrame = unrollBlock.readInt(deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset()); LeaveDeoptimizedStackFrameNode.leaveDeoptimizedStackFrame(sizeOfDeoptimizedFrame, initialInfo); @@ -144,13 +144,15 @@ * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for * total size of the interpreter frames plus shadow page size. Bang one page at a time * because large sizes can bang beyond yellow and red zones. + * + * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository. */ final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset()); final int bangPages = NumUtil.roundUp(totalFrameSizes, pageSize()) / pageSize() + stackShadowPages(); Word stackPointer = readRegister(stackPointerRegister); for (int i = 1; i < bangPages; i++) { - stackPointer.writeInt(-(i * pageSize()), i); + stackPointer.writeInt((-i * pageSize()) + stackBias(), 0); } // Load number of interpreter frames. @@ -221,6 +223,19 @@ return config().useStackBanging ? config().stackShadowPages : 0; } + /** + * Returns the stack bias for the host architecture. + * + * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository. + * + * @return stack bias + */ + @Deprecated + @Fold + private static int stackBias() { + return config().stackBias; + } + @Fold private static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { return config().deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Wed Apr 23 15:12:41 2014 -1000 @@ -68,7 +68,7 @@ FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR, DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR, INEG, LNEG, FNEG, DNEG, INOT, LNOT, - I2L, L2I, I2B, I2C, I2S, + L2I, B2I, S2I, B2L, S2L, I2L, F2D, D2F, I2F, I2D, F2I, D2I, L2F, L2D, F2L, D2L, @@ -572,11 +572,11 @@ case L2I: new Signx(asLongReg(src), asIntReg(dst)).emit(masm); break; - case I2B: + case B2I: new Sll(asIntReg(src), 24, asIntReg(dst)).emit(masm); new Srl(asIntReg(dst), 24, asIntReg(dst)).emit(masm); break; - case I2C: + case S2I: new Sll(asIntReg(src), 16, asIntReg(dst)).emit(masm); new Srl(asIntReg(dst), 16, asIntReg(dst)).emit(masm); break; diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Wed Apr 23 15:12:41 2014 -1000 @@ -270,13 +270,16 @@ @Opcode("CMOVE") public static class CondMoveOp extends SPARCLIRInstruction { + private final Kind kind; + @Def({REG, HINT}) protected Value result; @Alive({REG}) protected Value trueValue; @Use({REG, STACK, CONST}) protected Value falseValue; private final ConditionFlag condition; - public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) { + public CondMoveOp(Kind kind, Variable result, Condition condition, Variable trueValue, Value falseValue) { + this.kind = kind; this.result = result; this.condition = intCond(condition); this.trueValue = trueValue; @@ -285,20 +288,28 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - cmove(crb, masm, result, false, condition, false, trueValue, falseValue); + // check that we don't overwrite an input operand before it is used. + assert !result.equals(trueValue); + + SPARCMove.move(crb, masm, result, falseValue); + cmove(crb, masm, kind, result, condition, trueValue); } } @Opcode("CMOVE") public static class FloatCondMoveOp extends SPARCLIRInstruction { + private final Kind kind; + @Def({REG}) protected Value result; @Alive({REG}) protected Value trueValue; @Alive({REG}) protected Value falseValue; + private final ConditionFlag condition; private final boolean unorderedIsTrue; - public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { + public FloatCondMoveOp(Kind kind, Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) { + this.kind = kind; this.result = result; this.condition = floatCond(condition); this.unorderedIsTrue = unorderedIsTrue; @@ -308,18 +319,12 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - cmove(crb, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue); - } - } + // check that we don't overwrite an input operand before it is used. + assert !result.equals(trueValue); - private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, boolean isFloat, ConditionFlag condition, boolean unorderedIsTrue, Value trueValue, Value falseValue) { - // check that we don't overwrite an input operand before it is used. - assert !result.equals(trueValue); + SPARCMove.move(crb, masm, result, falseValue); + cmove(crb, masm, kind, result, condition, trueValue); - SPARCMove.move(crb, masm, result, falseValue); - cmove(crb, masm, result, condition, trueValue); - - if (isFloat) { if (unorderedIsTrue && !trueOnUnordered(condition)) { // cmove(crb, masm, result, ConditionFlag.Parity, trueValue); throw GraalInternalError.unimplemented(); @@ -330,18 +335,20 @@ } } - private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, ConditionFlag cond, Value other) { + private static void cmove(CompilationResultBuilder crb, SPARCMacroAssembler masm, Kind kind, Value result, ConditionFlag cond, Value other) { if (!isRegister(other)) { SPARCMove.move(crb, masm, result, other); - throw new InternalError("result should be scratch"); + throw GraalInternalError.shouldNotReachHere("result should be scratch"); } assert !asRegister(other).equals(asRegister(result)) : "other already overwritten by previous move"; - switch (other.getKind()) { + switch (kind) { case Int: - // XXX CC depends on compare new Movcc(cond, CC.Icc, asRegister(other), asRegister(result)).emit(masm); break; case Long: + case Object: + new Movcc(cond, CC.Xcc, asRegister(other), asRegister(result)).emit(masm); + break; default: throw GraalInternalError.shouldNotReachHere(); } diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java Wed Apr 23 22:37:18 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java Wed Apr 23 15:12:41 2014 -1000 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; import com.oracle.graal.lir.*; /** @@ -33,7 +34,7 @@ * *
  *   Base       Contents
- *
+ * 
  *            :                                :  -----
  *   caller   | incoming overflow argument n   |    ^
  *   frame    :     ...                        :    | positive
@@ -88,8 +89,7 @@
 
     @Override
     protected int alignFrameSize(int size) {
-        int x = size + (target.stackAlignment - 1);
-        return (x / target.stackAlignment) * target.stackAlignment;
+        return NumUtil.roundUp(size, target.stackAlignment);
     }
 
     @Override
diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Wed Apr 23 22:37:18 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Wed Apr 23 15:12:41 2014 -1000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -23,32 +23,14 @@
 package com.oracle.graal.lir.sparc;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CompilationResult.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Add;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Lddf;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldf;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsb;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsh;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Lduh;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Membar;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Rdpc;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stb;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Sth;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Stx;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cas;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Casx;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Clr;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setuw;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
@@ -154,32 +136,33 @@
 
         @Override
         public void emitMemAccess(SPARCMacroAssembler masm) {
-            SPARCAddress addr = address.toAddress();
+            final SPARCAddress addr = address.toAddress();
+            final Register dst = asRegister(result);
             switch (kind) {
                 case Boolean:
                 case Byte:
-                    new Ldsb(addr, asRegister(result)).emit(masm);
+                    new Ldsb(addr, dst).emit(masm);
                     break;
                 case Short:
-                    new Ldsh(addr, asRegister(result)).emit(masm);
+                    new Ldsh(addr, dst).emit(masm);
                     break;
                 case Char:
-                    new Lduh(addr, asRegister(result)).emit(masm);
+                    new Lduh(addr, dst).emit(masm);
                     break;
                 case Int:
-                    new Ldsw(addr, asRegister(result)).emit(masm);
+                    new Ldsw(addr, dst).emit(masm);
                     break;
                 case Long:
-                    new Ldx(addr, asRegister(result)).emit(masm);
+                    new Ldx(addr, dst).emit(masm);
                     break;
                 case Float:
-                    new Ldf(addr, asRegister(result)).emit(masm);
+                    new Ldf(addr, dst).emit(masm);
                     break;
                 case Double:
-                    new Lddf(addr, asRegister(result)).emit(masm);
+                    new Lddf(addr, dst).emit(masm);
                     break;
                 case Object:
-                    new Ldx(addr, asRegister(result)).emit(masm);
+                    new Ldx(addr, dst).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -208,6 +191,26 @@
         }
     }
 
+    public static class LoadDataAddressOp extends SPARCLIRInstruction {
+
+        @Def({REG}) protected AllocatableValue result;
+        private final byte[] data;
+
+        public LoadDataAddressOp(AllocatableValue result, byte[] data) {
+            this.result = result;
+            this.data = data;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            RawData rawData = new RawData(data, 16);
+            SPARCAddress addr = (SPARCAddress) crb.recordDataReferenceInCode(rawData);
+            assert addr == masm.getPlaceholder();
+            final boolean forceRelocatable = true;
+            new Setx(0, asRegister(result), forceRelocatable).emit(masm);
+        }
+    }
+
     public static class MembarOp extends SPARCLIRInstruction {
 
         private final int barriers;
@@ -395,19 +398,25 @@
     }
 
     private static void reg2reg(SPARCAssembler masm, Value result, Value input) {
-        if (asRegister(input).equals(asRegister(result))) {
+        final Register src = asRegister(input);
+        final Register dst = asRegister(result);
+        if (src.equals(dst)) {
             return;
         }
         switch (input.getKind()) {
             case Int:
             case Long:
             case Object:
-                new Mov(asRegister(input), asRegister(result)).emit(masm);
+                new Mov(src, dst).emit(masm);
                 break;
             case Float:
+                new Fmovs(src, dst).emit(masm);
+                break;
             case Double:
+                new Fmovd(src, dst).emit(masm);
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
+                throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -423,7 +432,11 @@
                 new Stx(src, dst).emit(masm);
                 break;
             case Float:
+                new Stf(src, dst).emit(masm);
+                break;
             case Double:
+                new Stdf(src, dst).emit(masm);
+                break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -461,7 +474,7 @@
                     }
                 }
                 break;
-            case Long: {
+            case Long:
                 if (crb.codeCache.needsDataPatch(input)) {
                     crb.recordInlineDataInCode(input);
                     new Setx(input.asLong(), asRegister(result), true).emit(masm);
@@ -473,8 +486,10 @@
                     }
                 }
                 break;
-            }
-            case Object: {
+            case Float:
+                new Ldf((SPARCAddress) crb.asFloatConstRef(input), asFloatReg(result)).emit(masm);
+                break;
+            case Object:
                 if (input.isNull()) {
                     new Clr(asRegister(result)).emit(masm);
                 } else if (crb.target.inlineObjects) {
@@ -488,7 +503,6 @@
                     throw GraalInternalError.shouldNotReachHere("the patched offset might be too big for the load");
                 }
                 break;
-            }
             default:
                 throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind());
         }
diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java	Wed Apr 23 15:12:41 2014 -1000
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2014, 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 java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Saves registers to stack slots.
+ */
+@Opcode("SAVE_REGISTER")
+public class SPARCSaveRegistersOp extends SPARCLIRInstruction implements SaveRegistersOp {
+
+    /**
+     * The registers (potentially) saved by this operation.
+     */
+    protected final Register[] savedRegisters;
+
+    /**
+     * The slots to which the registers are saved.
+     */
+    @Def(STACK) protected final StackSlot[] slots;
+
+    /**
+     * Specifies if {@link #remove(Set)} should have an effect.
+     */
+    protected final boolean supportsRemove;
+
+    /**
+     *
+     * @param savedRegisters the registers saved by this operation which may be subject to
+     *            {@linkplain #remove(Set) pruning}
+     * @param slots the slots to which the registers are saved
+     * @param supportsRemove determines if registers can be {@linkplain #remove(Set) pruned}
+     */
+    public SPARCSaveRegistersOp(Register[] savedRegisters, StackSlot[] slots, boolean supportsRemove) {
+        this.savedRegisters = savedRegisters;
+        this.slots = slots;
+        this.supportsRemove = supportsRemove;
+    }
+
+    private static void saveRegister(CompilationResultBuilder crb, SPARCMacroAssembler masm, StackSlot result, Register register) {
+        RegisterValue input = register.asValue(result.getKind());
+        SPARCMove.move(crb, masm, result, input);
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        for (int i = 0; i < savedRegisters.length; i++) {
+            if (savedRegisters[i] != null) {
+                saveRegister(crb, masm, slots[i], savedRegisters[i]);
+            }
+        }
+    }
+
+    public StackSlot[] getSlots() {
+        return slots;
+    }
+
+    public boolean supportsRemove() {
+        return supportsRemove;
+    }
+
+    public int remove(Set doNotSave) {
+        if (!supportsRemove) {
+            throw new UnsupportedOperationException();
+        }
+        return prune(doNotSave, savedRegisters);
+    }
+
+    static int prune(Set toRemove, Register[] registers) {
+        int pruned = 0;
+        for (int i = 0; i < registers.length; i++) {
+            if (registers[i] != null) {
+                if (toRemove.contains(registers[i])) {
+                    registers[i] = null;
+                    pruned++;
+                }
+            }
+        }
+        return pruned;
+    }
+
+    public RegisterSaveLayout getMap(FrameMap frameMap) {
+        int total = 0;
+        for (int i = 0; i < savedRegisters.length; i++) {
+            if (savedRegisters[i] != null) {
+                total++;
+            }
+        }
+        Register[] keys = new Register[total];
+        int[] values = new int[total];
+        if (total != 0) {
+            int mapIndex = 0;
+            for (int i = 0; i < savedRegisters.length; i++) {
+                if (savedRegisters[i] != null) {
+                    keys[mapIndex] = savedRegisters[i];
+                    values[mapIndex] = frameMap.indexForStackSlot(slots[i]);
+                    mapIndex++;
+                }
+            }
+            assert mapIndex == total;
+        }
+        return new RegisterSaveLayout(keys, values);
+    }
+}
diff -r 8065d79ccd49 -r 109d6c7c40b5 graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java
--- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Wed Apr 23 22:37:18 2014 +0200
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Wed Apr 23 15:12:41 2014 -1000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -35,28 +35,28 @@
  */
 public class SPARC extends Architecture {
 
-    // @formatter:off
-
     public static final RegisterCategory CPU = new RegisterCategory("CPU");
     public static final RegisterCategory FPU = new RegisterCategory("FPU");
 
     // General purpose registers
-    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 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);
@@ -65,6 +65,7 @@
     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);
@@ -113,12 +114,14 @@
     public static final Register sp = o6;
     public static final Register fp = i6;
 
+    // @formatter:off
     public static final Register[] cpuRegisters = {
         r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
         r8,  r9,  r10, r11, r12, r13, r14, r15,
         r16, r17, r18, r19, r20, r21, r22, r23,
         r24, r25, r26, r27, r28, r29, r30, r31
     };
+    // @formatter:on
 
     // Floating point registers
     public static final Register f0 = new Register(32, 0, "f0", FPU);
@@ -130,6 +133,43 @@
     public static final Register f6 = new Register(38, 6, "f6", FPU);
     public static final Register f7 = new Register(39, 7, "f7", FPU);
 
+    public static final Register f8 = new Register(40, 8, "f8", FPU);
+    public static final Register f9 = new Register(41, 9, "f9", FPU);
+    public static final Register f10 = new Register(42, 10, "f10", FPU);
+    public static final Register f11 = new Register(43, 11, "f11", FPU);
+    public static final Register f12 = new Register(44, 12, "f12", FPU);
+    public static final Register f13 = new Register(45, 13, "f13", FPU);
+    public static final Register f14 = new Register(46, 14, "f14", FPU);
+    public static final Register f15 = new Register(47, 15, "f15", FPU);
+
+    public static final Register f16 = new Register(48, 16, "f16", FPU);
+    public static final Register f17 = new Register(49, 17, "f17", FPU);
+    public static final Register f18 = new Register(50, 18, "f18", FPU);
+    public static final Register f19 = new Register(51, 19, "f19", FPU);
+    public static final Register f20 = new Register(52, 20, "f20", FPU);
+    public static final Register f21 = new Register(53, 21, "f21", FPU);
+    public static final Register f22 = new Register(54, 22, "f22", FPU);
+    public static final Register f23 = new Register(55, 23, "f23", FPU);
+
+    public static final Register f24 = new Register(56, 24, "f24", FPU);
+    public static final Register f25 = new Register(57, 25, "f25", FPU);
+    public static final Register f26 = new Register(58, 26, "f26", FPU);
+    public static final Register f27 = new Register(59, 27, "f27", FPU);
+    public static final Register f28 = new Register(60, 28, "f28", FPU);
+    public static final Register f29 = new Register(61, 29, "f29", FPU);
+    public static final Register f30 = new Register(62, 30, "f30", FPU);
+    public static final Register f31 = new Register(63, 31, "f31", FPU);
+
+    // @formatter:off
+    public static final Register[] fpuRegisters = {
+        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+        f8,  f9,  f10, f11, f12, f13, f14, f15,
+        f16, f17, f18, f19, f20, f21, f22, f23,
+        f24, f25, f26, f27, f28, f29, f30, f31
+    };
+    // @formatter:on
+
+    // @formatter:off
     public static final Register[] allRegisters = {
         // CPU
         r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
@@ -138,9 +178,16 @@
         r24, r25, r26, r27, r28, r29, r30, r31,
         // FPU
         f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+        f8,  f9,  f10, f11, f12, f13, f14, f15,
+        f16, f17, f18, f19, f20, f21, f22, f23,
+        f24, f25, f26, f27, f28, f29, f30, f31
     };
+    // @formatter:on
 
-    // @formatter:on
+    /**
+     * Stack bias for stack and frame pointer loads.
+     */
+    public static final int STACK_BIAS = 0x7ff;
 
     public SPARC() {
         super("SPARC", 8, ByteOrder.BIG_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 1, r31.encoding + 1, 8);