1 /* 2 * Copyright (c) 2013, 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 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; 69 @Use({REG, STACK, CONST}) protected Value x; 70 71 public Op1Stack(PTXArithmetic opcode, Value result, Value x) { 72 this.opcode = opcode; 73 this.result = result; 74 this.x = x; 75 } 76 77 @Override 78 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { 79 emit(tasm, masm, opcode, result, x, null); 80 } 81 } 82 83 public static class Op2Stack extends PTXLIRInstruction { 84 @Opcode private final PTXArithmetic opcode; 85 @Def({REG, HINT}) protected Value result; 86 @Use({REG, STACK, CONST}) protected Value x; 87 @Alive({REG, STACK, CONST}) protected Value y; 88 89 public Op2Stack(PTXArithmetic opcode, Value result, Value x, Value y) { 90 this.opcode = opcode; 91 this.result = result; 92 this.x = x; 93 this.y = y; 94 } 95 96 @Override 97 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { 98 emit(tasm, masm, opcode, result, x, y, null); 99 } 100 101 @Override 102 public void verify() { 103 super.verify(); 104 verifyKind(opcode, result, x, y); 105 } 106 } 107 108 public static class Op2Reg extends PTXLIRInstruction { 109 @Opcode private final PTXArithmetic opcode; 110 @Def({REG, HINT}) protected Value result; 111 @Use({REG, STACK, CONST}) protected Value x; 112 @Alive({REG, CONST}) protected Value y; 113 114 public Op2Reg(PTXArithmetic opcode, Value result, Value x, Value y) { 115 this.opcode = opcode; 116 this.result = result; 117 this.x = x; 118 this.y = y; 119 } 120 121 @Override 122 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { 123 emit(tasm, masm, opcode, result, x, y, null); 124 } 125 126 @Override 127 public void verify() { 128 super.verify(); 129 verifyKind(opcode, result, x, y); 130 } 131 } 132 133 public static class Op2RegCommutative extends PTXLIRInstruction { 134 @Opcode private final PTXArithmetic opcode; 135 @Def({REG, HINT}) protected Value result; 136 @Use({REG, STACK, CONST}) protected Value x; 137 @Use({REG, CONST}) protected Value y; 138 139 public Op2RegCommutative(PTXArithmetic opcode, Value result, Value x, Value y) { 140 this.opcode = opcode; 141 this.result = result; 142 this.x = x; 143 this.y = y; 144 } 145 146 @Override 147 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { 148 if (sameRegister(result, y)) { 149 emit(tasm, masm, opcode, result, x, null); 150 } else { 151 PTXMove.move(tasm, masm, result, x); 152 emit(tasm, masm, opcode, result, y, null); 153 } 154 } 155 156 @Override 157 protected void verify() { 158 super.verify(); 159 verifyKind(opcode, result, x, y); 160 } 161 } 162 163 public static class ShiftOp extends PTXLIRInstruction { 164 @Opcode private final PTXArithmetic opcode; 165 @Def({REG, HINT}) protected Value result; 166 @Use({REG, STACK, CONST}) protected Value x; 167 @Alive({REG, CONST}) protected Value y; 168 169 public ShiftOp(PTXArithmetic opcode, Value result, Value x, Value y) { 170 this.opcode = opcode; 171 this.result = result; 172 this.x = x; 173 this.y = y; 174 } 175 176 @Override 177 public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { 178 emit(tasm, masm, opcode, result, x, y, null); 179 } 180 181 @Override 182 public void verify() { 183 super.verify(); 184 verifyKind(opcode, result, x, x); 185 assert y.getKind().getStackKind() == Kind.Int; 186 } 187 } 188 189 public static class DivOp extends PTXLIRInstruction { 190 @Opcode private final PTXArithmetic opcode; 191 @Def protected Value result; 192 @Use protected Value x; 193 @Alive protected Value y; 194 @State protected LIRFrameState state; 195 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 }