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 inputs and one output. 039 */ 040public class AMD64Binary { 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 @Def({REG, HINT}) protected AllocatableValue result; 052 @Use({REG, STACK}) protected AllocatableValue x; 053 @Alive({REG, STACK}) protected AllocatableValue y; 054 055 public Op(AMD64RMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, AllocatableValue y) { 056 super(TYPE); 057 this.opcode = opcode; 058 this.size = size; 059 060 this.result = result; 061 this.x = x; 062 this.y = y; 063 } 064 065 @Override 066 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 067 AMD64Move.move(crb, masm, result, x); 068 if (isRegister(y)) { 069 opcode.emit(masm, size, asRegister(result), asRegister(y)); 070 } else { 071 assert isStackSlot(y); 072 opcode.emit(masm, size, asRegister(result), (AMD64Address) crb.asAddress(y)); 073 } 074 } 075 } 076 077 /** 078 * Commutative instruction that has two {@link AllocatableValue} operands. 079 */ 080 public static class CommutativeOp extends AMD64LIRInstruction { 081 public static final LIRInstructionClass<CommutativeOp> TYPE = LIRInstructionClass.create(CommutativeOp.class); 082 083 @Opcode private final AMD64RMOp opcode; 084 private final OperandSize size; 085 086 @Def({REG, HINT}) protected AllocatableValue result; 087 @Use({REG, STACK}) protected AllocatableValue x; 088 @Use({REG, STACK}) protected AllocatableValue y; 089 090 public CommutativeOp(AMD64RMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, AllocatableValue y) { 091 super(TYPE); 092 this.opcode = opcode; 093 this.size = size; 094 095 this.result = result; 096 this.x = x; 097 this.y = y; 098 } 099 100 @Override 101 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 102 AllocatableValue input; 103 if (sameRegister(result, y)) { 104 input = x; 105 } else { 106 AMD64Move.move(crb, masm, result, x); 107 input = y; 108 } 109 110 if (isRegister(input)) { 111 opcode.emit(masm, size, asRegister(result), asRegister(input)); 112 } else { 113 assert isStackSlot(input); 114 opcode.emit(masm, size, asRegister(result), (AMD64Address) crb.asAddress(input)); 115 } 116 } 117 } 118 119 /** 120 * Instruction that has one {@link AllocatableValue} operand and one 32-bit immediate operand. 121 */ 122 public static class ConstOp extends AMD64LIRInstruction { 123 public static final LIRInstructionClass<ConstOp> TYPE = LIRInstructionClass.create(ConstOp.class); 124 125 @Opcode private final AMD64MIOp opcode; 126 private final OperandSize size; 127 128 @Def({REG, HINT}) protected AllocatableValue result; 129 @Use({REG, STACK}) protected AllocatableValue x; 130 private final int y; 131 132 public ConstOp(AMD64BinaryArithmetic opcode, OperandSize size, AllocatableValue result, AllocatableValue x, int y) { 133 this(opcode.getMIOpcode(size, NumUtil.isByte(y)), size, result, x, y); 134 } 135 136 public ConstOp(AMD64MIOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, int y) { 137 super(TYPE); 138 this.opcode = opcode; 139 this.size = size; 140 141 this.result = result; 142 this.x = x; 143 this.y = y; 144 } 145 146 @Override 147 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 148 AMD64Move.move(crb, masm, result, x); 149 opcode.emit(masm, size, asRegister(result), y); 150 } 151 } 152 153 /** 154 * Instruction that has one {@link AllocatableValue} operand and one 155 * {@link DataSectionReference} operand. 156 */ 157 public static class DataOp extends AMD64LIRInstruction { 158 public static final LIRInstructionClass<DataOp> TYPE = LIRInstructionClass.create(DataOp.class); 159 160 @Opcode private final AMD64RMOp opcode; 161 private final OperandSize size; 162 163 @Def({REG, HINT}) protected AllocatableValue result; 164 @Use({REG, STACK}) protected AllocatableValue x; 165 private final JavaConstant y; 166 167 private final int alignment; 168 169 public DataOp(AMD64RMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, JavaConstant y) { 170 this(opcode, size, result, x, y, y.getKind().getByteCount()); 171 } 172 173 public DataOp(AMD64RMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, JavaConstant y, int alignment) { 174 super(TYPE); 175 this.opcode = opcode; 176 this.size = size; 177 178 this.result = result; 179 this.x = x; 180 this.y = y; 181 182 this.alignment = alignment; 183 } 184 185 @Override 186 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 187 AMD64Move.move(crb, masm, result, x); 188 opcode.emit(masm, size, asRegister(result), (AMD64Address) crb.recordDataReferenceInCode(y, alignment)); 189 } 190 } 191 192 /** 193 * Instruction that has one {@link AllocatableValue} operand and one {@link AMD64AddressValue 194 * memory} operand. 195 */ 196 public static class MemoryOp extends AMD64LIRInstruction implements ImplicitNullCheck { 197 public static final LIRInstructionClass<MemoryOp> TYPE = LIRInstructionClass.create(MemoryOp.class); 198 199 @Opcode private final AMD64RMOp opcode; 200 private final OperandSize size; 201 202 @Def({REG, HINT}) protected AllocatableValue result; 203 @Use({REG, STACK}) protected AllocatableValue x; 204 @Alive({COMPOSITE}) protected AMD64AddressValue y; 205 206 @State protected LIRFrameState state; 207 208 public MemoryOp(AMD64RMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, AMD64AddressValue y, LIRFrameState state) { 209 super(TYPE); 210 this.opcode = opcode; 211 this.size = size; 212 213 this.result = result; 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 AMD64Move.move(crb, masm, result, x); 223 if (state != null) { 224 crb.recordImplicitException(masm.position(), state); 225 } 226 opcode.emit(masm, size, asRegister(result), y.toAddress()); 227 } 228 229 @Override 230 public void verify() { 231 super.verify(); 232 assert differentRegisters(result, y) || sameRegister(x, y); 233 } 234 235 @Override 236 public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { 237 if (state == null && y.isValidImplicitNullCheckFor(value, implicitNullCheckLimit)) { 238 state = nullCheckState; 239 return true; 240 } 241 return false; 242 } 243 } 244 245 /** 246 * Instruction with a separate result operand, one {@link AllocatableValue} input and one 32-bit 247 * immediate input. 248 */ 249 public static class RMIOp extends AMD64LIRInstruction { 250 public static final LIRInstructionClass<RMIOp> TYPE = LIRInstructionClass.create(RMIOp.class); 251 252 @Opcode private final AMD64RMIOp opcode; 253 private final OperandSize size; 254 255 @Def({REG}) protected AllocatableValue result; 256 @Use({REG, STACK}) protected AllocatableValue x; 257 private final int y; 258 259 public RMIOp(AMD64RMIOp opcode, OperandSize size, AllocatableValue result, AllocatableValue x, int y) { 260 super(TYPE); 261 this.opcode = opcode; 262 this.size = size; 263 264 this.result = result; 265 this.x = x; 266 this.y = y; 267 } 268 269 @Override 270 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 271 if (isRegister(x)) { 272 opcode.emit(masm, size, asRegister(result), asRegister(x), y); 273 } else { 274 assert isStackSlot(x); 275 opcode.emit(masm, size, asRegister(result), (AMD64Address) crb.asAddress(x), y); 276 } 277 } 278 } 279}