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.LIRInstruction.Opcode;
  34 import com.oracle.graal.lir.StandardOp.MoveOp;
  35 import com.oracle.graal.lir.asm.*;
  36 
  37 public class PTXMove {
  38 
  39     @Opcode("MOVE")
  40     public static class SpillMoveOp extends PTXLIRInstruction implements MoveOp {
  41 
  42         @Def({REG, STACK}) protected Value result;
  43         @Use({REG, STACK, CONST}) protected Value input;
  44 
  45         public SpillMoveOp(Value result, Value input) {
  46             this.result = result;
  47             this.input = input;
  48         }
  49 
  50         @Override
  51         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
  52             move(tasm, masm, getResult(), getInput());
  53         }
  54 
  55         @Override
  56         public Value getInput() {
  57             return input;
  58         }
  59 
  60         @Override
  61         public Value getResult() {
  62             return result;
  63         }
  64     }
  65 
  66     @Opcode("MOVE")
  67     public static class MoveToRegOp extends PTXLIRInstruction implements MoveOp {
  68 
  69         @Def({REG, HINT}) protected Value result;
  70         @Use({REG, STACK, CONST}) protected Value input;
  71 
  72         public MoveToRegOp(Value result, Value input) {
  73             this.result = result;
  74             this.input = input;
  75         }
  76 
  77         @Override
  78         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
  79             move(tasm, masm, getResult(), getInput());
  80         }
  81 
  82         @Override
  83         public Value getInput() {
  84             return input;
  85         }
  86 
  87         @Override
  88         public Value getResult() {
  89             return result;
  90         }
  91     }
  92 
  93     @Opcode("MOVE")
  94     public static class MoveFromRegOp extends PTXLIRInstruction implements MoveOp {
  95 
  96         @Def({REG, STACK}) protected Value result;
  97         @Use({REG, CONST, HINT}) protected Value input;
  98 
  99         public MoveFromRegOp(Value result, Value input) {
 100             this.result = result;
 101             this.input = input;
 102         }
 103 
 104         @Override
 105         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
 106             move(tasm, masm, getResult(), getInput());
 107         }
 108 
 109         @Override
 110         public Value getInput() {
 111             return input;
 112         }
 113 
 114         @Override
 115         public Value getResult() {
 116             return result;
 117         }
 118     }
 119 
 120     public static class LoadOp extends PTXLIRInstruction {
 121 
 122         @Def({REG}) protected AllocatableValue result;
 123         @Use({COMPOSITE}) protected PTXAddressValue address;
 124         @State protected LIRFrameState state;
 125 
 126         public LoadOp(AllocatableValue result, PTXAddressValue address, LIRFrameState state) {
 127             this.result = result;
 128             this.address = address;
 129             this.state = state;
 130         }
 131 
 132         @Override
 133         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
 134             PTXAddress addr = address.toAddress();
 135             switch (address.getKind()) {
 136                 case Int:
 137                     masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement());
 138                     break;
 139                 case Object:
 140                     masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement());
 141                     break;
 142                 default:
 143                     throw GraalInternalError.shouldNotReachHere();
 144             }
 145         }
 146     }
 147 
 148     public static class StoreOp extends PTXLIRInstruction {
 149 
 150         @Use({COMPOSITE}) protected PTXAddressValue address;
 151         @Use({REG}) protected AllocatableValue input;
 152         @State protected LIRFrameState state;
 153 
 154         public StoreOp(PTXAddressValue address, AllocatableValue input, LIRFrameState state) {
 155             this.address = address;
 156             this.input = input;
 157             this.state = state;
 158         }
 159 
 160         @Override
 161         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
 162             assert isRegister(input);
 163             PTXAddress addr = address.toAddress();
 164             switch (address.getKind()) {
 165                 case Int:
 166                     masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input));
 167                     break;
 168                 default:
 169                     throw GraalInternalError.shouldNotReachHere();
 170             }
 171         }
 172     }
 173 
 174     public static class LeaOp extends PTXLIRInstruction {
 175 
 176         @Def({REG}) protected AllocatableValue result;
 177         @Use({COMPOSITE, UNINITIALIZED}) protected PTXAddressValue address;
 178 
 179         public LeaOp(AllocatableValue result, PTXAddressValue address) {
 180             this.result = result;
 181             this.address = address;
 182         }
 183 
 184         @Override
 185         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
 186             throw new InternalError("NYI");
 187         }
 188     }
 189 
 190     public static class StackLeaOp extends PTXLIRInstruction {
 191 
 192         @Def({REG}) protected AllocatableValue result;
 193         @Use({STACK, UNINITIALIZED}) protected StackSlot slot;
 194 
 195         public StackLeaOp(AllocatableValue result, StackSlot slot) {
 196             this.result = result;
 197             this.slot = slot;
 198         }
 199 
 200         @Override
 201         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
 202             throw new InternalError("NYI");
 203         }
 204     }
 205 
 206     @Opcode("CAS")
 207     public static class CompareAndSwapOp extends PTXLIRInstruction {
 208 
 209         @Def protected AllocatableValue result;
 210         @Use({COMPOSITE}) protected PTXAddressValue address;
 211         @Use protected AllocatableValue cmpValue;
 212         @Use protected AllocatableValue newValue;
 213 
 214         public CompareAndSwapOp(AllocatableValue result, PTXAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
 215             this.result = result;
 216             this.address = address;
 217             this.cmpValue = cmpValue;
 218             this.newValue = newValue;
 219         }
 220 
 221         @Override
 222         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
 223             compareAndSwap(tasm, masm, result, address, cmpValue, newValue);
 224         }
 225     }
 226 
 227     public static void move(TargetMethodAssembler tasm, PTXAssembler masm, Value result, Value input) {
 228         if (isRegister(input)) {
 229             if (isRegister(result)) {
 230                 reg2reg(masm, result, input);
 231             } else {
 232                 throw GraalInternalError.shouldNotReachHere();
 233             }
 234         } else if (isConstant(input)) {
 235             if (isRegister(result)) {
 236                 const2reg(tasm, masm, result, (Constant) input);
 237             } else {
 238                 throw GraalInternalError.shouldNotReachHere();
 239             }
 240         } else {
 241             throw GraalInternalError.shouldNotReachHere();
 242         }
 243     }
 244 
 245     private static void reg2reg(PTXAssembler masm, Value result, Value input) {
 246         if (asRegister(input).equals(asRegister(result))) {
 247             return;
 248         }
 249         switch (input.getKind()) {
 250             case Int:
 251                 masm.mov_s32(asRegister(result), asRegister(input));
 252                 break;
 253             case Object:
 254                 masm.mov_u64(asRegister(result), asRegister(input));
 255                 break;
 256             default:
 257                 throw GraalInternalError.shouldNotReachHere("kind=" + result.getKind());
 258         }
 259     }
 260 
 261     private static void const2reg(TargetMethodAssembler tasm, PTXAssembler masm, Value result, Constant input) {
 262         switch (input.getKind().getStackKind()) {
 263             case Int:
 264                 if (tasm.runtime.needsDataPatch(input)) {
 265                     tasm.recordDataReferenceInCode(input, 0, true);
 266                 }
 267                 masm.mov_s32(asRegister(result), input.asInt());
 268                 break;
 269             default:
 270                 throw GraalInternalError.shouldNotReachHere();
 271         }
 272     }
 273 
 274     @SuppressWarnings("unused")
 275     protected static void compareAndSwap(TargetMethodAssembler tasm, PTXAssembler masm, AllocatableValue result, PTXAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
 276         throw new InternalError("NYI");
 277     }
 278 }