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 package com.oracle.graal.lir.ptx;
24
25 import static com.oracle.graal.api.code.ValueUtil.*;
26 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
27
28 import com.oracle.graal.api.code.*;
29 import com.oracle.graal.api.meta.*;
30 import com.oracle.graal.asm.ptx.*;
31 import com.oracle.graal.graph.*;
32 import com.oracle.graal.lir.*;
33 import com.oracle.graal.lir.asm.*;
34
35 // @formatter:off
36 public enum PTXArithmetic {
37 IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
38 LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
39 FADD, FSUB, FMUL, FDIV, FAND, FOR, FXOR,
40 DADD, DSUB, DMUL, DDIV, DAND, DOR, DXOR,
41 INEG, LNEG,
42 I2L, L2I, I2B, I2C, I2S,
43 F2D, D2F,
44 I2F, I2D, F2I, D2I,
45 L2F, L2D, F2L, D2L,
46 MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L;
47
48
49 public static class Op1Reg extends PTXLIRInstruction {
50 @Opcode private final PTXArithmetic opcode;
51 @Def({REG, HINT}) protected Value result;
52 @Use({REG}) protected Value x;
53
54 public Op1Reg(PTXArithmetic opcode, Value result, Value x) {
55 this.opcode = opcode;
56 this.result = result;
57 this.x = x;
58 }
59
60 @Override
61 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
62 emit(tasm, masm, opcode, result, x, null);
63 }
64 }
65
66 public static class Op1Stack extends PTXLIRInstruction {
67 @Opcode private final PTXArithmetic opcode;
68 @Def({REG, HINT}) protected Value result;
196 public DivOp(PTXArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) {
197 this.opcode = opcode;
198 this.result = result;
199 this.x = x;
200 this.y = y;
201 this.state = state;
202 }
203
204 @Override
205 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
206 emit(tasm, masm, opcode, result, y, state);
207 }
208
209 @Override
210 protected void verify() {
211 super.verify();
212 verifyKind(opcode, result, x, y);
213 }
214 }
215
216
217 @SuppressWarnings("unused")
218 protected static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value result) {
219 switch (opcode) {
220 default: throw GraalInternalError.shouldNotReachHere();
221 }
222 }
223
224 public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src, LIRFrameState info) {
225 int exceptionOffset = -1;
226 if (isRegister(src)) {
227 Register a = asIntReg(src);
228 Register d = asIntReg(dst);
229 switch (opcode) {
230 case INEG: masm.neg_s32(d, a); break;
231 default:
232 throw GraalInternalError.shouldNotReachHere();
233 }
234 } else if (isConstant(src)) {
235 switch (opcode) {
236 case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break;
237 case IAND: masm.and_b32(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break;
238 default: throw GraalInternalError.shouldNotReachHere();
239 }
240 } else {
241 switch (opcode) {
242 default: throw GraalInternalError.shouldNotReachHere();
243 }
244 }
245
246 if (info != null) {
247 assert exceptionOffset != -1;
248 tasm.recordImplicitException(exceptionOffset, info);
249 }
250 }
251
252 public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) {
253 int exceptionOffset = -1;
254 if (isConstant(src1)) {
255 int a = tasm.asIntConst(src1);
256 Register b = asIntReg(src2);
257 Register d = asIntReg(dst);
258 switch (opcode) {
259 case ISUB: masm.sub_s32(d, a, b); break;
260 case IAND: masm.and_b32(d, b, a); break;
261 default: throw GraalInternalError.shouldNotReachHere();
262 }
263 } else if (isConstant(src2)) {
264 Register a = asIntReg(src1);
265 int b = tasm.asIntConst(src2);
266 Register d = asIntReg(dst);
267 switch (opcode) {
268 case IADD: masm.add_s32(d, a, b); break;
269 case IAND: masm.and_b32(d, a, b); break;
270 case IUSHR: masm.shr_u32(d, a, b); break;
271 default: throw GraalInternalError.shouldNotReachHere();
272 }
273 } else {
274 Register a = asIntReg(src1);
275 Register b = asIntReg(src2);
276 Register d = asIntReg(dst);
277 switch (opcode) {
278 case IADD: masm.add_s32(d, a, b); break;
279 case ISUB: masm.sub_s32(d, a, b); break;
280 case IMUL: masm.mul_s32(d, a, b); break;
281 default: throw GraalInternalError.shouldNotReachHere();
282 }
283 }
284
285 if (info != null) {
286 assert exceptionOffset != -1;
287 tasm.recordImplicitException(exceptionOffset, info);
288 }
289 }
290
291 private static void verifyKind(PTXArithmetic opcode, Value result, Value x, Value y) {
292 assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int)
293 || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
294 || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float)
295 || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double);
296 }
297 }
|
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 package com.oracle.graal.lir.ptx;
24
25 import static com.oracle.graal.api.code.ValueUtil.*;
26 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
27
28 import com.oracle.graal.api.code.*;
29 import com.oracle.graal.api.meta.*;
30 import com.oracle.graal.asm.ptx.*;
31 import com.oracle.graal.graph.*;
32 import com.oracle.graal.lir.*;
33 import com.oracle.graal.lir.LIRInstruction.Def;
34 import com.oracle.graal.lir.LIRInstruction.Opcode;
35 import com.oracle.graal.lir.LIRInstruction.Use;
36 import com.oracle.graal.lir.asm.*;
37
38 // @formatter:off
39 public enum PTXArithmetic {
40 IADD, ISUB, IMUL, IDIV, IDIVREM, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
41 LADD, LSUB, LMUL, LDIV, LDIVREM, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
42 FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
43 DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
44 INEG, LNEG, FNEG, DNEG,
45 I2L, L2I, I2B, I2C, I2S,
46 F2D, D2F,
47 I2F, I2D, F2I, D2I,
48 L2F, L2D, F2L, D2L,
49 MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L;
50
51
52 /**
53 * Unary operation with separate source and destination operand.
54 */
55 public static class Unary2Op extends PTXLIRInstruction {
56 @Opcode private final PTXArithmetic opcode;
57 @Def({REG}) protected AllocatableValue result;
58 @Use({REG, STACK}) protected AllocatableValue x;
59
60 public Unary2Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) {
61 this.opcode = opcode;
62 this.result = result;
63 this.x = x;
64 }
65
66 @Override
67 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
68 PTXMove.move(tasm, masm, result, x);
69 emit(tasm, masm, opcode, result, x, null);
70 }
71 }
72
73 /**
74 * Unary operation with single operand for source and destination.
75 */
76 public static class Unary1Op extends PTXLIRInstruction {
77 @Opcode private final PTXArithmetic opcode;
78 @Def({REG, HINT}) protected AllocatableValue result;
79 @Use({REG, STACK}) protected AllocatableValue x;
80
81 public Unary1Op(PTXArithmetic opcode, AllocatableValue result, AllocatableValue x) {
82 this.opcode = opcode;
83 this.result = result;
84 this.x = x;
85 }
86
87 @Override
88 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
89 emit(tasm, masm, opcode, result);
90 }
91 }
92
93 public static class Op1Reg extends PTXLIRInstruction {
94 @Opcode private final PTXArithmetic opcode;
95 @Def({REG, HINT}) protected Value result;
96 @Use({REG}) protected Value x;
97
98 public Op1Reg(PTXArithmetic opcode, Value result, Value x) {
99 this.opcode = opcode;
100 this.result = result;
101 this.x = x;
102 }
103
104 @Override
105 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
106 emit(tasm, masm, opcode, result, x, null);
107 }
108 }
109
110 public static class Op1Stack extends PTXLIRInstruction {
111 @Opcode private final PTXArithmetic opcode;
112 @Def({REG, HINT}) protected Value result;
240 public DivOp(PTXArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) {
241 this.opcode = opcode;
242 this.result = result;
243 this.x = x;
244 this.y = y;
245 this.state = state;
246 }
247
248 @Override
249 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
250 emit(tasm, masm, opcode, result, y, state);
251 }
252
253 @Override
254 protected void verify() {
255 super.verify();
256 verifyKind(opcode, result, x, y);
257 }
258 }
259
260 protected static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value result) {
261 switch (opcode) {
262 case L2I: masm.cvt_s32_s64(asLongReg(result), asIntReg(result)); break;
263 case I2C: masm.cvt_b16_s32(asIntReg(result), asIntReg(result)); break;
264 default:
265 System.err.println("missing: " + opcode);
266 throw GraalInternalError.shouldNotReachHere();
267 }
268 }
269
270 public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src, LIRFrameState info) {
271 int exceptionOffset = -1;
272 if (isRegister(src)) {
273 Register a = asIntReg(src);
274 Register d = asIntReg(dst);
275 switch (opcode) {
276 case INEG: masm.neg_s32(d, a); break;
277 case FNEG: masm.neg_f32(d, a); break;
278 case DNEG: masm.neg_f64(d, a); break;
279 case I2L: masm.cvt_s64_s32(d, a); break;
280 case I2C: masm.cvt_b16_s32(d, a); break;
281 case I2B: masm.cvt_s8_s32(d, a); break;
282 case I2F: masm.cvt_f32_s32(d, a); break;
283 case I2D: masm.cvt_f64_s32(d, a); break;
284 case F2I: masm.cvt_s32_f32(d, a); break;
285 case F2L: masm.cvt_s64_f32(d, a); break;
286 case F2D: masm.cvt_f64_f32(d, a); break;
287 case D2I: masm.cvt_s32_f64(d, a); break;
288 case D2L: masm.cvt_s64_f64(d, a); break;
289 case D2F: masm.cvt_f32_f64(d, a); break;
290 default:
291 System.err.println("missing: " + opcode);
292 throw GraalInternalError.shouldNotReachHere();
293 }
294 } else if (isConstant(src)) {
295 switch (opcode) {
296 case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break;
297 case IAND: masm.and_b32(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break;
298 default: throw GraalInternalError.shouldNotReachHere();
299 }
300 } else {
301 switch (opcode) {
302 default: throw GraalInternalError.shouldNotReachHere();
303 }
304 }
305
306 if (info != null) {
307 assert exceptionOffset != -1;
308 tasm.recordImplicitException(exceptionOffset, info);
309 }
310 }
311
312 public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) {
313 int exceptionOffset = -1;
314 if (isConstant(src1)) {
315 switch (opcode) {
316 case ISUB: masm.sub_s32(asIntReg(dst), tasm.asIntConst(src1), asIntReg(src2)); break;
317 case IAND: masm.and_b32(asIntReg(dst), asIntReg(src2), tasm.asIntConst(src1)); break;
318 case IDIV: masm.div_s32(asIntReg(dst), tasm.asIntConst(src1), asIntReg(src2)); break;
319 case FSUB: masm.sub_f32(asFloatReg(dst), tasm.asFloatConst(src1), asFloatReg(src2)); break;
320 case FDIV: masm.div_f32(asFloatReg(dst), tasm.asFloatConst(src1), asFloatReg(src2)); break;
321 case DSUB: masm.sub_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2)); break;
322 case DDIV: masm.div_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2)); break;
323 default:
324 throw GraalInternalError.shouldNotReachHere();
325 }
326 } else if (isConstant(src2)) {
327 switch (opcode) {
328 case IADD: masm.add_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break;
329 case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break;
330 case IMUL: masm.mul_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break;
331 case IAND: masm.and_b32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break;
332 case ISHL: masm.shl_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break;
333 case ISHR: masm.shr_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break;
334 case IUSHR: masm.shr_u32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break;
335 case IXOR: masm.xor_b32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break;
336 case LXOR: masm.xor_b64(asLongReg(dst), asLongReg(src1), tasm.asLongConst(src2)); break;
337 case LUSHR: masm.shr_u64(asLongReg(dst), asLongReg(src1), tasm.asLongConst(src2)); break;
338 case FADD: masm.add_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break;
339 case FMUL: masm.mul_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break;
340 case FDIV: masm.div_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break;
341 case DADD: masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
342 case DMUL: masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
343 case DDIV: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break;
344 default:
345 throw GraalInternalError.shouldNotReachHere();
346 }
347 } else {
348 switch (opcode) {
349 case IADD: masm.add_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break;
350 case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break;
351 case IMUL: masm.mul_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break;
352 case IDIV: masm.div_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break;
353 case IAND: masm.and_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break;
354 case IOR: masm.or_b32 (asIntReg(dst), asIntReg(src1), asIntReg(src2)); break;
355 case IXOR: masm.xor_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break;
356 case ISHL: masm.shl_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break;
357 case ISHR: masm.shr_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break;
358 case IUSHR: masm.shr_u32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break;
359 case IREM: masm.rem_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break;
360 case LADD: masm.add_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break;
361 case LSUB: masm.sub_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break;
362 case LMUL: masm.mul_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break;
363 case LDIV: masm.div_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break;
364 case LAND: masm.and_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break;
365 case LOR: masm.or_b64 (asLongReg(dst), asLongReg(src1), asLongReg(src2)); break;
366 case LXOR: masm.xor_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break;
367 case LSHL: masm.shl_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break;
368 case LSHR: masm.shr_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break;
369 case LUSHR: masm.shr_u64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break;
370 case LREM: masm.rem_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break;
371 case FADD: masm.add_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break;
372 case FSUB: masm.sub_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break;
373 case FMUL: masm.mul_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break;
374 case FDIV: masm.div_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break;
375 case FREM: masm.div_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break;
376 case DADD: masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
377 case DSUB: masm.sub_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
378 case DMUL: masm.mul_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
379 case DDIV: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
380 case DREM: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break;
381 default:
382 System.err.println("missing: " + opcode);
383 throw GraalInternalError.shouldNotReachHere();
384 }
385 }
386
387 if (info != null) {
388 assert exceptionOffset != -1;
389 tasm.recordImplicitException(exceptionOffset, info);
390 }
391 }
392
393 private static void verifyKind(PTXArithmetic opcode, Value result, Value x, Value y) {
394 assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int)
395 || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long)
396 || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float)
397 || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double);
398 }
399 }
|