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 }