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.meta.*; 026import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; 027import static jdk.internal.jvmci.code.ValueUtil.*; 028 029import com.oracle.graal.asm.amd64.*; 030import com.oracle.graal.asm.amd64.AMD64Assembler.*; 031import com.oracle.graal.lir.*; 032import com.oracle.graal.lir.StandardOp.ImplicitNullCheck; 033import com.oracle.graal.lir.asm.*; 034 035/** 036 * AMD64 LIR instructions that have one input and one output. 037 */ 038public class AMD64Unary { 039 040 /** 041 * Instruction with a single operand that is both input and output. 042 */ 043 public static class MOp extends AMD64LIRInstruction { 044 public static final LIRInstructionClass<MOp> TYPE = LIRInstructionClass.create(MOp.class); 045 046 @Opcode private final AMD64MOp opcode; 047 private final OperandSize size; 048 049 @Def({REG, HINT}) protected AllocatableValue result; 050 @Use({REG, STACK}) protected AllocatableValue value; 051 052 public MOp(AMD64MOp opcode, OperandSize size, AllocatableValue result, AllocatableValue value) { 053 super(TYPE); 054 this.opcode = opcode; 055 this.size = size; 056 057 this.result = result; 058 this.value = value; 059 } 060 061 @Override 062 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 063 AMD64Move.move(crb, masm, result, value); 064 opcode.emit(masm, size, asRegister(result)); 065 } 066 } 067 068 /** 069 * Instruction with separate input and output operands, and an operand encoding of RM. 070 */ 071 public static class RMOp extends AMD64LIRInstruction { 072 public static final LIRInstructionClass<RMOp> TYPE = LIRInstructionClass.create(RMOp.class); 073 074 @Opcode private final AMD64RMOp opcode; 075 private final OperandSize size; 076 077 @Def({REG}) protected AllocatableValue result; 078 @Use({REG, STACK}) protected AllocatableValue value; 079 080 public RMOp(AMD64RMOp opcode, OperandSize size, AllocatableValue result, AllocatableValue value) { 081 super(TYPE); 082 this.opcode = opcode; 083 this.size = size; 084 085 this.result = result; 086 this.value = value; 087 } 088 089 @Override 090 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 091 if (isRegister(value)) { 092 opcode.emit(masm, size, asRegister(result), asRegister(value)); 093 } else { 094 assert isStackSlot(value); 095 opcode.emit(masm, size, asRegister(result), (AMD64Address) crb.asAddress(value)); 096 } 097 } 098 } 099 100 /** 101 * Instruction with separate input and output operands, and an operand encoding of MR. 102 */ 103 public static class MROp extends AMD64LIRInstruction { 104 public static final LIRInstructionClass<MROp> TYPE = LIRInstructionClass.create(MROp.class); 105 106 @Opcode private final AMD64MROp opcode; 107 private final OperandSize size; 108 109 @Def({REG, STACK}) protected AllocatableValue result; 110 @Use({REG}) protected AllocatableValue value; 111 112 public MROp(AMD64MROp opcode, OperandSize size, AllocatableValue result, AllocatableValue value) { 113 super(TYPE); 114 this.opcode = opcode; 115 this.size = size; 116 117 this.result = result; 118 this.value = value; 119 } 120 121 @Override 122 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 123 if (isRegister(result)) { 124 opcode.emit(masm, size, asRegister(result), asRegister(value)); 125 } else { 126 assert isStackSlot(result); 127 opcode.emit(masm, size, (AMD64Address) crb.asAddress(result), asRegister(value)); 128 } 129 } 130 } 131 132 /** 133 * Instruction with a {@link AMD64AddressValue memory} operand. 134 */ 135 public static class MemoryOp extends AMD64LIRInstruction implements ImplicitNullCheck { 136 public static final LIRInstructionClass<MemoryOp> TYPE = LIRInstructionClass.create(MemoryOp.class); 137 138 @Opcode private final AMD64RMOp opcode; 139 private final OperandSize size; 140 141 @Def({REG}) protected AllocatableValue result; 142 @Use({COMPOSITE}) protected AMD64AddressValue input; 143 144 @State protected LIRFrameState state; 145 146 public MemoryOp(AMD64RMOp opcode, OperandSize size, AllocatableValue result, AMD64AddressValue input, LIRFrameState state) { 147 super(TYPE); 148 this.opcode = opcode; 149 this.size = size; 150 151 this.result = result; 152 this.input = input; 153 154 this.state = state; 155 } 156 157 @Override 158 public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { 159 if (state != null) { 160 crb.recordImplicitException(masm.position(), state); 161 } 162 opcode.emit(masm, size, asRegister(result), input.toAddress()); 163 } 164 165 public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { 166 if (state == null && input.isValidImplicitNullCheckFor(value, implicitNullCheckLimit)) { 167 state = nullCheckState; 168 return true; 169 } 170 return false; 171 } 172 } 173}