111308Santhony.gutierrez@amd.com/* 211308Santhony.gutierrez@amd.com * Copyright (c) 2012-2015 Advanced Micro Devices, Inc. 311308Santhony.gutierrez@amd.com * All rights reserved. 411308Santhony.gutierrez@amd.com * 511308Santhony.gutierrez@amd.com * For use for simulation and test purposes only 611308Santhony.gutierrez@amd.com * 711308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 811308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are met: 911308Santhony.gutierrez@amd.com * 1011308Santhony.gutierrez@amd.com * 1. Redistributions of source code must retain the above copyright notice, 1111308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer. 1211308Santhony.gutierrez@amd.com * 1311308Santhony.gutierrez@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice, 1411308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer in the documentation 1511308Santhony.gutierrez@amd.com * and/or other materials provided with the distribution. 1611308Santhony.gutierrez@amd.com * 1711308Santhony.gutierrez@amd.com * 3. Neither the name of the copyright holder nor the names of its contributors 1811308Santhony.gutierrez@amd.com * may be used to endorse or promote products derived from this software 1911308Santhony.gutierrez@amd.com * without specific prior written permission. 2011308Santhony.gutierrez@amd.com * 2111308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2211308Santhony.gutierrez@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2311308Santhony.gutierrez@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2411308Santhony.gutierrez@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2511308Santhony.gutierrez@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2611308Santhony.gutierrez@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2711308Santhony.gutierrez@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2811308Santhony.gutierrez@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2911308Santhony.gutierrez@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3011308Santhony.gutierrez@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3111308Santhony.gutierrez@amd.com * POSSIBILITY OF SUCH DAMAGE. 3211308Santhony.gutierrez@amd.com * 3311308Santhony.gutierrez@amd.com * Author: Steve Reinhardt 3411308Santhony.gutierrez@amd.com */ 3511308Santhony.gutierrez@amd.com 3611308Santhony.gutierrez@amd.com#ifndef __ARCH_HSAIL_OPERAND_HH__ 3711308Santhony.gutierrez@amd.com#define __ARCH_HSAIL_OPERAND_HH__ 3811308Santhony.gutierrez@amd.com 3911308Santhony.gutierrez@amd.com/** 4011308Santhony.gutierrez@amd.com * @file operand.hh 4111308Santhony.gutierrez@amd.com * 4211308Santhony.gutierrez@amd.com * Defines classes encapsulating HSAIL instruction operands. 4311308Santhony.gutierrez@amd.com */ 4411308Santhony.gutierrez@amd.com 4511534Sjohn.kalamatianos@amd.com#include <limits> 4611308Santhony.gutierrez@amd.com#include <string> 4711308Santhony.gutierrez@amd.com 4811308Santhony.gutierrez@amd.com#include "arch/hsail/Brig.h" 4911308Santhony.gutierrez@amd.com#include "base/trace.hh" 5011308Santhony.gutierrez@amd.com#include "base/types.hh" 5111308Santhony.gutierrez@amd.com#include "debug/GPUReg.hh" 5211308Santhony.gutierrez@amd.com#include "enums/RegisterType.hh" 5311308Santhony.gutierrez@amd.com#include "gpu-compute/brig_object.hh" 5411308Santhony.gutierrez@amd.com#include "gpu-compute/compute_unit.hh" 5511308Santhony.gutierrez@amd.com#include "gpu-compute/hsail_code.hh" 5611308Santhony.gutierrez@amd.com#include "gpu-compute/shader.hh" 5711308Santhony.gutierrez@amd.com#include "gpu-compute/vector_register_file.hh" 5811308Santhony.gutierrez@amd.com#include "gpu-compute/wavefront.hh" 5911308Santhony.gutierrez@amd.com 6011308Santhony.gutierrez@amd.comclass Label; 6111308Santhony.gutierrez@amd.comclass StorageElement; 6211308Santhony.gutierrez@amd.com 6311308Santhony.gutierrez@amd.comclass BaseOperand 6411308Santhony.gutierrez@amd.com{ 6511308Santhony.gutierrez@amd.com public: 6611308Santhony.gutierrez@amd.com Enums::RegisterType registerType; 6711308Santhony.gutierrez@amd.com uint32_t regOperandSize; 6811308Santhony.gutierrez@amd.com BaseOperand() { registerType = Enums::RT_NONE; regOperandSize = 0; } 6911308Santhony.gutierrez@amd.com bool isVectorRegister() { return registerType == Enums::RT_VECTOR; } 7011308Santhony.gutierrez@amd.com bool isScalarRegister() { return registerType == Enums::RT_SCALAR; } 7111308Santhony.gutierrez@amd.com bool isCondRegister() { return registerType == Enums::RT_CONDITION; } 7211308Santhony.gutierrez@amd.com unsigned int regIndex() { return 0; } 7311308Santhony.gutierrez@amd.com uint32_t opSize() { return regOperandSize; } 7411308Santhony.gutierrez@amd.com virtual ~BaseOperand() { } 7511308Santhony.gutierrez@amd.com}; 7611308Santhony.gutierrez@amd.com 7711308Santhony.gutierrez@amd.comclass BrigRegOperandInfo 7811308Santhony.gutierrez@amd.com{ 7911308Santhony.gutierrez@amd.com public: 8011308Santhony.gutierrez@amd.com Brig::BrigKind16_t kind; 8111308Santhony.gutierrez@amd.com Brig::BrigType type; 8211308Santhony.gutierrez@amd.com Brig::BrigRegisterKind regKind; 8311308Santhony.gutierrez@amd.com 8411308Santhony.gutierrez@amd.com BrigRegOperandInfo(Brig::BrigKind16_t _kind, 8511308Santhony.gutierrez@amd.com Brig::BrigRegisterKind _regKind) 8611308Santhony.gutierrez@amd.com : kind(_kind), regKind(_regKind) 8711308Santhony.gutierrez@amd.com { 8811308Santhony.gutierrez@amd.com } 8911308Santhony.gutierrez@amd.com 9011308Santhony.gutierrez@amd.com BrigRegOperandInfo(Brig::BrigKind16_t _kind, Brig::BrigType _type) 9111308Santhony.gutierrez@amd.com : kind(_kind), type(_type) 9211308Santhony.gutierrez@amd.com { 9311308Santhony.gutierrez@amd.com } 9411308Santhony.gutierrez@amd.com 9511308Santhony.gutierrez@amd.com BrigRegOperandInfo() : kind(Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES), 9611308Santhony.gutierrez@amd.com type(Brig::BRIG_TYPE_NONE) 9711308Santhony.gutierrez@amd.com { 9811308Santhony.gutierrez@amd.com } 9911308Santhony.gutierrez@amd.com}; 10011308Santhony.gutierrez@amd.com 10111308Santhony.gutierrez@amd.comBrigRegOperandInfo findRegDataType(unsigned opOffset, const BrigObject *obj); 10211308Santhony.gutierrez@amd.com 10311308Santhony.gutierrez@amd.comclass BaseRegOperand : public BaseOperand 10411308Santhony.gutierrez@amd.com{ 10511308Santhony.gutierrez@amd.com public: 10611308Santhony.gutierrez@amd.com unsigned regIdx; 10711308Santhony.gutierrez@amd.com char regFileChar; 10811308Santhony.gutierrez@amd.com 10911308Santhony.gutierrez@amd.com bool init(unsigned opOffset, const BrigObject *obj, 11011308Santhony.gutierrez@amd.com unsigned &maxRegIdx, char _regFileChar); 11111308Santhony.gutierrez@amd.com 11211308Santhony.gutierrez@amd.com bool init_from_vect(unsigned opOffset, const BrigObject *obj, int at, 11311308Santhony.gutierrez@amd.com unsigned &maxRegIdx, char _regFileChar); 11411308Santhony.gutierrez@amd.com 11511308Santhony.gutierrez@amd.com void initWithStrOffset(unsigned strOffset, const BrigObject *obj, 11611308Santhony.gutierrez@amd.com unsigned &maxRegIdx, char _regFileChar); 11711308Santhony.gutierrez@amd.com unsigned int regIndex() { return regIdx; } 11811308Santhony.gutierrez@amd.com}; 11911308Santhony.gutierrez@amd.com 12011308Santhony.gutierrez@amd.comclass SRegOperand : public BaseRegOperand 12111308Santhony.gutierrez@amd.com{ 12211308Santhony.gutierrez@amd.com public: 12311308Santhony.gutierrez@amd.com static unsigned maxRegIdx; 12411308Santhony.gutierrez@amd.com 12511308Santhony.gutierrez@amd.com bool 12611308Santhony.gutierrez@amd.com init(unsigned opOffset, const BrigObject *obj) 12711308Santhony.gutierrez@amd.com { 12811308Santhony.gutierrez@amd.com regOperandSize = sizeof(uint32_t); 12911308Santhony.gutierrez@amd.com registerType = Enums::RT_VECTOR; 13011308Santhony.gutierrez@amd.com 13111308Santhony.gutierrez@amd.com return BaseRegOperand::init(opOffset, obj, maxRegIdx, 's'); 13211308Santhony.gutierrez@amd.com } 13311308Santhony.gutierrez@amd.com 13411308Santhony.gutierrez@amd.com bool 13511308Santhony.gutierrez@amd.com init_from_vect(unsigned opOffset, const BrigObject *obj, int at) 13611308Santhony.gutierrez@amd.com { 13711308Santhony.gutierrez@amd.com regOperandSize = sizeof(uint32_t); 13811308Santhony.gutierrez@amd.com registerType = Enums::RT_VECTOR; 13911308Santhony.gutierrez@amd.com 14011308Santhony.gutierrez@amd.com return BaseRegOperand::init_from_vect(opOffset, obj, at, maxRegIdx, 14111308Santhony.gutierrez@amd.com 's'); 14211308Santhony.gutierrez@amd.com } 14311308Santhony.gutierrez@amd.com 14411308Santhony.gutierrez@amd.com void 14511308Santhony.gutierrez@amd.com initWithStrOffset(unsigned strOffset, const BrigObject *obj) 14611308Santhony.gutierrez@amd.com { 14711308Santhony.gutierrez@amd.com regOperandSize = sizeof(uint32_t); 14811308Santhony.gutierrez@amd.com registerType = Enums::RT_VECTOR; 14911308Santhony.gutierrez@amd.com 15011308Santhony.gutierrez@amd.com return BaseRegOperand::initWithStrOffset(strOffset, obj, maxRegIdx, 15111308Santhony.gutierrez@amd.com 's'); 15211308Santhony.gutierrez@amd.com } 15311308Santhony.gutierrez@amd.com 15411308Santhony.gutierrez@amd.com template<typename OperandType> 15511308Santhony.gutierrez@amd.com OperandType 15611308Santhony.gutierrez@amd.com get(Wavefront *w, int lane) 15711308Santhony.gutierrez@amd.com { 15811308Santhony.gutierrez@amd.com assert(sizeof(OperandType) <= sizeof(uint32_t)); 15911308Santhony.gutierrez@amd.com assert(regIdx < w->maxSpVgprs); 16011308Santhony.gutierrez@amd.com // if OperandType is smaller than 32-bit, we truncate the value 16111308Santhony.gutierrez@amd.com OperandType ret; 16211308Santhony.gutierrez@amd.com uint32_t vgprIdx; 16311308Santhony.gutierrez@amd.com 16411308Santhony.gutierrez@amd.com switch (sizeof(OperandType)) { 16511308Santhony.gutierrez@amd.com case 1: // 1 byte operand 16611308Santhony.gutierrez@amd.com vgprIdx = w->remap(regIdx, 1, 1); 16711308Santhony.gutierrez@amd.com ret = (w->computeUnit->vrf[w->simdId]-> 16811308Santhony.gutierrez@amd.com read<uint32_t>(vgprIdx, lane)) & 0xff; 16911308Santhony.gutierrez@amd.com break; 17011308Santhony.gutierrez@amd.com case 2: // 2 byte operand 17111308Santhony.gutierrez@amd.com vgprIdx = w->remap(regIdx, 2, 1); 17211308Santhony.gutierrez@amd.com ret = (w->computeUnit->vrf[w->simdId]-> 17311308Santhony.gutierrez@amd.com read<uint32_t>(vgprIdx, lane)) & 0xffff; 17411308Santhony.gutierrez@amd.com break; 17511308Santhony.gutierrez@amd.com case 4: // 4 byte operand 17611308Santhony.gutierrez@amd.com vgprIdx = w->remap(regIdx,sizeof(OperandType), 1); 17711308Santhony.gutierrez@amd.com ret = w->computeUnit->vrf[w->simdId]-> 17811308Santhony.gutierrez@amd.com read<OperandType>(vgprIdx, lane); 17911308Santhony.gutierrez@amd.com break; 18011308Santhony.gutierrez@amd.com default: 18111308Santhony.gutierrez@amd.com panic("Bad OperandType\n"); 18211308Santhony.gutierrez@amd.com break; 18311308Santhony.gutierrez@amd.com } 18411308Santhony.gutierrez@amd.com 18511308Santhony.gutierrez@amd.com return (OperandType)ret; 18611308Santhony.gutierrez@amd.com } 18711308Santhony.gutierrez@amd.com 18811308Santhony.gutierrez@amd.com // special get method for compatibility with LabelOperand 18911308Santhony.gutierrez@amd.com uint32_t 19011308Santhony.gutierrez@amd.com getTarget(Wavefront *w, int lane) 19111308Santhony.gutierrez@amd.com { 19211308Santhony.gutierrez@amd.com return get<uint32_t>(w, lane); 19311308Santhony.gutierrez@amd.com } 19411308Santhony.gutierrez@amd.com 19511308Santhony.gutierrez@amd.com template<typename OperandType> 19611308Santhony.gutierrez@amd.com void set(Wavefront *w, int lane, OperandType &val); 19711308Santhony.gutierrez@amd.com std::string disassemble(); 19811308Santhony.gutierrez@amd.com}; 19911308Santhony.gutierrez@amd.com 20011308Santhony.gutierrez@amd.comtemplate<typename OperandType> 20111308Santhony.gutierrez@amd.comvoid 20211308Santhony.gutierrez@amd.comSRegOperand::set(Wavefront *w, int lane, OperandType &val) 20311308Santhony.gutierrez@amd.com{ 20411308Santhony.gutierrez@amd.com DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $s%d <- %d\n", 20511308Santhony.gutierrez@amd.com w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx, val); 20611308Santhony.gutierrez@amd.com 20711308Santhony.gutierrez@amd.com assert(sizeof(OperandType) == sizeof(uint32_t)); 20811308Santhony.gutierrez@amd.com assert(regIdx < w->maxSpVgprs); 20911308Santhony.gutierrez@amd.com uint32_t vgprIdx = w->remap(regIdx, sizeof(OperandType), 1); 21011308Santhony.gutierrez@amd.com w->computeUnit->vrf[w->simdId]->write<OperandType>(vgprIdx,val,lane); 21111308Santhony.gutierrez@amd.com} 21211308Santhony.gutierrez@amd.com 21311308Santhony.gutierrez@amd.comtemplate<> 21411308Santhony.gutierrez@amd.cominline void 21511308Santhony.gutierrez@amd.comSRegOperand::set(Wavefront *w, int lane, uint64_t &val) 21611308Santhony.gutierrez@amd.com{ 21711308Santhony.gutierrez@amd.com DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $s%d <- %d\n", 21811308Santhony.gutierrez@amd.com w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx, val); 21911308Santhony.gutierrez@amd.com 22011308Santhony.gutierrez@amd.com assert(regIdx < w->maxSpVgprs); 22111308Santhony.gutierrez@amd.com uint32_t vgprIdx = w->remap(regIdx, sizeof(uint32_t), 1); 22211308Santhony.gutierrez@amd.com w->computeUnit->vrf[w->simdId]->write<uint32_t>(vgprIdx, val, lane); 22311308Santhony.gutierrez@amd.com} 22411308Santhony.gutierrez@amd.com 22511308Santhony.gutierrez@amd.comclass DRegOperand : public BaseRegOperand 22611308Santhony.gutierrez@amd.com{ 22711308Santhony.gutierrez@amd.com public: 22811308Santhony.gutierrez@amd.com static unsigned maxRegIdx; 22911308Santhony.gutierrez@amd.com 23011308Santhony.gutierrez@amd.com bool 23111308Santhony.gutierrez@amd.com init(unsigned opOffset, const BrigObject *obj) 23211308Santhony.gutierrez@amd.com { 23311308Santhony.gutierrez@amd.com regOperandSize = sizeof(uint64_t); 23411308Santhony.gutierrez@amd.com registerType = Enums::RT_VECTOR; 23511308Santhony.gutierrez@amd.com 23611308Santhony.gutierrez@amd.com return BaseRegOperand::init(opOffset, obj, maxRegIdx, 'd'); 23711308Santhony.gutierrez@amd.com } 23811308Santhony.gutierrez@amd.com 23911308Santhony.gutierrez@amd.com bool 24011308Santhony.gutierrez@amd.com init_from_vect(unsigned opOffset, const BrigObject *obj, int at) 24111308Santhony.gutierrez@amd.com { 24211308Santhony.gutierrez@amd.com regOperandSize = sizeof(uint64_t); 24311308Santhony.gutierrez@amd.com registerType = Enums::RT_VECTOR; 24411308Santhony.gutierrez@amd.com 24511308Santhony.gutierrez@amd.com return BaseRegOperand::init_from_vect(opOffset, obj, at, maxRegIdx, 24611308Santhony.gutierrez@amd.com 'd'); 24711308Santhony.gutierrez@amd.com } 24811308Santhony.gutierrez@amd.com 24911308Santhony.gutierrez@amd.com void 25011308Santhony.gutierrez@amd.com initWithStrOffset(unsigned strOffset, const BrigObject *obj) 25111308Santhony.gutierrez@amd.com { 25211308Santhony.gutierrez@amd.com regOperandSize = sizeof(uint64_t); 25311308Santhony.gutierrez@amd.com registerType = Enums::RT_VECTOR; 25411308Santhony.gutierrez@amd.com 25511308Santhony.gutierrez@amd.com return BaseRegOperand::initWithStrOffset(strOffset, obj, maxRegIdx, 25611308Santhony.gutierrez@amd.com 'd'); 25711308Santhony.gutierrez@amd.com } 25811308Santhony.gutierrez@amd.com 25911308Santhony.gutierrez@amd.com template<typename OperandType> 26011308Santhony.gutierrez@amd.com OperandType 26111308Santhony.gutierrez@amd.com get(Wavefront *w, int lane) 26211308Santhony.gutierrez@amd.com { 26311308Santhony.gutierrez@amd.com assert(sizeof(OperandType) <= sizeof(uint64_t)); 26411308Santhony.gutierrez@amd.com // TODO: this check is valid only for HSAIL 26511308Santhony.gutierrez@amd.com assert(regIdx < w->maxDpVgprs); 26611308Santhony.gutierrez@amd.com uint32_t vgprIdx = w->remap(regIdx, sizeof(OperandType), 1); 26711308Santhony.gutierrez@amd.com 26811308Santhony.gutierrez@amd.com return w->computeUnit->vrf[w->simdId]->read<OperandType>(vgprIdx,lane); 26911308Santhony.gutierrez@amd.com } 27011308Santhony.gutierrez@amd.com 27111308Santhony.gutierrez@amd.com template<typename OperandType> 27211308Santhony.gutierrez@amd.com void 27311308Santhony.gutierrez@amd.com set(Wavefront *w, int lane, OperandType &val) 27411308Santhony.gutierrez@amd.com { 27511308Santhony.gutierrez@amd.com DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $d%d <- %d\n", 27611308Santhony.gutierrez@amd.com w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx, 27711308Santhony.gutierrez@amd.com val); 27811308Santhony.gutierrez@amd.com 27911308Santhony.gutierrez@amd.com assert(sizeof(OperandType) <= sizeof(uint64_t)); 28011308Santhony.gutierrez@amd.com // TODO: this check is valid only for HSAIL 28111308Santhony.gutierrez@amd.com assert(regIdx < w->maxDpVgprs); 28211308Santhony.gutierrez@amd.com uint32_t vgprIdx = w->remap(regIdx, sizeof(OperandType), 1); 28311308Santhony.gutierrez@amd.com w->computeUnit->vrf[w->simdId]->write<OperandType>(vgprIdx,val,lane); 28411308Santhony.gutierrez@amd.com } 28511308Santhony.gutierrez@amd.com 28611308Santhony.gutierrez@amd.com std::string disassemble(); 28711308Santhony.gutierrez@amd.com}; 28811308Santhony.gutierrez@amd.com 28911308Santhony.gutierrez@amd.comclass CRegOperand : public BaseRegOperand 29011308Santhony.gutierrez@amd.com{ 29111308Santhony.gutierrez@amd.com public: 29211308Santhony.gutierrez@amd.com static unsigned maxRegIdx; 29311308Santhony.gutierrez@amd.com 29411308Santhony.gutierrez@amd.com bool 29511308Santhony.gutierrez@amd.com init(unsigned opOffset, const BrigObject *obj) 29611308Santhony.gutierrez@amd.com { 29711308Santhony.gutierrez@amd.com regOperandSize = sizeof(uint8_t); 29811308Santhony.gutierrez@amd.com registerType = Enums::RT_CONDITION; 29911308Santhony.gutierrez@amd.com 30011308Santhony.gutierrez@amd.com return BaseRegOperand::init(opOffset, obj, maxRegIdx, 'c'); 30111308Santhony.gutierrez@amd.com } 30211308Santhony.gutierrez@amd.com 30311308Santhony.gutierrez@amd.com bool 30411308Santhony.gutierrez@amd.com init_from_vect(unsigned opOffset, const BrigObject *obj, int at) 30511308Santhony.gutierrez@amd.com { 30611308Santhony.gutierrez@amd.com regOperandSize = sizeof(uint8_t); 30711308Santhony.gutierrez@amd.com registerType = Enums::RT_CONDITION; 30811308Santhony.gutierrez@amd.com 30911308Santhony.gutierrez@amd.com return BaseRegOperand::init_from_vect(opOffset, obj, at, maxRegIdx, 31011308Santhony.gutierrez@amd.com 'c'); 31111308Santhony.gutierrez@amd.com } 31211308Santhony.gutierrez@amd.com 31311308Santhony.gutierrez@amd.com void 31411308Santhony.gutierrez@amd.com initWithStrOffset(unsigned strOffset, const BrigObject *obj) 31511308Santhony.gutierrez@amd.com { 31611308Santhony.gutierrez@amd.com regOperandSize = sizeof(uint8_t); 31711308Santhony.gutierrez@amd.com registerType = Enums::RT_CONDITION; 31811308Santhony.gutierrez@amd.com 31911308Santhony.gutierrez@amd.com return BaseRegOperand::initWithStrOffset(strOffset, obj, maxRegIdx, 32011308Santhony.gutierrez@amd.com 'c'); 32111308Santhony.gutierrez@amd.com } 32211308Santhony.gutierrez@amd.com 32311308Santhony.gutierrez@amd.com template<typename OperandType> 32411308Santhony.gutierrez@amd.com OperandType 32511308Santhony.gutierrez@amd.com get(Wavefront *w, int lane) 32611308Santhony.gutierrez@amd.com { 32711308Santhony.gutierrez@amd.com assert(regIdx < w->condRegState->numRegs()); 32811308Santhony.gutierrez@amd.com 32911308Santhony.gutierrez@amd.com return w->condRegState->read<OperandType>((int)regIdx, lane); 33011308Santhony.gutierrez@amd.com } 33111308Santhony.gutierrez@amd.com 33211308Santhony.gutierrez@amd.com template<typename OperandType> 33311308Santhony.gutierrez@amd.com void 33411308Santhony.gutierrez@amd.com set(Wavefront *w, int lane, OperandType &val) 33511308Santhony.gutierrez@amd.com { 33611308Santhony.gutierrez@amd.com DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $c%d <- %d\n", 33711308Santhony.gutierrez@amd.com w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx, 33811308Santhony.gutierrez@amd.com val); 33911308Santhony.gutierrez@amd.com 34011308Santhony.gutierrez@amd.com assert(regIdx < w->condRegState->numRegs()); 34111308Santhony.gutierrez@amd.com w->condRegState->write<OperandType>(regIdx,lane,val); 34211308Santhony.gutierrez@amd.com } 34311308Santhony.gutierrez@amd.com 34411308Santhony.gutierrez@amd.com std::string disassemble(); 34511308Santhony.gutierrez@amd.com}; 34611308Santhony.gutierrez@amd.com 34711308Santhony.gutierrez@amd.comtemplate<typename T> 34811308Santhony.gutierrez@amd.comclass ImmOperand : public BaseOperand 34911308Santhony.gutierrez@amd.com{ 35011534Sjohn.kalamatianos@amd.com private: 35111534Sjohn.kalamatianos@amd.com uint16_t kind; 35211308Santhony.gutierrez@amd.com public: 35311308Santhony.gutierrez@amd.com T bits; 35411308Santhony.gutierrez@amd.com 35511308Santhony.gutierrez@amd.com bool init(unsigned opOffset, const BrigObject *obj); 35611308Santhony.gutierrez@amd.com bool init_from_vect(unsigned opOffset, const BrigObject *obj, int at); 35711308Santhony.gutierrez@amd.com std::string disassemble(); 35811308Santhony.gutierrez@amd.com 35911308Santhony.gutierrez@amd.com template<typename OperandType> 36011308Santhony.gutierrez@amd.com OperandType 36111534Sjohn.kalamatianos@amd.com get(Wavefront *w) 36211308Santhony.gutierrez@amd.com { 36311308Santhony.gutierrez@amd.com assert(sizeof(OperandType) <= sizeof(T)); 36411534Sjohn.kalamatianos@amd.com panic_if(w == nullptr, "WF pointer needs to be set"); 36511308Santhony.gutierrez@amd.com 36611534Sjohn.kalamatianos@amd.com switch (kind) { 36711534Sjohn.kalamatianos@amd.com // immediate operand is WF size 36811534Sjohn.kalamatianos@amd.com case Brig::BRIG_KIND_OPERAND_WAVESIZE: 36911534Sjohn.kalamatianos@amd.com return (OperandType)w->computeUnit->wfSize(); 37011534Sjohn.kalamatianos@amd.com break; 37111534Sjohn.kalamatianos@amd.com 37211534Sjohn.kalamatianos@amd.com default: 37311534Sjohn.kalamatianos@amd.com return *(OperandType*)&bits; 37411534Sjohn.kalamatianos@amd.com break; 37511534Sjohn.kalamatianos@amd.com } 37611308Santhony.gutierrez@amd.com } 37711308Santhony.gutierrez@amd.com 37811308Santhony.gutierrez@amd.com // This version of get() takes a WF* and a lane id for 37911308Santhony.gutierrez@amd.com // compatibility with the register-based get() methods. 38011308Santhony.gutierrez@amd.com template<typename OperandType> 38111308Santhony.gutierrez@amd.com OperandType 38211308Santhony.gutierrez@amd.com get(Wavefront *w, int lane) 38311308Santhony.gutierrez@amd.com { 38411534Sjohn.kalamatianos@amd.com return get<OperandType>(w); 38511308Santhony.gutierrez@amd.com } 38611308Santhony.gutierrez@amd.com}; 38711308Santhony.gutierrez@amd.com 38811308Santhony.gutierrez@amd.comtemplate<typename T> 38911308Santhony.gutierrez@amd.combool 39011308Santhony.gutierrez@amd.comImmOperand<T>::init(unsigned opOffset, const BrigObject *obj) 39111308Santhony.gutierrez@amd.com{ 39211308Santhony.gutierrez@amd.com const Brig::BrigOperand *brigOp = obj->getOperand(opOffset); 39311308Santhony.gutierrez@amd.com 39411308Santhony.gutierrez@amd.com switch (brigOp->kind) { 39511308Santhony.gutierrez@amd.com // this is immediate operand 39611308Santhony.gutierrez@amd.com case Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES: 39711308Santhony.gutierrez@amd.com { 39811308Santhony.gutierrez@amd.com DPRINTF(GPUReg, "sizeof(T): %lu, byteCount: %d\n", sizeof(T), 39911308Santhony.gutierrez@amd.com brigOp->byteCount); 40011308Santhony.gutierrez@amd.com 40111308Santhony.gutierrez@amd.com auto cbptr = (Brig::BrigOperandConstantBytes*)brigOp; 40211308Santhony.gutierrez@amd.com 40311308Santhony.gutierrez@amd.com bits = *((T*)(obj->getData(cbptr->bytes + 4))); 40411534Sjohn.kalamatianos@amd.com kind = brigOp->kind; 40511308Santhony.gutierrez@amd.com return true; 40611308Santhony.gutierrez@amd.com } 40711308Santhony.gutierrez@amd.com break; 40811308Santhony.gutierrez@amd.com 40911308Santhony.gutierrez@amd.com case Brig::BRIG_KIND_OPERAND_WAVESIZE: 41011534Sjohn.kalamatianos@amd.com kind = brigOp->kind; 41111534Sjohn.kalamatianos@amd.com bits = std::numeric_limits<unsigned long long>::digits; 41211308Santhony.gutierrez@amd.com return true; 41311308Santhony.gutierrez@amd.com 41411308Santhony.gutierrez@amd.com default: 41511534Sjohn.kalamatianos@amd.com kind = Brig::BRIG_KIND_NONE; 41611308Santhony.gutierrez@amd.com return false; 41711308Santhony.gutierrez@amd.com } 41811308Santhony.gutierrez@amd.com} 41911308Santhony.gutierrez@amd.com 42011308Santhony.gutierrez@amd.comtemplate <typename T> 42111308Santhony.gutierrez@amd.combool 42211308Santhony.gutierrez@amd.comImmOperand<T>::init_from_vect(unsigned opOffset, const BrigObject *obj, int at) 42311308Santhony.gutierrez@amd.com{ 42411308Santhony.gutierrez@amd.com const Brig::BrigOperand *brigOp = obj->getOperand(opOffset); 42511308Santhony.gutierrez@amd.com 42611308Santhony.gutierrez@amd.com if (brigOp->kind != Brig::BRIG_KIND_OPERAND_OPERAND_LIST) { 42711534Sjohn.kalamatianos@amd.com kind = Brig::BRIG_KIND_NONE; 42811308Santhony.gutierrez@amd.com return false; 42911308Santhony.gutierrez@amd.com } 43011308Santhony.gutierrez@amd.com 43111308Santhony.gutierrez@amd.com 43211308Santhony.gutierrez@amd.com const Brig::BrigOperandOperandList *brigVecOp = 43311308Santhony.gutierrez@amd.com (const Brig::BrigOperandOperandList *)brigOp; 43411308Santhony.gutierrez@amd.com 43511308Santhony.gutierrez@amd.com unsigned *data_offset = 43611308Santhony.gutierrez@amd.com (unsigned *)obj->getData(brigVecOp->elements + 4 * (at + 1)); 43711308Santhony.gutierrez@amd.com 43811308Santhony.gutierrez@amd.com const Brig::BrigOperand *p = 43911308Santhony.gutierrez@amd.com (const Brig::BrigOperand *)obj->getOperand(*data_offset); 44011308Santhony.gutierrez@amd.com 44111308Santhony.gutierrez@amd.com if (p->kind != Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES) { 44211534Sjohn.kalamatianos@amd.com kind = Brig::BRIG_KIND_NONE; 44311308Santhony.gutierrez@amd.com return false; 44411308Santhony.gutierrez@amd.com } 44511308Santhony.gutierrez@amd.com 44611308Santhony.gutierrez@amd.com return init(*data_offset, obj); 44711308Santhony.gutierrez@amd.com} 44811308Santhony.gutierrez@amd.comtemplate<typename T> 44911308Santhony.gutierrez@amd.comstd::string 45011308Santhony.gutierrez@amd.comImmOperand<T>::disassemble() 45111308Santhony.gutierrez@amd.com{ 45211308Santhony.gutierrez@amd.com return csprintf("0x%08x", bits); 45311308Santhony.gutierrez@amd.com} 45411308Santhony.gutierrez@amd.com 45511308Santhony.gutierrez@amd.comtemplate<typename RegOperand, typename T> 45611308Santhony.gutierrez@amd.comclass RegOrImmOperand : public BaseOperand 45711308Santhony.gutierrez@amd.com{ 45811308Santhony.gutierrez@amd.com private: 45911308Santhony.gutierrez@amd.com bool is_imm; 46011308Santhony.gutierrez@amd.com 46111308Santhony.gutierrez@amd.com public: 46211308Santhony.gutierrez@amd.com void setImm(const bool value) { is_imm = value; } 46311308Santhony.gutierrez@amd.com 46411308Santhony.gutierrez@amd.com ImmOperand<T> imm_op; 46511308Santhony.gutierrez@amd.com RegOperand reg_op; 46611308Santhony.gutierrez@amd.com 46711308Santhony.gutierrez@amd.com RegOrImmOperand() { is_imm = false; } 46811308Santhony.gutierrez@amd.com void init(unsigned opOffset, const BrigObject *obj); 46911308Santhony.gutierrez@amd.com void init_from_vect(unsigned opOffset, const BrigObject *obj, int at); 47011308Santhony.gutierrez@amd.com std::string disassemble(); 47111308Santhony.gutierrez@amd.com 47211308Santhony.gutierrez@amd.com template<typename OperandType> 47311308Santhony.gutierrez@amd.com OperandType 47411308Santhony.gutierrez@amd.com get(Wavefront *w, int lane) 47511308Santhony.gutierrez@amd.com { 47611534Sjohn.kalamatianos@amd.com return is_imm ? imm_op.template get<OperandType>(w) : 47711308Santhony.gutierrez@amd.com reg_op.template get<OperandType>(w, lane); 47811308Santhony.gutierrez@amd.com } 47911308Santhony.gutierrez@amd.com 48011308Santhony.gutierrez@amd.com uint32_t 48111308Santhony.gutierrez@amd.com opSize() 48211308Santhony.gutierrez@amd.com { 48311308Santhony.gutierrez@amd.com if (!is_imm) { 48411308Santhony.gutierrez@amd.com return reg_op.opSize(); 48511308Santhony.gutierrez@amd.com } 48611308Santhony.gutierrez@amd.com 48711308Santhony.gutierrez@amd.com return 0; 48811308Santhony.gutierrez@amd.com } 48911308Santhony.gutierrez@amd.com 49011308Santhony.gutierrez@amd.com bool 49111308Santhony.gutierrez@amd.com isVectorRegister() 49211308Santhony.gutierrez@amd.com { 49311308Santhony.gutierrez@amd.com if (!is_imm) { 49411308Santhony.gutierrez@amd.com return reg_op.registerType == Enums::RT_VECTOR; 49511308Santhony.gutierrez@amd.com } 49611308Santhony.gutierrez@amd.com return false; 49711308Santhony.gutierrez@amd.com } 49811308Santhony.gutierrez@amd.com 49911308Santhony.gutierrez@amd.com bool 50011308Santhony.gutierrez@amd.com isCondRegister() 50111308Santhony.gutierrez@amd.com { 50211308Santhony.gutierrez@amd.com if (!is_imm) { 50311308Santhony.gutierrez@amd.com return reg_op.registerType == Enums::RT_CONDITION; 50411308Santhony.gutierrez@amd.com } 50511308Santhony.gutierrez@amd.com 50611308Santhony.gutierrez@amd.com return false; 50711308Santhony.gutierrez@amd.com } 50811308Santhony.gutierrez@amd.com 50911308Santhony.gutierrez@amd.com bool 51011308Santhony.gutierrez@amd.com isScalarRegister() 51111308Santhony.gutierrez@amd.com { 51211308Santhony.gutierrez@amd.com if (!is_imm) { 51311308Santhony.gutierrez@amd.com return reg_op.registerType == Enums::RT_SCALAR; 51411308Santhony.gutierrez@amd.com } 51511308Santhony.gutierrez@amd.com 51611308Santhony.gutierrez@amd.com return false; 51711308Santhony.gutierrez@amd.com } 51811308Santhony.gutierrez@amd.com 51911308Santhony.gutierrez@amd.com unsigned int 52011308Santhony.gutierrez@amd.com regIndex() 52111308Santhony.gutierrez@amd.com { 52211308Santhony.gutierrez@amd.com if (!is_imm) { 52311308Santhony.gutierrez@amd.com return reg_op.regIndex(); 52411308Santhony.gutierrez@amd.com } 52511308Santhony.gutierrez@amd.com return 0; 52611308Santhony.gutierrez@amd.com } 52711308Santhony.gutierrez@amd.com}; 52811308Santhony.gutierrez@amd.com 52911308Santhony.gutierrez@amd.comtemplate<typename RegOperand, typename T> 53011308Santhony.gutierrez@amd.comvoid 53111308Santhony.gutierrez@amd.comRegOrImmOperand<RegOperand, T>::init(unsigned opOffset, const BrigObject *obj) 53211308Santhony.gutierrez@amd.com{ 53311308Santhony.gutierrez@amd.com is_imm = false; 53411308Santhony.gutierrez@amd.com 53511308Santhony.gutierrez@amd.com if (reg_op.init(opOffset, obj)) { 53611308Santhony.gutierrez@amd.com return; 53711308Santhony.gutierrez@amd.com } 53811308Santhony.gutierrez@amd.com 53911308Santhony.gutierrez@amd.com if (imm_op.init(opOffset, obj)) { 54011308Santhony.gutierrez@amd.com is_imm = true; 54111308Santhony.gutierrez@amd.com return; 54211308Santhony.gutierrez@amd.com } 54311308Santhony.gutierrez@amd.com 54411308Santhony.gutierrez@amd.com fatal("RegOrImmOperand::init(): bad operand kind %d\n", 54511308Santhony.gutierrez@amd.com obj->getOperand(opOffset)->kind); 54611308Santhony.gutierrez@amd.com} 54711308Santhony.gutierrez@amd.com 54811308Santhony.gutierrez@amd.comtemplate<typename RegOperand, typename T> 54911308Santhony.gutierrez@amd.comvoid 55011308Santhony.gutierrez@amd.comRegOrImmOperand<RegOperand, T>::init_from_vect(unsigned opOffset, 55111308Santhony.gutierrez@amd.com const BrigObject *obj, int at) 55211308Santhony.gutierrez@amd.com{ 55311308Santhony.gutierrez@amd.com if (reg_op.init_from_vect(opOffset, obj, at)) { 55411308Santhony.gutierrez@amd.com is_imm = false; 55511308Santhony.gutierrez@amd.com 55611308Santhony.gutierrez@amd.com return; 55711308Santhony.gutierrez@amd.com } 55811308Santhony.gutierrez@amd.com 55911308Santhony.gutierrez@amd.com if (imm_op.init_from_vect(opOffset, obj, at)) { 56011308Santhony.gutierrez@amd.com is_imm = true; 56111308Santhony.gutierrez@amd.com 56211308Santhony.gutierrez@amd.com return; 56311308Santhony.gutierrez@amd.com } 56411308Santhony.gutierrez@amd.com 56511308Santhony.gutierrez@amd.com fatal("RegOrImmOperand::init(): bad operand kind %d\n", 56611308Santhony.gutierrez@amd.com obj->getOperand(opOffset)->kind); 56711308Santhony.gutierrez@amd.com} 56811308Santhony.gutierrez@amd.com 56911308Santhony.gutierrez@amd.comtemplate<typename RegOperand, typename T> 57011308Santhony.gutierrez@amd.comstd::string 57111308Santhony.gutierrez@amd.comRegOrImmOperand<RegOperand, T>::disassemble() 57211308Santhony.gutierrez@amd.com{ 57311308Santhony.gutierrez@amd.com return is_imm ? imm_op.disassemble() : reg_op.disassemble(); 57411308Santhony.gutierrez@amd.com} 57511308Santhony.gutierrez@amd.com 57611308Santhony.gutierrez@amd.comtypedef RegOrImmOperand<SRegOperand, uint32_t> SRegOrImmOperand; 57711308Santhony.gutierrez@amd.comtypedef RegOrImmOperand<DRegOperand, uint64_t> DRegOrImmOperand; 57811308Santhony.gutierrez@amd.comtypedef RegOrImmOperand<CRegOperand, bool> CRegOrImmOperand; 57911308Santhony.gutierrez@amd.com 58011308Santhony.gutierrez@amd.comclass AddrOperandBase : public BaseOperand 58111308Santhony.gutierrez@amd.com{ 58211308Santhony.gutierrez@amd.com protected: 58311308Santhony.gutierrez@amd.com // helper function for init() 58411308Santhony.gutierrez@amd.com void parseAddr(const Brig::BrigOperandAddress *op, const BrigObject *obj); 58511308Santhony.gutierrez@amd.com 58611308Santhony.gutierrez@amd.com // helper function for disassemble() 58711308Santhony.gutierrez@amd.com std::string disassemble(std::string reg_disassembly); 58811308Santhony.gutierrez@amd.com uint64_t calcUniformBase(); 58911308Santhony.gutierrez@amd.com 59011308Santhony.gutierrez@amd.com public: 59111534Sjohn.kalamatianos@amd.com virtual void calcVector(Wavefront *w, std::vector<Addr> &addrVec) = 0; 59211308Santhony.gutierrez@amd.com virtual uint64_t calcLane(Wavefront *w, int lane=0) = 0; 59311308Santhony.gutierrez@amd.com 59411733Santhony.gutierrez@amd.com int64_t offset; 59511308Santhony.gutierrez@amd.com const char *name = nullptr; 59611308Santhony.gutierrez@amd.com StorageElement *storageElement; 59711308Santhony.gutierrez@amd.com}; 59811308Santhony.gutierrez@amd.com 59911308Santhony.gutierrez@amd.comtemplate<typename RegOperandType> 60011308Santhony.gutierrez@amd.comclass RegAddrOperand : public AddrOperandBase 60111308Santhony.gutierrez@amd.com{ 60211308Santhony.gutierrez@amd.com public: 60311308Santhony.gutierrez@amd.com RegOperandType reg; 60411308Santhony.gutierrez@amd.com void init(unsigned opOffset, const BrigObject *obj); 60511308Santhony.gutierrez@amd.com uint64_t calcUniform(); 60611534Sjohn.kalamatianos@amd.com void calcVector(Wavefront *w, std::vector<Addr> &addrVec); 60711308Santhony.gutierrez@amd.com uint64_t calcLane(Wavefront *w, int lane=0); 60811308Santhony.gutierrez@amd.com uint32_t opSize() { return reg.opSize(); } 60911308Santhony.gutierrez@amd.com bool isVectorRegister() { return reg.registerType == Enums::RT_VECTOR; } 61011308Santhony.gutierrez@amd.com bool isCondRegister() { return reg.registerType == Enums::RT_CONDITION; } 61111308Santhony.gutierrez@amd.com bool isScalarRegister() { return reg.registerType == Enums::RT_SCALAR; } 61211308Santhony.gutierrez@amd.com unsigned int regIndex() { return reg.regIndex(); } 61311308Santhony.gutierrez@amd.com std::string disassemble(); 61411308Santhony.gutierrez@amd.com}; 61511308Santhony.gutierrez@amd.com 61611308Santhony.gutierrez@amd.comtemplate<typename RegOperandType> 61711308Santhony.gutierrez@amd.comvoid 61811308Santhony.gutierrez@amd.comRegAddrOperand<RegOperandType>::init(unsigned opOffset, const BrigObject *obj) 61911308Santhony.gutierrez@amd.com{ 62011308Santhony.gutierrez@amd.com using namespace Brig; 62111308Santhony.gutierrez@amd.com 62211308Santhony.gutierrez@amd.com const BrigOperand *baseOp = obj->getOperand(opOffset); 62311308Santhony.gutierrez@amd.com 62411308Santhony.gutierrez@amd.com switch (baseOp->kind) { 62511308Santhony.gutierrez@amd.com case BRIG_KIND_OPERAND_ADDRESS: 62611308Santhony.gutierrez@amd.com { 62711308Santhony.gutierrez@amd.com const BrigOperandAddress *op = (BrigOperandAddress*)baseOp; 62811308Santhony.gutierrez@amd.com storageElement = nullptr; 62911308Santhony.gutierrez@amd.com 63011308Santhony.gutierrez@amd.com reg.init(op->reg, obj); 63111308Santhony.gutierrez@amd.com 63211308Santhony.gutierrez@amd.com if (reg.regFileChar == 's') { 63311733Santhony.gutierrez@amd.com // if the address expression is 32b, then the hi 63411733Santhony.gutierrez@amd.com // bits of the offset must be set to 0 in the BRIG 63511733Santhony.gutierrez@amd.com assert(!op->offset.hi); 63611733Santhony.gutierrez@amd.com /** 63711733Santhony.gutierrez@amd.com * the offset field of an HSAIL instruction may be negative 63811733Santhony.gutierrez@amd.com * so here we cast the raw bits we get from the BRIG file to 63911733Santhony.gutierrez@amd.com * a signed type to avoid address calculation errors 64011733Santhony.gutierrez@amd.com */ 64111733Santhony.gutierrez@amd.com offset = (int32_t)(op->offset.lo); 64211308Santhony.gutierrez@amd.com reg.regOperandSize = sizeof(uint32_t); 64311308Santhony.gutierrez@amd.com registerType = Enums::RT_VECTOR; 64411308Santhony.gutierrez@amd.com } 64511308Santhony.gutierrez@amd.com else if (reg.regFileChar == 'd') { 64611733Santhony.gutierrez@amd.com offset = (int64_t)(((uint64_t)(op->offset.hi) << 32) 64711733Santhony.gutierrez@amd.com | (uint64_t)(op->offset.lo)); 64811308Santhony.gutierrez@amd.com reg.regOperandSize = sizeof(uint64_t); 64911308Santhony.gutierrez@amd.com registerType = Enums::RT_VECTOR; 65011308Santhony.gutierrez@amd.com } 65111308Santhony.gutierrez@amd.com } 65211308Santhony.gutierrez@amd.com break; 65311308Santhony.gutierrez@amd.com 65411308Santhony.gutierrez@amd.com default: 65511308Santhony.gutierrez@amd.com fatal("RegAddrOperand: bad operand kind %d\n", baseOp->kind); 65611308Santhony.gutierrez@amd.com break; 65711308Santhony.gutierrez@amd.com } 65811308Santhony.gutierrez@amd.com} 65911308Santhony.gutierrez@amd.com 66011308Santhony.gutierrez@amd.comtemplate<typename RegOperandType> 66111308Santhony.gutierrez@amd.comuint64_t 66211308Santhony.gutierrez@amd.comRegAddrOperand<RegOperandType>::calcUniform() 66311308Santhony.gutierrez@amd.com{ 66411308Santhony.gutierrez@amd.com fatal("can't do calcUniform() on register-based address\n"); 66511308Santhony.gutierrez@amd.com 66611308Santhony.gutierrez@amd.com return 0; 66711308Santhony.gutierrez@amd.com} 66811308Santhony.gutierrez@amd.com 66911308Santhony.gutierrez@amd.comtemplate<typename RegOperandType> 67011308Santhony.gutierrez@amd.comvoid 67111534Sjohn.kalamatianos@amd.comRegAddrOperand<RegOperandType>::calcVector(Wavefront *w, 67211534Sjohn.kalamatianos@amd.com std::vector<Addr> &addrVec) 67311308Santhony.gutierrez@amd.com{ 67411308Santhony.gutierrez@amd.com Addr address = calcUniformBase(); 67511308Santhony.gutierrez@amd.com 67611534Sjohn.kalamatianos@amd.com for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) { 67711308Santhony.gutierrez@amd.com if (w->execMask(lane)) { 67811308Santhony.gutierrez@amd.com if (reg.regFileChar == 's') { 67911308Santhony.gutierrez@amd.com addrVec[lane] = address + reg.template get<uint32_t>(w, lane); 68011308Santhony.gutierrez@amd.com } else { 68111308Santhony.gutierrez@amd.com addrVec[lane] = address + reg.template get<Addr>(w, lane); 68211308Santhony.gutierrez@amd.com } 68311308Santhony.gutierrez@amd.com } 68411308Santhony.gutierrez@amd.com } 68511308Santhony.gutierrez@amd.com} 68611308Santhony.gutierrez@amd.com 68711308Santhony.gutierrez@amd.comtemplate<typename RegOperandType> 68811308Santhony.gutierrez@amd.comuint64_t 68911308Santhony.gutierrez@amd.comRegAddrOperand<RegOperandType>::calcLane(Wavefront *w, int lane) 69011308Santhony.gutierrez@amd.com{ 69111308Santhony.gutierrez@amd.com Addr address = calcUniformBase(); 69211308Santhony.gutierrez@amd.com 69311308Santhony.gutierrez@amd.com return address + reg.template get<Addr>(w, lane); 69411308Santhony.gutierrez@amd.com} 69511308Santhony.gutierrez@amd.com 69611308Santhony.gutierrez@amd.comtemplate<typename RegOperandType> 69711308Santhony.gutierrez@amd.comstd::string 69811308Santhony.gutierrez@amd.comRegAddrOperand<RegOperandType>::disassemble() 69911308Santhony.gutierrez@amd.com{ 70011308Santhony.gutierrez@amd.com return AddrOperandBase::disassemble(reg.disassemble()); 70111308Santhony.gutierrez@amd.com} 70211308Santhony.gutierrez@amd.com 70311308Santhony.gutierrez@amd.comtypedef RegAddrOperand<SRegOperand> SRegAddrOperand; 70411308Santhony.gutierrez@amd.comtypedef RegAddrOperand<DRegOperand> DRegAddrOperand; 70511308Santhony.gutierrez@amd.com 70611308Santhony.gutierrez@amd.comclass NoRegAddrOperand : public AddrOperandBase 70711308Santhony.gutierrez@amd.com{ 70811308Santhony.gutierrez@amd.com public: 70911308Santhony.gutierrez@amd.com void init(unsigned opOffset, const BrigObject *obj); 71011308Santhony.gutierrez@amd.com uint64_t calcUniform(); 71111534Sjohn.kalamatianos@amd.com void calcVector(Wavefront *w, std::vector<Addr> &addrVec); 71211308Santhony.gutierrez@amd.com uint64_t calcLane(Wavefront *w, int lane=0); 71311308Santhony.gutierrez@amd.com std::string disassemble(); 71411308Santhony.gutierrez@amd.com}; 71511308Santhony.gutierrez@amd.com 71611308Santhony.gutierrez@amd.cominline uint64_t 71711308Santhony.gutierrez@amd.comNoRegAddrOperand::calcUniform() 71811308Santhony.gutierrez@amd.com{ 71911308Santhony.gutierrez@amd.com return AddrOperandBase::calcUniformBase(); 72011308Santhony.gutierrez@amd.com} 72111308Santhony.gutierrez@amd.com 72211308Santhony.gutierrez@amd.cominline uint64_t 72311308Santhony.gutierrez@amd.comNoRegAddrOperand::calcLane(Wavefront *w, int lane) 72411308Santhony.gutierrez@amd.com{ 72511308Santhony.gutierrez@amd.com return calcUniform(); 72611308Santhony.gutierrez@amd.com} 72711308Santhony.gutierrez@amd.com 72811308Santhony.gutierrez@amd.cominline void 72911534Sjohn.kalamatianos@amd.comNoRegAddrOperand::calcVector(Wavefront *w, std::vector<Addr> &addrVec) 73011308Santhony.gutierrez@amd.com{ 73111308Santhony.gutierrez@amd.com uint64_t address = calcUniformBase(); 73211308Santhony.gutierrez@amd.com 73311534Sjohn.kalamatianos@amd.com for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) 73411308Santhony.gutierrez@amd.com addrVec[lane] = address; 73511308Santhony.gutierrez@amd.com} 73611308Santhony.gutierrez@amd.com 73711308Santhony.gutierrez@amd.comclass LabelOperand : public BaseOperand 73811308Santhony.gutierrez@amd.com{ 73911308Santhony.gutierrez@amd.com public: 74011308Santhony.gutierrez@amd.com Label *label; 74111308Santhony.gutierrez@amd.com 74211308Santhony.gutierrez@amd.com void init(unsigned opOffset, const BrigObject *obj); 74311308Santhony.gutierrez@amd.com std::string disassemble(); 74411308Santhony.gutierrez@amd.com 74511308Santhony.gutierrez@amd.com // special get method for compatibility with SRegOperand 74611308Santhony.gutierrez@amd.com uint32_t getTarget(Wavefront *w, int lane); 74711308Santhony.gutierrez@amd.com 74811308Santhony.gutierrez@amd.com}; 74911308Santhony.gutierrez@amd.com 75011308Santhony.gutierrez@amd.comclass ListOperand : public BaseOperand 75111308Santhony.gutierrez@amd.com{ 75211308Santhony.gutierrez@amd.com public: 75311308Santhony.gutierrez@amd.com int elementCount; 75411308Santhony.gutierrez@amd.com std::vector<StorageElement*> callArgs; 75511308Santhony.gutierrez@amd.com 75611308Santhony.gutierrez@amd.com int 75711308Santhony.gutierrez@amd.com getSrcOperand(int idx) 75811308Santhony.gutierrez@amd.com { 75911308Santhony.gutierrez@amd.com DPRINTF(GPUReg, "getSrcOperand, idx: %d, sz_args: %d\n", idx, 76011308Santhony.gutierrez@amd.com callArgs.size()); 76111308Santhony.gutierrez@amd.com 76211308Santhony.gutierrez@amd.com return callArgs.at(idx)->offset; 76311308Santhony.gutierrez@amd.com } 76411308Santhony.gutierrez@amd.com 76511308Santhony.gutierrez@amd.com void init(unsigned opOffset, const BrigObject *obj); 76611308Santhony.gutierrez@amd.com 76711308Santhony.gutierrez@amd.com std::string disassemble(); 76811308Santhony.gutierrez@amd.com 76911308Santhony.gutierrez@amd.com template<typename OperandType> 77011308Santhony.gutierrez@amd.com OperandType 77111308Santhony.gutierrez@amd.com get(Wavefront *w, int lane, int arg_idx) 77211308Santhony.gutierrez@amd.com { 77311308Santhony.gutierrez@amd.com return w->readCallArgMem<OperandType>(lane, getSrcOperand(arg_idx)); 77411308Santhony.gutierrez@amd.com } 77511308Santhony.gutierrez@amd.com 77611308Santhony.gutierrez@amd.com template<typename OperandType> 77711308Santhony.gutierrez@amd.com void 77811308Santhony.gutierrez@amd.com set(Wavefront *w, int lane, OperandType val) 77911308Santhony.gutierrez@amd.com { 78011308Santhony.gutierrez@amd.com w->writeCallArgMem<OperandType>(lane, getSrcOperand(0), val); 78111308Santhony.gutierrez@amd.com DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: arg[%d] <- %d\n", 78211308Santhony.gutierrez@amd.com w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, 78311308Santhony.gutierrez@amd.com getSrcOperand(0), val); 78411308Santhony.gutierrez@amd.com } 78511308Santhony.gutierrez@amd.com}; 78611308Santhony.gutierrez@amd.com 78711308Santhony.gutierrez@amd.comclass FunctionRefOperand : public BaseOperand 78811308Santhony.gutierrez@amd.com{ 78911308Santhony.gutierrez@amd.com public: 79011308Santhony.gutierrez@amd.com const char *func_name; 79111308Santhony.gutierrez@amd.com 79211308Santhony.gutierrez@amd.com void init(unsigned opOffset, const BrigObject *obj); 79311308Santhony.gutierrez@amd.com std::string disassemble(); 79411308Santhony.gutierrez@amd.com}; 79511308Santhony.gutierrez@amd.com 79611308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_OPERAND_HH__ 797