# HG changeset patch # User twisti # Date 1393291875 28800 # Node ID 4347ad3df3d71e09cbe193861c604947b6863c1f # Parent 1f34717ccaface2e8ff5926dcda6b8a8cb17aa68 make SPARC compile code again diff -r 1f34717ccafa -r 4347ad3df3d7 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 Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Mon Feb 24 17:31:15 2014 -0800 @@ -654,7 +654,7 @@ } /** - * Special constructor for Casa and Casxa. + * Special constructor for {@link Casa} and {@link Casxa}. */ public Fmt11(Op3s op3, Register rs1, Register rs2, Register rd, Asi asi) { this(rd.encoding(), op3.getValue(), rs1.encoding(), asi.isValid() ? 0 : 1, asi.isValid() ? asi.getValue() : 0, rs2.encoding(), 0); @@ -666,6 +666,18 @@ */ public Fmt11(Op3s op3, SPARCAddress addr, Register rd) { this(rd.encoding(), op3.getValue(), addr.getBase().encoding(), 0, 0, 0, 0); + decodeAddress(addr); + } + + /** + * Special constructor for {@link Prefetch} and Prefetcha. + */ + public Fmt11(Op3s op3, SPARCAddress addr, Prefetch.Fcn fcn) { + this(fcn.getValue(), op3.getValue(), addr.getBase().encoding(), 0, 0, 0, 0); + decodeAddress(addr); + } + + private void decodeAddress(SPARCAddress addr) { if (!addr.getIndex().equals(Register.None)) { this.rs2 = addr.getIndex().encoding(); } else { @@ -1009,6 +1021,8 @@ Retry(0x3e, "retry"), Casa(0b111100, "casa"), Casxa(0b111110, "casxa"), + Prefetch(0b101101, "prefetch"), + Prefetcha(0b111101, "prefetcha"), Lduw(0b00000, "lduw"), Ldub(0b00001, "ldub"), @@ -2921,6 +2935,27 @@ } } + public static class Prefetch extends Fmt11 { + + public enum Fcn { + SeveralReads(0), OneRead(1), SeveralWritesAndPossiblyReads(2), OneWrite(3), Page(4); + + private final int value; + + private Fcn(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + public Prefetch(SPARCAddress addr, Prefetch.Fcn fcn) { + super(Op3s.Prefetch, addr, fcn); + } + } + // A.44 Read State Register @Deprecated diff -r 1f34717ccafa -r 4347ad3df3d7 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64PrefetchOp.java Mon Feb 24 17:31:15 2014 -0800 @@ -32,7 +32,7 @@ public class AMD64PrefetchOp extends AMD64LIRInstruction { - private final int instr; // AllocatePrefecthInstr + private final int instr; // AllocatePrefetchInstr @Alive({COMPOSITE}) protected AMD64AddressValue address; public AMD64PrefetchOp(AMD64AddressValue address, int instr) { diff -r 1f34717ccafa -r 4347ad3df3d7 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java Mon Feb 24 17:31:15 2014 -0800 @@ -26,11 +26,12 @@ import com.oracle.graal.asm.sparc.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; @Opcode("DEOPT") -final class SPARCDeoptimizeOp extends SPARCLIRInstruction { +final class SPARCDeoptimizeOp extends SPARCLIRInstruction implements BlockEndOp { @State private LIRFrameState info; diff -r 1f34717ccafa -r 4347ad3df3d7 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Mon Feb 24 17:31:15 2014 -0800 @@ -49,7 +49,7 @@ assert host == null; TargetDescription target = createTarget(); - HotSpotRegistersProvider registers = new HotSpotRegisters(Register.None, Register.None, Register.None); // FIXME + HotSpotRegistersProvider registers = createRegisters(); HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime); HotSpotCodeCacheProvider codeCache = new SPARCHotSpotCodeCacheProvider(runtime, target); HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime); @@ -68,6 +68,10 @@ return new SPARCHotSpotBackend(runtime, providers); } + protected HotSpotRegistersProvider createRegisters() { + return new HotSpotRegisters(SPARC.g2, SPARC.g6, SPARC.sp); + } + @SuppressWarnings("unused") private static Value[] createNativeABICallerSaveRegisters(HotSpotVMConfig config, RegisterConfig regConfig) { CalleeSaveLayout csl = regConfig.getCalleeSaveLayout(); diff -r 1f34717ccafa -r 4347ad3df3d7 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java Mon Feb 24 17:31:15 2014 -0800 @@ -23,12 +23,13 @@ package com.oracle.graal.hotspot.sparc; import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.asm.*; /** * Superclass for operations that leave a method's frame. */ -abstract class SPARCHotSpotEpilogueOp extends SPARCLIRInstruction { +abstract class SPARCHotSpotEpilogueOp extends SPARCLIRInstruction implements BlockEndOp { protected void leaveFrame(CompilationResultBuilder crb) { crb.frameContext.leave(crb); diff -r 1f34717ccafa -r 4347ad3df3d7 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 Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Feb 24 17:31:15 2014 -0800 @@ -72,7 +72,6 @@ @SuppressWarnings("hiding") @Override protected DebugInfoBuilder createDebugInfoBuilder(NodeMap nodeOperands) { - assert config.basicLockSize == 8; HotSpotLockStack lockStack = new HotSpotLockStack(frameMap, Kind.Long); return new HotSpotDebugInfoBuilder(nodeOperands, lockStack); } @@ -97,10 +96,11 @@ @Override public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) { + Stub stub = getStub(); Variable result; if (linkage.canDeoptimize()) { - assert info != null; + assert info != null || stub != null; HotSpotRegistersProvider registers = getProviders().getRegisters(); Register thread = registers.getThreadRegister(); Register stackPointer = registers.getStackPointerRegister(); diff -r 1f34717ccafa -r 4347ad3df3d7 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 Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Mon Feb 24 17:31:15 2014 -0800 @@ -61,7 +61,7 @@ public static void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { final int pos = masm.codeBuffer.position(); new Setx(config.safepointPollingAddress, scratch).emit(masm); - crb.recordMark(atReturn ? MARK_POLL_RETURN_NEAR : MARK_POLL_NEAR); + crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR); if (state != null) { crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); } diff -r 1f34717ccafa -r 4347ad3df3d7 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCPrefetchOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCPrefetchOp.java Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCPrefetchOp.java Mon Feb 24 17:31:15 2014 -0800 @@ -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,16 +23,16 @@ package com.oracle.graal.hotspot.sparc; +import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.graph.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; public class SPARCPrefetchOp extends SPARCLIRInstruction { - private final int instr; // AllocatePrefecthInstr + private final int instr; // AllocatePrefetchInstr @Alive({COMPOSITE}) protected SPARCAddressValue address; public SPARCPrefetchOp(SPARCAddressValue address, int instr) { @@ -43,8 +43,6 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { assert instr == 0 : "only supported value is 0"; - // masm.prefetch(address.toAddress(), 2); - throw GraalInternalError.unimplemented("prefetch instruction"); + new Prefetch(address.toAddress(), Prefetch.Fcn.SeveralWritesAndPossiblyReads).emit(masm); } - } diff -r 1f34717ccafa -r 4347ad3df3d7 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 Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon Feb 24 17:31:15 2014 -0800 @@ -708,7 +708,7 @@ @HotSpotVMFlag(name = "CodeEntryAlignment") @Stable public int codeEntryAlignment; @HotSpotVMFlag(name = "VerifyOops") @Stable public boolean verifyOops; @HotSpotVMFlag(name = "CITime") @Stable public boolean ciTime; - @HotSpotVMFlag(name = "CITimeEach", optional = true) @Stable public boolean ciTimeEach; + @HotSpotVMFlag(name = "CITimeEach") @Stable public boolean ciTimeEach; @HotSpotVMFlag(name = "CompileThreshold") @Stable public long compileThreshold; @HotSpotVMFlag(name = "CompileTheWorld") @Stable public boolean compileTheWorld; @HotSpotVMFlag(name = "CompileTheWorldStartAt") @Stable public int compileTheWorldStartAt; @@ -724,7 +724,7 @@ @HotSpotVMFlag(name = "UseTLAB") @Stable public boolean useTLAB; @HotSpotVMFlag(name = "UseBiasedLocking") @Stable public boolean useBiasedLocking; @HotSpotVMFlag(name = "UsePopCountInstruction") @Stable public boolean usePopCountInstruction; - @HotSpotVMFlag(name = "UseCountLeadingZerosInstruction", optional = true) @Stable public boolean useCountLeadingZerosInstruction; + @HotSpotVMFlag(name = "UseCountLeadingZerosInstruction", archs = {"amd64"}) @Stable public boolean useCountLeadingZerosInstruction; @HotSpotVMFlag(name = "UseAESIntrinsics") @Stable public boolean useAESIntrinsics; @HotSpotVMFlag(name = "UseCRC32Intrinsics") @Stable public boolean useCRC32Intrinsics; @HotSpotVMFlag(name = "UseG1GC") @Stable public boolean useG1GC; diff -r 1f34717ccafa -r 4347ad3df3d7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMFlag.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMFlag.java Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMFlag.java Mon Feb 24 17:31:15 2014 -0800 @@ -36,6 +36,4 @@ * required on all architectures. */ String[] archs() default {}; - - boolean optional() default false; } diff -r 1f34717ccafa -r 4347ad3df3d7 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 Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Mon Feb 24 17:31:15 2014 -0800 @@ -490,6 +490,13 @@ } } else if (isConstant(src2)) { switch (opcode) { + case IREM: + assert isSimm13(crb.asIntConst(src2)); + new Sra(asIntReg(src1), 0, asIntReg(src1)).emit(masm); + new Sdivx(asIntReg(src1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm); + new Mulx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch2)).emit(masm); + new Sub(asIntReg(src1), asIntReg(scratch2), asIntReg(dst)).emit(masm); + break; case LREM: assert isSimm13(crb.asIntConst(src2)); new Sdivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(scratch1)).emit(masm); diff -r 1f34717ccafa -r 4347ad3df3d7 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 Mon Feb 24 15:08:02 2014 -0800 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Mon Feb 24 17:31:15 2014 -0800 @@ -57,6 +57,26 @@ public class SPARCControlFlow { + public static class ReturnOp extends SPARCLIRInstruction implements BlockEndOp { + + @Use({REG, ILLEGAL}) protected Value x; + + public ReturnOp(Value x) { + this.x = x; + } + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + emitCodeHelper(crb, masm); + } + + public static void emitCodeHelper(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + new Ret().emit(masm); + // On SPARC we always leave the frame (in the delay slot). + crb.frameContext.leave(crb); + } + } + public static class BranchOp extends SPARCLIRInstruction implements StandardOp.BranchOp { protected final Condition condition; @@ -132,6 +152,122 @@ } } + public static class StrategySwitchOp extends SPARCLIRInstruction implements BlockEndOp { + @Use({CONST}) protected Constant[] keyConstants; + private final LabelRef[] keyTargets; + private LabelRef defaultTarget; + @Alive({REG}) protected Value key; + @Temp({REG, ILLEGAL}) protected Value scratch; + private final SwitchStrategy strategy; + + public StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) { + this.strategy = strategy; + this.keyConstants = strategy.keyConstants; + this.keyTargets = keyTargets; + this.defaultTarget = defaultTarget; + this.key = key; + this.scratch = scratch; + assert keyConstants.length == keyTargets.length; + assert keyConstants.length == strategy.keyProbabilities.length; + assert (scratch.getKind() == Kind.Illegal) == (key.getKind() == Kind.Int); + } + + @Override + public void emitCode(final CompilationResultBuilder crb, final SPARCMacroAssembler masm) { + final Register keyRegister = asRegister(key); + + BaseSwitchClosure closure = new BaseSwitchClosure(crb, masm, keyTargets, defaultTarget) { + @Override + protected void conditionalJump(int index, Condition condition, Label target) { + switch (key.getKind()) { + case Int: + if (crb.codeCache.needsDataPatch(keyConstants[index])) { + crb.recordInlineDataInCode(keyConstants[index]); + } + long lc = keyConstants[index].asLong(); + assert NumUtil.isInt(lc); + new Cmp(keyRegister, (int) lc).emit(masm); + emitCompare(masm, target, condition, CC.Icc); + break; + case Long: { + Register temp = asLongReg(scratch); + SPARCMove.move(crb, masm, temp.asValue(Kind.Long), keyConstants[index]); + new Cmp(keyRegister, temp).emit(masm); + emitCompare(masm, target, condition, CC.Xcc); + break; + } + case Object: { + Register temp = asObjectReg(scratch); + SPARCMove.move(crb, masm, temp.asValue(Kind.Object), keyConstants[index]); + new Cmp(keyRegister, temp).emit(masm); + emitCompare(masm, target, condition, CC.Ptrcc); + break; + } + default: + throw new GraalInternalError("switch only supported for int, long and object"); + } + new Nop().emit(masm); // delay slot + } + }; + strategy.run(closure); + } + } + + public static class TableSwitchOp extends SPARCLIRInstruction implements BlockEndOp { + + private final int lowKey; + private final LabelRef defaultTarget; + private final LabelRef[] targets; + @Alive protected Value index; + @Temp protected Value scratch; + + public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) { + this.lowKey = lowKey; + this.defaultTarget = defaultTarget; + this.targets = targets; + this.index = index; + this.scratch = scratch; + } + + @Override + public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + Register value = asIntReg(index); + Register scratchReg = asLongReg(scratch); + + Buffer buf = masm.codeBuffer; + // Compare index against jump table bounds + int highKey = lowKey + targets.length - 1; + if (lowKey != 0) { + // subtract the low value from the switch value + new Sub(value, lowKey, value).emit(masm); + // masm.setp_gt_s32(value, highKey - lowKey); + } else { + // masm.setp_gt_s32(value, highKey); + } + + // Jump to default target if index is not within the jump table + if (defaultTarget != null) { + new Bpgu(CC.Icc, defaultTarget.label()).emit(masm); + new Nop().emit(masm); // delay slot + } + + // 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 + + // address of jump table + int tablePos = buf.position(); + + JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4); + crb.compilationResult.addAnnotation(jt); + + // SPARC: unimp: tableswitch extract + throw GraalInternalError.unimplemented(); + } + } + @Opcode("CMOVE") public static class CondMoveOp extends SPARCLIRInstruction { @@ -262,140 +398,4 @@ throw GraalInternalError.shouldNotReachHere(); } } - - public static class ReturnOp extends SPARCLIRInstruction { - - @Use({REG, ILLEGAL}) protected Value x; - - public ReturnOp(Value x) { - this.x = x; - } - - @Override - public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - emitCodeHelper(crb, masm); - } - - public static void emitCodeHelper(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - new Ret().emit(masm); - // On SPARC we always leave the frame (in the delay slot). - crb.frameContext.leave(crb); - } - } - - public static class StrategySwitchOp extends SPARCLIRInstruction implements BlockEndOp { - @Use({CONST}) protected Constant[] keyConstants; - private final LabelRef[] keyTargets; - private LabelRef defaultTarget; - @Alive({REG}) protected Value key; - @Temp({REG, ILLEGAL}) protected Value scratch; - private final SwitchStrategy strategy; - - public StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) { - this.strategy = strategy; - this.keyConstants = strategy.keyConstants; - this.keyTargets = keyTargets; - this.defaultTarget = defaultTarget; - this.key = key; - this.scratch = scratch; - assert keyConstants.length == keyTargets.length; - assert keyConstants.length == strategy.keyProbabilities.length; - assert (scratch.getKind() == Kind.Illegal) == (key.getKind() == Kind.Int); - } - - @Override - public void emitCode(final CompilationResultBuilder crb, final SPARCMacroAssembler masm) { - final Register keyRegister = asRegister(key); - - BaseSwitchClosure closure = new BaseSwitchClosure(crb, masm, keyTargets, defaultTarget) { - @Override - protected void conditionalJump(int index, Condition condition, Label target) { - switch (key.getKind()) { - case Int: - if (crb.codeCache.needsDataPatch(keyConstants[index])) { - crb.recordInlineDataInCode(keyConstants[index]); - } - long lc = keyConstants[index].asLong(); - assert NumUtil.isInt(lc); - new Cmp(keyRegister, (int) lc).emit(masm); - emitCompare(masm, target, condition, CC.Icc); - break; - case Long: { - Register temp = asLongReg(scratch); - SPARCMove.move(crb, masm, temp.asValue(Kind.Long), keyConstants[index]); - new Cmp(keyRegister, temp).emit(masm); - emitCompare(masm, target, condition, CC.Xcc); - break; - } - case Object: { - Register temp = asObjectReg(scratch); - SPARCMove.move(crb, masm, temp.asValue(Kind.Object), keyConstants[index]); - new Cmp(keyRegister, temp).emit(masm); - emitCompare(masm, target, condition, CC.Ptrcc); - break; - } - default: - throw new GraalInternalError("switch only supported for int, long and object"); - } - new Nop().emit(masm); // delay slot - } - }; - strategy.run(closure); - } - } - - public static class TableSwitchOp extends SPARCLIRInstruction implements BlockEndOp { - - private final int lowKey; - private final LabelRef defaultTarget; - private final LabelRef[] targets; - @Alive protected Value index; - @Temp protected Value scratch; - - public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) { - this.lowKey = lowKey; - this.defaultTarget = defaultTarget; - this.targets = targets; - this.index = index; - this.scratch = scratch; - } - - @Override - public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - Register value = asIntReg(index); - Register scratchReg = asLongReg(scratch); - - Buffer buf = masm.codeBuffer; - // Compare index against jump table bounds - int highKey = lowKey + targets.length - 1; - if (lowKey != 0) { - // subtract the low value from the switch value - new Sub(value, lowKey, value).emit(masm); - // masm.setp_gt_s32(value, highKey - lowKey); - } else { - // masm.setp_gt_s32(value, highKey); - } - - // Jump to default target if index is not within the jump table - if (defaultTarget != null) { - new Bpgu(CC.Icc, defaultTarget.label()).emit(masm); - new Nop().emit(masm); // delay slot - } - - // 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 - - // address of jump table - int tablePos = buf.position(); - - JumpTable jt = new JumpTable(tablePos, lowKey, highKey, 4); - crb.compilationResult.addAnnotation(jt); - - // SPARC: unimp: tableswitch extract - throw GraalInternalError.unimplemented(); - } - } }