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, LAND, INEG, 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, LSHL, ISHR, LSHR, IUSHR, LUSHR, 51 SQRT, UNDEF, CALL, L2I; 52 53 public static class Op1Stack extends HSAILLIRInstruction { 54 @Opcode private final HSAILArithmetic opcode; 55 @Def({REG, HINT}) protected Value result; 56 @Use({REG, STACK, CONST}) protected Value x; 57 58 public Op1Stack(HSAILArithmetic opcode, Value result, Value x) { 59 this.opcode = opcode; 60 this.result = result; 61 this.x = x; 62 } 63 64 @Override 65 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 66 emit(tasm, masm, opcode, result, x, null); 67 } 68 } 69 70 public static class Op2Stack extends HSAILLIRInstruction { 71 @Opcode private final HSAILArithmetic opcode; 72 @Def({REG, HINT}) protected Value result; 73 @Use({REG, CONST}) protected Value x; 74 @Alive({REG, CONST}) protected Value y; 75 76 public Op2Stack(HSAILArithmetic opcode, Value result, Value x, Value y) { 77 this.opcode = opcode; 78 this.result = result; 79 this.x = x; 80 this.y = y; 81 } 82 83 @Override 84 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 85 emit(tasm, masm, opcode, result, x, y, null); 86 } 87 88 @Override 89 public void verify() { 90 super.verify(); 91 verifyKind(opcode, result, x, y); 92 } 93 } 94 95 public static class Op1Reg extends HSAILLIRInstruction { 96 @Opcode private final HSAILArithmetic opcode; 97 @Def({REG, HINT}) protected Value result; 98 @Use({REG}) protected Value x; 99 100 public Op1Reg(HSAILArithmetic opcode, Value result, Value x) { 101 this.opcode = opcode; 102 this.result = result; 103 this.x = x; 104 } 105 106 @Override 107 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 108 emit(tasm, masm, opcode, result, x, null); 109 } 110 } 111 112 public static class Op2Reg extends HSAILLIRInstruction { 113 @Opcode private final HSAILArithmetic opcode; 114 @Def({REG, HINT}) protected Value result; 115 @Use({REG, STACK, CONST}) protected Value x; 116 @Alive({REG, CONST}) protected Value y; 117 118 public Op2Reg(HSAILArithmetic opcode, Value result, Value x, Value y) { 119 this.opcode = opcode; 120 this.result = result; 121 this.x = x; 122 this.y = y; 123 } 124 125 @Override 126 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 127 emit(tasm, masm, opcode, result, x, y, null); 128 } 129 130 @Override 131 public void verify() { 132 super.verify(); 133 verifyKind(opcode, result, x, y); 134 } 135 } 136 137 public static class Op2RegCommutative extends HSAILLIRInstruction { 138 @Opcode private final HSAILArithmetic opcode; 139 @Def({REG, HINT}) protected Value result; 140 @Use({REG, STACK, CONST}) protected Value x; 141 @Use({REG, CONST}) protected Value y; 142 143 public Op2RegCommutative(HSAILArithmetic opcode, Value result, Value x, Value y) { 144 this.opcode = opcode; 145 this.result = result; 146 this.x = x; 147 this.y = y; 148 } 149 150 @Override 151 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 152 throw GraalInternalError.shouldNotReachHere(); 153 } 154 155 @Override 156 protected void verify() { 157 super.verify(); 158 verifyKind(opcode, result, x, y); 159 } 160 } 161 162 public static class ShiftOp extends HSAILLIRInstruction { 163 @Opcode private final HSAILArithmetic opcode; 164 @Def({REG, HINT}) protected Value result; 165 @Use({REG, STACK, CONST}) protected Value x; 166 @Alive({REG, CONST}) protected Value y; 167 168 public ShiftOp(HSAILArithmetic opcode, Value result, Value x, Value y) { 169 this.opcode = opcode; 170 this.result = result; 171 this.x = x; 172 this.y = y; 173 } 174 175 @Override 176 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 177 emit(tasm, masm, opcode, result, x, y, null); 178 } 179 180 @Override 181 public void verify() { 182 super.verify(); 183 verifyKind(opcode, result, x, x); 184 assert y.getKind().getStackKind() == Kind.Int; 185 } 186 } 187 188 public static class DivOp extends HSAILLIRInstruction { 189 @Opcode private final HSAILArithmetic opcode; 190 @Def protected Value result; 191 @Use protected Value x; 192 @Alive protected Value y; 193 @State protected LIRFrameState state; 194 195 public DivOp(HSAILArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) { 196 this.opcode = opcode; 197 this.result = result; 198 this.x = x; 199 this.y = y; 200 this.state = state; 201 } 202 203 @Override 204 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 205 emit(tasm, masm, opcode, result, y, state); 206 } 207 208 @Override 209 protected void verify() { 210 super.verify(); 211 verifyKind(opcode, result, x, y); 212 } 213 } 214 215 @SuppressWarnings("unused") 216 protected static void emit(TargetMethodAssembler tasm, HSAILAssembler masm, HSAILArithmetic opcode, Value result) { 217 switch (opcode) { 218 default: throw GraalInternalError.shouldNotReachHere(); 219 } 220 } 221 222 public static void emit(TargetMethodAssembler tasm, HSAILAssembler masm, HSAILArithmetic opcode, Value dst, Value src, LIRFrameState info) { 223 int exceptionOffset = -1; 224 if (isRegister(src)) { 225 switch (opcode) { 226 case I2F: 227 case I2D: 228 case D2I: 229 case I2L: 230 case L2I: 231 case F2D: 232 case D2F: masm.emitConvert(dst, src); break; 233 case SQRT: masm.emitArg1("sqrt", dst, src); break; 234 case UNDEF: masm.undefined("undefined node"); break; 235 case CALL: masm.undefined("undefined node CALL"); break; 236 default: 237 throw GraalInternalError.shouldNotReachHere(); 238 } 239 } else { 240 throw GraalInternalError.shouldNotReachHere(); 241 } 242 if (info != null) { 243 assert exceptionOffset != -1; 244 tasm.recordImplicitException(exceptionOffset, info); 245 } 246 } 247 248 public static void emit(TargetMethodAssembler tasm, HSAILAssembler masm, HSAILArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) { 249 /** 250 * First check if one of src1 or src2 is an AddressValue. If it is, 251 * convert the address to a register using an lda instruction. We can 252 * just reuse the eventual dst register for this. 253 */ 254 if (src1 instanceof HSAILAddressValue) { 255 assert (!(src2 instanceof HSAILAddressValue)); 256 masm.emitLda(dst, ((HSAILAddressValue) src1).toAddress()); 257 emit(tasm, masm, opcode, dst, dst, src2, info); 258 return; 259 } else if (src2 instanceof HSAILAddressValue) { 260 assert (!(src1 instanceof HSAILAddressValue)); 261 masm.emitLda(dst, ((HSAILAddressValue) src2).toAddress()); 262 emit(tasm, masm, opcode, dst, src1, dst, info); 263 return; 264 } 265 int exceptionOffset = -1; 266 switch (opcode) { 267 case IADD: 268 case LADD: 269 case DADD: 270 case FADD: 271 case OADD: 272 masm.emit("add", dst, src1, src2); break; 273 case ISUB: 274 case LSUB: 275 case DSUB: 276 case FSUB: 277 masm.emit("sub", dst, src1, src2); break; 278 case IMUL: 279 case LMUL: 280 case FMUL: 281 case DMUL: 282 case LUMUL: 283 masm.emit("mul", dst, src1, src2); break; 284 case IDIV: 285 case LDIV: 286 case FDIV: 287 case DDIV: 288 masm.emit("div", dst, src1, src2); break; 289 case IMAX: 290 case LMAX: 291 masm.emit("max", dst, src1, src2); break; 292 case IMIN: 293 case LMIN: 294 masm.emit("min", dst, src1, src2); break; 295 case ISHL: 296 case LSHL: 297 masm.emit("shl", dst, src1, src2); break; 298 case ISHR: 299 case LSHR: 300 masm.emit("shr", dst, src1, src2); break; 301 case IUSHR: 302 case LUSHR: 303 masm.emitForceUnsigned("shr", dst, src1, src2); break; 304 case IREM: 305 masm.emit("rem", dst, src1, src2); break; 306 default: throw GraalInternalError.shouldNotReachHere(); 307 } 308 if (info != null) { 309 assert exceptionOffset != -1; 310 tasm.recordImplicitException(exceptionOffset, info); 311 } 312 } 313 314 private static void verifyKind(HSAILArithmetic opcode, Value result, Value x, Value y) { 315 assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) 316 || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long) 317 || (opcode.name().startsWith("LU") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Int) 318 || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float) 319 || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double) 320 || (opcode.name().startsWith("O") && result.getKind() == Kind.Object && x.getKind() == Kind.Object && (y.getKind() == Kind.Int || y.getKind() == Kind.Long) 321 ); 322 } 323 } --- EOF ---