< prev index next >
test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/amd64/AMD64TestAssembler.java
Print this page
rev 11569 : 8159368: [JVMCI] SPARCHotSpotRegisterConfig.callingConvention gives incorrect calling convention for native calls containing fp args
@@ -21,23 +21,28 @@
* questions.
*/
package jdk.vm.ci.code.test.amd64;
+import static jdk.vm.ci.amd64.AMD64.xmm0;
+
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64Kind;
+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.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.HotSpotConstant;
import jdk.vm.ci.hotspot.HotSpotForeignCallTarget;
+import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.VMConstant;
public class AMD64TestAssembler extends TestAssembler {
@@ -114,42 +119,74 @@
}
@Override
public Register emitLoadInt(int c) {
Register ret = newRegister();
+ return emitLoadInt(ret, c);
+ }
+
+ public Register emitLoadInt(Register ret, int c) {
emitREX(false, 0, 0, ret.encoding);
code.emitByte(0xB8 | (ret.encoding & 0x7)); // MOV r32, imm32
code.emitInt(c);
return ret;
}
@Override
public Register emitLoadLong(long c) {
Register ret = newRegister();
+ return emitLoadLong(ret, c);
+ }
+
+ public Register emitLoadLong(Register ret, long c) {
emitREX(true, 0, 0, ret.encoding);
code.emitByte(0xB8 | (ret.encoding & 0x7)); // MOV r64, imm64
code.emitLong(c);
return ret;
}
@Override
public Register emitLoadFloat(float c) {
+ Register ret = AMD64.xmm0;
+ return emitLoadFloat(ret, c);
+ }
+
+ public Register emitLoadFloat(Register ret, float c) {
DataSectionReference ref = new DataSectionReference();
ref.setOffset(data.position());
data.emitFloat(c);
recordDataPatchInCode(ref);
- Register ret = AMD64.xmm0;
emitREX(false, ret.encoding, 0, 0);
code.emitByte(0xF3);
code.emitByte(0x0F);
code.emitByte(0x10); // MOVSS xmm1, xmm2/m32
code.emitByte(0x05 | ((ret.encoding & 0x7) << 3)); // xmm, [rip+offset]
code.emitInt(0xDEADDEAD);
return ret;
}
+ public Register emitLoadDouble(double c) {
+ Register ret = AMD64.xmm0;
+ return emitLoadDouble(ret, c);
+ }
+
+ public Register emitLoadDouble(Register ret, double c) {
+ DataSectionReference ref = new DataSectionReference();
+ ref.setOffset(data.position());
+ data.emitDouble(c);
+
+ recordDataPatchInCode(ref);
+ emitREX(false, ret.encoding, 0, 0);
+ code.emitByte(0xF2);
+ code.emitByte(0x0F);
+ code.emitByte(0x10); // MOVSD xmm1, xmm2/m32
+ code.emitByte(0x05 | ((ret.encoding & 0x7) << 3)); // xmm, [rip+offset]
+ code.emitInt(0xDEADDEAD);
+ return ret;
+ }
+
@Override
public Register emitLoadPointer(HotSpotConstant c) {
recordDataPatchInCode(new ConstantReference((VMConstant) c));
if (c.isCompressed()) {
Register ret = newRegister();
@@ -190,32 +227,68 @@
}
@Override
public StackSlot emitIntToStack(Register a) {
StackSlot ret = newStackSlot(AMD64Kind.DWORD);
+ return emitIntToStack(ret, a);
+ }
+
+ public StackSlot emitIntToStack(StackSlot ret, Register a) {
// MOV r/m32,r32
emitModRMMemory(false, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16);
return ret;
}
@Override
public StackSlot emitLongToStack(Register a) {
StackSlot ret = newStackSlot(AMD64Kind.QWORD);
+ return emitLongToStack(ret, a);
+ }
+
+ public StackSlot emitLongToStack(StackSlot ret, Register a) {
// MOV r/m64,r64
emitModRMMemory(true, 0x89, a.encoding, AMD64.rbp.encoding, ret.getRawOffset() + 16);
return ret;
}
@Override
public StackSlot emitFloatToStack(Register a) {
StackSlot ret = newStackSlot(AMD64Kind.SINGLE);
+ return emitFloatToStack(ret, a);
+ }
+
+ public StackSlot emitFloatToStack(StackSlot ret, Register a) {
emitREX(false, a.encoding, 0, 0);
code.emitByte(0xF3);
code.emitByte(0x0F);
code.emitByte(0x11); // MOVSS xmm2/m32, xmm1
code.emitByte(0x85 | ((a.encoding & 0x7) << 3)); // [rbp+offset]
+ if (ret.getRawOffset() < 0) {
+ code.emitInt(ret.getRawOffset() + 16);
+ } else {
+ code.emitInt(-(frameSize - ret.getRawOffset()) + 16);
+ }
+ return ret;
+ }
+
+ @Override
+ public StackSlot emitDoubleToStack(Register a) {
+ StackSlot ret = newStackSlot(AMD64Kind.DOUBLE);
+ return emitDoubleToStack(ret, a);
+ }
+
+ public StackSlot emitDoubleToStack(StackSlot ret, Register a) {
+ emitREX(false, a.encoding, 0, 0);
+ code.emitByte(0xF2);
+ code.emitByte(0x0F);
+ code.emitByte(0x11); // MOVSD xmm2/m32, xmm1
+ code.emitByte(0x85 | ((a.encoding & 0x7) << 3)); // [rbp+offset]
+ if (ret.getRawOffset() < 0) {
code.emitInt(ret.getRawOffset() + 16);
+ } else {
+ code.emitInt(-(frameSize - ret.getRawOffset()) + 16);
+ }
return ret;
}
@Override
public StackSlot emitPointerToStack(Register a) {
@@ -267,10 +340,18 @@
code.emitByte(0x58 | AMD64.rbp.encoding); // POP rbp
code.emitByte(0xC3); // RET
}
@Override
+ public void emitFloatRet(Register a) {
+ assert a == xmm0 : "Unimplemented move " + a;
+ emitMove(true, AMD64.rsp, AMD64.rbp); // MOV rsp, rbp
+ code.emitByte(0x58 | AMD64.rbp.encoding); // POP rbp
+ code.emitByte(0xC3); // RET
+ }
+
+ @Override
public void emitPointerRet(Register a) {
emitMove(true, AMD64.rax, a); // MOV rax, ...
emitMove(true, AMD64.rsp, AMD64.rbp); // MOV rsp, rbp
code.emitByte(0x58 | AMD64.rbp.encoding); // POP rbp
code.emitByte(0xC3); // RET
@@ -283,6 +364,66 @@
code.emitByte(0x8B);
code.emitByte(0x04);
code.emitByte(0x25);
code.emitInt(0);
}
+
+ @Override
+ public void emitLoad(AllocatableValue av, Object prim) {
+ if (av instanceof RegisterValue) {
+ Register reg = ((RegisterValue) av).getRegister();
+ if (prim instanceof Float) {
+ emitLoadFloat(reg, (Float) prim);
+ } else if (prim instanceof Double) {
+ emitLoadDouble(reg, (Double) prim);
+ } else if (prim instanceof Integer) {
+ emitLoadInt(reg, (Integer) prim);
+ } else if (prim instanceof Long) {
+ emitLoadLong(reg, (Long) prim);
+ }
+ } else if (av instanceof StackSlot) {
+ StackSlot slot = (StackSlot) av;
+ if (prim instanceof Float) {
+ emitFloatToStack(slot, emitLoadFloat((Float) prim));
+ } else if (prim instanceof Double) {
+ emitDoubleToStack(slot, emitLoadDouble((Double) prim));
+ } else if (prim instanceof Integer) {
+ emitIntToStack(slot, emitLoadInt((Integer) prim));
+ } else if (prim instanceof Long) {
+ emitLongToStack(slot, emitLoadLong((Long) prim));
+ }
+ assert false : "Unimplemented";
+ } else {
+ throw new IllegalArgumentException("Unknown value " + av);
+ }
+ }
+
+ @Override
+ public void emitCallPrologue(CallingConvention cc, Object... prim) {
+ emitGrowStack(cc.getStackSize());
+ frameSize += cc.getStackSize();
+ AllocatableValue[] args = cc.getArguments();
+ // Do the emission in reverse, this avoids register collisons of xmm0 - which is used a
+ // scratch register when putting arguments on the stack.
+ for (int i = args.length - 1; i >= 0; i--) {
+ emitLoad(args[i], prim[i]);
+ }
+ }
+
+ @Override
+ public void emitCall(long addr) {
+ Register target = emitLoadLong(addr);
+ code.emitByte(0xFF); // CALL r/m64
+ int enc = target.encoding;
+ if (enc >= 8) {
+ code.emitByte(0x41);
+ enc -= 8;
+ }
+ code.emitByte(0xD0 | enc);
+ }
+
+ @Override
+ public void emitCallEpilogue(CallingConvention cc) {
+ emitGrowStack(-cc.getStackSize());
+ frameSize -= cc.getStackSize();
+ }
}
< prev index next >