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.hsail; 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.meta.*; 29 import com.oracle.graal.asm.hsail.*; 30 import com.oracle.graal.graph.*; 31 import com.oracle.graal.lir.*; 32 import com.oracle.graal.lir.asm.*; 33 34 // @formatter:off 35 /** 36 * Defines arithmetic instruction nodes. 37 */ 38 public enum HSAILArithmetic { 39 IADD, OADD, ISUB, FSUB, DSUB, IMUL, FMUL, 40 DMUL, IDIV, FDIV, DDIV, IUADD, IUSUB, 41 IUMUL, IUDIV, LADD, DADD, FADD, LSUB, 42 LMUL, LDIV, LUADD, LUSUB, LUMUL, 43 LUDIV, IMAX, LMAX, IUMAX, LUMAX, 44 IMIN, LMIN, IUMIN, LUMIN, IREM, 45 LREM, FREM, DREM, IUREM, LUREM, 46 ICARRY, LCARRY, IUCARRY, LUCARRY, 47 IAND, INEG, IUSHR, I2B, I2S, I2L, 48 F2D, F2I, F2L, D2F, I2F, I2D, D2I, 49 L2F, D2L, MOV_F2I, MOV_D2L, L2D, MOV_I2F, 50 MOV_L2D, ISHL, SQRT, UNDEF, CALL, L2I; 51 52 public static class Op1Stack extends HSAILLIRInstruction { 53 @Opcode private final HSAILArithmetic opcode; 54 @Def({REG, HINT}) protected Value result; 55 @Use({REG, STACK, CONST}) protected Value x; 56 57 public Op1Stack(HSAILArithmetic opcode, Value result, Value x) { 58 this.opcode = opcode; 59 this.result = result; 60 this.x = x; 61 } 62 63 @Override 64 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 65 emit(tasm, masm, opcode, result, x, null); 66 } 67 } 68 69 public static class Op2Stack extends HSAILLIRInstruction { 70 @Opcode private final HSAILArithmetic opcode; 71 @Def({REG, HINT}) protected Value result; 72 @Use({REG, CONST}) protected Value x; 73 @Alive({REG, CONST}) protected Value y; 74 75 public Op2Stack(HSAILArithmetic opcode, Value result, Value x, Value y) { 76 this.opcode = opcode; 77 this.result = result; 78 this.x = x; 79 this.y = y; 80 } 81 82 @Override 83 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 84 emit(tasm, masm, opcode, result, x, y, null); 85 } 86 87 @Override 88 public void verify() { 89 super.verify(); 90 verifyKind(opcode, result, x, y); 91 } 92 } 93 94 public static class Op1Reg extends HSAILLIRInstruction { 95 @Opcode private final HSAILArithmetic opcode; 96 @Def({REG, HINT}) protected Value result; 97 @Use({REG}) protected Value x; 98 99 public Op1Reg(HSAILArithmetic opcode, Value result, Value x) { 100 this.opcode = opcode; 101 this.result = result; 102 this.x = x; 103 } 104 105 @Override 106 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 107 emit(tasm, masm, opcode, result, x, null); 108 } 109 } 110 111 public static class Op2Reg extends HSAILLIRInstruction { 112 @Opcode private final HSAILArithmetic opcode; 113 @Def({REG, HINT}) protected Value result; 114 @Use({REG, STACK, CONST}) protected Value x; 115 @Alive({REG, CONST}) protected Value y; 116 117 public Op2Reg(HSAILArithmetic opcode, Value result, Value x, Value y) { 118 this.opcode = opcode; 119 this.result = result; 120 this.x = x; 121 this.y = y; 122 } 123 124 @Override 125 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 126 emit(tasm, masm, opcode, result, x, y, null); 127 } 128 129 @Override 130 public void verify() { 131 super.verify(); 132 verifyKind(opcode, result, x, y); 133 } 134 } 135 136 public static class Op2RegCommutative extends HSAILLIRInstruction { 137 @Opcode private final HSAILArithmetic opcode; 138 @Def({REG, HINT}) protected Value result; 139 @Use({REG, STACK, CONST}) protected Value x; 140 @Use({REG, CONST}) protected Value y; 141 142 public Op2RegCommutative(HSAILArithmetic opcode, Value result, Value x, Value y) { 143 this.opcode = opcode; 144 this.result = result; 145 this.x = x; 146 this.y = y; 147 } 148 149 @Override 150 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 151 throw GraalInternalError.shouldNotReachHere(); 152 } 153 154 @Override 155 protected void verify() { 156 super.verify(); 157 verifyKind(opcode, result, x, y); 158 } 159 } 160 161 public static class ShiftOp extends HSAILLIRInstruction { 162 @Opcode private final HSAILArithmetic opcode; 163 @Def({REG, HINT}) protected Value result; 164 @Use({REG, STACK, CONST}) protected Value x; 165 @Alive({REG, CONST}) protected Value y; 166 167 public ShiftOp(HSAILArithmetic opcode, Value result, Value x, Value y) { 168 this.opcode = opcode; 169 this.result = result; 170 this.x = x; 171 this.y = y; 172 } 173 174 @Override 175 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 176 emit(tasm, masm, opcode, result, x, y, null); 177 } 178 179 @Override 180 public void verify() { 181 super.verify(); 182 verifyKind(opcode, result, x, x); 183 assert y.getKind().getStackKind() == Kind.Int; 184 } 185 } 186 187 public static class DivOp extends HSAILLIRInstruction { 188 @Opcode private final HSAILArithmetic opcode; 189 @Def protected Value result; 190 @Use protected Value x; 191 @Alive protected Value y; 192 @State protected LIRFrameState state; 193 194 public DivOp(HSAILArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) { 195 this.opcode = opcode; 196 this.result = result; 197 this.x = x; 198 this.y = y; 199 this.state = state; 200 } 201 202 @Override 203 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 204 emit(tasm, masm, opcode, result, y, state); 205 } 206 207 @Override 208 protected void verify() { 209 super.verify(); 210 verifyKind(opcode, result, x, y); 211 } 212 } 213 214 @SuppressWarnings("unused") 215 protected static void emit(TargetMethodAssembler tasm, HSAILAssembler masm, HSAILArithmetic opcode, Value result) { 216 switch (opcode) { 217 default: throw GraalInternalError.shouldNotReachHere(); 218 } 219 } 220 221 public static void emit(TargetMethodAssembler tasm, HSAILAssembler masm, HSAILArithmetic opcode, Value dst, Value src, LIRFrameState info) { 222 int exceptionOffset = -1; 223 if (isRegister(src)) { 224 switch (opcode) { 225 case I2F: 226 case I2D: 227 case D2I: 228 case I2L: 229 case L2I: 230 case F2D: 231 case D2F: masm.emitConvert(dst, src); break; 232 case SQRT: masm.emitArg1("sqrt", dst, src); break; 233 case UNDEF: masm.undefined("undefined node"); break; 234 case CALL: masm.undefined("undefined node CALL"); break; 235 default: 236 throw GraalInternalError.shouldNotReachHere(); 237 } 238 } else { 239 throw GraalInternalError.shouldNotReachHere(); 240 } 241 if (info != null) { 242 assert exceptionOffset != -1; 243 tasm.recordImplicitException(exceptionOffset, info); 244 } 245 } 246 247 public static void emit(TargetMethodAssembler tasm, HSAILAssembler masm, HSAILArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) { 248 int exceptionOffset = -1; 249 switch (opcode) { 250 case IADD: 251 case LADD: 252 case DADD: 253 case FADD: 254 case OADD: 255 masm.emit("add", dst, src1, src2); break; 256 case ISUB: 257 case LSUB: 258 case DSUB: 259 case FSUB: 260 masm.emit("sub", dst, src1, src2); break; 261 case IMUL: 262 case LMUL: 263 case FMUL: 264 case DMUL: 265 case LUMUL: 266 masm.emit("mul", dst, src1, src2); break; 267 case IDIV: 268 case LDIV: 269 case FDIV: 270 case DDIV: 271 masm.emit("div", dst, src1, src2); break; 272 case IMAX: 273 case LMAX: 274 masm.emit("max", dst, src1, src2); break; 275 case IMIN: 276 case LMIN: 277 masm.emit("min", dst, src1, src2); break; 278 case ISHL: 279 masm.emit("shl", dst, src1, src2); break; 280 case IREM: 281 masm.emit("rem", dst, src1, src2); break; 282 default: throw GraalInternalError.shouldNotReachHere(); 283 } 284 if (info != null) { 285 assert exceptionOffset != -1; 286 tasm.recordImplicitException(exceptionOffset, info); 287 } 288 } 289 290 private static void verifyKind(HSAILArithmetic opcode, Value result, Value x, Value y) { 291 assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) 292 || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long) 293 || (opcode.name().startsWith("LU") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Int) 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 || (opcode.name().startsWith("O") && result.getKind() == Kind.Object && x.getKind() == Kind.Object && (y.getKind() == Kind.Int || y.getKind() == Kind.Long) 297 ); 298 } 299 }