1 /* 2 * Copyright (c) 2009, 2012, 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.asm.hsail; 24 25 import static com.oracle.graal.api.code.MemoryBarriers.*; 26 import static com.oracle.graal.api.code.ValueUtil.*; 27 28 import com.oracle.graal.api.code.*; 29 import com.oracle.graal.api.meta.*; 30 import com.oracle.graal.compiler.common.*; 31 import com.oracle.graal.hsail.*; 32 33 /** 34 * This class contains routines to emit HSAIL assembly code. 35 */ 36 public abstract class HSAILAssembler extends AbstractHSAILAssembler { 37 38 /** 39 * Stack size in bytes (used to keep track of spilling). 40 */ 41 private int maxDataTypeSize; 42 43 /** 44 * Maximum stack offset used by a store operation. 45 */ 46 private long maxStackOffset = 0; 47 48 public long upperBoundStackSize() { 49 return maxStackOffset + maxDataTypeSize; 50 } 51 52 public HSAILAssembler(TargetDescription target) { 53 super(target); 54 } 55 56 @Override 57 public HSAILAddress makeAddress(Register base, int displacement) { 58 return new HSAILAddress(base, displacement); 59 } 60 61 @Override 62 public HSAILAddress getPlaceholder() { 63 return null; 64 } 65 66 @Override 67 public final void ensureUniquePC() { 68 throw GraalInternalError.unimplemented(); 69 } 70 71 public final void undefined(String str) { 72 emitString("undefined operation " + str); 73 } 74 75 public final void exit() { 76 emitString("ret;" + ""); 77 } 78 79 /** 80 * Moves an Object into a register. 81 * 82 * Because Object references become stale after Garbage collection (GC) the technique used here 83 * is to load a JNI global reference to that Object into the register. These JNI global 84 * references get updated by the GC whenever the GC moves an Object. 85 * 86 * @param a the destination register 87 * @param src the Object Constant being moved 88 */ 89 public abstract void mov(Register a, Constant src); 90 91 public final void emitMov(Kind kind, Value dst, Value src) { 92 if (isRegister(dst) && isConstant(src) && kind.getStackKind() == Kind.Object) { 93 mov(asRegister(dst), asConstant(src)); 94 } else { 95 String argtype = getArgTypeFromKind(kind).substring(1); 96 emitString("mov_b" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";"); 97 } 98 } 99 100 private void emitAddrOp(String instr, Value reg, HSAILAddress addr) { 101 String storeValue = mapRegOrConstToString(reg); 102 emitString(instr + " " + storeValue + ", " + mapAddress(addr) + ";"); 103 } 104 105 /** 106 * Emits a memory barrier instruction. 107 * 108 * @param barriers the kind of barrier to emit 109 */ 110 public final void emitMembar(int barriers) { 111 if (barriers == 0) { 112 emitString("// no barrier before volatile read"); 113 } else if (barriers == JMM_POST_VOLATILE_READ) { 114 emitString("sync; // barriers=" + MemoryBarriers.barriersString(barriers)); 115 } else if (barriers == JMM_PRE_VOLATILE_WRITE) { 116 emitString("sync; // barriers=" + MemoryBarriers.barriersString(barriers)); 117 } else if (barriers == JMM_POST_VOLATILE_WRITE) { 118 emitString("sync; // barriers=" + MemoryBarriers.barriersString(barriers)); 119 } 120 } 121 122 public final void emitLoad(Kind kind, Value dest, HSAILAddress addr) { 123 emitLoad(dest, addr, getArgTypeFromKind(kind)); 124 } 125 126 public final void emitLoad(Value dest, HSAILAddress addr, String argTypeStr) { 127 emitAddrOp("ld_global_" + argTypeStr, dest, addr); 128 } 129 130 public final void emitLda(Value dest, HSAILAddress addr) { 131 emitAddrOp("lda_global_u64", dest, addr); 132 } 133 134 public final void emitLea(Value dest, HSAILAddress addr) { 135 String prefix = getArgType(dest); 136 emitString(String.format("add_%s %s, $%s, 0x%s;", prefix, HSAIL.mapRegister(dest), addr.getBase().name, Long.toHexString(addr.getDisplacement()))); 137 } 138 139 public final void emitLoadKernelArg(Value dest, String kernArgName, String argTypeStr) { 140 emitString("ld_kernarg_" + argTypeStr + " " + HSAIL.mapRegister(dest) + ", [" + kernArgName + "];"); 141 } 142 143 public final void emitStore(Kind kind, Value src, HSAILAddress addr) { 144 emitStore(src, addr, getArgTypeFromKind(kind)); 145 } 146 147 public final void emitStore(Value dest, HSAILAddress addr, String argTypeStr) { 148 emitAddrOp("st_global_" + argTypeStr, dest, addr); 149 } 150 151 private void storeImmediateImpl(String storeType, String value, HSAILAddress addr) { 152 emitString("st_global_" + storeType + " " + value + ", " + mapAddress(addr) + ";"); 153 } 154 155 public final void emitStoreImmediate(Kind kind, long src, HSAILAddress addr) { 156 assert (kind != Kind.Float && kind != Kind.Double); 157 storeImmediateImpl(getArgTypeFromKind(kind), Long.toString(src), addr); 158 } 159 160 public final void emitStoreImmediate(float src, HSAILAddress addr) { 161 storeImmediateImpl("f32", floatToString(src), addr); 162 } 163 164 public final void emitStoreImmediate(double src, HSAILAddress addr) { 165 storeImmediateImpl("f64", doubleToString(src), addr); 166 } 167 168 public final void emitSpillLoad(Kind kind, Value dest, Value src) { 169 emitString("ld_spill_" + getArgTypeFromKind(kind) + " " + HSAIL.mapRegister(dest) + ", " + mapStackSlot(src, getArgSizeFromKind(kind)) + ";"); 170 } 171 172 public final void emitStore(Value src, HSAILAddress addr) { 173 emitString("st_global_" + getArgType(src) + " " + HSAIL.mapRegister(src) + ", " + mapAddress(addr) + ";"); 174 } 175 176 public final void emitSpillStore(Kind kind, Value src, Value dest) { 177 int sizestored = getArgSizeFromKind(kind); 178 if (maxDataTypeSize < sizestored) { 179 maxDataTypeSize = sizestored; 180 } 181 int stackoffset = HSAIL.getStackOffset(dest); 182 if (maxStackOffset < stackoffset) { 183 maxStackOffset = stackoffset; 184 } 185 emitString("st_spill_" + getArgTypeFromKind(kind) + " " + HSAIL.mapRegister(src) + ", " + mapStackSlot(dest, getArgSizeFromKind(kind)) + ";"); 186 } 187 188 public static String mapStackSlot(Value reg, int argSize) { 189 long startOffset = HSAIL.getStackOffsetStart(reg, argSize); 190 return "[%spillseg]" + "[" + startOffset + "]"; 191 } 192 193 public void cbr(String target1) { 194 emitString("cbr " + "$c0" + ", " + target1 + ";"); 195 } 196 197 public int getArgSize(Value src) { 198 return getArgSizeFromKind(src.getKind()); 199 } 200 201 private static int getArgSizeFromKind(Kind kind) { 202 switch (kind) { 203 case Int: 204 case Float: 205 return 32; 206 case Double: 207 case Long: 208 case Object: 209 return 64; 210 default: 211 throw GraalInternalError.shouldNotReachHere(); 212 } 213 } 214 215 private static String getArgType(Value src) { 216 return getArgTypeFromKind(src.getKind()); 217 } 218 219 private static String getArgTypeFromKind(Kind kind) { 220 String prefix = ""; 221 switch (kind) { 222 case Float: 223 prefix = "f32"; 224 break; 225 case Double: 226 prefix = "f64"; 227 break; 228 case Int: 229 prefix = "s32"; 230 break; 231 case Long: 232 prefix = "s64"; 233 break; 234 case Object: 235 prefix = "u64"; 236 break; 237 case Char: 238 prefix = "u16"; 239 break; 240 case Short: 241 prefix = "s16"; 242 break; 243 case Byte: 244 prefix = "s8"; 245 break; 246 case Boolean: 247 prefix = "u8"; 248 break; 249 default: 250 throw GraalInternalError.shouldNotReachHere(); 251 } 252 return prefix; 253 } 254 255 public static final String getArgTypeForceUnsigned(Value src) { 256 return getArgTypeForceUnsignedKind(src.getKind()); 257 } 258 259 public static final String getArgTypeForceUnsignedKind(Kind kind) { 260 switch (kind) { 261 case Int: 262 return "u32"; 263 case Long: 264 case Object: 265 return "u64"; 266 default: 267 throw GraalInternalError.shouldNotReachHere(); 268 } 269 } 270 271 public static final String getArgTypeBitwiseLogical(Value src) { 272 String length = getArgType(src); 273 String prefix = "_b" + (length.endsWith("64") ? "64" : "32"); 274 return prefix; 275 } 276 277 /** 278 * Emits a compare instruction. 279 * 280 * @param src0 - the first source register 281 * @param src1 - the second source register 282 * @param condition - the compare condition i.e., eq, ne, lt, gt 283 * @param unordered - flag specifying if this is an unordered compare. This only applies to 284 * float compares. 285 * @param isUnsignedCompare - flag specifying if this is a compare of unsigned values. 286 */ 287 public void emitCompare(Kind compareKind, Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) { 288 // Formulate the prefix of the instruction. 289 // if unordered is true, it should be ignored unless the src type is f32 or f64 290 String argType = getArgTypeFromKind(compareKind); 291 String unorderedPrefix = (argType.startsWith("f") && unordered ? "u" : ""); 292 String prefix = "cmp_" + condition + unorderedPrefix + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : argType); 293 // Generate a comment for debugging purposes 294 String comment = (isConstant(src1) && (src1.getKind() == Kind.Object) && (asConstant(src1).isNull()) ? " // null test " : ""); 295 // Emit the instruction. 296 emitString(prefix + " $c0, " + mapRegOrConstToString(src0) + ", " + mapRegOrConstToString(src1) + ";" + comment); 297 } 298 299 public void emitConvert(Value dest, Value src, String destType, String srcType) { 300 String prefix = "cvt_"; 301 if (destType.equals("f32") && srcType.equals("f64")) { 302 prefix = "cvt_near_"; 303 } else if (srcType.startsWith("f") && (destType.startsWith("s") || destType.startsWith("u"))) { 304 prefix = "cvt_zeroi_sat_"; 305 } 306 emitString(prefix + destType + "_" + srcType + " " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapRegister(src) + ";"); 307 } 308 309 public void emitConvert(Value dest, Value src, Kind destKind, Kind srcKind) { 310 String destType = getArgTypeFromKind(destKind); 311 String srcType = getArgTypeFromKind(srcKind); 312 emitConvert(dest, src, destType, srcType); 313 } 314 315 /** 316 * Emits a convert instruction that uses unsigned prefix, regardless of the type of dest and 317 * src. 318 * 319 * @param dest the destination operand 320 * @param src the source operand 321 */ 322 public void emitConvertForceUnsigned(Value dest, Value src) { 323 emitString("cvt_" + getArgTypeForceUnsigned(dest) + "_" + getArgTypeForceUnsigned(src) + " " + HSAIL.mapRegister(dest) + ", " + HSAIL.mapRegister(src) + ";"); 324 } 325 326 public static String mapAddress(HSAILAddress addr) { 327 if (addr.getBase().encoding() < 0) { 328 return "[0x" + Long.toHexString(addr.getDisplacement()) + "]"; 329 } else { 330 return "[$d" + addr.getBase().encoding() + " + " + addr.getDisplacement() + "]"; 331 } 332 } 333 334 private static String doubleToString(double dval) { 335 long lval = Double.doubleToRawLongBits(dval); 336 long lvalIgnoreSign = lval & 0x7fffffffffffffffL; 337 if (lvalIgnoreSign >= 0x7ff0000000000000L) { 338 return "0D" + String.format("%16x", lval); 339 } else { 340 return Double.toString(dval); 341 } 342 } 343 344 private static String floatToString(float fval) { 345 int ival = Float.floatToRawIntBits(fval); 346 int ivalIgnoreSign = ival & 0x7fffffff; 347 if (ivalIgnoreSign >= 0x7f800000) { 348 return "0F" + String.format("%8x", ival); 349 } else { 350 return Float.toString(fval) + "f"; 351 } 352 } 353 354 private static String mapRegOrConstToString(Value src) { 355 if (!isConstant(src)) { 356 return HSAIL.mapRegister(src); 357 } else { 358 Constant consrc = asConstant(src); 359 switch (src.getKind()) { 360 case Boolean: 361 case Int: 362 return Integer.toString(consrc.asInt()); 363 case Float: 364 return floatToString(consrc.asFloat()); 365 case Double: 366 return doubleToString(consrc.asDouble()); 367 case Long: 368 return "0x" + Long.toHexString(consrc.asLong()); 369 case Object: 370 if (consrc.isNull()) { 371 return "0"; 372 } else { 373 throw GraalInternalError.shouldNotReachHere("unknown type: " + src); 374 } 375 default: 376 throw GraalInternalError.shouldNotReachHere("unknown type: " + src); 377 } 378 } 379 380 } 381 382 /** 383 * Emits an instruction. 384 * 385 * @param mnemonic the instruction mnemonic 386 * @param dest the destination operand 387 * @param sources the source operands 388 */ 389 public final void emit(String mnemonic, Value dest, Value... sources) { 390 String prefix = getArgType(dest); 391 emitTextFormattedInstruction(mnemonic + "_" + prefix, dest, sources); 392 } 393 394 /** 395 * Emits an unsigned instruction. 396 * 397 * @param mnemonic the instruction mnemonic 398 * @param dest the destination argument 399 * @param sources the source arguments 400 * 401 */ 402 public final void emitForceUnsigned(String mnemonic, Value dest, Value... sources) { 403 String prefix = getArgTypeForceUnsigned(dest); 404 emitTextFormattedInstruction(mnemonic + "_" + prefix, dest, sources); 405 } 406 407 public final void emitForceUnsignedKind(String mnemonic, Kind kind, Value dest, Value... sources) { 408 String prefix = getArgTypeForceUnsignedKind(kind); 409 emitTextFormattedInstruction(mnemonic + "_" + prefix, dest, sources); 410 } 411 412 /** 413 * Emits an instruction for a bitwise logical operation. 414 * 415 * @param mnemonic the instruction mnemonic 416 * @param dest the destination 417 * @param sources the source operands 418 */ 419 public final void emitForceBitwise(String mnemonic, Value dest, Value... sources) { 420 String prefix = getArgTypeBitwiseLogical(dest); 421 emitTextFormattedInstruction(mnemonic + prefix, dest, sources); 422 } 423 424 /** 425 * Central helper routine that emits a text formatted HSAIL instruction via call to 426 * AbstractAssembler.emitString. All the emit routines in the assembler end up calling this one. 427 * 428 * @param instr the full instruction mnenomics including any prefixes 429 * @param dest the destination operand 430 * @param sources the source operand 431 */ 432 private void emitTextFormattedInstruction(String instr, Value dest, Value... sources) { 433 /** 434 * Destination can't be a constant and no instruction has > 3 source operands. 435 */ 436 assert (!isConstant(dest) && sources.length <= 3); 437 switch (sources.length) { 438 case 3: 439 // Emit an instruction with three source operands. 440 emitString(String.format("%s %s, %s, %s, %s;", instr, HSAIL.mapRegister(dest), mapRegOrConstToString(sources[0]), mapRegOrConstToString(sources[1]), mapRegOrConstToString(sources[2]))); 441 break; 442 case 2: 443 // Emit an instruction with two source operands. 444 emitString(String.format("%s %s, %s, %s;", instr, HSAIL.mapRegister(dest), mapRegOrConstToString(sources[0]), mapRegOrConstToString(sources[1]))); 445 break; 446 case 1: 447 // Emit an instruction with one source operand. 448 emitString(String.format("%s %s, %s;", instr, HSAIL.mapRegister(dest), mapRegOrConstToString(sources[0]))); 449 break; 450 default: 451 // Emit an instruction with one source operand. 452 emitString(String.format("%s %s;", instr, HSAIL.mapRegister(dest))); 453 break; 454 } 455 } 456 457 /** 458 * Emits a conditional move instruction. 459 * 460 * @param dest the destination operand storing result of the move 461 * @param trueReg the register that should be copied to dest if the condition is true 462 * @param falseReg the register that should be copied to dest if the condition is false 463 * @param width the width of the instruction (32 or 64 bits) 464 */ 465 public final void emitConditionalMove(Value dest, Value trueReg, Value falseReg, int width) { 466 assert (!isConstant(dest)); 467 String instr = (width == 32 ? "cmov_b32" : "cmov_b64"); 468 emitString(String.format("%s %s, %s%s, %s;", instr, HSAIL.mapRegister(dest), "$c0, ", mapRegOrConstToString(trueReg), mapRegOrConstToString(falseReg))); 469 } 470 471 /** 472 * Emits code to build a 64-bit pointer from a compressed value and the associated base and 473 * shift. The compressed value could represent either a normal oop or a klass ptr. If the 474 * compressed value is 0, the uncompressed must also be 0. We only emit this if base and shift 475 * are not both zero. 476 * 477 * @param result the register containing the compressed value on input and the uncompressed ptr 478 * on output 479 * @param base the amount to be added to the compressed value 480 * @param shift the number of bits to shift left the compressed value 481 * @param testForNull true if the compressed value might be null 482 */ 483 public void emitCompressedOopDecode(Value result, long base, int shift, boolean testForNull) { 484 assert (base != 0 || shift != 0); 485 assert (!isConstant(result)); 486 if (base == 0) { 487 // we don't have to test for null if shl is the only operation 488 emitForceUnsignedKind("shl", Kind.Long, result, result, Constant.forInt(shift)); 489 } else if (shift == 0) { 490 // only use add if result is not starting as null (test only if testForNull is true) 491 emitWithOptionalTestForNull(testForNull, "add", result, result, Constant.forLong(base)); 492 } else { 493 // only use mad if result is not starting as null (test only if testForNull is true) 494 emitWithOptionalTestForNull(testForNull, "mad", result, result, Constant.forInt(1 << shift), Constant.forLong(base)); 495 } 496 } 497 498 /** 499 * Emits code to build a compressed value from a full 64-bit pointer using the associated base 500 * and shift. The compressed value could represent either a normal oop or a klass ptr. If the 501 * ptr is 0, the compressed value must also be 0. We only emit this if base and shift are not 502 * both zero. 503 * 504 * @param result the register containing the 64-bit pointer on input and the compressed value on 505 * output 506 * @param base the amount to be subtracted from the 64-bit pointer 507 * @param shift the number of bits to shift right the 64-bit pointer 508 * @param testForNull true if the 64-bit pointer might be null 509 */ 510 public void emitCompressedOopEncode(Value result, long base, int shift, boolean testForNull) { 511 assert (base != 0 || shift != 0); 512 assert (!isConstant(result)); 513 if (base != 0) { 514 // only use sub if result is not starting as null (test only if testForNull is true) 515 emitWithOptionalTestForNull(testForNull, "sub", result, result, Constant.forLong(base)); 516 } 517 if (shift != 0) { 518 // note that the shr can still be done even if the result is null 519 emitForceUnsignedKind("shr", Kind.Long, result, result, Constant.forInt(shift)); 520 } 521 } 522 523 /** 524 * Emits code for the requested mnemonic on the result and sources. In addition, if testForNull 525 * is true, surrounds the instruction with code that will guarantee that if the result starts as 526 * 0, it will remain 0. 527 * 528 * @param testForNull true if we want to add the code to check for and preserve null 529 * @param mnemonic the instruction to be applied (without size prefix) 530 * @param result the register which is both an input and the final output 531 * @param sources the sources for the mnemonic instruction 532 */ 533 private void emitWithOptionalTestForNull(boolean testForNull, String mnemonic, Value result, Value... sources) { 534 if (testForNull) { 535 emitCompare(Kind.Long, result, Constant.forLong(0), "eq", false, true); 536 } 537 emitForceUnsigned(mnemonic, result, sources); 538 if (testForNull) { 539 emitConditionalMove(result, Constant.forLong(0), result, 64); 540 } 541 } 542 543 /** 544 * Emits an atomic_cas_global instruction. 545 * 546 * @param result result operand that gets the original contents of the memory location 547 * @param address the memory location 548 * @param cmpValue the value that will be compared against the memory location 549 * @param newValue the new value that will be written to the memory location if the cmpValue 550 * comparison matches 551 */ 552 public void emitAtomicCas(Kind accessKind, AllocatableValue result, HSAILAddress address, Value cmpValue, Value newValue) { 553 emitString(String.format("atomic_cas_global_b%d %s, %s, %s, %s;", getArgSizeFromKind(accessKind), HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(cmpValue), 554 mapRegOrConstToString(newValue))); 555 } 556 557 /** 558 * Emits an atomic_add_global instruction. 559 * 560 * @param result result operand that gets the original contents of the memory location 561 * @param address the memory location 562 * @param delta the amount to add 563 */ 564 public void emitAtomicAdd(AllocatableValue result, HSAILAddress address, Value delta) { 565 // ensure result and delta agree (this should probably be at some higher level) 566 Value mydelta = delta; 567 if (!isConstant(delta) && (getArgSize(result) != getArgSize(delta))) { 568 emitConvert(result, delta, result.getKind(), delta.getKind()); 569 mydelta = result; 570 } 571 String prefix = getArgTypeForceUnsigned(result); 572 emitString(String.format("atomic_add_global_%s %s, %s, %s;", prefix, HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(mydelta))); 573 } 574 575 /** 576 * Emits an atomic_exch_global instruction. 577 * 578 * @param result result operand that gets the original contents of the memory location 579 * @param address the memory location 580 * @param newValue the new value to write to the memory location 581 */ 582 public void emitAtomicExch(Kind accessKind, AllocatableValue result, HSAILAddress address, Value newValue) { 583 emitString(String.format("atomic_exch_global_b%d %s, %s, %s;", getArgSizeFromKind(accessKind), HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(newValue))); 584 } 585 586 /** 587 * Emits a comment. Useful for debugging purposes. 588 * 589 * @param comment 590 */ 591 public void emitComment(String comment) { 592 emitString(comment); 593 } 594 595 public String getDeoptInfoName() { 596 return "%_deoptInfo"; 597 } 598 599 public String getDeoptLabelName() { 600 return "@L_Deopt"; 601 } 602 603 public void emitWorkItemAbsId(Value dest) { 604 emitString(String.format("workitemabsid_u32 %s, 0;", HSAIL.mapRegister(dest))); 605 } 606 607 public void emitCuId(Value dest) { 608 emitString(String.format("cuid_u32 %s;", HSAIL.mapRegister(dest))); 609 } 610 611 public void emitLaneId(Value dest) { 612 emitString(String.format("laneid_u32 %s;", HSAIL.mapRegister(dest))); 613 } 614 615 public void emitWaveId(Value dest) { 616 emitString(String.format("waveid_u32 %s;", HSAIL.mapRegister(dest))); 617 } 618 619 public void emitMaxWaveId(Value dest) { 620 // emitString(String.format("maxwaveid_u32 %s;", HSAIL.mapRegister(dest))); 621 int hardCodedMaxWaveId = 36; 622 emitComment("// Hard-coded maxwaveid=" + hardCodedMaxWaveId + " until it works"); 623 emitMov(Kind.Int, dest, Constant.forInt(hardCodedMaxWaveId)); 624 } 625 626 public void emitMultiplyByWavesize(Value dest) { 627 String regName = HSAIL.mapRegister(dest); 628 emitString(String.format("mul_u%d %s, %s, WAVESIZE;", getArgSize(dest), regName, regName)); 629 } 630 631 public void emitGetWavesize(Value dest) { 632 String regName = HSAIL.mapRegister(dest); 633 emitString(String.format("mov_b%d %s, WAVESIZE;", getArgSize(dest), regName)); 634 } 635 636 public void emitLoadAcquire(Value dest, HSAILAddress address) { 637 emitString(String.format("ld_global_acq_u%d %s, %s;", getArgSize(dest), HSAIL.mapRegister(dest), mapAddress(address))); 638 } 639 640 public void emitStoreRelease(Value src, HSAILAddress address) { 641 emitString(String.format("st_global_rel_u%d %s, %s;", getArgSize(src), HSAIL.mapRegister(src), mapAddress(address))); 642 } 643 }