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 ---