operand.hh revision 11308:7d8836fd043d
1/* 2 * Copyright (c) 2012-2015 Advanced Micro Devices, Inc. 3 * All rights reserved. 4 * 5 * For use for simulation and test purposes only 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the copyright holder nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 * Author: Steve Reinhardt 34 */ 35 36#ifndef __ARCH_HSAIL_OPERAND_HH__ 37#define __ARCH_HSAIL_OPERAND_HH__ 38 39/** 40 * @file operand.hh 41 * 42 * Defines classes encapsulating HSAIL instruction operands. 43 */ 44 45#include <string> 46 47#include "arch/hsail/Brig.h" 48#include "base/trace.hh" 49#include "base/types.hh" 50#include "debug/GPUReg.hh" 51#include "enums/RegisterType.hh" 52#include "gpu-compute/brig_object.hh" 53#include "gpu-compute/compute_unit.hh" 54#include "gpu-compute/hsail_code.hh" 55#include "gpu-compute/shader.hh" 56#include "gpu-compute/vector_register_file.hh" 57#include "gpu-compute/wavefront.hh" 58 59class Label; 60class StorageElement; 61 62class BaseOperand 63{ 64 public: 65 Enums::RegisterType registerType; 66 uint32_t regOperandSize; 67 BaseOperand() { registerType = Enums::RT_NONE; regOperandSize = 0; } 68 bool isVectorRegister() { return registerType == Enums::RT_VECTOR; } 69 bool isScalarRegister() { return registerType == Enums::RT_SCALAR; } 70 bool isCondRegister() { return registerType == Enums::RT_CONDITION; } 71 unsigned int regIndex() { return 0; } 72 uint32_t opSize() { return regOperandSize; } 73 virtual ~BaseOperand() { } 74}; 75 76class BrigRegOperandInfo 77{ 78 public: 79 Brig::BrigKind16_t kind; 80 Brig::BrigType type; 81 Brig::BrigRegisterKind regKind; 82 83 BrigRegOperandInfo(Brig::BrigKind16_t _kind, 84 Brig::BrigRegisterKind _regKind) 85 : kind(_kind), regKind(_regKind) 86 { 87 } 88 89 BrigRegOperandInfo(Brig::BrigKind16_t _kind, Brig::BrigType _type) 90 : kind(_kind), type(_type) 91 { 92 } 93 94 BrigRegOperandInfo() : kind(Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES), 95 type(Brig::BRIG_TYPE_NONE) 96 { 97 } 98}; 99 100BrigRegOperandInfo findRegDataType(unsigned opOffset, const BrigObject *obj); 101 102class BaseRegOperand : public BaseOperand 103{ 104 public: 105 unsigned regIdx; 106 char regFileChar; 107 108 bool init(unsigned opOffset, const BrigObject *obj, 109 unsigned &maxRegIdx, char _regFileChar); 110 111 bool init_from_vect(unsigned opOffset, const BrigObject *obj, int at, 112 unsigned &maxRegIdx, char _regFileChar); 113 114 void initWithStrOffset(unsigned strOffset, const BrigObject *obj, 115 unsigned &maxRegIdx, char _regFileChar); 116 unsigned int regIndex() { return regIdx; } 117}; 118 119class SRegOperand : public BaseRegOperand 120{ 121 public: 122 static unsigned maxRegIdx; 123 124 bool 125 init(unsigned opOffset, const BrigObject *obj) 126 { 127 regOperandSize = sizeof(uint32_t); 128 registerType = Enums::RT_VECTOR; 129 130 return BaseRegOperand::init(opOffset, obj, maxRegIdx, 's'); 131 } 132 133 bool 134 init_from_vect(unsigned opOffset, const BrigObject *obj, int at) 135 { 136 regOperandSize = sizeof(uint32_t); 137 registerType = Enums::RT_VECTOR; 138 139 return BaseRegOperand::init_from_vect(opOffset, obj, at, maxRegIdx, 140 's'); 141 } 142 143 void 144 initWithStrOffset(unsigned strOffset, const BrigObject *obj) 145 { 146 regOperandSize = sizeof(uint32_t); 147 registerType = Enums::RT_VECTOR; 148 149 return BaseRegOperand::initWithStrOffset(strOffset, obj, maxRegIdx, 150 's'); 151 } 152 153 template<typename OperandType> 154 OperandType 155 get(Wavefront *w, int lane) 156 { 157 assert(sizeof(OperandType) <= sizeof(uint32_t)); 158 assert(regIdx < w->maxSpVgprs); 159 // if OperandType is smaller than 32-bit, we truncate the value 160 OperandType ret; 161 uint32_t vgprIdx; 162 163 switch (sizeof(OperandType)) { 164 case 1: // 1 byte operand 165 vgprIdx = w->remap(regIdx, 1, 1); 166 ret = (w->computeUnit->vrf[w->simdId]-> 167 read<uint32_t>(vgprIdx, lane)) & 0xff; 168 break; 169 case 2: // 2 byte operand 170 vgprIdx = w->remap(regIdx, 2, 1); 171 ret = (w->computeUnit->vrf[w->simdId]-> 172 read<uint32_t>(vgprIdx, lane)) & 0xffff; 173 break; 174 case 4: // 4 byte operand 175 vgprIdx = w->remap(regIdx,sizeof(OperandType), 1); 176 ret = w->computeUnit->vrf[w->simdId]-> 177 read<OperandType>(vgprIdx, lane); 178 break; 179 default: 180 panic("Bad OperandType\n"); 181 break; 182 } 183 184 return (OperandType)ret; 185 } 186 187 // special get method for compatibility with LabelOperand 188 uint32_t 189 getTarget(Wavefront *w, int lane) 190 { 191 return get<uint32_t>(w, lane); 192 } 193 194 template<typename OperandType> 195 void set(Wavefront *w, int lane, OperandType &val); 196 std::string disassemble(); 197}; 198 199template<typename OperandType> 200void 201SRegOperand::set(Wavefront *w, int lane, OperandType &val) 202{ 203 DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $s%d <- %d\n", 204 w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx, val); 205 206 assert(sizeof(OperandType) == sizeof(uint32_t)); 207 assert(regIdx < w->maxSpVgprs); 208 uint32_t vgprIdx = w->remap(regIdx, sizeof(OperandType), 1); 209 w->computeUnit->vrf[w->simdId]->write<OperandType>(vgprIdx,val,lane); 210} 211 212template<> 213inline void 214SRegOperand::set(Wavefront *w, int lane, uint64_t &val) 215{ 216 DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $s%d <- %d\n", 217 w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx, val); 218 219 assert(regIdx < w->maxSpVgprs); 220 uint32_t vgprIdx = w->remap(regIdx, sizeof(uint32_t), 1); 221 w->computeUnit->vrf[w->simdId]->write<uint32_t>(vgprIdx, val, lane); 222} 223 224class DRegOperand : public BaseRegOperand 225{ 226 public: 227 static unsigned maxRegIdx; 228 229 bool 230 init(unsigned opOffset, const BrigObject *obj) 231 { 232 regOperandSize = sizeof(uint64_t); 233 registerType = Enums::RT_VECTOR; 234 235 return BaseRegOperand::init(opOffset, obj, maxRegIdx, 'd'); 236 } 237 238 bool 239 init_from_vect(unsigned opOffset, const BrigObject *obj, int at) 240 { 241 regOperandSize = sizeof(uint64_t); 242 registerType = Enums::RT_VECTOR; 243 244 return BaseRegOperand::init_from_vect(opOffset, obj, at, maxRegIdx, 245 'd'); 246 } 247 248 void 249 initWithStrOffset(unsigned strOffset, const BrigObject *obj) 250 { 251 regOperandSize = sizeof(uint64_t); 252 registerType = Enums::RT_VECTOR; 253 254 return BaseRegOperand::initWithStrOffset(strOffset, obj, maxRegIdx, 255 'd'); 256 } 257 258 template<typename OperandType> 259 OperandType 260 get(Wavefront *w, int lane) 261 { 262 assert(sizeof(OperandType) <= sizeof(uint64_t)); 263 // TODO: this check is valid only for HSAIL 264 assert(regIdx < w->maxDpVgprs); 265 uint32_t vgprIdx = w->remap(regIdx, sizeof(OperandType), 1); 266 267 return w->computeUnit->vrf[w->simdId]->read<OperandType>(vgprIdx,lane); 268 } 269 270 template<typename OperandType> 271 void 272 set(Wavefront *w, int lane, OperandType &val) 273 { 274 DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $d%d <- %d\n", 275 w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx, 276 val); 277 278 assert(sizeof(OperandType) <= sizeof(uint64_t)); 279 // TODO: this check is valid only for HSAIL 280 assert(regIdx < w->maxDpVgprs); 281 uint32_t vgprIdx = w->remap(regIdx, sizeof(OperandType), 1); 282 w->computeUnit->vrf[w->simdId]->write<OperandType>(vgprIdx,val,lane); 283 } 284 285 std::string disassemble(); 286}; 287 288class CRegOperand : public BaseRegOperand 289{ 290 public: 291 static unsigned maxRegIdx; 292 293 bool 294 init(unsigned opOffset, const BrigObject *obj) 295 { 296 regOperandSize = sizeof(uint8_t); 297 registerType = Enums::RT_CONDITION; 298 299 return BaseRegOperand::init(opOffset, obj, maxRegIdx, 'c'); 300 } 301 302 bool 303 init_from_vect(unsigned opOffset, const BrigObject *obj, int at) 304 { 305 regOperandSize = sizeof(uint8_t); 306 registerType = Enums::RT_CONDITION; 307 308 return BaseRegOperand::init_from_vect(opOffset, obj, at, maxRegIdx, 309 'c'); 310 } 311 312 void 313 initWithStrOffset(unsigned strOffset, const BrigObject *obj) 314 { 315 regOperandSize = sizeof(uint8_t); 316 registerType = Enums::RT_CONDITION; 317 318 return BaseRegOperand::initWithStrOffset(strOffset, obj, maxRegIdx, 319 'c'); 320 } 321 322 template<typename OperandType> 323 OperandType 324 get(Wavefront *w, int lane) 325 { 326 assert(regIdx < w->condRegState->numRegs()); 327 328 return w->condRegState->read<OperandType>((int)regIdx, lane); 329 } 330 331 template<typename OperandType> 332 void 333 set(Wavefront *w, int lane, OperandType &val) 334 { 335 DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $c%d <- %d\n", 336 w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx, 337 val); 338 339 assert(regIdx < w->condRegState->numRegs()); 340 w->condRegState->write<OperandType>(regIdx,lane,val); 341 } 342 343 std::string disassemble(); 344}; 345 346template<typename T> 347class ImmOperand : public BaseOperand 348{ 349 public: 350 T bits; 351 352 bool init(unsigned opOffset, const BrigObject *obj); 353 bool init_from_vect(unsigned opOffset, const BrigObject *obj, int at); 354 std::string disassemble(); 355 356 template<typename OperandType> 357 OperandType 358 get() 359 { 360 assert(sizeof(OperandType) <= sizeof(T)); 361 362 return *(OperandType*)&bits; 363 } 364 365 // This version of get() takes a WF* and a lane id for 366 // compatibility with the register-based get() methods. 367 template<typename OperandType> 368 OperandType 369 get(Wavefront *w, int lane) 370 { 371 return get<OperandType>(); 372 } 373}; 374 375template<typename T> 376bool 377ImmOperand<T>::init(unsigned opOffset, const BrigObject *obj) 378{ 379 const Brig::BrigOperand *brigOp = obj->getOperand(opOffset); 380 381 switch (brigOp->kind) { 382 // this is immediate operand 383 case Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES: 384 { 385 DPRINTF(GPUReg, "sizeof(T): %lu, byteCount: %d\n", sizeof(T), 386 brigOp->byteCount); 387 388 auto cbptr = (Brig::BrigOperandConstantBytes*)brigOp; 389 390 bits = *((T*)(obj->getData(cbptr->bytes + 4))); 391 392 return true; 393 } 394 break; 395 396 case Brig::BRIG_KIND_OPERAND_WAVESIZE: 397 bits = VSZ; 398 return true; 399 400 default: 401 return false; 402 } 403} 404 405template <typename T> 406bool 407ImmOperand<T>::init_from_vect(unsigned opOffset, const BrigObject *obj, int at) 408{ 409 const Brig::BrigOperand *brigOp = obj->getOperand(opOffset); 410 411 if (brigOp->kind != Brig::BRIG_KIND_OPERAND_OPERAND_LIST) { 412 return false; 413 } 414 415 416 const Brig::BrigOperandOperandList *brigVecOp = 417 (const Brig::BrigOperandOperandList *)brigOp; 418 419 unsigned *data_offset = 420 (unsigned *)obj->getData(brigVecOp->elements + 4 * (at + 1)); 421 422 const Brig::BrigOperand *p = 423 (const Brig::BrigOperand *)obj->getOperand(*data_offset); 424 425 if (p->kind != Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES) { 426 return false; 427 } 428 429 return init(*data_offset, obj); 430} 431template<typename T> 432std::string 433ImmOperand<T>::disassemble() 434{ 435 return csprintf("0x%08x", bits); 436} 437 438template<typename RegOperand, typename T> 439class RegOrImmOperand : public BaseOperand 440{ 441 private: 442 bool is_imm; 443 444 public: 445 void setImm(const bool value) { is_imm = value; } 446 447 ImmOperand<T> imm_op; 448 RegOperand reg_op; 449 450 RegOrImmOperand() { is_imm = false; } 451 void init(unsigned opOffset, const BrigObject *obj); 452 void init_from_vect(unsigned opOffset, const BrigObject *obj, int at); 453 std::string disassemble(); 454 455 template<typename OperandType> 456 OperandType 457 get(Wavefront *w, int lane) 458 { 459 return is_imm ? imm_op.template get<OperandType>() : 460 reg_op.template get<OperandType>(w, lane); 461 } 462 463 uint32_t 464 opSize() 465 { 466 if (!is_imm) { 467 return reg_op.opSize(); 468 } 469 470 return 0; 471 } 472 473 bool 474 isVectorRegister() 475 { 476 if (!is_imm) { 477 return reg_op.registerType == Enums::RT_VECTOR; 478 } 479 return false; 480 } 481 482 bool 483 isCondRegister() 484 { 485 if (!is_imm) { 486 return reg_op.registerType == Enums::RT_CONDITION; 487 } 488 489 return false; 490 } 491 492 bool 493 isScalarRegister() 494 { 495 if (!is_imm) { 496 return reg_op.registerType == Enums::RT_SCALAR; 497 } 498 499 return false; 500 } 501 502 unsigned int 503 regIndex() 504 { 505 if (!is_imm) { 506 return reg_op.regIndex(); 507 } 508 return 0; 509 } 510}; 511 512template<typename RegOperand, typename T> 513void 514RegOrImmOperand<RegOperand, T>::init(unsigned opOffset, const BrigObject *obj) 515{ 516 is_imm = false; 517 518 if (reg_op.init(opOffset, obj)) { 519 return; 520 } 521 522 if (imm_op.init(opOffset, obj)) { 523 is_imm = true; 524 return; 525 } 526 527 fatal("RegOrImmOperand::init(): bad operand kind %d\n", 528 obj->getOperand(opOffset)->kind); 529} 530 531template<typename RegOperand, typename T> 532void 533RegOrImmOperand<RegOperand, T>::init_from_vect(unsigned opOffset, 534 const BrigObject *obj, int at) 535{ 536 if (reg_op.init_from_vect(opOffset, obj, at)) { 537 is_imm = false; 538 539 return; 540 } 541 542 if (imm_op.init_from_vect(opOffset, obj, at)) { 543 is_imm = true; 544 545 return; 546 } 547 548 fatal("RegOrImmOperand::init(): bad operand kind %d\n", 549 obj->getOperand(opOffset)->kind); 550} 551 552template<typename RegOperand, typename T> 553std::string 554RegOrImmOperand<RegOperand, T>::disassemble() 555{ 556 return is_imm ? imm_op.disassemble() : reg_op.disassemble(); 557} 558 559typedef RegOrImmOperand<SRegOperand, uint32_t> SRegOrImmOperand; 560typedef RegOrImmOperand<DRegOperand, uint64_t> DRegOrImmOperand; 561typedef RegOrImmOperand<CRegOperand, bool> CRegOrImmOperand; 562 563class AddrOperandBase : public BaseOperand 564{ 565 protected: 566 // helper function for init() 567 void parseAddr(const Brig::BrigOperandAddress *op, const BrigObject *obj); 568 569 // helper function for disassemble() 570 std::string disassemble(std::string reg_disassembly); 571 uint64_t calcUniformBase(); 572 573 public: 574 virtual void calcVector(Wavefront *w, uint64_t *addrVec) = 0; 575 virtual uint64_t calcLane(Wavefront *w, int lane=0) = 0; 576 577 uint64_t offset; 578 const char *name = nullptr; 579 StorageElement *storageElement; 580}; 581 582template<typename RegOperandType> 583class RegAddrOperand : public AddrOperandBase 584{ 585 public: 586 RegOperandType reg; 587 void init(unsigned opOffset, const BrigObject *obj); 588 uint64_t calcUniform(); 589 void calcVector(Wavefront *w, uint64_t *addrVec); 590 uint64_t calcLane(Wavefront *w, int lane=0); 591 uint32_t opSize() { return reg.opSize(); } 592 bool isVectorRegister() { return reg.registerType == Enums::RT_VECTOR; } 593 bool isCondRegister() { return reg.registerType == Enums::RT_CONDITION; } 594 bool isScalarRegister() { return reg.registerType == Enums::RT_SCALAR; } 595 unsigned int regIndex() { return reg.regIndex(); } 596 std::string disassemble(); 597}; 598 599template<typename RegOperandType> 600void 601RegAddrOperand<RegOperandType>::init(unsigned opOffset, const BrigObject *obj) 602{ 603 using namespace Brig; 604 605 const BrigOperand *baseOp = obj->getOperand(opOffset); 606 607 switch (baseOp->kind) { 608 case BRIG_KIND_OPERAND_ADDRESS: 609 { 610 const BrigOperandAddress *op = (BrigOperandAddress*)baseOp; 611 storageElement = nullptr; 612 613 offset = (uint64_t(op->offset.hi) << 32) | uint64_t(op->offset.lo); 614 reg.init(op->reg, obj); 615 616 if (reg.regFileChar == 's') { 617 reg.regOperandSize = sizeof(uint32_t); 618 registerType = Enums::RT_VECTOR; 619 } 620 else if (reg.regFileChar == 'd') { 621 reg.regOperandSize = sizeof(uint64_t); 622 registerType = Enums::RT_VECTOR; 623 } 624 } 625 break; 626 627 default: 628 fatal("RegAddrOperand: bad operand kind %d\n", baseOp->kind); 629 break; 630 } 631} 632 633template<typename RegOperandType> 634uint64_t 635RegAddrOperand<RegOperandType>::calcUniform() 636{ 637 fatal("can't do calcUniform() on register-based address\n"); 638 639 return 0; 640} 641 642template<typename RegOperandType> 643void 644RegAddrOperand<RegOperandType>::calcVector(Wavefront *w, uint64_t *addrVec) 645{ 646 Addr address = calcUniformBase(); 647 648 for (int lane = 0; lane < VSZ; ++lane) { 649 if (w->execMask(lane)) { 650 if (reg.regFileChar == 's') { 651 addrVec[lane] = address + reg.template get<uint32_t>(w, lane); 652 } else { 653 addrVec[lane] = address + reg.template get<Addr>(w, lane); 654 } 655 } 656 } 657} 658 659template<typename RegOperandType> 660uint64_t 661RegAddrOperand<RegOperandType>::calcLane(Wavefront *w, int lane) 662{ 663 Addr address = calcUniformBase(); 664 665 return address + reg.template get<Addr>(w, lane); 666} 667 668template<typename RegOperandType> 669std::string 670RegAddrOperand<RegOperandType>::disassemble() 671{ 672 return AddrOperandBase::disassemble(reg.disassemble()); 673} 674 675typedef RegAddrOperand<SRegOperand> SRegAddrOperand; 676typedef RegAddrOperand<DRegOperand> DRegAddrOperand; 677 678class NoRegAddrOperand : public AddrOperandBase 679{ 680 public: 681 void init(unsigned opOffset, const BrigObject *obj); 682 uint64_t calcUniform(); 683 void calcVector(Wavefront *w, uint64_t *addrVec); 684 uint64_t calcLane(Wavefront *w, int lane=0); 685 std::string disassemble(); 686}; 687 688inline uint64_t 689NoRegAddrOperand::calcUniform() 690{ 691 return AddrOperandBase::calcUniformBase(); 692} 693 694inline uint64_t 695NoRegAddrOperand::calcLane(Wavefront *w, int lane) 696{ 697 return calcUniform(); 698} 699 700inline void 701NoRegAddrOperand::calcVector(Wavefront *w, uint64_t *addrVec) 702{ 703 uint64_t address = calcUniformBase(); 704 705 for (int lane = 0; lane < VSZ; ++lane) 706 addrVec[lane] = address; 707} 708 709class LabelOperand : public BaseOperand 710{ 711 public: 712 Label *label; 713 714 void init(unsigned opOffset, const BrigObject *obj); 715 std::string disassemble(); 716 717 // special get method for compatibility with SRegOperand 718 uint32_t getTarget(Wavefront *w, int lane); 719 720}; 721 722class ListOperand : public BaseOperand 723{ 724 public: 725 int elementCount; 726 std::vector<StorageElement*> callArgs; 727 728 int 729 getSrcOperand(int idx) 730 { 731 DPRINTF(GPUReg, "getSrcOperand, idx: %d, sz_args: %d\n", idx, 732 callArgs.size()); 733 734 return callArgs.at(idx)->offset; 735 } 736 737 void init(unsigned opOffset, const BrigObject *obj); 738 739 std::string disassemble(); 740 741 template<typename OperandType> 742 OperandType 743 get(Wavefront *w, int lane, int arg_idx) 744 { 745 return w->readCallArgMem<OperandType>(lane, getSrcOperand(arg_idx)); 746 } 747 748 template<typename OperandType> 749 void 750 set(Wavefront *w, int lane, OperandType val) 751 { 752 w->writeCallArgMem<OperandType>(lane, getSrcOperand(0), val); 753 DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: arg[%d] <- %d\n", 754 w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, 755 getSrcOperand(0), val); 756 } 757}; 758 759class FunctionRefOperand : public BaseOperand 760{ 761 public: 762 const char *func_name; 763 764 void init(unsigned opOffset, const BrigObject *obj); 765 std::string disassemble(); 766}; 767 768#endif // __ARCH_HSAIL_OPERAND_HH__ 769