1 /*
2 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24
25
26 package org.graalvm.compiler.core.aarch64;
27
28 import static jdk.vm.ci.aarch64.AArch64.sp;
29 import static jdk.vm.ci.aarch64.AArch64Kind.DWORD;
30 import static jdk.vm.ci.aarch64.AArch64Kind.QWORD;
31 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
32 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
33 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.BSR;
34 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CLZ;
35 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CTZ;
36
37 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
38 import org.graalvm.compiler.core.common.LIRKind;
39 import org.graalvm.compiler.core.common.NumUtil;
40 import org.graalvm.compiler.core.common.calc.FloatConvert;
41 import org.graalvm.compiler.debug.GraalError;
42 import org.graalvm.compiler.lir.ConstantValue;
43 import org.graalvm.compiler.lir.LIRFrameState;
44 import org.graalvm.compiler.lir.Variable;
45 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
46 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool;
47 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
48 import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp;
49 import org.graalvm.compiler.lir.aarch64.AArch64Move.LoadOp;
50 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreConstantOp;
51 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp;
52 import org.graalvm.compiler.lir.aarch64.AArch64ReinterpretOp;
53 import org.graalvm.compiler.lir.aarch64.AArch64SignExtendOp;
54 import org.graalvm.compiler.lir.aarch64.AArch64Unary;
55 import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
56
57 import jdk.vm.ci.aarch64.AArch64Kind;
58 import jdk.vm.ci.code.RegisterValue;
59 import jdk.vm.ci.meta.AllocatableValue;
60 import jdk.vm.ci.meta.JavaConstant;
61 import jdk.vm.ci.meta.PlatformKind;
62 import jdk.vm.ci.meta.Value;
63 import jdk.vm.ci.meta.ValueKind;
64
65 public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implements AArch64ArithmeticLIRGeneratorTool {
66
67 @Override
68 public AArch64LIRGenerator getLIRGen() {
69 return (AArch64LIRGenerator) super.getLIRGen();
70 }
71
72 @Override
73 protected boolean isNumericInteger(PlatformKind kind) {
74 return ((AArch64Kind) kind).isInteger();
75 }
76
77 @Override
78 protected Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) {
117 }
118
119 @Override
120 public Value emitMul(Value a, Value b, boolean setFlags) {
121 AArch64ArithmeticOp intOp = setFlags ? AArch64ArithmeticOp.MULVS : AArch64ArithmeticOp.MUL;
122 return emitBinary(LIRKind.combine(a, b), getOpCode(a, intOp, AArch64ArithmeticOp.FMUL), true, a, b);
123 }
124
125 @Override
126 public Value emitMulHigh(Value a, Value b) {
127 assert isNumericInteger(a.getPlatformKind());
128 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.SMULH, true, a, b);
129 }
130
131 @Override
132 public Value emitUMulHigh(Value a, Value b) {
133 assert isNumericInteger(a.getPlatformKind());
134 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UMULH, true, a, b);
135 }
136
137 @Override
138 public Value emitDiv(Value a, Value b, LIRFrameState state) {
139 return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.DIV, AArch64ArithmeticOp.FDIV), false, asAllocatable(a), asAllocatable(b));
140 }
141
142 @Override
143 public Value emitRem(Value a, Value b, LIRFrameState state) {
144 return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.REM, AArch64ArithmeticOp.FREM), false, asAllocatable(a), asAllocatable(b));
145 }
146
147 @Override
148 public Value emitUDiv(Value a, Value b, LIRFrameState state) {
149 assert isNumericInteger(a.getPlatformKind());
150 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UDIV, false, asAllocatable(a), asAllocatable(b));
151 }
152
153 @Override
154 public Value emitURem(Value a, Value b, LIRFrameState state) {
155 assert isNumericInteger(a.getPlatformKind());
156 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UREM, false, asAllocatable(a), asAllocatable(b));
184 public Value emitShr(Value a, Value b) {
185 assert isNumericInteger(a.getPlatformKind());
186 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.ASHR, false, a, b);
187 }
188
189 @Override
190 public Value emitUShr(Value a, Value b) {
191 assert isNumericInteger(a.getPlatformKind());
192 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.LSHR, false, a, b);
193 }
194
195 @Override
196 public Value emitFloatConvert(FloatConvert op, Value inputVal) {
197 PlatformKind resultPlatformKind = getFloatConvertResultKind(op);
198 LIRKind resultLirKind = LIRKind.combine(inputVal).changeType(resultPlatformKind);
199 Variable result = getLIRGen().newVariable(resultLirKind);
200 getLIRGen().append(new AArch64FloatConvertOp(op, result, asAllocatable(inputVal)));
201 return result;
202 }
203
204 public Value emitAddSubShift(AArch64ArithmeticOp op, Value a, Value b, AArch64MacroAssembler.ShiftType shiftType, int shiftAmount) {
205 assert isNumericInteger(a.getPlatformKind());
206 assert isNumericInteger(b.getPlatformKind());
207 Variable result = getLIRGen().newVariable(LIRKind.combine(a, b));
208 AllocatableValue x = moveSp(asAllocatable(a));
209 AllocatableValue y = moveSp(asAllocatable(b));
210 getLIRGen().append(new AArch64ArithmeticOp.AddSubShiftOp(op, result, x, y, shiftType, shiftAmount));
211 return result;
212 }
213
214 private static PlatformKind getFloatConvertResultKind(FloatConvert op) {
215 switch (op) {
216 case F2I:
217 case D2I:
218 return AArch64Kind.DWORD;
219 case F2L:
220 case D2L:
221 return AArch64Kind.QWORD;
222 case I2F:
223 case L2F:
224 case D2F:
225 return AArch64Kind.SINGLE;
226 case I2D:
227 case L2D:
228 case F2D:
229 return AArch64Kind.DOUBLE;
230 default:
417 public Value emitCountLeadingZeros(Value value) {
418 Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
419 getLIRGen().append(new AArch64BitManipulationOp(CLZ, result, asAllocatable(value)));
420 return result;
421 }
422
423 @Override
424 public Value emitCountTrailingZeros(Value value) {
425 Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
426 getLIRGen().append(new AArch64BitManipulationOp(CTZ, result, asAllocatable(value)));
427 return result;
428 }
429
430 private Variable emitUnary(AArch64ArithmeticOp op, Value inputVal) {
431 AllocatableValue input = asAllocatable(inputVal);
432 Variable result = getLIRGen().newVariable(LIRKind.combine(input));
433 getLIRGen().append(new AArch64ArithmeticOp.UnaryOp(op, result, input));
434 return result;
435 }
436
437 /**
438 * If val denotes the stackpointer, move it to another location. This is necessary since most
439 * ops cannot handle the stackpointer as input or output.
440 */
441 private AllocatableValue moveSp(AllocatableValue val) {
442 if (val instanceof RegisterValue && ((RegisterValue) val).getRegister().equals(sp)) {
443 assert val.getPlatformKind() == AArch64Kind.QWORD : "Stackpointer must be long";
444 return getLIRGen().emitMove(val);
445 }
446 return val;
447 }
448
449 /**
450 * Returns the opcode depending on the platform kind of val.
451 */
452 private AArch64ArithmeticOp getOpCode(Value val, AArch64ArithmeticOp intOp, AArch64ArithmeticOp floatOp) {
453 return isNumericInteger(val.getPlatformKind()) ? intOp : floatOp;
454 }
455
456 @Override
457 public Variable emitLoad(LIRKind kind, Value address, LIRFrameState state) {
458 AArch64AddressValue loadAddress = getLIRGen().asAddressValue(address);
459 Variable result = getLIRGen().newVariable(getLIRGen().toRegisterKind(kind));
460 getLIRGen().append(new LoadOp((AArch64Kind) kind.getPlatformKind(), result, loadAddress, state));
461 return result;
462 }
463
464 @Override
465 public void emitStore(ValueKind<?> lirKind, Value address, Value inputVal, LIRFrameState state) {
466 AArch64AddressValue storeAddress = getLIRGen().asAddressValue(address);
|
1 /*
2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24
25
26 package org.graalvm.compiler.core.aarch64;
27
28 import static jdk.vm.ci.aarch64.AArch64Kind.DWORD;
29 import static jdk.vm.ci.aarch64.AArch64Kind.QWORD;
30 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
31 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
32 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.BSR;
33 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CLZ;
34 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CTZ;
35
36 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
37 import org.graalvm.compiler.core.common.LIRKind;
38 import org.graalvm.compiler.core.common.NumUtil;
39 import org.graalvm.compiler.core.common.calc.FloatConvert;
40 import org.graalvm.compiler.debug.GraalError;
41 import org.graalvm.compiler.lir.ConstantValue;
42 import org.graalvm.compiler.lir.LIRFrameState;
43 import org.graalvm.compiler.lir.Variable;
44 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
45 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool;
46 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
47 import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp;
48 import org.graalvm.compiler.lir.aarch64.AArch64Move.LoadOp;
49 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreConstantOp;
50 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp;
51 import org.graalvm.compiler.lir.aarch64.AArch64ReinterpretOp;
52 import org.graalvm.compiler.lir.aarch64.AArch64SignExtendOp;
53 import org.graalvm.compiler.lir.aarch64.AArch64Unary;
54 import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
55
56 import jdk.vm.ci.aarch64.AArch64Kind;
57 import jdk.vm.ci.meta.AllocatableValue;
58 import jdk.vm.ci.meta.JavaConstant;
59 import jdk.vm.ci.meta.PlatformKind;
60 import jdk.vm.ci.meta.Value;
61 import jdk.vm.ci.meta.ValueKind;
62
63 public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implements AArch64ArithmeticLIRGeneratorTool {
64
65 @Override
66 public AArch64LIRGenerator getLIRGen() {
67 return (AArch64LIRGenerator) super.getLIRGen();
68 }
69
70 @Override
71 protected boolean isNumericInteger(PlatformKind kind) {
72 return ((AArch64Kind) kind).isInteger();
73 }
74
75 @Override
76 protected Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) {
115 }
116
117 @Override
118 public Value emitMul(Value a, Value b, boolean setFlags) {
119 AArch64ArithmeticOp intOp = setFlags ? AArch64ArithmeticOp.MULVS : AArch64ArithmeticOp.MUL;
120 return emitBinary(LIRKind.combine(a, b), getOpCode(a, intOp, AArch64ArithmeticOp.FMUL), true, a, b);
121 }
122
123 @Override
124 public Value emitMulHigh(Value a, Value b) {
125 assert isNumericInteger(a.getPlatformKind());
126 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.SMULH, true, a, b);
127 }
128
129 @Override
130 public Value emitUMulHigh(Value a, Value b) {
131 assert isNumericInteger(a.getPlatformKind());
132 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UMULH, true, a, b);
133 }
134
135 public Value emitMNeg(Value a, Value b) {
136 assert isNumericInteger(a.getPlatformKind()) && isNumericInteger(b.getPlatformKind());
137 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.MNEG, true, a, b);
138 }
139
140 @Override
141 public Value emitDiv(Value a, Value b, LIRFrameState state) {
142 return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.DIV, AArch64ArithmeticOp.FDIV), false, asAllocatable(a), asAllocatable(b));
143 }
144
145 @Override
146 public Value emitRem(Value a, Value b, LIRFrameState state) {
147 return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.REM, AArch64ArithmeticOp.FREM), false, asAllocatable(a), asAllocatable(b));
148 }
149
150 @Override
151 public Value emitUDiv(Value a, Value b, LIRFrameState state) {
152 assert isNumericInteger(a.getPlatformKind());
153 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UDIV, false, asAllocatable(a), asAllocatable(b));
154 }
155
156 @Override
157 public Value emitURem(Value a, Value b, LIRFrameState state) {
158 assert isNumericInteger(a.getPlatformKind());
159 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UREM, false, asAllocatable(a), asAllocatable(b));
187 public Value emitShr(Value a, Value b) {
188 assert isNumericInteger(a.getPlatformKind());
189 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.ASHR, false, a, b);
190 }
191
192 @Override
193 public Value emitUShr(Value a, Value b) {
194 assert isNumericInteger(a.getPlatformKind());
195 return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.LSHR, false, a, b);
196 }
197
198 @Override
199 public Value emitFloatConvert(FloatConvert op, Value inputVal) {
200 PlatformKind resultPlatformKind = getFloatConvertResultKind(op);
201 LIRKind resultLirKind = LIRKind.combine(inputVal).changeType(resultPlatformKind);
202 Variable result = getLIRGen().newVariable(resultLirKind);
203 getLIRGen().append(new AArch64FloatConvertOp(op, result, asAllocatable(inputVal)));
204 return result;
205 }
206
207 public Value emitMAdd(Value a, Value b, Value c) {
208 return emitMultiplyAddSub(AArch64ArithmeticOp.ADD, a, b, c);
209 }
210
211 public Value emitMSub(Value a, Value b, Value c) {
212 return emitMultiplyAddSub(AArch64ArithmeticOp.SUB, a, b, c);
213 }
214
215 private Value emitMultiplyAddSub(AArch64ArithmeticOp op, Value a, Value b, Value c) {
216 assert isNumericInteger(a.getPlatformKind());
217 assert isNumericInteger(b.getPlatformKind());
218 assert isNumericInteger(c.getPlatformKind());
219
220 Variable result = getLIRGen().newVariable(LIRKind.combine(a, b, c));
221 AllocatableValue x = moveSp(asAllocatable(a));
222 AllocatableValue y = moveSp(asAllocatable(b));
223 AllocatableValue z = moveSp(asAllocatable(c));
224 getLIRGen().append(new AArch64ArithmeticOp.MultiplyAddSubOp(op, result, x, y, z));
225 return result;
226 }
227
228 private static PlatformKind getFloatConvertResultKind(FloatConvert op) {
229 switch (op) {
230 case F2I:
231 case D2I:
232 return AArch64Kind.DWORD;
233 case F2L:
234 case D2L:
235 return AArch64Kind.QWORD;
236 case I2F:
237 case L2F:
238 case D2F:
239 return AArch64Kind.SINGLE;
240 case I2D:
241 case L2D:
242 case F2D:
243 return AArch64Kind.DOUBLE;
244 default:
431 public Value emitCountLeadingZeros(Value value) {
432 Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
433 getLIRGen().append(new AArch64BitManipulationOp(CLZ, result, asAllocatable(value)));
434 return result;
435 }
436
437 @Override
438 public Value emitCountTrailingZeros(Value value) {
439 Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
440 getLIRGen().append(new AArch64BitManipulationOp(CTZ, result, asAllocatable(value)));
441 return result;
442 }
443
444 private Variable emitUnary(AArch64ArithmeticOp op, Value inputVal) {
445 AllocatableValue input = asAllocatable(inputVal);
446 Variable result = getLIRGen().newVariable(LIRKind.combine(input));
447 getLIRGen().append(new AArch64ArithmeticOp.UnaryOp(op, result, input));
448 return result;
449 }
450
451 private AllocatableValue moveSp(AllocatableValue val) {
452 return getLIRGen().moveSp(val);
453 }
454
455 /**
456 * Returns the opcode depending on the platform kind of val.
457 */
458 private AArch64ArithmeticOp getOpCode(Value val, AArch64ArithmeticOp intOp, AArch64ArithmeticOp floatOp) {
459 return isNumericInteger(val.getPlatformKind()) ? intOp : floatOp;
460 }
461
462 @Override
463 public Variable emitLoad(LIRKind kind, Value address, LIRFrameState state) {
464 AArch64AddressValue loadAddress = getLIRGen().asAddressValue(address);
465 Variable result = getLIRGen().newVariable(getLIRGen().toRegisterKind(kind));
466 getLIRGen().append(new LoadOp((AArch64Kind) kind.getPlatformKind(), result, loadAddress, state));
467 return result;
468 }
469
470 @Override
471 public void emitStore(ValueKind<?> lirKind, Value address, Value inputVal, LIRFrameState state) {
472 AArch64AddressValue storeAddress = getLIRGen().asAddressValue(address);
|