1 /* 2 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 package org.graalvm.compiler.lir.amd64; 26 27 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; 28 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; 29 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; 30 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; 31 import static jdk.vm.ci.code.ValueUtil.asRegister; 32 import static jdk.vm.ci.code.ValueUtil.isRegister; 33 import static jdk.vm.ci.code.ValueUtil.isStackSlot; 34 35 import org.graalvm.compiler.asm.amd64.AMD64Address; 36 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp; 37 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MROp; 38 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; 39 import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize; 40 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; 41 import org.graalvm.compiler.lir.LIRFrameState; 42 import org.graalvm.compiler.lir.LIRInstructionClass; 43 import org.graalvm.compiler.lir.Opcode; 44 import org.graalvm.compiler.lir.StandardOp.ImplicitNullCheck; 45 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 46 47 import jdk.vm.ci.meta.AllocatableValue; 48 import jdk.vm.ci.meta.Value; 49 50 /** 51 * AMD64 LIR instructions that have one input and one output. 52 */ 53 public class AMD64Unary { 54 55 /** 56 * Instruction with a single operand that is both input and output. 57 */ 58 public static class MOp extends AMD64LIRInstruction { 59 public static final LIRInstructionClass<MOp> TYPE = LIRInstructionClass.create(MOp.class); 60 61 @Opcode private final AMD64MOp opcode; 62 private final OperandSize size; 63 64 @Def({REG, HINT}) protected AllocatableValue result; 65 @Use({REG, STACK}) protected AllocatableValue value; 66 MOp(AMD64MOp opcode, OperandSize size, AllocatableValue result, AllocatableValue value)67 public MOp(AMD64MOp opcode, OperandSize size, AllocatableValue result, AllocatableValue value) { 68 super(TYPE); 69 this.opcode = opcode; 70 this.size = size; 71 72 this.result = result; 73 this.value = value; 74 } 75 76 @Override emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm)77 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 78 AMD64Move.move(crb, masm, result, value); 79 opcode.emit(masm, size, asRegister(result)); 80 } 81 } 82 83 /** 84 * Instruction with separate input and output operands, and an operand encoding of RM. 85 */ 86 public static class RMOp extends AMD64LIRInstruction { 87 public static final LIRInstructionClass<RMOp> TYPE = LIRInstructionClass.create(RMOp.class); 88 89 @Opcode private final AMD64RMOp opcode; 90 private final OperandSize size; 91 92 @Def({REG}) protected AllocatableValue result; 93 @Use({REG, STACK}) protected AllocatableValue value; 94 RMOp(AMD64RMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue value)95 public RMOp(AMD64RMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue value) { 96 super(TYPE); 97 this.opcode = opcode; 98 this.size = size; 99 100 this.result = result; 101 this.value = value; 102 } 103 104 @Override emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm)105 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 106 if (isRegister(value)) { 107 opcode.emit(masm, size, asRegister(result), asRegister(value)); 108 } else { 109 assert isStackSlot(value); 110 opcode.emit(masm, size, asRegister(result), (AMD64Address) crb.asAddress(value)); 111 } 112 } 113 } 114 115 /** 116 * Instruction with separate input and output operands, and an operand encoding of MR. 117 */ 118 public static class MROp extends AMD64LIRInstruction { 119 public static final LIRInstructionClass<MROp> TYPE = LIRInstructionClass.create(MROp.class); 120 121 @Opcode private final AMD64MROp opcode; 122 private final OperandSize size; 123 124 @Def({REG, STACK}) protected AllocatableValue result; 125 @Use({REG}) protected AllocatableValue value; 126 MROp(AMD64MROp opcode, OperandSize size, AllocatableValue result, AllocatableValue value)127 public MROp(AMD64MROp opcode, OperandSize size, AllocatableValue result, AllocatableValue value) { 128 super(TYPE); 129 this.opcode = opcode; 130 this.size = size; 131 132 this.result = result; 133 this.value = value; 134 } 135 136 @Override emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm)137 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 138 if (isRegister(result)) { 139 opcode.emit(masm, size, asRegister(result), asRegister(value)); 140 } else { 141 assert isStackSlot(result); 142 opcode.emit(masm, size, (AMD64Address) crb.asAddress(result), asRegister(value)); 143 } 144 } 145 } 146 147 /** 148 * Instruction with a {@link AMD64AddressValue memory} operand. 149 */ 150 public static class MemoryOp extends AMD64LIRInstruction implements ImplicitNullCheck { 151 public static final LIRInstructionClass<MemoryOp> TYPE = LIRInstructionClass.create(MemoryOp.class); 152 153 @Opcode private final AMD64RMOp opcode; 154 private final OperandSize size; 155 156 @Def({REG}) protected AllocatableValue result; 157 @Use({COMPOSITE}) protected AMD64AddressValue input; 158 159 @State protected LIRFrameState state; 160 MemoryOp(AMD64RMOp opcode, OperandSize size, AllocatableValue result, AMD64AddressValue input, LIRFrameState state)161 public MemoryOp(AMD64RMOp opcode, OperandSize size, AllocatableValue result, AMD64AddressValue input, LIRFrameState state) { 162 super(TYPE); 163 this.opcode = opcode; 164 this.size = size; 165 166 this.result = result; 167 this.input = input; 168 169 this.state = state; 170 } 171 172 @Override emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm)173 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 174 if (state != null) { 175 crb.recordImplicitException(masm.position(), state); 176 } 177 opcode.emit(masm, size, asRegister(result), input.toAddress()); 178 } 179 180 @Override makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit)181 public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { 182 if (state == null && input.isValidImplicitNullCheckFor(value, implicitNullCheckLimit)) { 183 state = nullCheckState; 184 return true; 185 } 186 return false; 187 } 188 } 189 } 190