# HG changeset patch # User Stefan Anzinger # Date 1406816953 25200 # Node ID 2f4487a0b588a7c454acca8357ec479352b8bd7a # Parent 62f295bdea36b767c406ddf6e09a7d700b98769d# Parent be59a1d392817608ca4fee2a84f6c541ce584029 Merge diff -r be59a1d39281 -r 2f4487a0b588 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 Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Thu Jul 31 07:29:13 2014 -0700 @@ -63,8 +63,8 @@ protected static final int OP2_SHIFT = 22; // @formatter:off - protected static final int OP_MASK = 0b11000000000000000000000000000000; - protected static final int OP2_MASK = 0b00000001110000000000000000000000; + protected static final int OP_MASK = 0b1100_0000_0000_0000_0000_0000_0000_0000; + protected static final int OP2_MASK = 0b0000_0001_1100_0000_0000_0000_0000_0000; // @formatter:off private int op2; @@ -1264,31 +1264,31 @@ Prefetch(0b101101, "prefetch"), Prefetcha(0b111101, "prefetcha"), - Lduw(0b00000, "lduw"), - Ldub(0b00001, "ldub"), - Lduh(0b00010, "lduh"), - Stw(0b000100, "stw"), - Stb(0b000101, "stb"), - Sth(0b000110, "sth"), - Ldsw(0b001000, "ldsw"), - Ldsb(0b001001, "ldsb"), - Ldsh(0b001010, "ldsh"), - Ldx(0b001011, "ldx"), - Stx(0b001110, "stx"), - - Ldf(0b100000, "ldf"), - Ldfsr(0x21, "ldfsr"), - Ldaf(0x22, "ldaf"), - Lddf(0b100011, "lddf"), - Stf(0b100100, "stf"), - Stfsr(0x25, "stfsr"), - Staf(0x26, "staf"), - Stdf(0b100111, "stdf"), - - Fcmp(0b110101, "fcmp"), - - Ldxa (0b01_1011, "ldxa"), - Lduwa(0b01_0000, "lduwa"); + Lduw (0b00_0000, "lduw"), + Ldub (0b00_0001, "ldub"), + Lduh (0b00_0010, "lduh"), + Stw (0b00_0100, "stw"), + Stb (0b00_0101, "stb"), + Sth (0b00_0110, "sth"), + Ldsw (0b00_1000, "ldsw"), + Ldsb (0b00_1001, "ldsb"), + Ldsh (0b00_1010, "ldsh"), + Ldx (0b00_1011, "ldx"), + Stx (0b00_1110, "stx"), + + Ldf (0b10_0000, "ldf"), + Ldfsr (0b10_0001, "ldfsr"), + Ldaf (0b10_0010, "ldaf"), + Lddf (0b10_0011, "lddf"), + Stf (0b10_0100, "stf"), + Stfsr (0b10_0101, "stfsr"), + Staf (0x10_0110, "staf"), + Stdf (0b10_0111, "stdf"), + + Fcmp (0b11_0101, "fcmp"), + + Ldxa (0b01_1011, "ldxa"), + Lduwa (0b01_0000, "lduwa"); // @formatter:on @@ -3405,6 +3405,10 @@ public Jmpl(Register src, int simm13, Register dst) { super(Op3s.Jmpl, src, simm13, dst); } + + public Jmpl(Register src1, Register src2, Register dst) { + super(Op3s.Jmpl, src1, src2, dst); + } } public static class Lddf extends Fmt11 { @@ -3687,6 +3691,8 @@ public Return(Register src1, Register src2) { super(Op3s.Rett, src1, src2, r0); } + + public static int PC_RETURN_OFFSET = 8; } public static class Save extends Fmt10 { diff -r be59a1d39281 -r 2f4487a0b588 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 Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Thu Jul 31 07:29:13 2014 -0700 @@ -221,7 +221,7 @@ @Override public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { - boolean mirrored = emitCompare(left, right); + boolean mirrored = emitCompare(cmpKind, left, right); Condition finalCondition = mirrored ? cond.mirror() : cond; Kind kind = left.getKind().getStackKind(); switch (kind) { @@ -262,7 +262,7 @@ @Override public Variable emitConditionalMove(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { - boolean mirrored = emitCompare(left, right); + boolean mirrored = emitCompare(cmpKind, left, right); Condition finalCondition = mirrored ? cond.mirror() : cond; Variable result = newVariable(trueValue.getLIRKind()); @@ -287,11 +287,12 @@ * This method emits the compare instruction, and may reorder the operands. It returns true if * it did so. * + * @param cmpKind Kind how a and b have to be compared * @param a the left operand of the comparison * @param b the right operand of the comparison * @return true if the left and right operands were switched, false otherwise */ - protected boolean emitCompare(Value a, Value b) { + protected boolean emitCompare(PlatformKind cmpKind, Value a, Value b) { Variable left; Value right; boolean mirrored; @@ -304,7 +305,14 @@ right = loadNonConst(b); mirrored = false; } - switch (left.getKind().getStackKind()) { + switch ((Kind) cmpKind) { + case Short: + case Char: + append(new CompareOp(ICMP, emitZeroExtend(left, 16, 32), emitZeroExtend(right, 16, 32))); + break; + case Byte: + append(new CompareOp(ICMP, emitZeroExtend(left, 8, 32), emitZeroExtend(right, 8, 32))); + break; case Int: append(new CompareOp(ICMP, left, right)); break; @@ -653,33 +661,36 @@ } @Override - public Value emitUDiv(Value a, Value b, LIRFrameState state) { - // LIRFrameState state = state(deopting); + public Value emitURem(Value a, Value b, LIRFrameState state) { + Variable result = newVariable(LIRKind.derive(a, b)); switch (a.getKind().getStackKind()) { case Int: - // emitDivRem(IUDIV, a, b, state); - // return emitMove(RAX_I); + append(new RemOp(IUREM, result, a, loadNonConst(b), state, this)); + break; case Long: - // emitDivRem(LUDIV, a, b, state); - // return emitMove(RAX_L); + append(new RemOp(LUREM, result, a, loadNonConst(b), state, this)); + break; default: throw GraalInternalError.shouldNotReachHere(); } + return result; + } @Override - public Value emitURem(Value a, Value b, LIRFrameState state) { - // LIRFrameState state = state(deopting); + public Value emitUDiv(Value a, Value b, LIRFrameState state) { + SPARCArithmetic op; switch (a.getKind().getStackKind()) { case Int: - // emitDivRem(IUREM, a, b, state); - // return emitMove(RDX_I); + op = IUDIV; + break; case Long: - // emitDivRem(LUREM, a, b, state); - // return emitMove(RDX_L); + op = LUDIV; + break; default: throw GraalInternalError.shouldNotReachHere(); } + return emitBinary(op, false, a, b, state); } @Override @@ -903,14 +914,16 @@ } else { assert inputVal.getKind() == Kind.Int || inputVal.getKind() == Kind.Short || inputVal.getKind() == Kind.Byte : inputVal.getKind(); Variable result = newVariable(LIRKind.derive(inputVal).changeType(Kind.Int)); - int mask = (int) IntegerStamp.defaultMask(fromBits); - Constant constant = Constant.forInt(mask); + long mask = IntegerStamp.defaultMask(fromBits); + Constant constant = Constant.forLong(mask); if (canInlineConstant(constant)) { append(new BinaryRegConst(SPARCArithmetic.IAND, result, asAllocatable(inputVal), constant, null)); + } else if (fromBits == 32) { + append(new ShiftOp(IUSHR, result, inputVal, Constant.forInt(0))); } else { Variable maskVar = newVariable(LIRKind.derive(inputVal).changeType(Kind.Int)); emitMove(maskVar, constant); - append(new BinaryRegReg(IAND, result, maskVar, (inputVal))); + append(new BinaryRegReg(IAND, result, maskVar, asAllocatable(inputVal))); } if (toBits > 32) { Variable longResult = newVariable(LIRKind.derive(inputVal).changeType(Kind.Long)); diff -r be59a1d39281 -r 2f4487a0b588 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 Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Thu Jul 31 07:29:13 2014 -0700 @@ -172,6 +172,7 @@ public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { SPARCHotSpotLIRGenerationResult gen = (SPARCHotSpotLIRGenerationResult) lirGenRes; FrameMap frameMap = gen.getFrameMap(); + LIR lir = gen.getLIR(); assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; Stub stub = gen.getStub(); @@ -186,10 +187,10 @@ } if (stub != null) { - // SPARC stubs always enter a frame which saves the registers. - Set destroyedRegisters = Collections.emptySet(); - Map calleeSaveInfo = Collections.emptyMap(); - updateStub(stub, destroyedRegisters, calleeSaveInfo, frameMap); + // Even on sparc we need to save floating point registers + Set definedRegisters = gatherDefinedRegisters(lir); + Map calleeSaveInfo = gen.getCalleeSaveInfo(); + updateStub(stub, definedRegisters, calleeSaveInfo, frameMap); } return crb; diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java Thu Jul 31 07:29:13 2014 -0700 @@ -22,13 +22,14 @@ */ package com.oracle.graal.hotspot.sparc; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import static com.oracle.graal.sparc.SPARC.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; import com.oracle.graal.asm.sparc.SPARCAssembler.Stw; import com.oracle.graal.asm.sparc.SPARCAssembler.Stx; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; @@ -40,19 +41,21 @@ private final int threadLastJavaPcOffset; private final int threadJavaFrameAnchorFlagsOffset; private final Register thread; + @Use({REG, STACK}) protected Value threadTemp; - public SPARCHotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset, Register thread) { + public SPARCHotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset, Register thread, Value threadTemp) { this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.threadLastJavaPcOffset = threadLastJavaPcOffset; this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset; this.thread = thread; + this.threadTemp = threadTemp; } @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { // Restore the thread register when coming back from the runtime. - new Mov(l7, thread).emit(masm); + SPARCMove.move(crb, masm, thread.asValue(LIRKind.value(Kind.Long)), threadTemp); // Reset last Java frame, last Java PC and flags. new Stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm); diff -r be59a1d39281 -r 2f4487a0b588 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 Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java Thu Jul 31 07:29:13 2014 -0700 @@ -22,13 +22,14 @@ */ package com.oracle.graal.hotspot.sparc; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import static com.oracle.graal.sparc.SPARC.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; import com.oracle.graal.asm.sparc.SPARCAssembler.Add; import com.oracle.graal.asm.sparc.SPARCAssembler.Stx; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; @@ -39,11 +40,13 @@ private final int threadLastJavaSpOffset; private final Register thread; private final Register stackPointer; + @Def({REG, STACK}) protected Value threadTemp; - public SPARCHotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, Register thread, Register stackPointer) { + public SPARCHotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, Register thread, Register stackPointer, Value threadTemp) { this.threadLastJavaSpOffset = threadLastJavaSpOffset; this.thread = thread; this.stackPointer = stackPointer; + this.threadTemp = threadTemp; } @Override @@ -53,6 +56,6 @@ new Stx(g4, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm); // Save the thread register when calling out to the runtime. - new Mov(thread, l7).emit(masm); + SPARCMove.move(crb, masm, threadTemp, thread.asValue(LIRKind.value(Kind.Long))); } } diff -r be59a1d39281 -r 2f4487a0b588 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 Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Thu Jul 31 07:29:13 2014 -0700 @@ -27,6 +27,8 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.sparc.SPARC.*; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; @@ -46,6 +48,7 @@ final HotSpotVMConfig config; private HotSpotLockStack lockStack; + private LIRFrameState currentRuntimeCallInfo; public SPARCHotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) { super(providers, cc, lirGenRes); @@ -90,6 +93,21 @@ } @Override + public void beforeRegisterAllocation() { + super.beforeRegisterAllocation(); + boolean hasDebugInfo = getResult().getLIR().hasDebugInfo(); + if (hasDebugInfo) { + ((SPARCHotSpotLIRGenerationResult) getResult()).setDeoptimizationRescueSlot(getResult().getFrameMap().allocateSpillSlot(LIRKind.value(Kind.Long))); + } + } + + @Override + protected void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { + currentRuntimeCallInfo = info; + super.emitForeignCall(linkage, result, arguments, temps, info); + } + + @Override public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; Variable result; @@ -103,10 +121,11 @@ if (hotspotLinkage.needsJavaFrameAnchor()) { HotSpotRegistersProvider registers = getProviders().getRegisters(); Register thread = registers.getThreadRegister(); + Value threadTemp = newVariable(LIRKind.value(Kind.Long)); Register stackPointer = registers.getStackPointerRegister(); - append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread, stackPointer)); + append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread, stackPointer, threadTemp)); result = super.emitForeignCall(hotspotLinkage, deoptInfo, args); - append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), thread)); + append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), thread, threadTemp)); } else { result = super.emitForeignCall(hotspotLinkage, deoptInfo, args); } @@ -278,10 +297,16 @@ ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); Register threadRegister = getProviders().getRegisters().getThreadRegister(); + Value threadTemp = newVariable(LIRKind.value(Kind.Long)); Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); - append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister)); + append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp)); Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(Kind.Long)), trapRequest); - append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister)); + append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp)); + + Map calleeSaveInfo = ((SPARCHotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo(); + assert currentRuntimeCallInfo != null; + assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); + calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); return result; } @@ -291,10 +316,16 @@ ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(FETCH_UNROLL_INFO); Register threadRegister = getProviders().getRegisters().getThreadRegister(); + Value threadTemp = newVariable(LIRKind.value(Kind.Long)); Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); - append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister)); + append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp)); Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(Kind.Long))); - append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister)); + append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp)); + + Map calleeSaveInfo = ((SPARCHotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo(); + assert currentRuntimeCallInfo != null; + assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); + calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); return result; } diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Thu Jul 31 07:29:13 2014 -0700 @@ -73,7 +73,8 @@ Value offset = operand(x.offset()); Variable cmpValue = (Variable) gen.loadNonConst(operand(x.expectedValue())); Variable newValue = gen.load(operand(x.newValue())); - + Variable newValueTemp = gen.newVariable(newValue.getLIRKind()); + getGen().emitMove(newValueTemp, newValue); LIRKind kind = cmpValue.getLIRKind(); assert kind.equals(newValue.getLIRKind()); @@ -88,8 +89,8 @@ } } - append(new CompareAndSwapOp(address, cmpValue, newValue)); - setResult(x, gen.emitMove(newValue)); + append(new CompareAndSwapOp(address, cmpValue, newValueTemp)); + setResult(x, gen.emitMove(newValueTemp)); } @Override diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java Thu Jul 31 07:29:13 2014 -0700 @@ -26,9 +26,9 @@ import static com.oracle.graal.sparc.SPARC.*; import static com.oracle.graal.api.code.ValueUtil.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import com.oracle.graal.asm.sparc.SPARCAssembler.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; @@ -48,19 +48,7 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - // FIXME This is non-trivial. On SPARC we need to flush all register windows first before we - // can patch the return address (see: frame::patch_pc). - new Flushw().emit(masm); - // int frameSize = crb.frameMap.frameSize(); - // new SPARCAssembler.Ldx(new SPARCAddress(o7, 1), g3).emit(masm); - // new Setx(8 * 15 - 1, g4, false).emit(masm); - new Mov(asLongReg(address), g4).emit(masm); - new Save(sp, -2000, sp).emit(masm); - - new Sub(g4, 0, i7).emit(masm); - new Stx(i7, new SPARCAddress(fp, 8 * 15)).emit(masm); - new Restore(g0, g0, g0).emit(masm); - new Flushw().emit(masm); - // new Ldx(new SPARCAddress(g0, 0x123), g0).emit(masm); + Register addrRegister = asLongReg(address); + new Sub(addrRegister, Return.PC_RETURN_OFFSET, i7).emit(masm); } } diff -r be59a1d39281 -r 2f4487a0b588 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 Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Thu Jul 31 07:29:13 2014 -0700 @@ -59,7 +59,8 @@ for (Register reg : getAllocatableRegisters()) { if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) { // Special treatment for double precision - if (kind == Kind.Double) { + // TODO: This is wasteful it uses only half of the registers as float. + if (kind == Kind.Double || kind == Kind.Float) { // Only even register numbers are valid double precision regs if (reg.number % 2 == 0) { list.add(reg); @@ -235,8 +236,14 @@ } if (locations[i] == null) { + // Stack slot is always aligned to its size in bytes but minimum wordsize + int typeSize = SPARC.spillSlotSize(target, kind); + int modulus = currentStackOffset % typeSize; + if (modulus != 0) { + currentStackOffset += typeSize - modulus; + } locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), currentStackOffset, !type.out); - currentStackOffset += Math.max(target.getSizeInBytes(kind), target.wordSize); + currentStackOffset += typeSize; } } diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Thu Jul 31 07:29:13 2014 -0700 @@ -62,12 +62,12 @@ } public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { - final int pos = masm.position(); new Setx(config.safepointPollingAddress, scratch).emit(masm); MarkId.recordMark(crb, atReturn ? MarkId.POLL_RETURN_FAR : MarkId.POLL_FAR); + final int pos = masm.position(); + new Ldx(new SPARCAddress(scratch, 0), g0).emit(masm); if (state != null) { crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); } - new Ldx(new SPARCAddress(scratch, 0), g0).emit(masm); } } diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java Thu Jul 31 07:29:13 2014 -0700 @@ -24,9 +24,10 @@ import static com.oracle.graal.sparc.SPARC.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.lir.*; @@ -54,7 +55,8 @@ // The mark for an invocation that uses an inline cache must be placed at the // instruction that loads the Klass from the inline cache. MarkId.recordMark(crb, invokeKind == InvokeKind.Virtual ? MarkId.INVOKEVIRTUAL : MarkId.INVOKEINTERFACE); - new Setx(HotSpotGraalRuntime.runtime().getConfig().nonOopBits, g3, true).emit(masm); + Register scratchRegister = g5; + new Setx(HotSpotGraalRuntime.runtime().getConfig().nonOopBits, scratchRegister, true).emit(masm); super.emitCode(crb, masm); } } diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Thu Jul 31 07:29:13 2014 -0700 @@ -253,7 +253,7 @@ // assuming both the stack pointer and page_size have their least // significant 2 bits cleared and page_size is a power of 2 final Word alignedMask = Word.unsigned(wordSize() - 1); - final Word stackPointer = registerAsWord(stackPointerRegister); + final Word stackPointer = registerAsWord(stackPointerRegister).add(config().stackBias); if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) { // Most likely not a recursive lock, go into a slow runtime call traceObject(trace, "+lock{stub:failed-cas}", object, true); diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_irem.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_irem.java Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_irem.java Thu Jul 31 07:29:13 2014 -0700 @@ -34,6 +34,16 @@ return a % b; } + // Left as constant + public static int test2(int b) { + return 13 % b; + } + + // Right as constant + public static int test3(int a) { + return a % 13; + } + @Test public void run0() throws Throwable { runTest("test", 1, 2); @@ -54,4 +64,33 @@ runTest("test", 135, 7); } + @Test + public void run20() throws Throwable { + runTest("test2", 2); + } + + @Test + public void run21() throws Throwable { + runTest("test2", 20000000); + } + + @Test + public void run22() throws Throwable { + runTest("test2", -20000000); + } + + @Test + public void run30() throws Throwable { + runTest("test3", 2); + } + + @Test + public void run31() throws Throwable { + runTest("test3", 200000000); + } + + @Test + public void run32() throws Throwable { + runTest("test3", -200000000); + } } diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigMixedParams04.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigMixedParams04.java Thu Jul 31 07:29:13 2014 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2007, 2012, 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. + */ +/* + * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + */ +package com.oracle.graal.jtt.micro; + +import org.junit.*; + +import com.oracle.graal.jtt.*; + +/** + * Tests different alignment on the stack with extended parameters (index > 5) + */ +public class BigMixedParams04 extends JTTTest { + + @SuppressWarnings("unused") + public static long test(int choice, int i0, int i1, int i2, int i3, double d1, double d2, boolean bo1, boolean bo2, byte by, short sh, char ch, int in) { + switch (choice) { + case 0: + return bo1 ? 1l : 2l; + case 1: + return bo2 ? 1l : 2l; + case 2: + return by; + case 3: + return sh; + case 4: + return ch; + case 5: + return in; + } + return 42; + } + + @Test + public void run0() throws Throwable { + runTest("test", 0, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF); + } + + @Test + public void run1() throws Throwable { + runTest("test", 1, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF); + } + + @Test + public void run2() throws Throwable { + runTest("test", 2, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF); + } + + @Test + public void run3() throws Throwable { + runTest("test", 3, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF); + } + + @Test + public void run4() throws Throwable { + runTest("test", 4, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF); + } + + @Test + public void run5() throws Throwable { + runTest("test", 5, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF); + } +} diff -r be59a1d39281 -r 2f4487a0b588 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 Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Thu Jul 31 07:29:13 2014 -0700 @@ -250,8 +250,8 @@ @Def({REG}) protected Value result; @Use({REG, CONST}) protected Value x; @Alive({REG, CONST}) protected Value y; - @Def({REG}) protected Value scratch1; - @Def({REG}) protected Value scratch2; + @Temp({REG}) protected Value scratch1; + @Temp({REG}) protected Value scratch2; @State protected LIRFrameState state; public RemOp(SPARCArithmetic opcode, Value result, Value x, Value y, LIRFrameState state, LIRGeneratorTool gen) { @@ -324,6 +324,10 @@ assert isSimm13(crb.asIntConst(src2)); new Sdivx(asIntReg(src1), crb.asIntConst(src2), asIntReg(dst)).emit(masm); break; + case IUDIV: + assert isSimm13(crb.asIntConst(src2)); + new Udivx(asIntReg(src1), crb.asIntConst(src2), asIntReg(dst)).emit(masm); + break; case IAND: assert isSimm13(crb.asIntConst(src2)) : src2; new And(asIntReg(src1), crb.asIntConst(src2), asIntReg(dst)).emit(masm); @@ -360,7 +364,7 @@ assert isSimm13(crb.asIntConst(src2)); new Mulx(asLongReg(src1), crb.asIntConst(src2), asLongReg(dst)).emit(masm); break; - case LDIV: + case LDIV: { int c = crb.asIntConst(src2); exceptionOffset = masm.position(); if (c == 0) { // Generate div by zero trap @@ -372,8 +376,14 @@ new Sdivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(dst)).emit(masm); } break; - case LUDIV: - throw GraalInternalError.unimplemented(); + } + case LUDIV: { + int c = crb.asIntConst(src2); + assert isSimm13(c); + exceptionOffset = masm.position(); + new Udivx(asLongReg(src1), c, asLongReg(dst)).emit(masm); + break; + } case LAND: assert isSimm13(crb.asIntConst(src2)); new And(asLongReg(src1), crb.asIntConst(src2), asLongReg(dst)).emit(masm); @@ -425,9 +435,15 @@ break; case IDIV: new Signx(asIntReg(src1), asIntReg(src1)).emit(masm); + new Signx(asIntReg(src2), asIntReg(src2)).emit(masm); exceptionOffset = masm.position(); new Sdivx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm); break; + case IUDIV: + new Srl(asIntReg(src1), 0, asIntReg(src1)).emit(masm); + exceptionOffset = masm.position(); + new Udivx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm); + break; case IAND: new And(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm); break; @@ -462,7 +478,9 @@ new Sdivx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm); break; case LUDIV: - throw GraalInternalError.unimplemented(); + exceptionOffset = masm.position(); + new Udivx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm); + break; case LAND: new And(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm); break; @@ -532,8 +550,8 @@ } else { new Setx(a % b, asIntReg(dst), false).emit(masm); } + break; } - break; case LREM: { long a = crb.asLongConst(src1); long b = crb.asLongConst(src2); @@ -543,16 +561,11 @@ } else { new Setx(a % b, asLongReg(dst), false).emit(masm); } + break; } - break; default: throw GraalInternalError.shouldNotReachHere("not implemented"); } - } else if (isConstant(src1)) { - switch (opcode) { - default: - throw GraalInternalError.shouldNotReachHere(); - } } else if (isConstant(src2)) { switch (opcode) { case IREM: @@ -563,6 +576,13 @@ new Mulx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch2)).emit(masm); new Sub(asIntReg(src1), asIntReg(scratch2), asIntReg(dst)).emit(masm); break; + case IUREM: + new Sra(asIntReg(src1), 0, asIntReg(scratch1)).emit(masm); + exceptionOffset = masm.position(); + new Udivx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm); + new Mulx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm); + new Sub(asIntReg(src1), asIntReg(scratch1), asIntReg(dst)).emit(masm); + break; case LREM: assert isSimm13(crb.asIntConst(src2)); exceptionOffset = masm.position(); @@ -571,26 +591,55 @@ new Sub(asLongReg(src1), asLongReg(scratch2), asLongReg(dst)).emit(masm); break; case LUREM: - throw GraalInternalError.unimplemented(); + assert isSimm13(crb.asIntConst(src2)); + exceptionOffset = masm.position(); + new Udivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(scratch1)).emit(masm); + new Mulx(asLongReg(scratch1), crb.asIntConst(src2), asLongReg(scratch2)).emit(masm); + new Sub(asLongReg(src1), asLongReg(scratch2), asLongReg(dst)).emit(masm); + break; default: throw GraalInternalError.shouldNotReachHere(); } } else { + Value srcLeft = src1; switch (opcode) { case LREM: + if (isConstant(src1)) { + new Setx(crb.asLongConst(src1), asLongReg(scratch2), false).emit(masm); + srcLeft = scratch2; + } exceptionOffset = masm.position(); - new Sdivx(asLongReg(src1), asLongReg(src2), asLongReg(scratch1)).emit(masm); - new Mulx(asLongReg(scratch1), asLongReg(src2), asLongReg(scratch2)).emit(masm); - new Sub(asLongReg(src1), asLongReg(scratch2), asLongReg(dst)).emit(masm); + new Sdivx(asLongReg(srcLeft), asLongReg(src2), asLongReg(scratch1)).emit(masm); + new Mulx(asLongReg(scratch1), asLongReg(src2), asLongReg(scratch1)).emit(masm); + new Sub(asLongReg(srcLeft), asLongReg(scratch1), asLongReg(dst)).emit(masm); + break; + case LUREM: + if (isConstant(src1)) { + new Setx(crb.asLongConst(src1), asLongReg(scratch2), false).emit(masm); + srcLeft = scratch2; + } + exceptionOffset = masm.position(); + new Udivx(asLongReg(srcLeft), asLongReg(src2), asLongReg(scratch1)).emit(masm); + new Mulx(asLongReg(scratch1), asLongReg(src2), asLongReg(scratch1)).emit(masm); + new Sub(asLongReg(srcLeft), asLongReg(scratch1), asLongReg(dst)).emit(masm); break; case IREM: + if (isConstant(src1)) { + new Setx(crb.asIntConst(src1), asIntReg(scratch2), false).emit(masm); + srcLeft = scratch2; + } exceptionOffset = masm.position(); - new Sdivx(asIntReg(src1), asIntReg(src2), asIntReg(scratch1)).emit(masm); - new Mulx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch2)).emit(masm); - new Sub(asIntReg(src1), asIntReg(scratch2), asIntReg(dst)).emit(masm); + new Sdivx(asIntReg(srcLeft), asIntReg(src2), asIntReg(scratch1)).emit(masm); + new Mulx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch1)).emit(masm); + new Sub(asIntReg(srcLeft), asIntReg(scratch1), asIntReg(dst)).emit(masm); break; - case LUREM: - throw GraalInternalError.unimplemented(); + case IUREM: + new Sra(asIntReg(src1), 0, asIntReg(scratch1)).emit(masm); + exceptionOffset = masm.position(); + new Udivx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch1)).emit(masm); + new Mulx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch1)).emit(masm); + new Sub(asIntReg(src1), asIntReg(scratch1), asIntReg(dst)).emit(masm); + break; default: throw GraalInternalError.shouldNotReachHere(); } @@ -668,28 +717,40 @@ break; case F2L: new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm); - new Fbe(false, 4).emit(masm); + new Fbe(false, 4 * 4).emit(masm); new Fstox(asFloatReg(src), asFloatReg(dst)).emit(masm); new Fitos(asFloatReg(dst), asFloatReg(dst)).emit(masm); new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm); break; case F2I: new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm); - new Fbo(false, 4).emit(masm); + new Fbo(false, 4 * 4).emit(masm); new Fstoi(asFloatReg(src), asFloatReg(dst)).emit(masm); new Fitos(asFloatReg(dst), asFloatReg(dst)).emit(masm); new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm); break; + case MOV_D2L: + new Movdtox(asDoubleReg(src), asLongReg(dst)).emit(masm); + break; + case MOV_L2D: + new Movxtod(asLongReg(src), asDoubleReg(dst)).emit(masm); + break; + case MOV_F2I: + new Movstosw(asFloatReg(src), asIntReg(dst)).emit(masm); + break; + case MOV_I2F: + new Movwtos(asIntReg(src), asFloatReg(dst)).emit(masm); + break; case D2L: new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(dst), asDoubleReg(dst)).emit(masm); - new Fbo(false, 4).emit(masm); + new Fbo(false, 4 * 4).emit(masm); new Fdtox(asDoubleReg(src), asDoubleReg(dst)).emit(masm); new Fxtod(asDoubleReg(dst), asDoubleReg(dst)).emit(masm); new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm); break; case D2I: new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(dst), asDoubleReg(dst)).emit(masm); - new Fbo(false, 4).emit(masm); + new Fbo(false, 4 * 4).emit(masm); new Fdtoi(asDoubleReg(src), asDoubleReg(dst)).emit(masm); new Fitod(asDoubleReg(dst), asDoubleReg(dst)).emit(masm); new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm); @@ -740,6 +801,8 @@ case ISHL: case ISHR: case IUSHR: + case IUDIV: + case IUREM: rk = result.getKind(); xsk = x.getKind().getStackKind(); ysk = y.getKind().getStackKind(); @@ -753,6 +816,8 @@ case LAND: case LOR: case LXOR: + case LUDIV: + case LUREM: rk = result.getKind(); xk = x.getKind(); yk = y.getKind(); diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java Thu Jul 31 07:29:13 2014 -0700 @@ -160,10 +160,10 @@ } else { new Call(0).emit(masm); } + new Nop().emit(masm); // delay slot int after = masm.position(); crb.recordDirectCall(before, after, callTarget, info); crb.recordExceptionHandlers(after, info); - new Nop().emit(masm); // delay slot masm.ensureUniquePC(); } @@ -171,19 +171,19 @@ int before = masm.position(); new Sethix(0L, dst, true).emit(masm); new Jmp(new SPARCAddress(dst, 0)).emit(masm); + new Nop().emit(masm); // delay slot int after = masm.position(); crb.recordIndirectCall(before, after, target, null); - new Nop().emit(masm); // delay slot masm.ensureUniquePC(); } public static void indirectCall(CompilationResultBuilder crb, SPARCMacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) { int before = masm.position(); new Jmpl(dst, 0, o7).emit(masm); + new Nop().emit(masm); // delay slot int after = masm.position(); crb.recordIndirectCall(before, after, callTarget, info); crb.recordExceptionHandlers(after, info); - new Nop().emit(masm); // delay slot masm.ensureUniquePC(); } } diff -r be59a1d39281 -r 2f4487a0b588 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 Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Thu Jul 31 07:29:13 2014 -0700 @@ -24,8 +24,8 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import static com.oracle.graal.sparc.SPARC.*; -import com.oracle.graal.api.code.CompilationResult.JumpTable; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; @@ -256,9 +256,9 @@ if (lowKey != 0) { // subtract the low value from the switch value new Sub(value, lowKey, value).emit(masm); - // masm.setp_gt_s32(value, highKey - lowKey); + new Cmp(value, highKey - lowKey).emit(masm); } else { - // masm.setp_gt_s32(value, highKey); + new Cmp(value, highKey).emit(masm); } // Jump to default target if index is not within the jump table @@ -268,19 +268,21 @@ } // Load jump table entry into scratch and jump to it - // masm.movslq(value, new AMD64Address(scratch, value, Scale.Times4, 0)); - // masm.addq(scratch, value); - new Jmp(new SPARCAddress(scratchReg, 0)).emit(masm); - new Nop().emit(masm); // delay slot + new Sll(value, 3, value).emit(masm); // Multiply by 8 + new Rdpc(scratchReg).emit(masm); + + // The jump table follows four instructions after rdpc + new Add(scratchReg, 4 * 4, scratchReg).emit(masm); + new Jmpl(value, scratchReg, g0).emit(masm); + new Sra(value, 3, value).emit(masm); // delay slot, correct the value (division by 8) - // address of jump table - int tablePos = masm.position(); - - JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4); - crb.compilationResult.addAnnotation(jt); - - // SPARC: unimp: tableswitch extract - throw GraalInternalError.unimplemented(); + // Emit jump table entries + for (LabelRef target : targets) { + Label label = target.label(); + label.addPatchAt(masm.position()); + new Bpa(0).emit(masm); + new Nop().emit(masm); // delay slot + } } } @@ -404,20 +406,24 @@ return ConditionFlag.Equal; case NE: return ConditionFlag.NotEqual; + case BT: + return ConditionFlag.LessUnsigned; case LT: return ConditionFlag.Less; + case BE: + return ConditionFlag.LessEqualUnsigned; case LE: return ConditionFlag.LessEqual; + case AE: + return ConditionFlag.GreaterEqualUnsigned; case GE: return ConditionFlag.GreaterEqual; + case AT: + return ConditionFlag.GreaterUnsigned; case GT: return ConditionFlag.Greater; - case BE: - case AE: - case AT: - case BT: default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("Unimplemented for: " + cond); } } diff -r be59a1d39281 -r 2f4487a0b588 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 Thu Jul 31 14:43:37 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java Thu Jul 31 07:29:13 2014 -0700 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.lir.*; +import com.oracle.graal.sparc.*; /** * SPARC specific frame map. @@ -34,11 +35,15 @@ * *
  *   Base       Contents
- *
+ * 
  *            :                                :  -----
  *   caller   | incoming overflow argument n   |    ^
  *   frame    :     ...                        :    | positive
  *            | incoming overflow argument 0   |    | offsets
+ *            +--------------------------------+    |
+ *            |                                |    |
+ *            : register save area             :    |
+ *            |                                |    |
  *   ---------+--------------------------------+---------------------------
  *            | spill slot 0                   |    | negative   ^      ^
  *            :     ...                        :    v offsets    |      |
@@ -101,4 +106,29 @@
     protected StackSlot allocateNewSpillSlot(LIRKind kind, int additionalOffset) {
         return StackSlot.get(kind, -spillSize + additionalOffset, true);
     }
+
+    /**
+     * In SPARC we have spill slots word aligned
+     */
+    @Override
+    public int spillSlotSize(LIRKind kind) {
+        return SPARC.spillSlotSize(target, kind.getPlatformKind());
+    }
+
+    /**
+     * We must add the calleSaveAreaSize() when it is a in or out parameter
+     */
+    @Override
+    public int offsetForStackSlot(StackSlot slot) {
+        int offset = super.offsetForStackSlot(slot);
+        if (slot.getRawOffset() >= 0) { // If In or Out parameter
+            offset += calleeSaveAreaSize();
+        }
+        return offset;
+    }
+
+    @Override
+    public boolean frameNeedsAllocating() {
+        return super.frameNeedsAllocating() || spillSize > 0;
+    }
 }
diff -r be59a1d39281 -r 2f4487a0b588 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	Thu Jul 31 14:43:37 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Thu Jul 31 07:29:13 2014 -0700
@@ -387,8 +387,13 @@
         } else if (isConstant(input)) {
             if (isRegister(result)) {
                 const2reg(crb, masm, result, (Constant) input);
+            } else if (isStackSlot(result)) {
+                // Move a Constant to a stack slot (Probably a 7th output parameter)
+                Value scratch = input.getKind() == Kind.Float || input.getKind() == Kind.Double ? f30.asValue(input.getLIRKind()) : g5.asValue(input.getLIRKind());
+                const2reg(crb, masm, scratch, (Constant) input);
+                reg2stack(crb, masm, result, scratch);
             } else {
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("Result is a: " + result);
             }
         } else {
             throw GraalInternalError.shouldNotReachHere();
@@ -405,6 +410,10 @@
             return;
         }
         switch (input.getKind()) {
+            case Boolean:
+            case Byte:
+            case Short:
+            case Char:
             case Int:
             case Long:
             case Object:
@@ -438,7 +447,7 @@
                 }
                 break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("Input is a: " + input.getKind());
         }
     }
 
@@ -446,6 +455,14 @@
         SPARCAddress dst = (SPARCAddress) crb.asAddress(result);
         Register src = asRegister(input);
         switch (input.getKind()) {
+            case Byte:
+            case Boolean:
+                new Stb(src, dst).emit(masm);
+                break;
+            case Char:
+            case Short:
+                new Sth(src, dst).emit(masm);
+                break;
             case Int:
                 new Stw(src, dst).emit(masm);
                 break;
@@ -460,7 +477,7 @@
                 new Stdf(src, dst).emit(masm);
                 break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("Input is a: " + input.getKind() + "(" + input + ")");
         }
     }
 
@@ -468,6 +485,16 @@
         SPARCAddress src = (SPARCAddress) crb.asAddress(input);
         Register dst = asRegister(result);
         switch (input.getKind()) {
+            case Boolean:
+            case Byte:
+                new Ldsb(src, dst).emit(masm);
+                break;
+            case Short:
+                new Ldsh(src, dst).emit(masm);
+                break;
+            case Char:
+                new Lduh(src, dst).emit(masm);
+                break;
             case Int:
                 new Ldsw(src, dst).emit(masm);
                 break;
@@ -476,9 +503,13 @@
                 new Ldx(src, dst).emit(masm);
                 break;
             case Float:
+                new Ldf(src, dst).emit(masm);
+                break;
             case Double:
+                new Lddf(src, dst).emit(masm);
+                break;
             default:
-                throw GraalInternalError.shouldNotReachHere();
+                throw GraalInternalError.shouldNotReachHere("Input is a: " + input.getKind());
         }
     }
 
@@ -510,6 +541,7 @@
                 }
                 break;
             case Float:
+                // TODO: Handle it the same way, as in the double case with Movwtos
                 crb.asFloatConstRef(input);
                 // First load the address into the scratch register
                 new Setx(0, scratch, true).emit(masm);
@@ -517,9 +549,8 @@
                 new Ldf(scratch, asFloatReg(result)).emit(masm);
                 break;
             case Double:
-                // before we load this from memory and do the complicated lookup,
+                // instead loading this from memory and do the complicated lookup,
                 // just load it directly into a scratch register
-                scratch = g5;
                 // First load the address into the scratch register
                 new Setx(Double.doubleToLongBits(input.asDouble()), scratch, true).emit(masm);
                 // Now load the float value
diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Thu Jul 31 14:43:37 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Thu Jul 31 07:29:13 2014 -0700
@@ -29,15 +29,13 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldsw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.asm.*;
 
 public class SPARCTestOp extends SPARCLIRInstruction {
 
     @Use({REG}) protected Value x;
-    @Use({REG, STACK, CONST}) protected Value y;
+    @Use({REG, CONST}) protected Value y;
 
     public SPARCTestOp(Value x, Value y) {
         this.x = x;
@@ -48,6 +46,10 @@
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
         if (isRegister(y)) {
             switch (x.getKind()) {
+                case Short:
+                case Byte:
+                case Char:
+                case Boolean:
                 case Int:
                     new Andcc(asIntReg(x), asIntReg(y), g0).emit(masm);
                     break;
@@ -59,6 +61,10 @@
             }
         } else if (isConstant(y)) {
             switch (x.getKind()) {
+                case Short:
+                case Byte:
+                case Char:
+                case Boolean:
                 case Int:
                     new Andcc(asIntReg(x), crb.asIntConst(y), g0).emit(masm);
                     break;
@@ -69,18 +75,7 @@
                     throw GraalInternalError.shouldNotReachHere();
             }
         } else {
-            switch (x.getKind()) {
-                case Int:
-                    new Ldsw((SPARCAddress) crb.asIntAddr(y), asIntReg(y)).emit(masm);
-                    new Andcc(asIntReg(x), asIntReg(y), g0).emit(masm);
-                    break;
-                case Long:
-                    new Ldx((SPARCAddress) crb.asLongAddr(y), asLongReg(y)).emit(masm);
-                    new Andcc(asLongReg(x), asLongReg(y), g0).emit(masm);
-                    break;
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
+            throw GraalInternalError.shouldNotReachHere();
         }
     }
 
diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Thu Jul 31 14:43:37 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Thu Jul 31 07:29:13 2014 -0700
@@ -201,8 +201,11 @@
      * @return the offset of the stack slot
      */
     public int offsetForStackSlot(StackSlot slot) {
-        assert (!slot.getRawAddFrameSize() && slot.getRawOffset() < outgoingSize) || (slot.getRawAddFrameSize() && slot.getRawOffset() < 0 && -slot.getRawOffset() <= spillSize) ||
-                        (slot.getRawAddFrameSize() && slot.getRawOffset() >= 0);
+        // @formatter:off
+        assert (!slot.getRawAddFrameSize() && slot.getRawOffset() <  outgoingSize) ||
+               ( slot.getRawAddFrameSize() && slot.getRawOffset() <  0 && -slot.getRawOffset() <= spillSize) ||
+               ( slot.getRawAddFrameSize() && slot.getRawOffset() >= 0);
+        // @formatter:on
         if (slot.isInCallerFrame()) {
             accessesCallerFrame = true;
         }
diff -r be59a1d39281 -r 2f4487a0b588 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Thu Jul 31 14:43:37 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Thu Jul 31 07:29:13 2014 -0700
@@ -258,7 +258,12 @@
             } else if (type == double[].class) {
                 return Arrays.toString((double[]) value);
             } else if (type == byte[].class) {
-                return Arrays.toString((byte[]) value);
+                byte[] byteValue = (byte[]) value;
+                if (isPrintableAsciiString(byteValue)) {
+                    return toString(byteValue);
+                } else {
+                    return Arrays.toString(byteValue);
+                }
             } else if (!type.getComponentType().isPrimitive()) {
                 return Arrays.toString((Object[]) value);
             }
@@ -266,4 +271,39 @@
         assert false : "unhandled field type: " + type;
         return "";
     }
+
+    /**
+     * Tests if all values in this string are printable ASCII characters or value \0 (b in
+     * [0x20,0x7F]) or b == 0
+     *
+     * @param array
+     * @return true if there are only printable ASCII characters and \0, false otherwise
+     */
+    private static boolean isPrintableAsciiString(byte[] array) {
+        for (byte b : array) {
+            char c = (char) b;
+            if (c != 0 && c < 0x20 && c > 0x7F) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static String toString(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        sb.append('"');
+        for (byte b : bytes) {
+            if (b == 0) {
+                sb.append("\\0");
+            } else if (b == '"') {
+                sb.append("\\\"");
+            } else if (b == '\n') {
+                sb.append("\\n");
+            } else {
+                sb.append((char) b);
+            }
+        }
+        sb.append('"');
+        return sb.toString();
+    }
 }
diff -r be59a1d39281 -r 2f4487a0b588 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	Thu Jul 31 14:43:37 2014 +0200
+++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java	Thu Jul 31 07:29:13 2014 -0700
@@ -189,9 +189,19 @@
      * Stack bias for stack and frame pointer loads.
      */
     public static final int STACK_BIAS = 0x7ff;
+    /**
+     * In fact there are 64 single floating point registers, 32 of them could be accessed. TODO:
+     * Improve handling of these float registers
+     */
+    public static final int FLOAT_REGISTER_COUNT = 64;
+
+    /**
+     * Alignment for valid memory access
+     */
+    public static final int MEMORY_ACCESS_ALIGN = 4;
 
     public SPARC() {
-        super("SPARC", 8, ByteOrder.BIG_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 1, r31.encoding + 1, 8);
+        super("SPARC", 8, ByteOrder.BIG_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 1, r31.encoding + FLOAT_REGISTER_COUNT + 1, 8);
     }
 
     @Override
@@ -232,4 +242,8 @@
             return Kind.Illegal;
         }
     }
+
+    public static int spillSlotSize(TargetDescription td, PlatformKind kind) {
+        return Math.max(td.getSizeInBytes(kind), MEMORY_ACCESS_ALIGN);
+    }
 }
diff -r be59a1d39281 -r 2f4487a0b588 src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp	Thu Jul 31 14:43:37 2014 +0200
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp	Thu Jul 31 07:29:13 2014 -0700
@@ -61,9 +61,11 @@
   address pc = _instructions->start() + pc_offset;
   address const_start = _constants->start();
   jint offset = DataSectionReference::offset(data);
+  address dest = _constants->start() + offset;
 
-  NativeMovRegMem* load = nativeMovRegMem_at(pc);
-  load->add_offset_in_bytes((long)const_start+offset);
+  _instructions->relocate(pc + NativeMovConstReg::sethi_offset, internal_word_Relocation::spec((address) dest));
+  _instructions->relocate(pc + NativeMovConstReg::add_offset, internal_word_Relocation::spec((address) dest));
+  TRACE_graal_3("relocating at %p with destination at %p (%d)", pc, dest, offset);
 }
 
 void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
diff -r be59a1d39281 -r 2f4487a0b588 src/cpu/sparc/vm/sharedRuntime_sparc.cpp
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Thu Jul 31 14:43:37 2014 +0200
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Thu Jul 31 07:29:13 2014 -0700
@@ -3561,6 +3561,7 @@
   int exception_in_tls_offset = __ offset() - start;
 
   // No need to update oop_map  as each call to save_live_registers will produce identical oopmap
+  // Opens a new stack frame
   (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
 
   // Restore G2_thread
@@ -3592,7 +3593,10 @@
   // Reexecute entry, similar to c2 uncommon trap
   //
   int reexecute_offset = __ offset() - start;
-
+#if defined(COMPILERGRAAL) && !defined(COMPILER1)
+  // Graal does not use this kind of deoptimization
+  __ should_not_reach_here();
+#endif
   // No need to update oop_map  as each call to save_live_registers will produce identical oopmap
   (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
 
diff -r be59a1d39281 -r 2f4487a0b588 src/share/vm/code/nmethod.hpp
--- a/src/share/vm/code/nmethod.hpp	Thu Jul 31 14:43:37 2014 +0200
+++ b/src/share/vm/code/nmethod.hpp	Thu Jul 31 07:29:13 2014 -0700
@@ -643,7 +643,21 @@
 
   // (thomaswue) When using graal, the address might be off by 5 (because this is the size of the call instruction.
   // (thomaswue) TODO: Replace this by a more general mechanism.
-  bool is_deopt_entry   (address pc) { return pc == deopt_handler_begin() GRAAL_ONLY( || pc == deopt_handler_begin() + 5); }
+  // (sanzinger) SPARC has another offset, looked for some variable existing in HotSpot which describes this offset, but i have not
+  // found anything.
+  bool is_deopt_entry   (address pc) {
+    return pc == deopt_handler_begin()
+#ifdef GRAAL
+      || pc == deopt_handler_begin() +
+#ifdef TARGET_ARCH_sparc
+  8
+#endif // sparc
+#ifdef TARGET_ARCH_x86
+  5
+#endif // x86
+#endif // GRAAL
+      ;
+  }
   bool is_deopt_mh_entry(address pc) { return pc == deopt_mh_handler_begin(); }
   // Accessor/mutator for the original pc of a frame before a frame was deopted.
   address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
diff -r be59a1d39281 -r 2f4487a0b588 src/share/vm/graal/graalCodeInstaller.cpp
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Thu Jul 31 14:43:37 2014 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Thu Jul 31 07:29:13 2014 -0700
@@ -68,6 +68,11 @@
       return as_XMMRegister(remainder)->as_VMReg();
     }
 #endif
+#ifdef TARGET_ARCH_sparc
+    if (remainder < FloatRegisterImpl::number_of_registers) {
+      return as_FloatRegister(remainder)->as_VMReg();
+    }
+#endif
     ShouldNotReachHere();
     return NULL;
   }
@@ -129,6 +134,13 @@
       }
     }
 #endif
+#ifdef TARGET_ARCH_sparc
+    for (jint i = 0; i < FloatRegisterImpl::number_of_registers; i++) {
+      VMReg reg = as_FloatRegister(i)->as_VMReg();
+      int idx = RegisterImpl::number_of_registers + i;
+      set_vmreg_oops(map, reg, register_map, idx);
+    }
+#endif
   }
 
   for (jint i = 0; i < bitset_size(frame_map) / 3; i++) {
@@ -214,6 +226,7 @@
 
   if (value->is_a(RegisterValue::klass())) {
     jint number = code_Register::number(RegisterValue::reg(value));
+    jint encoding = code_Register::encoding(RegisterValue::reg(value));
     if (number < RegisterImpl::number_of_registers) {
       Location::Type locationType;
       if (type == T_INT) {
@@ -249,9 +262,9 @@
       return value;
 #else
 #ifdef TARGET_ARCH_sparc
-      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_FloatRegister(number)->as_VMReg()));
+      ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_FloatRegister(encoding)->as_VMReg()));
       if (type == T_DOUBLE) {
-        second = value;
+        second = new ConstantIntValue(0);
       }
       return value;
 #else
diff -r be59a1d39281 -r 2f4487a0b588 src/share/vm/graal/graalJavaAccess.hpp
--- a/src/share/vm/graal/graalJavaAccess.hpp	Thu Jul 31 14:43:37 2014 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu Jul 31 07:29:13 2014 -0700
@@ -239,6 +239,7 @@
   end_class                                                                                                                                                    \
   start_class(code_Register)                                                                                                                                   \
     int_field(code_Register, number)                                                                                                                           \
+    int_field(code_Register, encoding)                                                                                                                         \
   end_class                                                                                                                                                    \
   start_class(StackSlot)                                                                                                                                       \
     int_field(StackSlot, offset)                                                                                                                               \