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}