001/* 002 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.lir.amd64; 024 025import jdk.internal.jvmci.code.CompilationResult.*; 026import jdk.internal.jvmci.meta.*; 027import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; 028import static jdk.internal.jvmci.code.ValueUtil.*; 029 030import com.oracle.graal.asm.*; 031import com.oracle.graal.asm.amd64.*; 032import com.oracle.graal.asm.amd64.AMD64Assembler.*; 033import com.oracle.graal.lir.*; 034import com.oracle.graal.lir.StandardOp.ImplicitNullCheck; 035import com.oracle.graal.lir.asm.*; 036 037/** 038 * AMD64 LIR instructions that have two input operands, but no output operand. 039 */ 040public class AMD64BinaryConsumer { 041 042 /** 043 * Instruction that has two {@link AllocatableValue} operands. 044 */ 045 public static class Op extends AMD64LIRInstruction { 046 public static final LIRInstructionClass<Op> TYPE = LIRInstructionClass.create(Op.class); 047 048 @Opcode private final AMD64RMOp opcode; 049 private final OperandSize size; 050 051 @Use({REG}) protected AllocatableValue x; 052 @Use({REG, STACK}) protected AllocatableValue y; 053 054 public Op(AMD64RMOp opcode, OperandSize size, AllocatableValue x, AllocatableValue y) { 055 super(TYPE); 056 this.opcode = opcode; 057 this.size = size; 058 059 this.x = x; 060 this.y = y; 061 } 062 063 @Override 064 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 065 if (isRegister(y)) { 066 opcode.emit(masm, size, asRegister(x), asRegister(y)); 067 } else { 068 assert isStackSlot(y); 069 opcode.emit(masm, size, asRegister(x), (AMD64Address) crb.asAddress(y)); 070 } 071 } 072 } 073 074 /** 075 * Instruction that has one {@link AllocatableValue} operand and one 32-bit immediate operand. 076 */ 077 public static class ConstOp extends AMD64LIRInstruction { 078 public static final LIRInstructionClass<ConstOp> TYPE = LIRInstructionClass.create(ConstOp.class); 079 080 @Opcode private final AMD64MIOp opcode; 081 private final OperandSize size; 082 083 @Use({REG, STACK}) protected AllocatableValue x; 084 private final int y; 085 086 public ConstOp(AMD64BinaryArithmetic opcode, OperandSize size, AllocatableValue x, int y) { 087 this(opcode.getMIOpcode(size, NumUtil.isByte(y)), size, x, y); 088 } 089 090 public ConstOp(AMD64MIOp opcode, OperandSize size, AllocatableValue x, int y) { 091 this(TYPE, opcode, size, x, y); 092 } 093 094 protected ConstOp(LIRInstructionClass<? extends ConstOp> c, AMD64MIOp opcode, OperandSize size, AllocatableValue x, int y) { 095 super(c); 096 this.opcode = opcode; 097 this.size = size; 098 099 this.x = x; 100 this.y = y; 101 } 102 103 @Override 104 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 105 if (isRegister(x)) { 106 opcode.emit(masm, size, asRegister(x), y); 107 } else { 108 assert isStackSlot(x); 109 opcode.emit(masm, size, (AMD64Address) crb.asAddress(x), y); 110 } 111 } 112 } 113 114 /** 115 * Instruction that has one {@link AllocatableValue} operand and one 116 * {@link DataSectionReference} operand. 117 */ 118 public static class DataOp extends AMD64LIRInstruction { 119 public static final LIRInstructionClass<DataOp> TYPE = LIRInstructionClass.create(DataOp.class); 120 121 @Opcode private final AMD64RMOp opcode; 122 private final OperandSize size; 123 124 @Use({REG}) protected AllocatableValue x; 125 private final Constant y; 126 127 private final int alignment; 128 129 public DataOp(AMD64RMOp opcode, OperandSize size, AllocatableValue x, Constant y) { 130 this(opcode, size, x, y, size.getBytes()); 131 } 132 133 public DataOp(AMD64RMOp opcode, OperandSize size, AllocatableValue x, Constant y, int alignment) { 134 super(TYPE); 135 this.opcode = opcode; 136 this.size = size; 137 138 this.x = x; 139 this.y = y; 140 141 this.alignment = alignment; 142 } 143 144 @Override 145 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 146 opcode.emit(masm, size, asRegister(x), (AMD64Address) crb.recordDataReferenceInCode(y, alignment)); 147 } 148 } 149 150 /** 151 * Instruction that has an {@link AllocatableValue} as first input and a 152 * {@link AMD64AddressValue memory} operand as second input. 153 */ 154 public static class MemoryRMOp extends AMD64LIRInstruction implements ImplicitNullCheck { 155 public static final LIRInstructionClass<MemoryRMOp> TYPE = LIRInstructionClass.create(MemoryRMOp.class); 156 157 @Opcode private final AMD64RMOp opcode; 158 private final OperandSize size; 159 160 @Use({REG}) protected AllocatableValue x; 161 @Use({COMPOSITE}) protected AMD64AddressValue y; 162 163 @State protected LIRFrameState state; 164 165 public MemoryRMOp(AMD64RMOp opcode, OperandSize size, AllocatableValue x, AMD64AddressValue y, LIRFrameState state) { 166 super(TYPE); 167 this.opcode = opcode; 168 this.size = size; 169 170 this.x = x; 171 this.y = y; 172 173 this.state = state; 174 } 175 176 @Override 177 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 178 if (state != null) { 179 crb.recordImplicitException(masm.position(), state); 180 } 181 opcode.emit(masm, size, asRegister(x), y.toAddress()); 182 } 183 184 @Override 185 public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { 186 if (state == null && y.isValidImplicitNullCheckFor(value, implicitNullCheckLimit)) { 187 state = nullCheckState; 188 return true; 189 } 190 return false; 191 } 192 } 193 194 /** 195 * Instruction that has a {@link AMD64AddressValue memory} operand as first input and an 196 * {@link AllocatableValue} as second input. 197 */ 198 public static class MemoryMROp extends AMD64LIRInstruction implements ImplicitNullCheck { 199 public static final LIRInstructionClass<MemoryMROp> TYPE = LIRInstructionClass.create(MemoryMROp.class); 200 201 @Opcode private final AMD64MROp opcode; 202 private final OperandSize size; 203 204 @Use({COMPOSITE}) protected AMD64AddressValue x; 205 @Use({REG}) protected AllocatableValue y; 206 207 @State protected LIRFrameState state; 208 209 public MemoryMROp(AMD64MROp opcode, OperandSize size, AMD64AddressValue x, AllocatableValue y, LIRFrameState state) { 210 super(TYPE); 211 this.opcode = opcode; 212 this.size = size; 213 214 this.x = x; 215 this.y = y; 216 217 this.state = state; 218 } 219 220 @Override 221 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 222 if (state != null) { 223 crb.recordImplicitException(masm.position(), state); 224 } 225 opcode.emit(masm, size, x.toAddress(), asRegister(y)); 226 } 227 228 @Override 229 public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { 230 if (state == null && x.isValidImplicitNullCheckFor(value, implicitNullCheckLimit)) { 231 state = nullCheckState; 232 return true; 233 } 234 return false; 235 } 236 } 237 238 /** 239 * Instruction that has one {@link AMD64AddressValue memory} operand and one 32-bit immediate 240 * operand. 241 */ 242 public static class MemoryConstOp extends AMD64LIRInstruction implements ImplicitNullCheck { 243 public static final LIRInstructionClass<MemoryConstOp> TYPE = LIRInstructionClass.create(MemoryConstOp.class); 244 245 @Opcode private final AMD64MIOp opcode; 246 private final OperandSize size; 247 248 @Use({COMPOSITE}) protected AMD64AddressValue x; 249 private final int y; 250 251 @State protected LIRFrameState state; 252 253 public MemoryConstOp(AMD64BinaryArithmetic opcode, OperandSize size, AMD64AddressValue x, int y, LIRFrameState state) { 254 this(opcode.getMIOpcode(size, NumUtil.isByte(y)), size, x, y, state); 255 } 256 257 public MemoryConstOp(AMD64MIOp opcode, OperandSize size, AMD64AddressValue x, int y, LIRFrameState state) { 258 this(TYPE, opcode, size, x, y, state); 259 } 260 261 protected MemoryConstOp(LIRInstructionClass<? extends MemoryConstOp> c, AMD64MIOp opcode, OperandSize size, AMD64AddressValue x, int y, LIRFrameState state) { 262 super(c); 263 this.opcode = opcode; 264 this.size = size; 265 266 this.x = x; 267 this.y = y; 268 269 this.state = state; 270 } 271 272 @Override 273 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 274 if (state != null) { 275 crb.recordImplicitException(masm.position(), state); 276 } 277 opcode.emit(masm, size, x.toAddress(), y); 278 } 279 280 @Override 281 public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { 282 if (state == null && x.isValidImplicitNullCheckFor(value, implicitNullCheckLimit)) { 283 state = nullCheckState; 284 return true; 285 } 286 return false; 287 } 288 } 289}