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}