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