# HG changeset patch # User Roland Schatz # Date 1426874948 -3600 # Node ID f259c81821ef37e042ef55d79d9f3c80fbc30300 # Parent 46dde3e927158aa6811211ab039761ac132fa79c Simplify code generation for AMD64 memory access instructions. diff -r 46dde3e92715 -r f259c81821ef graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Fri Mar 20 17:59:37 2015 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Fri Mar 20 19:09:08 2015 +0100 @@ -601,11 +601,14 @@ public static final AMD64RMOp MOVSXB = new AMD64RMOp("MOVSXB", P_0F, 0xBE, false, true, OpAssertion.IntegerAssertion); public static final AMD64RMOp MOVSX = new AMD64RMOp("MOVSX", P_0F, 0xBF, OpAssertion.No16BitAssertion); public static final AMD64RMOp MOVSXD = new AMD64RMOp("MOVSXD", 0x63, OpAssertion.QwordOnlyAssertion); + public static final AMD64RMOp MOVB = new AMD64RMOp("MOVB", 0x8A, OpAssertion.ByteAssertion); public static final AMD64RMOp MOV = new AMD64RMOp("MOV", 0x8B); - // MOVD and MOVQ are the same opcode, just with different operand size prefix + // MOVD/MOVQ and MOVSS/MOVSD are the same opcode, just with different operand size prefix public static final AMD64RMOp MOVD = new AMD64RMOp("MOVD", 0x66, P_0F, 0x6E, OpAssertion.IntToFloatingAssertion, CPUFeature.SSE2); public static final AMD64RMOp MOVQ = new AMD64RMOp("MOVQ", 0x66, P_0F, 0x6E, OpAssertion.IntToFloatingAssertion, CPUFeature.SSE2); + public static final AMD64RMOp MOVSS = new AMD64RMOp("MOVSS", P_0F, 0x10, OpAssertion.FloatingAssertion, CPUFeature.SSE); + public static final AMD64RMOp MOVSD = new AMD64RMOp("MOVSD", P_0F, 0x10, OpAssertion.FloatingAssertion, CPUFeature.SSE); // TEST is documented as MR operation, but it's symmetric, and using it as RM operation is more convenient. public static final AMD64RMOp TESTB = new AMD64RMOp("TEST", 0x84, OpAssertion.ByteAssertion); @@ -628,6 +631,10 @@ this(opcode, 0, prefix, op, assertion, null); } + protected AMD64RMOp(String opcode, int prefix, int op, OpAssertion assertion, CPUFeature feature) { + this(opcode, 0, prefix, op, assertion, feature); + } + protected AMD64RMOp(String opcode, int prefix, int op, boolean dstIsByte, boolean srcIsByte, OpAssertion assertion) { super(opcode, 0, prefix, op, dstIsByte, srcIsByte, assertion, null); } @@ -659,12 +666,17 @@ */ public static class AMD64MROp extends AMD64RROp { // @formatter:off + public static final AMD64MROp MOVB = new AMD64MROp("MOVB", 0x88, OpAssertion.ByteAssertion); public static final AMD64MROp MOV = new AMD64MROp("MOV", 0x89); // MOVD and MOVQ are the same opcode, just with different operand size prefix // Note that as MR opcodes, they have reverse operand order, so the IntToFloatingAssertion must be used. public static final AMD64MROp MOVD = new AMD64MROp("MOVD", 0x66, P_0F, 0x7E, OpAssertion.IntToFloatingAssertion, CPUFeature.SSE2); public static final AMD64MROp MOVQ = new AMD64MROp("MOVQ", 0x66, P_0F, 0x7E, OpAssertion.IntToFloatingAssertion, CPUFeature.SSE2); + + // MOVSS and MOVSD are the same opcode, just with different operand size prefix + public static final AMD64MROp MOVSS = new AMD64MROp("MOVSS", P_0F, 0x11, OpAssertion.FloatingAssertion, CPUFeature.SSE); + public static final AMD64MROp MOVSD = new AMD64MROp("MOVSD", P_0F, 0x11, OpAssertion.FloatingAssertion, CPUFeature.SSE); // @formatter:on protected AMD64MROp(String opcode, int op) { @@ -680,7 +692,11 @@ } protected AMD64MROp(String opcode, int prefix, int op, OpAssertion assertion) { - this(opcode, 0, prefix, op, assertion, null); + this(opcode, prefix, op, assertion, null); + } + + protected AMD64MROp(String opcode, int prefix, int op, OpAssertion assertion, CPUFeature feature) { + this(opcode, 0, prefix, op, assertion, feature); } protected AMD64MROp(String opcode, int prefix1, int prefix2, int op, OpAssertion assertion, CPUFeature feature) { @@ -747,6 +763,7 @@ */ public static class AMD64MIOp extends AMD64ImmOp { // @formatter:off + public static final AMD64MIOp MOVB = new AMD64MIOp("MOVB", true, 0xC6, 0, OpAssertion.ByteAssertion); public static final AMD64MIOp MOV = new AMD64MIOp("MOV", false, 0xC7, 0); public static final AMD64MIOp TEST = new AMD64MIOp("TEST", false, 0xF7, 0); // @formatter:on @@ -754,7 +771,11 @@ private final int ext; protected AMD64MIOp(String opcode, boolean immIsByte, int op, int ext) { - this(opcode, immIsByte, 0, op, ext, OpAssertion.IntegerAssertion); + this(opcode, immIsByte, op, ext, OpAssertion.IntegerAssertion); + } + + protected AMD64MIOp(String opcode, boolean immIsByte, int op, int ext, OpAssertion assertion) { + this(opcode, immIsByte, 0, op, ext, assertion); } protected AMD64MIOp(String opcode, boolean immIsByte, int prefix, int op, int ext, OpAssertion assertion) { diff -r 46dde3e92715 -r f259c81821ef graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Mar 20 17:59:37 2015 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Mar 20 19:09:08 2015 +0100 @@ -50,7 +50,6 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.spi.*; -import com.oracle.graal.compiler.common.util.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; import com.oracle.graal.lir.amd64.*; @@ -68,7 +67,6 @@ import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp; import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp; -import com.oracle.graal.lir.amd64.AMD64Move.ZeroExtendLoadOp; import com.oracle.graal.lir.gen.*; import com.oracle.graal.phases.util.*; @@ -107,28 +105,6 @@ } } - /** - * Checks whether the supplied constant can be used without loading it into a register for store - * operations, i.e., on the right hand side of a memory access. - * - * @param c The constant to check. - * @return True if the constant can be used directly, false if the constant needs to be in a - * register. - */ - protected boolean canStoreConstant(JavaConstant c) { - // there is no immediate move of 64-bit constants on Intel - switch (c.getKind()) { - case Long: - return Util.isInt(c.asLong()) && !getCodeCache().needsDataPatch(c); - case Double: - return false; - case Object: - return c.isNull(); - default: - return true; - } - } - protected AMD64LIRInstruction createMove(AllocatableValue dst, Value src) { if (src instanceof AMD64AddressValue) { return new LeaOp(dst, (AMD64AddressValue) src); @@ -640,7 +616,24 @@ // Issue a zero extending load of the proper bit size and set the result to // the proper kind. Variable result = newVariable(LIRKind.value(resultBits == 32 ? Kind.Int : Kind.Long)); - append(new ZeroExtendLoadOp(memoryKind, result, address, state)); + switch (memoryKind) { + case Boolean: + case Byte: + append(new AMD64Unary.MemoryOp(MOVZXB, DWORD, result, address, state)); + break; + case Char: + case Short: + append(new AMD64Unary.MemoryOp(MOVZX, DWORD, result, address, state)); + break; + case Int: + append(new AMD64Unary.MemoryOp(MOV, DWORD, result, address, state)); + break; + case Long: + append(new AMD64Unary.MemoryOp(MOV, QWORD, result, address, state)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } return result; } diff -r 46dde3e92715 -r f259c81821ef graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBinaryConsumer.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBinaryConsumer.java Fri Mar 20 17:59:37 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBinaryConsumer.java Fri Mar 20 19:09:08 2015 +0100 @@ -50,6 +50,7 @@ @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + assert crb.target.inlineObjects || !(c instanceof HotSpotObjectConstant); crb.recordInlineDataInCode(c); super.emitCode(crb, masm); } @@ -72,6 +73,7 @@ @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + assert crb.target.inlineObjects || !(c instanceof HotSpotObjectConstant); crb.recordInlineDataInCode(c); super.emitCode(crb, masm); } diff -r 46dde3e92715 -r f259c81821ef graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Mar 20 17:59:37 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Mar 20 19:09:08 2015 +0100 @@ -34,6 +34,9 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MIOp; +import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MROp; import com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize; import com.oracle.graal.compiler.amd64.*; import com.oracle.graal.compiler.common.*; @@ -42,7 +45,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; -import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.HotSpotStoreConstantOp; import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; @@ -53,9 +55,7 @@ import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp; import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp; -import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp; -import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; @@ -506,22 +506,137 @@ public Variable emitLoad(LIRKind kind, Value address, LIRFrameState state) { AMD64AddressValue loadAddress = asAddressValue(address); Variable result = newVariable(toStackKind(kind)); - append(new LoadOp((Kind) kind.getPlatformKind(), result, loadAddress, state)); + switch ((Kind) kind.getPlatformKind()) { + case Boolean: + append(new AMD64Unary.MemoryOp(MOVZXB, DWORD, result, loadAddress, state)); + break; + case Byte: + append(new AMD64Unary.MemoryOp(MOVSXB, DWORD, result, loadAddress, state)); + break; + case Char: + append(new AMD64Unary.MemoryOp(MOVZX, DWORD, result, loadAddress, state)); + break; + case Short: + append(new AMD64Unary.MemoryOp(MOVSX, DWORD, result, loadAddress, state)); + break; + case Int: + append(new AMD64Unary.MemoryOp(MOV, DWORD, result, loadAddress, state)); + break; + case Long: + case Object: + append(new AMD64Unary.MemoryOp(MOV, QWORD, result, loadAddress, state)); + break; + case Float: + append(new AMD64Unary.MemoryOp(MOVSS, SS, result, loadAddress, state)); + break; + case Double: + append(new AMD64Unary.MemoryOp(MOVSD, SD, result, loadAddress, state)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } return result; } + private void emitStoreConst(Kind kind, AMD64AddressValue address, JavaConstant value, LIRFrameState state) { + if (value.isNull()) { + assert kind == Kind.Int || kind == Kind.Long || kind == Kind.Object; + OperandSize size = kind == Kind.Int ? DWORD : QWORD; + append(new AMD64BinaryConsumer.MemoryConstOp(AMD64MIOp.MOV, size, address, 0, state)); + } else if (value instanceof HotSpotConstant) { + HotSpotConstant c = (HotSpotConstant) value; + if (c.isCompressed()) { + assert kind == Kind.Int; + if (!target().inlineObjects && c instanceof HotSpotObjectConstant) { + emitStore(kind, address, asAllocatable(value), state); + } else { + append(new AMD64HotSpotBinaryConsumer.MemoryConstOp(AMD64MIOp.MOV, address, c, state)); + } + } else { + emitStore(kind, address, asAllocatable(value), state); + } + } else { + AMD64MIOp op = AMD64MIOp.MOV; + OperandSize size; + long imm; + + switch (kind) { + case Boolean: + case Byte: + op = AMD64MIOp.MOVB; + size = BYTE; + imm = value.asInt(); + break; + case Char: + case Short: + size = WORD; + imm = value.asInt(); + break; + case Int: + size = DWORD; + imm = value.asInt(); + break; + case Long: + size = QWORD; + imm = value.asLong(); + break; + case Float: + size = DWORD; + imm = Float.floatToRawIntBits(value.asFloat()); + break; + case Double: + size = QWORD; + imm = Double.doubleToRawLongBits(value.asDouble()); + break; + default: + throw GraalInternalError.shouldNotReachHere("unexpected kind " + kind); + } + + if (NumUtil.isInt(imm)) { + append(new AMD64BinaryConsumer.MemoryConstOp(op, size, address, (int) imm, state)); + } else { + emitStore(kind, address, asAllocatable(value), state); + } + } + } + + private void emitStore(Kind kind, AMD64AddressValue address, AllocatableValue value, LIRFrameState state) { + switch (kind) { + case Boolean: + case Byte: + append(new AMD64BinaryConsumer.MemoryMROp(AMD64MROp.MOVB, BYTE, address, value, state)); + break; + case Char: + case Short: + append(new AMD64BinaryConsumer.MemoryMROp(AMD64MROp.MOV, WORD, address, value, state)); + break; + case Int: + append(new AMD64BinaryConsumer.MemoryMROp(AMD64MROp.MOV, DWORD, address, value, state)); + break; + case Long: + case Object: + append(new AMD64BinaryConsumer.MemoryMROp(AMD64MROp.MOV, QWORD, address, value, state)); + break; + case Float: + append(new AMD64BinaryConsumer.MemoryMROp(AMD64MROp.MOVSS, SS, address, value, state)); + break; + case Double: + append(new AMD64BinaryConsumer.MemoryMROp(AMD64MROp.MOVSD, SD, address, value, state)); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + @Override - public void emitStore(LIRKind kind, Value address, Value inputVal, LIRFrameState state) { + public void emitStore(LIRKind lirKind, Value address, Value input, LIRFrameState state) { AMD64AddressValue storeAddress = asAddressValue(address); - if (isConstant(inputVal)) { - JavaConstant c = asConstant(inputVal); - if (canStoreConstant(c)) { - append(new HotSpotStoreConstantOp((Kind) kind.getPlatformKind(), storeAddress, c, state)); - return; - } + Kind kind = (Kind) lirKind.getPlatformKind(); + if (isConstant(input)) { + emitStoreConst(kind, storeAddress, asConstant(input), state); + } else { + emitStore(kind, storeAddress, asAllocatable(input), state); } - Variable input = load(inputVal); - append(new StoreOp((Kind) kind.getPlatformKind(), storeAddress, input, state)); } @Override diff -r 46dde3e92715 -r f259c81821ef graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Fri Mar 20 17:59:37 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMove.java Fri Mar 20 19:09:08 2015 +0100 @@ -38,7 +38,6 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp; import com.oracle.graal.lir.asm.*; public class AMD64HotSpotMove { @@ -146,44 +145,6 @@ } } - public static class HotSpotStoreConstantOp extends StoreConstantOp { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(HotSpotStoreConstantOp.class); - - public HotSpotStoreConstantOp(Kind kind, AMD64AddressValue address, JavaConstant input, LIRFrameState state) { - super(TYPE, kind, address, input, state); - } - - @Override - public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (input.isNull() && kind == Kind.Int) { - // compressed null - masm.movl(address.toAddress(), 0); - } else if (input instanceof HotSpotObjectConstant) { - HotSpotObjectConstant c = (HotSpotObjectConstant) input; - if (c.isCompressed() && crb.target.inlineObjects) { - // compressed oop - crb.recordInlineDataInCode(input); - masm.movl(address.toAddress(), 0xDEADDEAD); - } else { - // uncompressed oop - throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); - } - } else if (input instanceof HotSpotMetaspaceConstant) { - if (input.getKind() == Kind.Int) { - // compressed metaspace pointer - crb.recordInlineDataInCode(input); - masm.movl(address.toAddress(), input.asInt()); - } else { - // uncompressed metaspace pointer - throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); - } - } else { - // primitive value - super.emitMemAccess(crb, masm); - } - } - } - public static final class CompressPointer extends AMD64LIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(CompressPointer.class); diff -r 46dde3e92715 -r f259c81821ef graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Fri Mar 20 17:59:37 2015 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Fri Mar 20 19:09:08 2015 +0100 @@ -30,11 +30,9 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.*; 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.asm.*; @@ -110,210 +108,6 @@ } } - public abstract static class MemOp extends AMD64LIRInstruction implements ImplicitNullCheck { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MemOp.class); - - protected final Kind kind; - @Use({COMPOSITE}) protected AMD64AddressValue address; - @State protected LIRFrameState state; - - public MemOp(LIRInstructionClass c, Kind kind, AMD64AddressValue address, LIRFrameState state) { - super(c); - this.kind = kind; - this.address = address; - this.state = state; - } - - protected abstract void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm); - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (state != null) { - crb.recordImplicitException(masm.position(), state); - } - emitMemAccess(crb, masm); - } - - public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { - if (state == null && value.equals(address.base) && address.index.equals(Value.ILLEGAL) && address.displacement >= 0 && address.displacement < implicitNullCheckLimit) { - state = nullCheckState; - return true; - } - return false; - } - } - - public static final class LoadOp extends MemOp { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LoadOp.class); - - @Def({REG}) protected AllocatableValue result; - - public LoadOp(Kind kind, AllocatableValue result, AMD64AddressValue address, LIRFrameState state) { - super(TYPE, kind, address, state); - this.result = result; - } - - @Override - public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - switch (kind) { - case Boolean: - masm.movzbl(asRegister(result), address.toAddress()); - break; - case Byte: - masm.movsbl(asRegister(result), address.toAddress()); - break; - case Char: - masm.movzwl(asRegister(result), address.toAddress()); - break; - case Short: - masm.movswl(asRegister(result), address.toAddress()); - break; - case Int: - masm.movl(asRegister(result), address.toAddress()); - break; - case Long: - masm.movq(asRegister(result), address.toAddress()); - break; - case Float: - masm.movflt(asFloatReg(result), address.toAddress()); - break; - case Double: - masm.movdbl(asDoubleReg(result), address.toAddress()); - break; - case Object: - masm.movq(asRegister(result), address.toAddress()); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - } - - public static final class ZeroExtendLoadOp extends MemOp { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(ZeroExtendLoadOp.class); - - @Def({REG}) protected AllocatableValue result; - - public ZeroExtendLoadOp(Kind kind, AllocatableValue result, AMD64AddressValue address, LIRFrameState state) { - super(TYPE, kind, address, state); - this.result = result; - } - - @Override - public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - switch (kind) { - case Boolean: - case Byte: - masm.movzbl(asRegister(result), address.toAddress()); - break; - case Char: - case Short: - masm.movzwl(asRegister(result), address.toAddress()); - break; - case Int: - masm.movl(asRegister(result), address.toAddress()); - break; - case Long: - masm.movq(asRegister(result), address.toAddress()); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - } - - public static final class StoreOp extends MemOp { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(StoreOp.class); - - @Use({REG}) protected AllocatableValue input; - - public StoreOp(Kind kind, AMD64AddressValue address, AllocatableValue input, LIRFrameState state) { - super(TYPE, kind, address, state); - this.input = input; - } - - @Override - public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - assert isRegister(input); - switch (kind) { - case Boolean: - case Byte: - masm.movb(address.toAddress(), asRegister(input)); - break; - case Char: - case Short: - masm.movw(address.toAddress(), asRegister(input)); - break; - case Int: - masm.movl(address.toAddress(), asRegister(input)); - break; - case Long: - masm.movq(address.toAddress(), asRegister(input)); - break; - case Float: - masm.movflt(address.toAddress(), asFloatReg(input)); - break; - case Double: - masm.movsd(address.toAddress(), asDoubleReg(input)); - break; - case Object: - masm.movq(address.toAddress(), asRegister(input)); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - } - - public abstract static class StoreConstantOp extends MemOp { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(StoreConstantOp.class); - - protected final JavaConstant input; - - protected StoreConstantOp(LIRInstructionClass c, Kind kind, AMD64AddressValue address, JavaConstant input, LIRFrameState state) { - super(c, kind, address, state); - this.input = input; - } - - @Override - public void emitMemAccess(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - switch (kind) { - case Boolean: - case Byte: - masm.movb(address.toAddress(), input.asInt() & 0xFF); - break; - case Char: - case Short: - masm.movw(address.toAddress(), input.asInt() & 0xFFFF); - break; - case Int: - masm.movl(address.toAddress(), input.asInt()); - break; - case Long: - if (NumUtil.isInt(input.asLong())) { - masm.movslq(address.toAddress(), (int) input.asLong()); - } else { - throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); - } - break; - case Float: - masm.movl(address.toAddress(), floatToRawIntBits(input.asFloat())); - break; - case Double: - throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); - case Object: - if (input.isNull()) { - masm.movptr(address.toAddress(), 0); - } else { - throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); - } - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - } - public static final class LeaOp extends AMD64LIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LeaOp.class);