Mercurial > hg > graal-jvmci-8
changeset 16327:5f01f7c48d40
Merge with 5cdcb94a7cf7d9782107cc582f3e4b50000d5d1f
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Mon Jun 30 12:02:19 2014 +0200 @@ -107,17 +107,17 @@ } public static Register asObjectReg(Value value) { - assert value.getKind() == Kind.Object; + assert value.getKind() == Kind.Object : value.getKind(); return asRegister(value); } public static Register asFloatReg(Value value) { - assert value.getKind() == Kind.Float; + assert value.getKind() == Kind.Float : value.getKind(); return asRegister(value); } public static Register asDoubleReg(Value value) { - assert value.getKind() == Kind.Double; + assert value.getKind() == Kind.Double : value.getKind(); return asRegister(value); }
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Mon Jun 30 12:02:19 2014 +0200 @@ -456,6 +456,43 @@ // @formatter:off /** + * Instruction format for fcmp + * + * | 10 | --- |cc1|cc0|desc | rs1 | opf | rs2 | + * |31 30|29 27|26 |25 |24 19|18 14|13 5|4 0| + */ + // @formatter:on + public static class Fmt3c { + private int op; + private int cc; + private int desc; + private int opf; + private int rs1; + private int rs2; + + public Fmt3c(Ops op, CC cc, int desc, Opfs opf, Register rs1, Register rs2) { + this.op = op.getValue(); + this.opf = opf.getValue(); + this.desc = desc; + this.rs1 = rs1.encoding(); + this.rs2 = rs2.encoding(); + this.cc = cc.getValue(); + } + + public void emit(SPARCAssembler masm) { + assert op == 2 || op == 3; + assert cc >= 0 && cc < 0x4; + assert opf >= 0 && opf < 0x200; + assert rs1 >= 0 && rs1 < 0x20; + assert rs2 >= 0 && rs2 < 0x20; + assert desc >= 0 && desc < 0x40; + + masm.emitInt(op << 30 | cc << 25 | desc << 19 | rs1 << 14 | opf << 5 | rs2); + } + } + + // @formatter:off + /** * Instruction format for Arithmetic, Logical, Moves, Tcc, Prefetch, and Misc. * * | 10 | rd | op3 | rs1 | i| imm_asi | rs2 | @@ -1043,7 +1080,9 @@ Stf(0b100100, "stf"), Stfsr(0x25, "stfsr"), Staf(0x26, "staf"), - Stdf(0b100111, "stdf"); + Stdf(0b100111, "stdf"), + + Fcmp(0b110101, "fcmp"); // @formatter:on @@ -1181,6 +1220,11 @@ Fnsmuld(0x79, "fnsmuld"), Fnhadds(0x71, "fnhadds"), Fnhaddd(0x72, "fnhaddd"), + Movdtox(0x110, "movdtox"), + Movstouw(0x111, "movstouw"), + Movstosw(0x113, "movstosw"), + Movxtod(0x118, "movxtod"), + Movwtos(0x119, "movwtos"), // end VIS3 // start CAMMELLIA @@ -1215,9 +1259,9 @@ Fsubq(0x47, "fsubq"), Fmuls(0x49, "fmuls"), Fmuld(0x4A, "fmuld"), - Fdivs(0x4C, "fdivs"), - Fdivd(0x4D, "fdivd"), - Fdivq(0x4E, "fdivq"), + Fdivs(0x4D, "fdivs"), + Fdivd(0x4E, "fdivd"), + Fdivq(0x4F, "fdivq"), Fsqrts(0x29, "fsqrts"), Fsqrtd(0x2A, "fsqrtd"), @@ -1228,7 +1272,24 @@ Fdmuldq(0x6E, "fdmulq"), Fstoi(0xD1, "fstoi"), - Fdtoi(0xD2, "fdtoi"); + Fdtoi(0xD2, "fdtoi"), + Fstox(0x81, "fstox"), + Fdtox(0x82, "fdtox"), + Fxtos(0x84, "fxtos"), + Fxtod(0x88, "fxtod"), + Fxtoq(0x8C, "fxtoq"), + Fitos(0xC4, "fitos"), + Fdtos(0xC6, "fdtos"), + Fitod(0xC8, "fitod"), + Fstod(0xC9, "fstod"), + Fitoq(0xCC, "fitoq"), + + + Fcmps(0x51, "fcmps"), + Fcmpd(0x52, "fcmpd"), + Fcmpq(0x53, "fcmpq"), + + ; // @formatter:on private final int value; @@ -1278,10 +1339,18 @@ } } + /** + * Condition Codes to use for instruction + */ public enum CC { // @formatter:off - + /** + * Condition is considered as 32bit operation condition + */ Icc(0b00, "icc"), + /** + * Condition is considered as 64bit operation condition + */ Xcc(0b10, "xcc"), Ptrcc(getHostWordKind() == Kind.Long ? Xcc.getValue() : Icc.getValue(), "ptrcc"), Fcc0(0b00, "fcc0"), @@ -1308,6 +1377,41 @@ } } + public enum FCond { + Fba(0x8, "fba"), + Fbn(0x0, "fbn"), + Fbu(0x7, "fbu"), + Fbg(0x6, "fbg"), + Fbug(0x5, "fbug"), + Fbl(0x4, "fbl"), + Fbul(0x3, "fbul"), + Fblg(0x2, "fblg"), + Fbne(0x1, "fbne"), + Fbe(0x9, "fbe"), + Fbue(0xA, "fbue"), + Fbge(0xB, "fbge"), + Fbuge(0xC, "fbuge"), + Fble(0xD, "fble"), + Fbule(0xE, "fbule"), + Fbo(0xF, "fbo"); + private final int value; + private final String operator; + + private FCond(int value, String op) { + assert value >= 0 && value < 1 << 5 : value; // 4 bits + this.value = value; + this.operator = op; + } + + public int getValue() { + return value; + } + + public String getOperator() { + return operator; + } + } + public enum ConditionFlag { // @formatter:off @@ -1402,6 +1506,9 @@ } } + /** + * Represents the <b>Address Space Identifier</b> defined in the SPARC architec + */ public enum Asi { // @formatter:off @@ -1656,6 +1763,48 @@ } } + public static class Movwtos extends Fmt3p { + public Movwtos(Register src, Register dst) { + /* VIS3 only */ + super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movwtos, g0, src, dst); + } + } + + public static class Movxtod extends Fmt3p { + public Movxtod(Register src, Register dst) { + /* VIS3 only */ + super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movxtod, g0, src, dst); + } + } + + public static class Movdtox extends Fmt3p { + public Movdtox(Register src, Register dst) { + /* VIS3 only */ + super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movdtox, g0, src, dst); + } + } + + public static class Movstosw extends Fmt3p { + public Movstosw(Register src, Register dst) { + /* VIS3 only */ + super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movstosw, g0, src, dst); + } + } + + public static class Movstouw extends Fmt3p { + public Movstouw(Register src, Register dst) { + /* VIS3 only */ + super(Ops.ArithOp, Op3s.Impdep1, Opfs.Movstouw, g0, src, dst); + } + } + + public static class Fdtos extends Fmt3p { + public Fdtos(Register src, Register dst) { + /* VIS3 only */ + super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fdtos, g0, src, dst); + } + } + public static class Bpa extends Fmt00c { public Bpa(int simm19) { @@ -1906,6 +2055,9 @@ } } + /** + * Compare and Branch if Carry Clear ( Greater not C Than or Equal, Unsigned ) + */ public static class Cwbcc extends Fmt00e { public Cwbcc(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -1917,6 +2069,9 @@ } } + /** + * Compare and Branch if Carry Set (Less Than, Unsigned) + */ public static class Cwbcs extends Fmt00e { public Cwbcs(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -1928,6 +2083,9 @@ } } + /** + * Compare and Branch if Equal + */ public static class Cwbe extends Fmt00e { public Cwbe(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -1939,6 +2097,9 @@ } } + /** + * Compare and Branch if Greater + */ public static class Cwbg extends Fmt00e { public Cwbg(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -1950,6 +2111,9 @@ } } + /** + * Compare and Branch if Greater or Equal + */ public static class Cwbge extends Fmt00e { public Cwbge(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -1961,6 +2125,9 @@ } } + /** + * Compare and Branch if Greater Unsigned + */ public static class Cwbgu extends Fmt00e { public Cwbgu(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -1972,6 +2139,9 @@ } } + /** + * Compare and Branch if Less + */ public static class Cwbl extends Fmt00e { public Cwbl(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -1983,6 +2153,9 @@ } } + /** + * Compare and Branch if Less or Equal + */ public static class Cwble extends Fmt00e { public Cwble(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -1994,6 +2167,9 @@ } } + /** + * Compare and Branch if Less or Equal Unsigned + */ public static class Cwbleu extends Fmt00e { public Cwbleu(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -2005,6 +2181,9 @@ } } + /** + * Compare and Branch if Not Equal + */ public static class Cwbne extends Fmt00e { public Cwbne(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -2016,6 +2195,9 @@ } } + /** + * Compare and Branch if Negative + */ public static class Cwbneg extends Fmt00e { public Cwbneg(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -2027,6 +2209,9 @@ } } + /** + * Compare and Branch if Positive + */ public static class Cwbpos extends Fmt00e { public Cwbpos(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -2038,6 +2223,9 @@ } } + /** + * Compare and Branch if Overflow Clear + */ public static class Cwbvc extends Fmt00e { public Cwbvc(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -2049,6 +2237,9 @@ } } + /** + * Compare and Branch if Overflow Set + */ public static class Cwbvs extends Fmt00e { public Cwbvs(SPARCAssembler asm, Register src1, Register src2, int simm10) { @@ -2340,6 +2531,9 @@ } } + /** + * Floating-point multiply-add single (fused) + */ public static class Fmadds extends Fmt5a { public Fmadds(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) { @@ -2347,6 +2541,9 @@ } } + /** + * Floating-point multiply-add double (fused) + */ public static class Fmaddd extends Fmt5a { public Fmaddd(SPARCAssembler asm, Register src1, Register src2, Register src3, Register dst) { @@ -2354,6 +2551,9 @@ } } + /** + * 16-bit partitioned average + */ public static class Fmean16 extends Fmt3p { public Fmean16(Register src1, Register src2, Register dst) { @@ -2565,6 +2765,30 @@ } } + public static class Fstox extends Fmt3n { + + public Fstox(SPARCAssembler masm, Register src2, Register dst) { + super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fstox.getValue(), src2.encoding(), dst.encoding()); + } + } + + public static class Fdtox extends Fmt3n { + + public Fdtox(SPARCAssembler masm, Register src2, Register dst) { + super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fdtox.getValue(), src2.encoding(), dst.encoding()); + } + } + + public static class Fstod extends Fmt3n { + + public Fstod(SPARCAssembler masm, Register src2, Register dst) { + super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fstod.getValue(), src2.encoding(), dst.encoding()); + } + } + + /** + * Convert Double to 32-bit Integer + */ public static class Fdtoi extends Fmt3n { public Fdtoi(SPARCAssembler masm, Register src2, Register dst) { @@ -2572,6 +2796,30 @@ } } + public static class Fitos extends Fmt3n { + + public Fitos(SPARCAssembler masm, Register src2, Register dst) { + super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fitos.getValue(), src2.encoding(), dst.encoding()); + } + } + + public static class Fitod extends Fmt3n { + + public Fitod(SPARCAssembler masm, Register src2, Register dst) { + super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fitod.getValue(), src2.encoding(), dst.encoding()); + } + } + + public static class Fxtod extends Fmt3n { + + public Fxtod(SPARCAssembler masm, Register src2, Register dst) { + super(masm, Ops.ArithOp.getValue(), Op3s.Fpop1.getValue(), Opfs.Fxtod.getValue(), src2.encoding(), dst.encoding()); + } + } + + /** + * Flush register windows + */ public static class Flushw extends Fmt10 { public Flushw() { @@ -2770,6 +3018,20 @@ } } + public static class Fcmp extends Fmt3c { + + public Fcmp(CC cc, Opfs opf, Register r1, Register r2) { + super(Ops.ArithOp, cc, 0b110101, opf, r1, r2); + } + } + + public static class Fbfcc extends Fmt00b { + + public Fbfcc(SPARCAssembler asm, FCond cond, boolean annul, int disp) { + super(asm, Ops.BranchOp.getValue(), annul ? 1 : 0, cond.getValue(), 0b110, disp); + } + } + public static class Illtrap extends Fmt00a { public Illtrap(int const22) { @@ -2789,6 +3051,10 @@ public Lddf(SPARCAddress src, Register dst) { super(Op3s.Lddf, src, dst); } + + public Lddf(Register src, Register dst) { + super(Op3s.Lddf, src, dst); + } } public static class Ldf extends Fmt11 { @@ -2796,6 +3062,10 @@ public Ldf(SPARCAddress src, Register dst) { super(Op3s.Ldf, src, dst); } + + public Ldf(Register src, Register dst) { + super(Op3s.Ldf, src, dst); + } } public static class Ldsb extends Fmt11 {
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Jun 30 12:02:19 2014 +0200 @@ -452,6 +452,9 @@ public Value emitNegate(Value input) { Variable result = newVariable(input.getLIRKind()); switch (input.getKind().getStackKind()) { + case Long: + append(new Op1Stack(LNEG, result, input)); + break; case Int: append(new Op1Stack(INEG, result, input)); break; @@ -623,6 +626,7 @@ @Override public Value emitRem(Value a, Value b, LIRFrameState state) { Variable result = newVariable(a.getLIRKind()); + Variable q = null; switch (a.getKind().getStackKind()) { case Int: append(new RemOp(IREM, result, a, loadNonConst(b), state, this)); @@ -630,6 +634,22 @@ case Long: append(new RemOp(LREM, result, a, loadNonConst(b), state, this)); break; + case Float: + q = newVariable(LIRKind.value(Kind.Float)); + append(new Op2Stack(FDIV, q, a, b)); + append(new Unary2Op(F2I, q, q)); + append(new Unary2Op(I2F, q, q)); + append(new Op2Stack(FMUL, q, q, b)); + append(new Op2Stack(FSUB, result, a, q)); + break; + case Double: + q = newVariable(LIRKind.value(Kind.Double)); + append(new Op2Stack(DDIV, q, a, b)); + append(new Unary2Op(D2L, q, q)); + append(new Unary2Op(L2D, q, q)); + append(new Op2Stack(DMUL, q, q, b)); + append(new Op2Stack(DSUB, result, a, q)); + break; default: throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind()); } @@ -777,19 +797,33 @@ @Override public Value emitFloatConvert(FloatConvert op, Value inputVal) { AllocatableValue input = asAllocatable(inputVal); + Kind fromRegisterKind = null; + Kind toRegisterKind = null; + SPARCArithmetic conversionInstruction = null; switch (op) { case D2F: return emitConvert2Op(LIRKind.value(Kind.Float), D2F, input); case D2I: - return emitConvert2Op(LIRKind.value(Kind.Int), D2I, input); + fromRegisterKind = Kind.Double; + toRegisterKind = Kind.Int; + conversionInstruction = D2I; + break; + case F2L: + Variable v = newVariable(LIRKind.value(Kind.Double)); + emitMove(v, input); + input = v; case D2L: - return emitConvert2Op(LIRKind.value(Kind.Long), D2L, input); + fromRegisterKind = Kind.Double; + toRegisterKind = Kind.Long; + conversionInstruction = D2L; + break; case F2D: return emitConvert2Op(LIRKind.value(Kind.Double), F2D, input); case F2I: - return emitConvert2Op(LIRKind.value(Kind.Int), F2I, input); - case F2L: - return emitConvert2Op(LIRKind.value(Kind.Long), F2L, input); + fromRegisterKind = Kind.Float; + toRegisterKind = Kind.Int; + conversionInstruction = F2I; + break; case I2D: return emitConvert2Op(LIRKind.value(Kind.Double), I2D, input); case I2F: @@ -801,6 +835,13 @@ default: throw GraalInternalError.shouldNotReachHere(); } + if (fromRegisterKind != null) { + AllocatableValue var = newVariable(LIRKind.value(toRegisterKind)); + emitMove(var, emitConvert2Op(LIRKind.value(fromRegisterKind), conversionInstruction, input)); + return var; + } else { + throw GraalInternalError.shouldNotReachHere(); + } } @Override @@ -856,10 +897,17 @@ append(new BinaryRegConst(SPARCArithmetic.LAND, result, asAllocatable(inputVal), Constant.forLong(mask))); return result; } else { - assert inputVal.getKind() == Kind.Int; + assert inputVal.getKind() == Kind.Int || inputVal.getKind() == Kind.Short || inputVal.getKind() == Kind.Byte : inputVal.getKind(); Variable result = newVariable(LIRKind.value(Kind.Int)); int mask = (int) IntegerStamp.defaultMask(fromBits); - append(new BinaryRegConst(SPARCArithmetic.IAND, result, asAllocatable(inputVal), Constant.forInt(mask))); + Constant constant = Constant.forInt(mask); + if (canInlineConstant(constant)) { + append(new BinaryRegConst(SPARCArithmetic.IAND, result, asAllocatable(inputVal), constant)); + } else { + Variable maskVar = newVariable(LIRKind.value(Kind.Int)); + emitMove(maskVar, constant); + append(new BinaryRegReg(IAND, result, maskVar, (inputVal))); + } if (toBits > 32) { Variable longResult = newVariable(LIRKind.value(Kind.Long)); emitMove(longResult, result);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Mon Jun 30 12:02:19 2014 +0200 @@ -61,7 +61,8 @@ register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); - link(new SPARCDeoptimizationStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new SPARCDeoptimizationStub(providers, target, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new SPARCUncommonTrapStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); super.initialize(providers, config); }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -61,6 +61,10 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + // Move the values up one level to be the input for the next call. + new SPARCMacroAssembler.Mov(asRegister(handlerInCallerPc), i2).emit(masm); + new SPARCMacroAssembler.Mov(asRegister(exception), i0).emit(masm); + new SPARCMacroAssembler.Mov(asRegister(exceptionPc), i1).emit(masm); leaveFrame(crb); // Restore SP from L7 if the exception PC is a method handle call site.
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Jun 30 12:02:19 2014 +0200 @@ -290,6 +290,19 @@ return result; } + @Override + public Value emitDeoptimizationFetchUnrollInfoCall(SaveRegistersOp saveRegisterOp) { + ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(FETCH_UNROLL_INFO); + + 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(LIRKind.value(Kind.Long))); + append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister)); + + return result; + } + public void emitNullCheck(Value address, LIRFrameState state) { assert address.getKind() == Kind.Object : address + " - " + address.getKind() + " not an object!"; append(new NullCheckOp(load(address), state));
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,12 +28,13 @@ import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.sparc.*; /** * Pops the current frame off the stack. */ @Opcode("LEAVE_CURRENT_STACK_FRAME") -final class SPARCHotSpotLeaveCurrentStackFrameOp extends SPARCHotSpotEpilogueOp { +final class SPARCHotSpotLeaveCurrentStackFrameOp extends SPARCLIRInstruction { @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { @@ -44,6 +45,6 @@ new Mov(o3, i3).emit(masm); new Mov(o4, i4).emit(masm); - leaveFrame(crb); + crb.frameContext.leave(crb); } }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveDeoptimizedStackFrameOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,12 +28,13 @@ import com.oracle.graal.asm.sparc.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.sparc.*; /** * Pops the current frame off the stack including the return address. */ @Opcode("LEAVE_DEOPTIMIZED_STACK_FRAME") -final class SPARCHotSpotLeaveDeoptimizedStackFrameOp extends SPARCHotSpotEpilogueOp { +final class SPARCHotSpotLeaveDeoptimizedStackFrameOp extends SPARCLIRInstruction { @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -24,10 +24,14 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; 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.SPARCAssembler.Ldx; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; +import com.oracle.graal.asm.sparc.SPARCAssembler.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; @@ -48,8 +52,17 @@ 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). - // int frameSize = crb.frameMap.frameSize(); - // new Stx(asRegister(address), new SPARCAddress(sp, frameSize)); - new Ldx(new SPARCAddress(g0, 0x123), g0).emit(masm); + 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); } }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Mon Jun 30 12:02:19 2014 +0200 @@ -58,7 +58,15 @@ ArrayList<Register> list = new ArrayList<>(); for (Register reg : getAllocatableRegisters()) { if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) { - list.add(reg); + // Special treatment for double precision + if (kind == Kind.Double) { + // Only even register numbers are valid double precision regs + if (reg.number % 2 == 0) { + list.add(reg); + } + } else { + list.add(reg); + } } } @@ -201,8 +209,18 @@ locations[i] = register.asValue(target.getLIRKind(kind)); } break; + case Double: + if (!stackOnly && currentFloating < fpuParameterRegisters.length) { + if (currentFloating % 2 != 0) { + // Make register number even to be a double reg + currentFloating++; + } + Register register = fpuParameterRegisters[currentFloating]; + currentFloating += 2; // Only every second is a double register + locations[i] = register.asValue(target.getLIRKind(kind)); + } + break; case Float: - case Double: if (!stackOnly && currentFloating < fpuParameterRegisters.length) { Register register = fpuParameterRegisters[currentFloating++]; locations[i] = register.asValue(target.getLIRKind(kind));
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java Mon Jun 30 12:02:19 2014 +0200 @@ -49,6 +49,9 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + // This Frame is left but the called unwind (which is sibling) method needs the exception as + // input in i0 + new Mov(o0, i0).emit(masm); leaveFrame(crb); ForeignCallLinkage linkage = crb.foreignCalls.lookupForeignCall(UNWIND_EXCEPTION_TO_CALLER); @@ -59,7 +62,6 @@ // Get return address (is in o7 after leave). Register returnAddress = asRegister(cc.getArgument(1)); new Mov(o7, returnAddress).emit(masm); - Register scratch = g5; SPARCCall.indirectJmp(crb, masm, scratch, linkage); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCUncommonTrapStub.java Mon Jun 30 12:02:19 2014 +0200 @@ -0,0 +1,48 @@ +/* + * 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.api.code.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.stubs.*; + +final class SPARCUncommonTrapStub extends UncommonTrapStub { + + private RegisterConfig registerConfig; + + public SPARCUncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { + super(providers, target, linkage); + // 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; + } + +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotForeignCallsProviderImpl.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotForeignCallsProviderImpl.java Mon Jun 30 12:02:19 2014 +0200 @@ -69,7 +69,7 @@ /** * Creates and registers the details for linking a foreign call to a {@link Stub}. - * + * * @param descriptor the signature of the call to the stub * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side * effects. Deoptimization will not return to a point before a stub call that cannot @@ -83,7 +83,7 @@ /** * Creates and registers the linkage for a foreign call. - * + * * @param descriptor the signature of the foreign call * @param address the address of the code to call * @param outgoingCcType outgoing (caller) calling convention type @@ -104,7 +104,7 @@ /** * Creates a {@linkplain ForeignCallStub stub} for a foreign call. - * + * * @param descriptor the signature of the call to the stub * @param address the address of the foreign code to call * @param prependThread true if the JavaThread value for the current thread is to be prepended
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_fadd.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_fadd.java Mon Jun 30 12:02:19 2014 +0200 @@ -49,4 +49,14 @@ runTest("test", 253.11f, 54.43f); } + @Test + public void run3() throws Throwable { + runTest("test", Float.MAX_VALUE, Float.MIN_VALUE); + } + + @Test + public void run4() throws Throwable { + runTest("test", Float.MAX_VALUE / 2, Float.MAX_VALUE / 2); + } + }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_i2d.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_i2d.java Mon Jun 30 12:02:19 2014 +0200 @@ -49,4 +49,24 @@ runTest("test", -34); } + @Test + public void run3() throws Throwable { + runTest("test", Integer.MIN_VALUE); + } + + @Test + public void run4() throws Throwable { + runTest("test", Integer.MAX_VALUE); + } + + @Test + public void run5() throws Throwable { + runTest("test", 34); + } + + @Test + public void run6() throws Throwable { + runTest("test", new Integer(Short.MAX_VALUE)); + } + }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_lcmp.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_lcmp.java Mon Jun 30 12:02:19 2014 +0200 @@ -49,4 +49,24 @@ runTest("test", -1L, 0L); } + /** + * Test with ugly numbers (which probably does not fit into one instruction + * + * @throws Throwable + */ + @Test + public void run3() throws Throwable { + runTest("test", 293521900824L, 97726785831L); + } + + /** + * Test with big numbers where it makes difference if the value is handled with 64 bits + * + * @throws Throwable + */ + @Test + public void run4() throws Throwable { + runTest("test", -1L, Long.MIN_VALUE); + } + }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_ldiv2.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_ldiv2.java Mon Jun 30 12:02:19 2014 +0200 @@ -49,4 +49,19 @@ runTest("test", 11L, 0L); } + @Test + public void run2() throws Throwable { + runTest("test", 11L, 1000000000000L); + } + + @Test + public void run3() throws Throwable { + runTest("test", 1000000000000L, 11L); + } + + @Test + public void run4() throws Throwable { + runTest("test", 1000000000000L, 0L); + } + }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Mon Jun 30 12:02:19 2014 +0200 @@ -28,38 +28,12 @@ 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.And; -import com.oracle.graal.asm.sparc.SPARCAssembler.Faddd; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fadds; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fdivd; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fdivs; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fdtoi; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fmuld; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fmuls; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fnegd; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fnegs; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fstoi; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fsubd; -import com.oracle.graal.asm.sparc.SPARCAssembler.Fsubs; -import com.oracle.graal.asm.sparc.SPARCAssembler.Mulx; -import com.oracle.graal.asm.sparc.SPARCAssembler.Or; -import com.oracle.graal.asm.sparc.SPARCAssembler.Sdivx; -import com.oracle.graal.asm.sparc.SPARCAssembler.Sll; -import com.oracle.graal.asm.sparc.SPARCAssembler.Sllx; -import com.oracle.graal.asm.sparc.SPARCAssembler.Sra; -import com.oracle.graal.asm.sparc.SPARCAssembler.Srax; -import com.oracle.graal.asm.sparc.SPARCAssembler.Srl; -import com.oracle.graal.asm.sparc.SPARCAssembler.Srlx; -import com.oracle.graal.asm.sparc.SPARCAssembler.Sub; -import com.oracle.graal.asm.sparc.SPARCAssembler.Xor; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Neg; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Not; -import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Signx; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.gen.*; +import com.oracle.graal.sparc.*; public enum SPARCArithmetic { // @formatter:off @@ -150,17 +124,23 @@ @Def({REG}) protected Value result; @Use({REG, CONST}) protected Value x; @Alive({REG, CONST}) protected Value y; + @State LIRFrameState state; public BinaryRegReg(SPARCArithmetic opcode, Value result, Value x, Value y) { + this(opcode, result, x, y, null); + } + + public BinaryRegReg(SPARCArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) { this.opcode = opcode; this.result = result; this.x = x; this.y = y; + this.state = state; } @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - emit(crb, masm, opcode, result, x, y, null); + emit(crb, masm, opcode, result, x, y, state); } @Override @@ -288,9 +268,9 @@ } } - public static void emit(CompilationResultBuilder crb, SPARCAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) { + public static void emit(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) { int exceptionOffset = -1; - if (isConstant(src1)) { + if (isConstant(src1) && !isConstant(src2)) { switch (opcode) { case ISUB: assert isSimm13(crb.asIntConst(src1)); @@ -303,6 +283,13 @@ throw GraalInternalError.unimplemented(); // new Sdivx(masm, asIntReg(src1), asIntReg(src2), // asIntReg(dst)); + case LDIV: + int c = crb.asIntConst(src1); + assert isSimm13(c); + exceptionOffset = masm.position(); + new Sdivx(asLongReg(src2), c, asLongReg(dst)).emit(masm); + new Mulx(asLongReg(src1), asLongReg(dst), asLongReg(dst)).emit(masm); + break; case FSUB: case FDIV: case DSUB: @@ -330,7 +317,7 @@ new Sdivx(asIntReg(src1), crb.asIntConst(src2), asIntReg(dst)).emit(masm); break; case IAND: - assert isSimm13(crb.asIntConst(src2)); + assert isSimm13(crb.asIntConst(src2)) : src2; new And(asIntReg(src1), crb.asIntConst(src2), asIntReg(dst)).emit(masm); break; case ISHL: @@ -366,7 +353,17 @@ new Mulx(asLongReg(src1), crb.asIntConst(src2), asLongReg(dst)).emit(masm); break; case LDIV: - throw GraalInternalError.unimplemented(); + int c = crb.asIntConst(src2); + exceptionOffset = masm.position(); + if (c == 0) { // Generate div by zero trap + new Sdivx(SPARC.g0, 0, asLongReg(dst)).emit(masm); + } else if (isConstant(src1)) { // Both are const, therefore just load the const + new Setx(crb.asIntConst(src1) / c, asLongReg(dst), false).emit(masm); + } else { // Otherwise try to divide + assert isSimm13(crb.asLongConst(src2)); + new Sdivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(dst)).emit(masm); + } + break; case LUDIV: throw GraalInternalError.unimplemented(); case LAND: @@ -431,10 +428,10 @@ new Sll(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm); break; case ISHR: - new Srl(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm); + new Sra(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm); break; case IUSHR: - new Sra(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm); + new Srl(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm); break; case IREM: throw GraalInternalError.unimplemented(); @@ -448,6 +445,7 @@ new Mulx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm); break; case LDIV: + exceptionOffset = masm.position(); new Sdivx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm); break; case LUDIV: @@ -502,16 +500,42 @@ throw GraalInternalError.shouldNotReachHere(); } } - if (info != null) { assert exceptionOffset != -1; crb.recordImplicitException(exceptionOffset, info); } } - public static void emit(CompilationResultBuilder crb, SPARCAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, Value src2, Value scratch1, Value scratch2, LIRFrameState info) { + public static void emit(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, Value src2, Value scratch1, Value scratch2, LIRFrameState info) { int exceptionOffset = -1; - if (isConstant(src1)) { + if (isConstant(src1) && isConstant(src2)) { + switch (opcode) { + case IREM: { + int a = crb.asIntConst(src1); + int b = crb.asIntConst(src2); + if (b == 0) { + exceptionOffset = masm.position(); + new Sdivx(SPARC.g0, 0, asIntReg(dst)).emit(masm); + } else { + new Setx(a % b, asIntReg(dst), false).emit(masm); + } + } + break; + case LREM: { + long a = crb.asLongConst(src1); + long b = crb.asLongConst(src2); + if (b == 0) { + exceptionOffset = masm.position(); + new Sdivx(SPARC.g0, 0, asLongReg(dst)).emit(masm); + } else { + new Setx(a % b, asLongReg(dst), false).emit(masm); + } + } + break; + default: + throw GraalInternalError.shouldNotReachHere("not implemented"); + } + } else if (isConstant(src1)) { switch (opcode) { default: throw GraalInternalError.shouldNotReachHere(); @@ -521,12 +545,14 @@ case IREM: assert isSimm13(crb.asIntConst(src2)); new Sra(asIntReg(src1), 0, asIntReg(src1)).emit(masm); + exceptionOffset = masm.position(); 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)); + exceptionOffset = masm.position(); new Sdivx(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); @@ -539,6 +565,17 @@ } else { switch (opcode) { case LREM: + 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); + break; + case IREM: + 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); + break; case LUREM: throw GraalInternalError.unimplemented(); default: @@ -560,31 +597,90 @@ case INEG: new Neg(asIntReg(src), asIntReg(dst)).emit(masm); break; + case LNEG: + new Neg(asLongReg(src), asLongReg(dst)).emit(masm); + break; case INOT: new Not(asIntReg(src), asIntReg(dst)).emit(masm); break; case LNOT: new Not(asLongReg(src), asLongReg(dst)).emit(masm); break; + case D2F: + new Fdtos(asDoubleReg(src), asFloatReg(dst)).emit(masm); + break; + case L2D: + if (src.getPlatformKind() == Kind.Long) { + new Movxtod(asLongReg(src), asDoubleReg(dst)).emit(masm); + new Fxtod(masm, asDoubleReg(dst), asDoubleReg(dst)); + } else if (src.getPlatformKind() == Kind.Double) { + new Fxtod(masm, asDoubleReg(src), asDoubleReg(dst)); + } else { + throw GraalInternalError.shouldNotReachHere("cannot handle source register " + src.getPlatformKind()); + } + break; case I2L: new Signx(asIntReg(src), asLongReg(dst)).emit(masm); break; case L2I: new Signx(asLongReg(src), asIntReg(dst)).emit(masm); break; + case B2L: + new Sllx(asIntReg(src), 56, asLongReg(dst)).emit(masm); + new Srax(asLongReg(dst), 56, asLongReg(dst)).emit(masm); + break; + case S2L: + new Sllx(asIntReg(src), 48, asLongReg(dst)).emit(masm); + new Srax(asLongReg(dst), 48, asLongReg(dst)).emit(masm); + break; case B2I: new Sll(asIntReg(src), 24, asIntReg(dst)).emit(masm); - new Srl(asIntReg(dst), 24, asIntReg(dst)).emit(masm); + new Sra(asIntReg(dst), 24, asIntReg(dst)).emit(masm); break; case S2I: new Sll(asIntReg(src), 16, asIntReg(dst)).emit(masm); - new Srl(asIntReg(dst), 16, asIntReg(dst)).emit(masm); + new Sra(asIntReg(dst), 16, asIntReg(dst)).emit(masm); break; case I2F: - new Fstoi(masm, asIntReg(src), asFloatReg(dst)); + if (src.getPlatformKind() == Kind.Int) { + new Movwtos(asIntReg(src), asFloatReg(dst)).emit(masm); + new Fitos(masm, asFloatReg(dst), asFloatReg(dst)); + } else if (src.getPlatformKind() == Kind.Float) { + new Fitos(masm, asFloatReg(src), asFloatReg(dst)); + } else { + throw GraalInternalError.shouldNotReachHere("cannot handle source register " + src.getPlatformKind()); + } + break; + case F2D: + new Fstod(masm, asFloatReg(src), asDoubleReg(dst)); + break; + case F2L: + new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm); + new Fbfcc(masm, FCond.Fbo, false, 4); + new Fstox(masm, asFloatReg(src), asFloatReg(dst)); + new Fitos(masm, asFloatReg(dst), asFloatReg(dst)); + new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm); break; - case I2D: - new Fdtoi(masm, asIntReg(src), asDoubleReg(dst)); + case F2I: + new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm); + new Fbfcc(masm, FCond.Fbo, false, 4); + new Fstoi(masm, asFloatReg(src), asFloatReg(dst)); + new Fitos(masm, asFloatReg(dst), asFloatReg(dst)); + new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm); + break; + case D2L: + new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(dst), asDoubleReg(dst)).emit(masm); + new Fbfcc(masm, FCond.Fbo, false, 4); + new Fdtox(masm, asDoubleReg(src), asDoubleReg(dst)); + new Fxtod(masm, asDoubleReg(dst), asDoubleReg(dst)); + 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 Fbfcc(masm, FCond.Fbo, false, 4); + new Fdtoi(masm, asDoubleReg(src), asDoubleReg(dst)); + new Fitod(masm, asDoubleReg(dst), asDoubleReg(dst)); + new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm); break; case FNEG: new Fnegs(masm, asFloatReg(src), asFloatReg(dst));
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java Mon Jun 30 12:02:19 2014 +0200 @@ -60,9 +60,17 @@ @Override protected void verify() { super.verify(); - assert (name().startsWith("I") && x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long) || - (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object) || - (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double); + + // @formatter:off + assert (name().startsWith("I") && (x.getKind() == Kind.Int || x.getKind()==Kind.Byte) && + (y.getKind().getStackKind() == Kind.Int || y.getKind().getStackKind() == Kind.Byte)) || + (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long) || + (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object) || + (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || + (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double) + : "Name; " + name() + " x: " + x + " y: " + y; + + // @formatter:on } } @@ -79,11 +87,11 @@ new Cmp(asObjectReg(x), asObjectReg(y)).emit(masm); break; case FCMP: - // masm.ucomiss(asFloatReg(x), asFloatReg(y)); - // break; + new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(x), asFloatReg(y)).emit(masm); + break; case DCMP: - // masm.ucomisd(asDoubleReg(x), asDoubleReg(y)); - // break; + new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(x), asDoubleReg(y)).emit(masm); + break; default: throw GraalInternalError.shouldNotReachHere(); } @@ -106,11 +114,11 @@ throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons"); } case FCMP: - // masm.ucomiss(asFloatReg(x), (AMD64Address) crb.asFloatConstRef(y)); - // break; + new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(x), asFloatReg(y)).emit(masm); + break; case DCMP: - // masm.ucomisd(asDoubleReg(x), (AMD64Address) crb.asDoubleConstRef(y)); - // break; + new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(x), asDoubleReg(y)).emit(masm); + break; default: throw GraalInternalError.shouldNotReachHere(); }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Mon Jun 30 12:02:19 2014 +0200 @@ -40,6 +40,8 @@ import com.oracle.graal.asm.sparc.SPARCAssembler.Bpne; import com.oracle.graal.asm.sparc.SPARCAssembler.CC; import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag; +import com.oracle.graal.asm.sparc.SPARCAssembler.FCond; +import com.oracle.graal.asm.sparc.SPARCAssembler.Fbfcc; import com.oracle.graal.asm.sparc.SPARCAssembler.Movcc; import com.oracle.graal.asm.sparc.SPARCAssembler.Sub; import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Bpgeu; @@ -320,15 +322,12 @@ // 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); - - if (unorderedIsTrue && !trueOnUnordered(condition)) { - // cmove(crb, masm, result, ConditionFlag.Parity, trueValue); - throw GraalInternalError.unimplemented(); - } else if (!unorderedIsTrue && trueOnUnordered(condition)) { - // cmove(crb, masm, result, ConditionFlag.Parity, falseValue); - throw GraalInternalError.unimplemented(); + SPARCMove.move(crb, masm, result, trueValue); + cmove(crb, masm, kind, result, condition, falseValue); + // TODO: This may be omitted, when doing the right check beforehand (There are + // instructions which control the unordered behavior as well) + if (!unorderedIsTrue) { + cmove(crb, masm, kind, result, ConditionFlag.F_Unordered, falseValue); } } } @@ -347,6 +346,35 @@ case Object: new Movcc(cond, CC.Xcc, asRegister(other), asRegister(result)).emit(masm); break; + case Float: + case Double: + FCond fc = null; + switch (cond) { + case Equal: + fc = FCond.Fbne; + break; + case Greater: + fc = FCond.Fble; + break; + case GreaterEqual: + fc = FCond.Fbl; + break; + case Less: + fc = FCond.Fbge; + break; + case LessEqual: + fc = FCond.Fbg; + break; + case F_Ordered: + fc = FCond.Fbo; + break; + case F_Unordered: + fc = FCond.Fbu; + break; + } + new Fbfcc(masm, fc, true, 2).equals(masm); + SPARCMove.move(crb, masm, result, other); + break; default: throw GraalInternalError.shouldNotReachHere(); } @@ -382,24 +410,15 @@ case NE: return ConditionFlag.NotEqual; case LT: + return ConditionFlag.Less; case LE: + return ConditionFlag.LessEqual; case GE: + return ConditionFlag.GreaterEqual; case GT: + return ConditionFlag.Greater; default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - private static boolean trueOnUnordered(ConditionFlag condition) { - switch (condition) { - case NotEqual: - case Less: - return false; - case Equal: - case GreaterEqual: - return true; - default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("Unimplemented for " + cond); } } }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Fri Jun 27 23:04:59 2014 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Mon Jun 30 12:02:19 2014 +0200 @@ -23,24 +23,23 @@ 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.CompilationResult.RawData; 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.*; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.ImplicitNullCheck; -import com.oracle.graal.lir.StandardOp.MoveOp; -import com.oracle.graal.lir.StandardOp.NullCheck; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.lir.asm.*; public class SPARCMove { - @Opcode("MOVE") + @Opcode("MOVE_TOREG") public static class MoveToRegOp extends SPARCLIRInstruction implements MoveOp { @Def({REG, HINT}) protected AllocatableValue result; @@ -67,7 +66,7 @@ } } - @Opcode("MOVE") + @Opcode("MOVE_FROMREG") public static class MoveFromRegOp extends SPARCLIRInstruction implements MoveOp { @Def({REG, STACK}) protected AllocatableValue result; @@ -207,7 +206,8 @@ SPARCAddress addr = (SPARCAddress) crb.recordDataReferenceInCode(rawData); assert addr == masm.getPlaceholder(); final boolean forceRelocatable = true; - new Setx(0, asRegister(result), forceRelocatable).emit(masm); + Register dstReg = asRegister(result); + new Setx(0, dstReg, forceRelocatable).emit(masm); } } @@ -319,9 +319,13 @@ new Stx(asRegister(input), addr).emit(masm); break; case Float: + new Stf(asRegister(input), addr).emit(masm); + break; case Double: + new Stdf(asRegister(input), addr).emit(masm); + break; default: - throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind()); + throw GraalInternalError.shouldNotReachHere("missing: " + kind); } } } @@ -391,10 +395,14 @@ } } + @SuppressWarnings("unused") private static void reg2reg(SPARCAssembler masm, Value result, Value input) { final Register src = asRegister(input); final Register dst = asRegister(result); - if (src.equals(dst)) { + // implicit conversions between double and float registers can happen in the "same Register" +// f0->d0 + boolean isFloatToDoubleConversion = result.getKind() == Kind.Double && input.getKind() == Kind.Float; + if (src.equals(dst) && !isFloatToDoubleConversion) { return; } switch (input.getKind()) { @@ -404,10 +412,31 @@ new Mov(src, dst).emit(masm); break; case Float: - new Fmovs(src, dst).emit(masm); + switch (result.getKind()) { + case Long: + new Movstosw(src, dst).emit(masm); + break; + case Int: + new Movstouw(src, dst).emit(masm); + break; + case Float: + new Fmovs(src, dst).emit(masm); + break; + case Double: + new Fstod(masm, src, dst); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } break; case Double: - new Fmovd(src, dst).emit(masm); + if (result.getPlatformKind() == Kind.Long) { + new Movdtox(src, dst).emit(masm); + } else if (result.getPlatformKind() == Kind.Int) { + new Movstouw(src, dst).emit(masm); + } else { + new Fmovd(src, dst).emit(masm); + } break; default: throw GraalInternalError.shouldNotReachHere(); @@ -455,6 +484,7 @@ } private static void const2reg(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Constant input) { + Register scratch = g5; switch (input.getKind().getStackKind()) { case Int: if (crb.codeCache.needsDataPatch(input)) { @@ -481,7 +511,19 @@ } break; case Float: - new Ldf((SPARCAddress) crb.asFloatConstRef(input), asFloatReg(result)).emit(masm); + crb.asFloatConstRef(input); + // First load the address into the scratch register + new Setx(0, scratch, true).emit(masm); + // Now load the float value + new Ldf(scratch, asFloatReg(result)).emit(masm); + break; + case Double: + crb.asDoubleConstRef(input); + scratch = g5; + // First load the address into the scratch register + new Setx(0, scratch, true).emit(masm); + // Now load the float value + new Lddf(scratch, asDoubleReg(result)).emit(masm); break; case Object: if (input.isNull()) {
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp Fri Jun 27 23:04:59 2014 +0200 +++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -59,11 +59,11 @@ void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, oop data) { address pc = _instructions->start() + pc_offset; + address const_start = _constants->start(); jint offset = DataSectionReference::offset(data); NativeMovRegMem* load = nativeMovRegMem_at(pc); - int disp = _constants_size + pc_offset - offset - BytesPerInstWord; - load->set_offset(-disp); + load->add_offset_in_bytes((long)const_start+offset); } void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Jun 27 23:04:59 2014 +0200 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -43,6 +43,9 @@ #include "compiler/compileBroker.hpp" #include "shark/sharkCompiler.hpp" #endif +#ifdef GRAAL +#include "graal/graalJavaAccess.hpp" +#endif #define __ masm-> @@ -990,6 +993,19 @@ // Jump to the compiled code just as if compiled code was doing it. __ ld_ptr(G5_method, in_bytes(Method::from_compiled_offset()), G3); +#ifdef GRAAL + // check if this call should be routed towards a specific entry point + __ ld(Address(G2_thread, in_bytes(JavaThread::graal_alternate_call_target_offset())), G1); + __ cmp(G0, G1); + Label no_alternative_target; + __ br(Assembler::equal, false, Assembler::pn, no_alternative_target); + __ delayed()->nop(); + + __ ld_ptr(G2_thread, in_bytes(JavaThread::graal_alternate_call_target_offset()), G3); + __ st(G0, Address(G2_thread, in_bytes(JavaThread::graal_alternate_call_target_offset()))); + + __ bind(no_alternative_target); +#endif // 6243940 We might end up in handle_wrong_method if // the callee is deoptimized as we race thru here. If that @@ -3483,6 +3499,46 @@ __ ba(cont); __ delayed()->mov(Deoptimization::Unpack_deopt, L0deopt_mode); + +#ifdef GRAAL + masm->block_comment("BEGIN GRAAL"); + int implicit_exception_uncommon_trap_offset = __ offset() - start; + //__ pushptr(Address(G2_thread, in_bytes(JavaThread::graal_implicit_exception_pc_offset()))); + __ ld_ptr(G2_thread, in_bytes(JavaThread::graal_implicit_exception_pc_offset()), O7); + //__ add(G0, 0x321, O7); + __ add(O7, -8, O7); + //__ st_ptr(I7, SP, I7->sp_offset_in_saved_window()*wordSize + STACK_BIAS); + // Save everything in sight. + masm->block_comment("save_live_regs"); + (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words); + masm->block_comment("/save_live_regs"); + //__ ld_ptr(G2_thread, in_bytes(JavaThread::graal_implicit_exception_pc_offset()), O7); + // fetch_unroll_info needs to call last_java_frame() + masm->block_comment("set_last_java_frame"); + __ set_last_Java_frame(SP, NULL); + masm->block_comment("/set_last_java_frame"); + + //__ movl(c_rarg1, Address(r15_thread, in_bytes(ThreadShadow::pending_deoptimization_offset()))); + __ ld(G2_thread, in_bytes(ThreadShadow::pending_deoptimization_offset()), O1); + //__ movl(Address(r15_thread, in_bytes(ThreadShadow::pending_deoptimization_offset())), -1); + __ sub(G0, 1, L1); + __ st_ptr(L1, G2_thread, in_bytes(ThreadShadow::pending_deoptimization_offset())); + + __ mov((int32_t)Deoptimization::Unpack_reexecute, L0deopt_mode); + __ mov(G2_thread, O0); + __ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)); + __ delayed()->nop(); + oop_maps->add_gc_map( __ offset()-start, map->deep_copy()); + __ get_thread(); + __ add(O7, 8, O7); + __ reset_last_Java_frame(); + + Label after_fetch_unroll_info_call; + __ ba(after_fetch_unroll_info_call); + __ delayed()->nop(); // Delay slot + masm->block_comment("END GRAAL"); +#endif // GRAAL + int exception_offset = __ offset() - start; // restore G2, the trampoline destroyed it @@ -3560,6 +3616,9 @@ __ reset_last_Java_frame(); +#ifdef GRAAL + __ bind(after_fetch_unroll_info_call); +#endif // NOTE: we know that only O0/O1 will be reloaded by restore_result_registers // so this move will survive @@ -3568,7 +3627,6 @@ __ mov(O0, O2UnrollBlock->after_save()); RegisterSaver::restore_result_registers(masm); - Label noException; __ cmp_and_br_short(G4deopt_mode, Deoptimization::Unpack_exception, Assembler::notEqual, Assembler::pt, noException); @@ -3625,6 +3683,9 @@ masm->flush(); _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_words); _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); +#ifdef GRAAL + _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset); +#endif } #ifdef COMPILER2
--- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Jun 27 23:04:59 2014 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Jun 30 12:02:19 2014 +0200 @@ -587,7 +587,23 @@ } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) { return JNIHandles::make_local((oop) result.get_jobject()); } else { - oop o = java_lang_boxing_object::create(jap.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL); + jvalue *value = (jvalue *) result.get_value_addr(); + // Narrow the value down if required (Important on big endian machines) + switch (jap.get_ret_type()) { + case T_BOOLEAN: + value->z = (jboolean) value->i; + break; + case T_BYTE: + value->b = (jbyte) value->i; + break; + case T_CHAR: + value->c = (jchar) value->i; + break; + case T_SHORT: + value->s = (jshort) value->i; + break; + } + oop o = java_lang_boxing_object::create(jap.get_ret_type(), value, CHECK_NULL); return JNIHandles::make_local(o); } C2V_END