< prev index next >
test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/sparc/SPARCTestAssembler.java
Print this page
rev 11569 : 8159368: [JVMCI] SPARCHotSpotRegisterConfig.callingConvention gives incorrect calling convention for native calls containing fp args
@@ -21,31 +21,38 @@
* questions.
*/
package jdk.vm.ci.code.test.sparc;
+import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.DebugInfo;
import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.code.RegisterValue;
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.code.site.ConstantReference;
import jdk.vm.ci.code.site.DataSectionReference;
import jdk.vm.ci.code.test.TestAssembler;
import jdk.vm.ci.code.test.TestHotSpotVMConfig;
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
import jdk.vm.ci.hotspot.HotSpotConstant;
import jdk.vm.ci.hotspot.HotSpotForeignCallTarget;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.VMConstant;
import jdk.vm.ci.sparc.SPARC;
import jdk.vm.ci.sparc.SPARCKind;
public class SPARCTestAssembler extends TestAssembler {
private static final int MASK13 = (1 << 13) - 1;
+ private static final Register scratchRegister = SPARC.g5;
+ private static final Register floatScratch = SPARC.f30;
+ private static final Register doubleScratch = SPARC.d62;
public SPARCTestAssembler(CodeCacheProvider codeCache, TestHotSpotVMConfig config) {
super(codeCache, config, 0, 16, SPARCKind.WORD, SPARC.l0, SPARC.l1, SPARC.l2, SPARC.l3, SPARC.l4, SPARC.l5, SPARC.l6, SPARC.l7);
}
@@ -134,21 +141,22 @@
Register ret = newRegister();
loadIntToRegister(c, ret);
return ret;
}
- private void loadIntToRegister(int c, Register ret) {
+ private Register loadIntToRegister(int c, Register ret) {
int hi = c >>> 10;
int lo = c & ((1 << 10) - 1);
if (hi == 0) {
emitOp3(0b10, ret, 0b000010, SPARC.g0, lo); // OR g0, lo, ret
} else {
emitOp2(ret, 0b100, hi); // SETHI hi, ret
if (lo != 0) {
emitOp3(0b10, ret, 0b000010, ret, lo); // OR ret, lo, ret
}
}
+ return ret;
}
@Override
public Register emitLoadLong(long c) {
Register ret = newRegister();
@@ -162,16 +170,17 @@
ref.setOffset(data.position());
data.emitLong(c);
emitLoadPointerToRegister(ref, ret);
}
- public void emitLoadLongToRegister(long c, Register r) {
+ public Register emitLoadLongToRegister(long c, Register r) {
if ((c & 0xFFFF_FFFFL) == c) {
loadIntToRegister((int) c, r);
} else {
loadLongToRegister(c, r);
}
+ return r;
}
private void emitPatchableSethi(Register ret, boolean wide) {
int startPos = code.position();
emitOp2(ret, 0b100, 0); // SETHI 0, ret
@@ -183,20 +192,43 @@
}
}
@Override
public Register emitLoadFloat(float c) {
+ return emitLoadFloat(SPARC.f0, c);
+ }
+
+ public Register emitLoadFloat(Register reg, float c) {
+ return emitLoadFloat(reg, c, newRegister());
+ }
+
+ public Register emitLoadFloat(Register reg, float c, Register scratch) {
DataSectionReference ref = new DataSectionReference();
data.align(4);
ref.setOffset(data.position());
data.emitFloat(c);
- Register ptr = newRegister();
recordDataPatchInCode(ref);
- emitPatchableSethi(ptr, true);
- emitOp3(0b11, SPARC.f0, 0b100000, ptr, 0); // LDF [ptr+0], f0
- return SPARC.f0;
+ emitPatchableSethi(scratch, true);
+ emitOp3(0b11, reg, 0b100000, scratch, 0); // LDF [scratch+0], f0
+ return reg;
+ }
+
+ public Register emitLoadDouble(Register reg, double c) {
+ return emitLoadDouble(reg, c, newRegister());
+ }
+
+ public Register emitLoadDouble(Register reg, double c, Register scratch) {
+ DataSectionReference ref = new DataSectionReference();
+ data.align(8);
+ ref.setOffset(data.position());
+ data.emitDouble(c);
+
+ recordDataPatchInCode(ref);
+ emitPatchableSethi(scratch, true);
+ emitOp3(0b11, reg, 0b100011, scratch, 0); // LDDF [ptr+0], f0
+ return reg;
}
@Override
public Register emitLoadPointer(HotSpotConstant c) {
Register ret = newRegister();
@@ -238,28 +270,52 @@
}
@Override
public StackSlot emitIntToStack(Register a) {
StackSlot ret = newStackSlot(SPARCKind.WORD);
- // STW a, [fp+offset]
- emitStore(0b000100, a, ret);
+ intToStack(a, ret);
return ret;
}
+ public void intToStack(Register a, StackSlot ret) {
+ // STW a, [(s|f)p+offset]
+ emitStore(0b000100, a, ret);
+ }
+
@Override
public StackSlot emitLongToStack(Register a) {
StackSlot ret = newStackSlot(SPARCKind.XWORD);
- // STX a, [sp+offset]
- emitStore(0b001110, a, ret);
+ longToStack(a, ret);
return ret;
}
+ public void longToStack(Register a, StackSlot ret) {
+ // STX a, [(f|s)p+offset]
+ emitStore(0b001110, a, ret);
+ }
+
@Override
public StackSlot emitFloatToStack(Register a) {
StackSlot ret = newStackSlot(SPARCKind.SINGLE);
+ floatToStack(a, ret);
+ return ret;
+ }
+
+ public void floatToStack(Register a, StackSlot ret) {
// STF a, [fp+offset]
emitStore(0b100100, a, ret);
+ }
+
+ @Override
+ public StackSlot emitDoubleToStack(Register a) {
+ StackSlot ret = newStackSlot(SPARCKind.DOUBLE);
+ return doubleToStack(a, ret);
+ }
+
+ public StackSlot doubleToStack(Register a, StackSlot ret) {
+ // STD a, [(s|f)p+offset]
+ emitStore(0b100111, a, ret);
return ret;
}
@Override
public StackSlot emitPointerToStack(Register a) {
@@ -276,20 +332,26 @@
emitStore(0b000100, a, ret);
return ret;
}
private void emitStore(int op3, Register a, StackSlot ret) {
+ Register base;
+ if (ret.getRawOffset() < 0) {
+ base = SPARC.fp;
+ } else {
+ base = SPARC.sp;
+ }
int offset = ret.getRawOffset() + SPARC.STACK_BIAS;
if (isSimm(offset, 13)) {
// op3 a, [sp+offset]
- emitOp3(0b11, a, op3, SPARC.fp, offset);
+ emitOp3(0b11, a, op3, base, offset);
} else {
assert a != SPARC.g3;
Register r = SPARC.g3;
loadLongToRegister(offset, r);
// op3 a, [sp+g3]
- emitOp3(0b11, a, op3, SPARC.fp, r);
+ emitOp3(0b11, a, op3, base, r);
}
}
@Override
public Register emitUncompressPointer(Register compressed, long base, int shift) {
@@ -326,10 +388,17 @@
public void emitIntRet(Register a) {
emitPointerRet(a);
}
@Override
+ public void emitFloatRet(Register a) {
+ assert a == SPARC.f0 : "Unimplemented";
+ emitOp3(0b10, SPARC.g0, 0b111000, SPARC.i7, 8); // JMPL [i7+8], g0
+ emitOp3(0b10, SPARC.g0, 0b111101, SPARC.g0, SPARC.g0); // RESTORE g0, g0, g0
+ }
+
+ @Override
public void emitPointerRet(Register a) {
emitMove(SPARC.i0, a);
emitOp3(0b10, SPARC.g0, 0b111000, SPARC.i7, 8); // JMPL [i7+8], g0
emitOp3(0b10, SPARC.g0, 0b111101, SPARC.g0, SPARC.g0); // RESTORE g0, g0, g0
}
@@ -347,6 +416,59 @@
} else {
data.align(8);
}
return super.emitDataItem(c);
}
+
+ @Override
+ public void emitCall(long addr) {
+ Register dst = emitLoadLong(addr);
+ emitOp3(0b10, SPARC.o7, 0b111000, dst, 0); // JMPL [dst+0], o7
+ emitNop();
+ }
+
+ @Override
+ public void emitLoad(AllocatableValue av, Object prim) {
+ if (av instanceof RegisterValue) {
+ Register reg = ((RegisterValue) av).getRegister();
+ RegisterCategory cat = reg.getRegisterCategory();
+ if (cat.equals(SPARC.FPUs)) {
+ emitLoadFloat(reg, (Float) prim, scratchRegister);
+ } else if (cat.equals(SPARC.FPUd)) {
+ emitLoadDouble(reg, (Double) prim, scratchRegister);
+ } else if (prim instanceof Integer) {
+ loadIntToRegister((Integer) prim, reg);
+ } else if (prim instanceof Long) {
+ loadLongToRegister((Long) prim, reg);
+ }
+ } else if (av instanceof StackSlot) {
+ StackSlot slot = (StackSlot) av;
+ if (prim instanceof Float) {
+ floatToStack(emitLoadFloat(floatScratch, (Float) prim, scratchRegister), slot);
+ } else if (prim instanceof Double) {
+ doubleToStack(emitLoadDouble(doubleScratch, (Double) prim, scratchRegister), slot);
+ } else if (prim instanceof Integer) {
+ intToStack(loadIntToRegister((Integer) prim, scratchRegister), slot);
+ } else if (prim instanceof Long) {
+ longToStack(emitLoadLongToRegister((Long) prim, scratchRegister), slot);
+ }
+ } else {
+ throw new IllegalArgumentException("Unknown value " + av);
+ }
+ }
+
+ @Override
+ public void emitCallEpilogue(CallingConvention cc) {
+ // Nothing to do here.
+ }
+
+ @Override
+ public void emitCallPrologue(CallingConvention cc, Object... prim) {
+ emitGrowStack(cc.getStackSize());
+ frameSize += cc.getStackSize();
+ AllocatableValue[] args = cc.getArguments();
+ for (int i = 0; i < args.length; i++) {
+ emitLoad(args[i], prim[i]);
+ }
+ }
+
}
< prev index next >