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.code.*; 29 import com.oracle.graal.api.meta.*; 30 import com.oracle.graal.asm.hsail.*; 31 import com.oracle.graal.debug.*; 32 import com.oracle.graal.graph.*; 33 import com.oracle.graal.lir.*; 34 import com.oracle.graal.lir.StandardOp.MoveOp; 35 import com.oracle.graal.lir.asm.*; 36 37 /** 38 * Implementation of move instructions. 39 */ 40 public class HSAILMove { 41 42 // Stack size in bytes (used to keep track of spilling). 43 static int maxDatatypeSize; 44 // Maximum stack offset used by a store operation. 45 static long maxStackOffset = 0; 46 47 public static long upperBoundStackSize() { 48 return maxStackOffset + maxDatatypeSize; 49 } 50 51 @Opcode("MOVE") 52 public static class SpillMoveOp extends HSAILLIRInstruction implements MoveOp { 53 54 @Def({REG, STACK}) protected AllocatableValue result; 55 @Use({REG, STACK, CONST}) protected Value input; 56 57 public SpillMoveOp(AllocatableValue result, Value input) { 58 this.result = result; 59 this.input = input; 60 } 61 62 @Override 63 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 64 move(tasm, masm, getResult(), getInput()); 65 } 66 67 @Override 68 public Value getInput() { 69 return input; 70 } 71 72 @Override 73 public AllocatableValue getResult() { 74 return result; 75 } 76 } 77 78 @Opcode("MOVE") 79 public static class MoveToRegOp extends HSAILLIRInstruction implements MoveOp { 80 81 @Def({REG, HINT}) protected AllocatableValue result; 82 @Use({REG, STACK, CONST}) protected Value input; 83 84 public MoveToRegOp(AllocatableValue result, Value input) { 85 this.result = result; 86 this.input = input; 87 } 88 89 @Override 90 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 91 move(tasm, masm, getResult(), getInput()); 92 } 93 94 @Override 95 public Value getInput() { 96 return input; 97 } 98 99 @Override 100 public AllocatableValue getResult() { 101 return result; 102 } 103 } 104 105 @Opcode("MOVE") 106 public static class MoveFromRegOp extends HSAILLIRInstruction implements MoveOp { 107 108 @Def({REG, STACK}) protected AllocatableValue result; 109 @Use({REG, CONST, HINT}) protected Value input; 110 111 public MoveFromRegOp(AllocatableValue result, Value input) { 112 this.result = result; 113 this.input = input; 114 } 115 116 @Override 117 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 118 move(tasm, masm, getResult(), getInput()); 119 } 120 121 @Override 122 public Value getInput() { 123 return input; 124 } 125 126 @Override 127 public AllocatableValue getResult() { 128 return result; 129 } 130 } 131 132 133 public abstract static class MemOp extends HSAILLIRInstruction { 134 135 protected final Kind kind; 136 @Use({COMPOSITE}) protected HSAILAddressValue address; 137 @State protected LIRFrameState state; 138 139 public MemOp(Kind kind, HSAILAddressValue address, LIRFrameState state) { 140 this.kind = kind; 141 this.address = address; 142 this.state = state; 143 } 144 145 protected abstract void emitMemAccess(HSAILAssembler masm); 146 147 @Override 148 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 149 if (state != null) { 150 // tasm.recordImplicitException(masm.codeBuffer.position(), state); 151 throw new InternalError("NYI"); 152 } 153 emitMemAccess(masm); 154 } 155 } 156 157 public static class LoadOp extends MemOp { 158 159 @Def({REG}) protected AllocatableValue result; 160 161 public LoadOp(Kind kind, AllocatableValue result, HSAILAddressValue address, LIRFrameState state) { 162 super(kind, address, state); 163 this.result = result; 164 } 165 166 @Override 167 public void emitMemAccess(HSAILAssembler masm) { 168 HSAILAddress addr = address.toAddress(); 169 masm.emitLoad(result, addr); 170 } 171 } 172 173 public static class StoreOp extends MemOp { 174 175 @Use({REG}) protected AllocatableValue input; 176 177 public StoreOp(Kind kind, HSAILAddressValue address, AllocatableValue input, LIRFrameState state) { 178 super(kind, address, state); 179 this.input = input; 180 } 181 182 @Override 183 public void emitMemAccess(HSAILAssembler masm) { 184 assert isRegister(input); 185 HSAILAddress addr = address.toAddress(); 186 masm.emitStore(input, addr); 187 } 188 } 189 190 public static class LoadCompressedPointer extends LoadOp { 191 192 private long narrowOopBase; 193 private int narrowOopShift; 194 private int logMinObjAlignment; 195 @Temp({REG}) private AllocatableValue scratch; 196 197 public LoadCompressedPointer(Kind kind, AllocatableValue result, AllocatableValue scratch, HSAILAddressValue address, LIRFrameState state, long narrowOopBase, int narrowOopShift, 198 int logMinObjAlignment) { 199 super(kind, result, address, state); 200 this.narrowOopBase = narrowOopBase; 201 this.narrowOopShift = narrowOopShift; 202 this.logMinObjAlignment = logMinObjAlignment; 203 this.scratch = scratch; 204 assert kind == Kind.Object; 205 } 206 207 @Override 208 public void emitMemAccess(HSAILAssembler masm) { 209 // we will do a 32 bit load, zero extending into a 64 bit register 210 masm.emitLoad(result, address.toAddress(), "u32"); 211 decodePointer(masm, result, narrowOopBase, narrowOopShift, logMinObjAlignment); 212 } 213 } 214 215 public static class StoreCompressedPointer extends HSAILLIRInstruction { 216 217 protected final Kind kind; 218 private long narrowOopBase; 219 private int narrowOopShift; 220 private int logMinObjAlignment; 221 @Temp({REG}) private AllocatableValue scratch; 222 @Alive({REG}) protected AllocatableValue input; 223 @Alive({COMPOSITE}) protected HSAILAddressValue address; 224 @State protected LIRFrameState state; 225 226 public StoreCompressedPointer(Kind kind, HSAILAddressValue address, AllocatableValue input, AllocatableValue scratch, LIRFrameState state, long narrowOopBase, int narrowOopShift, 227 int logMinObjAlignment) { 228 this.narrowOopBase = narrowOopBase; 229 this.narrowOopShift = narrowOopShift; 230 this.logMinObjAlignment = logMinObjAlignment; 231 this.scratch = scratch; 232 this.kind = kind; 233 this.address = address; 234 this.state = state; 235 this.input = input; 236 assert kind == Kind.Object; 237 } 238 239 @Override 240 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 241 masm.emitMov(scratch, input); 242 encodePointer(masm, scratch, narrowOopBase, narrowOopShift, logMinObjAlignment); 243 if (state != null) { 244 throw new InternalError("NYI"); 245 // tasm.recordImplicitException(masm.codeBuffer.position(), state); 246 } 247 masm.emitStore(scratch, address.toAddress(), "u32"); 248 } 249 } 250 251 private static void encodePointer(HSAILAssembler masm, Value scratch, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) { 252 if (narrowOopBase == 0 && narrowOopShift == 0) { 253 return; 254 } 255 if (narrowOopShift != 0) { 256 assert logMinObjAlignment == narrowOopShift : "Encode algorithm is wrong"; 257 } 258 masm.emitCompressedOopEncode(scratch, narrowOopBase, narrowOopShift); 259 } 260 261 private static void decodePointer(HSAILAssembler masm, Value result, long narrowOopBase, int narrowOopShift, int logMinObjAlignment) { 262 if (narrowOopBase == 0 && narrowOopShift == 0) { 263 return; 264 } 265 if (narrowOopShift != 0) { 266 assert logMinObjAlignment == narrowOopShift : "Decode algorithm is wrong"; 267 } 268 masm.emitCompressedOopDecode(result, narrowOopBase, narrowOopShift); 269 } 270 271 272 273 public static class LeaOp extends HSAILLIRInstruction { 274 275 @Def({REG}) protected AllocatableValue result; 276 @Use({COMPOSITE, UNINITIALIZED}) protected HSAILAddressValue address; 277 278 public LeaOp(AllocatableValue result, HSAILAddressValue address) { 279 this.result = result; 280 this.address = address; 281 } 282 283 @Override 284 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 285 throw new InternalError("NYI"); 286 } 287 } 288 289 public static class StackLeaOp extends HSAILLIRInstruction { 290 291 @Def({REG}) protected AllocatableValue result; 292 @Use({STACK, UNINITIALIZED}) protected StackSlot slot; 293 294 public StackLeaOp(AllocatableValue result, StackSlot slot) { 295 this.result = result; 296 this.slot = slot; 297 } 298 299 @Override 300 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 301 throw new InternalError("NYI"); 302 } 303 } 304 305 @Opcode("CAS") 306 public static class CompareAndSwapOp extends HSAILLIRInstruction { 307 308 @Def protected AllocatableValue result; 309 @Use({COMPOSITE}) protected HSAILAddressValue address; 310 @Use protected AllocatableValue cmpValue; 311 @Use protected AllocatableValue newValue; 312 313 public CompareAndSwapOp(AllocatableValue result, HSAILAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { 314 this.result = result; 315 this.address = address; 316 this.cmpValue = cmpValue; 317 this.newValue = newValue; 318 } 319 320 @Override 321 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 322 compareAndSwap(tasm, masm, result, address, cmpValue, newValue); 323 } 324 } 325 326 public static class NullCheckOp extends HSAILLIRInstruction { 327 328 @Use protected Value input; 329 @State protected LIRFrameState state; 330 331 public NullCheckOp(Variable input, LIRFrameState state) { 332 this.input = input; 333 this.state = state; 334 } 335 336 @Override 337 public void emitCode(TargetMethodAssembler tasm, HSAILAssembler masm) { 338 Debug.log("NullCheckOp unimplemented"); 339 } 340 } 341 342 @SuppressWarnings("unused") 343 public static void move(TargetMethodAssembler tasm, HSAILAssembler masm, Value result, Value input) { 344 if (isRegister(input)) { 345 if (isRegister(result)) { 346 masm.emitMov(result, input); 347 } else if (isStackSlot(result)) { 348 masm.emitSpillStore(input, result); 349 } else { 350 throw GraalInternalError.shouldNotReachHere(); 351 } 352 } else if (isStackSlot(input)) { 353 if (isRegister(result)) { 354 masm.emitSpillLoad(result, input); 355 } else { 356 throw GraalInternalError.shouldNotReachHere(); 357 } 358 } else if (isConstant(input)) { 359 if (isRegister(result)) { 360 masm.emitMov(result, input); 361 } else { 362 throw GraalInternalError.shouldNotReachHere(); 363 } 364 } else { 365 throw GraalInternalError.shouldNotReachHere(); 366 } 367 } 368 369 @SuppressWarnings("unused") 370 protected static void compareAndSwap(TargetMethodAssembler tasm, HSAILAssembler masm, AllocatableValue result, HSAILAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { 371 throw new InternalError("NYI"); 372 } 373 } --- EOF ---