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_INSTS_MEM_HH__ 3711308Santhony.gutierrez@amd.com#define __ARCH_HSAIL_INSTS_MEM_HH__ 3811308Santhony.gutierrez@amd.com 3911693Santhony.gutierrez@amd.com#include <type_traits> 4011693Santhony.gutierrez@amd.com 4111308Santhony.gutierrez@amd.com#include "arch/hsail/insts/decl.hh" 4211308Santhony.gutierrez@amd.com#include "arch/hsail/insts/gpu_static_inst.hh" 4311308Santhony.gutierrez@amd.com#include "arch/hsail/operand.hh" 4411693Santhony.gutierrez@amd.com#include "gpu-compute/compute_unit.hh" 4511308Santhony.gutierrez@amd.com 4611308Santhony.gutierrez@amd.comnamespace HsailISA 4711308Santhony.gutierrez@amd.com{ 4811308Santhony.gutierrez@amd.com class MemInst 4911308Santhony.gutierrez@amd.com { 5011308Santhony.gutierrez@amd.com public: 5111308Santhony.gutierrez@amd.com MemInst() : size(0), addr_operand(nullptr) { } 5211308Santhony.gutierrez@amd.com 5311308Santhony.gutierrez@amd.com MemInst(Enums::MemType m_type) 5411308Santhony.gutierrez@amd.com { 5511308Santhony.gutierrez@amd.com if (m_type == Enums::M_U64 || 5611308Santhony.gutierrez@amd.com m_type == Enums::M_S64 || 5711308Santhony.gutierrez@amd.com m_type == Enums::M_F64) { 5811308Santhony.gutierrez@amd.com size = 8; 5911308Santhony.gutierrez@amd.com } else if (m_type == Enums::M_U32 || 6011308Santhony.gutierrez@amd.com m_type == Enums::M_S32 || 6111308Santhony.gutierrez@amd.com m_type == Enums::M_F32) { 6211308Santhony.gutierrez@amd.com size = 4; 6311308Santhony.gutierrez@amd.com } else if (m_type == Enums::M_U16 || 6411308Santhony.gutierrez@amd.com m_type == Enums::M_S16 || 6511308Santhony.gutierrez@amd.com m_type == Enums::M_F16) { 6611308Santhony.gutierrez@amd.com size = 2; 6711308Santhony.gutierrez@amd.com } else { 6811308Santhony.gutierrez@amd.com size = 1; 6911308Santhony.gutierrez@amd.com } 7011308Santhony.gutierrez@amd.com 7111308Santhony.gutierrez@amd.com addr_operand = nullptr; 7211308Santhony.gutierrez@amd.com } 7311308Santhony.gutierrez@amd.com 7411308Santhony.gutierrez@amd.com void 7511308Santhony.gutierrez@amd.com init_addr(AddrOperandBase *_addr_operand) 7611308Santhony.gutierrez@amd.com { 7711308Santhony.gutierrez@amd.com addr_operand = _addr_operand; 7811308Santhony.gutierrez@amd.com } 7911308Santhony.gutierrez@amd.com 8011308Santhony.gutierrez@amd.com private: 8111308Santhony.gutierrez@amd.com int size; 8211308Santhony.gutierrez@amd.com AddrOperandBase *addr_operand; 8311308Santhony.gutierrez@amd.com 8411308Santhony.gutierrez@amd.com public: 8511308Santhony.gutierrez@amd.com int getMemOperandSize() { return size; } 8611308Santhony.gutierrez@amd.com AddrOperandBase *getAddressOperand() { return addr_operand; } 8711308Santhony.gutierrez@amd.com }; 8811308Santhony.gutierrez@amd.com 8911308Santhony.gutierrez@amd.com template<typename DestOperandType, typename AddrOperandType> 9011308Santhony.gutierrez@amd.com class LdaInstBase : public HsailGPUStaticInst 9111308Santhony.gutierrez@amd.com { 9211308Santhony.gutierrez@amd.com public: 9311308Santhony.gutierrez@amd.com typename DestOperandType::DestOperand dest; 9411308Santhony.gutierrez@amd.com AddrOperandType addr; 9511308Santhony.gutierrez@amd.com 9611308Santhony.gutierrez@amd.com LdaInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj, 9711308Santhony.gutierrez@amd.com const char *_opcode) 9811308Santhony.gutierrez@amd.com : HsailGPUStaticInst(obj, _opcode) 9911308Santhony.gutierrez@amd.com { 10011308Santhony.gutierrez@amd.com using namespace Brig; 10111308Santhony.gutierrez@amd.com 10211692Santhony.gutierrez@amd.com setFlag(ALU); 10311692Santhony.gutierrez@amd.com 10411308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 10511308Santhony.gutierrez@amd.com dest.init(op_offs, obj); 10611308Santhony.gutierrez@amd.com op_offs = obj->getOperandPtr(ib->operands, 1); 10711308Santhony.gutierrez@amd.com addr.init(op_offs, obj); 10811308Santhony.gutierrez@amd.com } 10911308Santhony.gutierrez@amd.com 11011347Sandreas.hansson@arm.com int numSrcRegOperands() override 11111347Sandreas.hansson@arm.com { return(this->addr.isVectorRegister()); } 11211347Sandreas.hansson@arm.com int numDstRegOperands() override 11311347Sandreas.hansson@arm.com { return dest.isVectorRegister(); } 11411347Sandreas.hansson@arm.com bool isVectorRegister(int operandIndex) override 11511308Santhony.gutierrez@amd.com { 11611308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 11711308Santhony.gutierrez@amd.com return((operandIndex == 0) ? dest.isVectorRegister() : 11811308Santhony.gutierrez@amd.com this->addr.isVectorRegister()); 11911308Santhony.gutierrez@amd.com } 12011347Sandreas.hansson@arm.com bool isCondRegister(int operandIndex) override 12111308Santhony.gutierrez@amd.com { 12211308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 12311308Santhony.gutierrez@amd.com return((operandIndex == 0) ? dest.isCondRegister() : 12411308Santhony.gutierrez@amd.com this->addr.isCondRegister()); 12511308Santhony.gutierrez@amd.com } 12611347Sandreas.hansson@arm.com bool isScalarRegister(int operandIndex) override 12711308Santhony.gutierrez@amd.com { 12811308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 12911308Santhony.gutierrez@amd.com return((operandIndex == 0) ? dest.isScalarRegister() : 13011308Santhony.gutierrez@amd.com this->addr.isScalarRegister()); 13111308Santhony.gutierrez@amd.com } 13211347Sandreas.hansson@arm.com bool isSrcOperand(int operandIndex) override 13311308Santhony.gutierrez@amd.com { 13411308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 13511308Santhony.gutierrez@amd.com if (operandIndex > 0) 13611308Santhony.gutierrez@amd.com return(this->addr.isVectorRegister()); 13711308Santhony.gutierrez@amd.com return false; 13811308Santhony.gutierrez@amd.com } 13911347Sandreas.hansson@arm.com bool isDstOperand(int operandIndex) override { 14011308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 14111308Santhony.gutierrez@amd.com return(operandIndex == 0); 14211308Santhony.gutierrez@amd.com } 14311347Sandreas.hansson@arm.com int getOperandSize(int operandIndex) override 14411308Santhony.gutierrez@amd.com { 14511308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 14611308Santhony.gutierrez@amd.com return((operandIndex == 0) ? dest.opSize() : 14711308Santhony.gutierrez@amd.com this->addr.opSize()); 14811308Santhony.gutierrez@amd.com } 14911699Santhony.gutierrez@amd.com int 15011699Santhony.gutierrez@amd.com getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override 15111308Santhony.gutierrez@amd.com { 15211308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 15311308Santhony.gutierrez@amd.com return((operandIndex == 0) ? dest.regIndex() : 15411308Santhony.gutierrez@amd.com this->addr.regIndex()); 15511308Santhony.gutierrez@amd.com } 15611347Sandreas.hansson@arm.com int getNumOperands() override 15711308Santhony.gutierrez@amd.com { 15811308Santhony.gutierrez@amd.com if (this->addr.isVectorRegister()) 15911308Santhony.gutierrez@amd.com return 2; 16011308Santhony.gutierrez@amd.com return 1; 16111308Santhony.gutierrez@amd.com } 16211308Santhony.gutierrez@amd.com }; 16311308Santhony.gutierrez@amd.com 16411308Santhony.gutierrez@amd.com template<typename DestDataType, typename AddrOperandType> 16511308Santhony.gutierrez@amd.com class LdaInst : 16611308Santhony.gutierrez@amd.com public LdaInstBase<typename DestDataType::OperandType, AddrOperandType>, 16711308Santhony.gutierrez@amd.com public MemInst 16811308Santhony.gutierrez@amd.com { 16911308Santhony.gutierrez@amd.com public: 17011308Santhony.gutierrez@amd.com void generateDisassembly(); 17111308Santhony.gutierrez@amd.com 17211308Santhony.gutierrez@amd.com LdaInst(const Brig::BrigInstBase *ib, const BrigObject *obj, 17311308Santhony.gutierrez@amd.com const char *_opcode) 17411308Santhony.gutierrez@amd.com : LdaInstBase<typename DestDataType::OperandType, 17511308Santhony.gutierrez@amd.com AddrOperandType>(ib, obj, _opcode) 17611308Santhony.gutierrez@amd.com { 17711308Santhony.gutierrez@amd.com init_addr(&this->addr); 17811308Santhony.gutierrez@amd.com } 17911308Santhony.gutierrez@amd.com 18011308Santhony.gutierrez@amd.com void execute(GPUDynInstPtr gpuDynInst); 18111308Santhony.gutierrez@amd.com }; 18211308Santhony.gutierrez@amd.com 18311308Santhony.gutierrez@amd.com template<typename DataType> 18411308Santhony.gutierrez@amd.com GPUStaticInst* 18511308Santhony.gutierrez@amd.com decodeLda(const Brig::BrigInstBase *ib, const BrigObject *obj) 18611308Santhony.gutierrez@amd.com { 18711308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 1); 18811308Santhony.gutierrez@amd.com BrigRegOperandInfo regDataType = findRegDataType(op_offs, obj); 18911308Santhony.gutierrez@amd.com 19011308Santhony.gutierrez@amd.com if (regDataType.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) { 19111308Santhony.gutierrez@amd.com return new LdaInst<DataType, NoRegAddrOperand>(ib, obj, "ldas"); 19211308Santhony.gutierrez@amd.com } else if (regDataType.kind == Brig::BRIG_KIND_OPERAND_REGISTER) { 19311308Santhony.gutierrez@amd.com // V2/V4 not allowed 19411308Santhony.gutierrez@amd.com switch (regDataType.regKind) { 19511308Santhony.gutierrez@amd.com case Brig::BRIG_REGISTER_KIND_SINGLE: 19611308Santhony.gutierrez@amd.com return new LdaInst<DataType, SRegAddrOperand>(ib, obj, "ldas"); 19711308Santhony.gutierrez@amd.com case Brig::BRIG_REGISTER_KIND_DOUBLE: 19811308Santhony.gutierrez@amd.com return new LdaInst<DataType, DRegAddrOperand>(ib, obj, "ldas"); 19911308Santhony.gutierrez@amd.com default: 20011308Santhony.gutierrez@amd.com fatal("Bad ldas register operand type %d\n", regDataType.type); 20111308Santhony.gutierrez@amd.com } 20211308Santhony.gutierrez@amd.com } else { 20311308Santhony.gutierrez@amd.com fatal("Bad ldas register operand kind %d\n", regDataType.kind); 20411308Santhony.gutierrez@amd.com } 20511308Santhony.gutierrez@amd.com } 20611308Santhony.gutierrez@amd.com 20711308Santhony.gutierrez@amd.com template<typename MemOperandType, typename DestOperandType, 20811308Santhony.gutierrez@amd.com typename AddrOperandType> 20911308Santhony.gutierrez@amd.com class LdInstBase : public HsailGPUStaticInst 21011308Santhony.gutierrez@amd.com { 21111308Santhony.gutierrez@amd.com public: 21211308Santhony.gutierrez@amd.com Brig::BrigWidth8_t width; 21311308Santhony.gutierrez@amd.com typename DestOperandType::DestOperand dest; 21411308Santhony.gutierrez@amd.com AddrOperandType addr; 21511308Santhony.gutierrez@amd.com 21611308Santhony.gutierrez@amd.com Brig::BrigSegment segment; 21711308Santhony.gutierrez@amd.com Brig::BrigMemoryOrder memoryOrder; 21811308Santhony.gutierrez@amd.com Brig::BrigMemoryScope memoryScope; 21911308Santhony.gutierrez@amd.com unsigned int equivClass; 22011308Santhony.gutierrez@amd.com 22111308Santhony.gutierrez@amd.com LdInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj, 22211308Santhony.gutierrez@amd.com const char *_opcode) 22311308Santhony.gutierrez@amd.com : HsailGPUStaticInst(obj, _opcode) 22411308Santhony.gutierrez@amd.com { 22511308Santhony.gutierrez@amd.com using namespace Brig; 22611308Santhony.gutierrez@amd.com 22711692Santhony.gutierrez@amd.com setFlag(MemoryRef); 22811692Santhony.gutierrez@amd.com setFlag(Load); 22911692Santhony.gutierrez@amd.com 23011308Santhony.gutierrez@amd.com if (ib->opcode == BRIG_OPCODE_LD) { 23111692Santhony.gutierrez@amd.com const BrigInstMem *ldst = (const BrigInstMem*)ib; 23211692Santhony.gutierrez@amd.com 23311692Santhony.gutierrez@amd.com segment = (BrigSegment)ldst->segment; 23411692Santhony.gutierrez@amd.com memoryOrder = BRIG_MEMORY_ORDER_NONE; 23511692Santhony.gutierrez@amd.com memoryScope = BRIG_MEMORY_SCOPE_NONE; 23611692Santhony.gutierrez@amd.com equivClass = ldst->equivClass; 23711692Santhony.gutierrez@amd.com 23811692Santhony.gutierrez@amd.com width = ldst->width; 23911692Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 24011692Santhony.gutierrez@amd.com const Brig::BrigOperand *brigOp = obj->getOperand(op_offs); 24111692Santhony.gutierrez@amd.com if (brigOp->kind == BRIG_KIND_OPERAND_REGISTER) 24211692Santhony.gutierrez@amd.com dest.init(op_offs, obj); 24311692Santhony.gutierrez@amd.com 24411692Santhony.gutierrez@amd.com op_offs = obj->getOperandPtr(ib->operands, 1); 24511692Santhony.gutierrez@amd.com addr.init(op_offs, obj); 24611308Santhony.gutierrez@amd.com } else { 24711692Santhony.gutierrez@amd.com const BrigInstAtomic *at = (const BrigInstAtomic*)ib; 24811692Santhony.gutierrez@amd.com 24911692Santhony.gutierrez@amd.com segment = (BrigSegment)at->segment; 25011692Santhony.gutierrez@amd.com memoryOrder = (BrigMemoryOrder)at->memoryOrder; 25111692Santhony.gutierrez@amd.com memoryScope = (BrigMemoryScope)at->memoryScope; 25211692Santhony.gutierrez@amd.com equivClass = 0; 25311692Santhony.gutierrez@amd.com 25411692Santhony.gutierrez@amd.com width = BRIG_WIDTH_1; 25511692Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 25611692Santhony.gutierrez@amd.com const Brig::BrigOperand *brigOp = obj->getOperand(op_offs); 25711692Santhony.gutierrez@amd.com 25811692Santhony.gutierrez@amd.com if (brigOp->kind == BRIG_KIND_OPERAND_REGISTER) 25911692Santhony.gutierrez@amd.com dest.init(op_offs, obj); 26011692Santhony.gutierrez@amd.com 26111692Santhony.gutierrez@amd.com op_offs = obj->getOperandPtr(ib->operands,1); 26211692Santhony.gutierrez@amd.com addr.init(op_offs, obj); 26311692Santhony.gutierrez@amd.com } 26411692Santhony.gutierrez@amd.com 26511692Santhony.gutierrez@amd.com switch (memoryOrder) { 26611692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_NONE: 26711692Santhony.gutierrez@amd.com setFlag(NoOrder); 26811692Santhony.gutierrez@amd.com break; 26911692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_RELAXED: 27011692Santhony.gutierrez@amd.com setFlag(RelaxedOrder); 27111692Santhony.gutierrez@amd.com break; 27211692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_SC_ACQUIRE: 27311692Santhony.gutierrez@amd.com setFlag(Acquire); 27411692Santhony.gutierrez@amd.com break; 27511692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_SC_RELEASE: 27611692Santhony.gutierrez@amd.com setFlag(Release); 27711692Santhony.gutierrez@amd.com break; 27811692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE: 27911692Santhony.gutierrez@amd.com setFlag(AcquireRelease); 28011692Santhony.gutierrez@amd.com break; 28111692Santhony.gutierrez@amd.com default: 28211692Santhony.gutierrez@amd.com fatal("LdInst has bad memory order type\n"); 28311692Santhony.gutierrez@amd.com } 28411692Santhony.gutierrez@amd.com 28511692Santhony.gutierrez@amd.com switch (memoryScope) { 28611692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_NONE: 28711692Santhony.gutierrez@amd.com setFlag(NoScope); 28811692Santhony.gutierrez@amd.com break; 28911692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_WORKITEM: 29011692Santhony.gutierrez@amd.com setFlag(WorkitemScope); 29111692Santhony.gutierrez@amd.com break; 29211692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_WORKGROUP: 29311692Santhony.gutierrez@amd.com setFlag(WorkgroupScope); 29411692Santhony.gutierrez@amd.com break; 29511692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_AGENT: 29611692Santhony.gutierrez@amd.com setFlag(DeviceScope); 29711692Santhony.gutierrez@amd.com break; 29811692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_SYSTEM: 29911692Santhony.gutierrez@amd.com setFlag(SystemScope); 30011692Santhony.gutierrez@amd.com break; 30111692Santhony.gutierrez@amd.com default: 30211692Santhony.gutierrez@amd.com fatal("LdInst has bad memory scope type\n"); 30311692Santhony.gutierrez@amd.com } 30411692Santhony.gutierrez@amd.com 30511692Santhony.gutierrez@amd.com switch (segment) { 30611692Santhony.gutierrez@amd.com case BRIG_SEGMENT_GLOBAL: 30711692Santhony.gutierrez@amd.com setFlag(GlobalSegment); 30811692Santhony.gutierrez@amd.com break; 30911692Santhony.gutierrez@amd.com case BRIG_SEGMENT_GROUP: 31011692Santhony.gutierrez@amd.com setFlag(GroupSegment); 31111692Santhony.gutierrez@amd.com break; 31211692Santhony.gutierrez@amd.com case BRIG_SEGMENT_PRIVATE: 31311692Santhony.gutierrez@amd.com setFlag(PrivateSegment); 31411692Santhony.gutierrez@amd.com break; 31511692Santhony.gutierrez@amd.com case BRIG_SEGMENT_READONLY: 31611692Santhony.gutierrez@amd.com setFlag(ReadOnlySegment); 31711692Santhony.gutierrez@amd.com break; 31811692Santhony.gutierrez@amd.com case BRIG_SEGMENT_SPILL: 31911692Santhony.gutierrez@amd.com setFlag(SpillSegment); 32011692Santhony.gutierrez@amd.com break; 32111692Santhony.gutierrez@amd.com case BRIG_SEGMENT_FLAT: 32211692Santhony.gutierrez@amd.com setFlag(Flat); 32311692Santhony.gutierrez@amd.com break; 32411692Santhony.gutierrez@amd.com case BRIG_SEGMENT_KERNARG: 32511692Santhony.gutierrez@amd.com setFlag(KernArgSegment); 32611692Santhony.gutierrez@amd.com break; 32711692Santhony.gutierrez@amd.com case BRIG_SEGMENT_ARG: 32811692Santhony.gutierrez@amd.com setFlag(ArgSegment); 32911692Santhony.gutierrez@amd.com break; 33011692Santhony.gutierrez@amd.com default: 33111692Santhony.gutierrez@amd.com panic("Ld: segment %d not supported\n", segment); 33211308Santhony.gutierrez@amd.com } 33311308Santhony.gutierrez@amd.com } 33411308Santhony.gutierrez@amd.com 33511347Sandreas.hansson@arm.com int numSrcRegOperands() override 33611347Sandreas.hansson@arm.com { return(this->addr.isVectorRegister()); } 33711347Sandreas.hansson@arm.com int numDstRegOperands() override { return dest.isVectorRegister(); } 33811347Sandreas.hansson@arm.com int getNumOperands() override 33911308Santhony.gutierrez@amd.com { 34011308Santhony.gutierrez@amd.com if (this->addr.isVectorRegister()) 34111308Santhony.gutierrez@amd.com return 2; 34211308Santhony.gutierrez@amd.com else 34311308Santhony.gutierrez@amd.com return 1; 34411308Santhony.gutierrez@amd.com } 34511347Sandreas.hansson@arm.com bool isVectorRegister(int operandIndex) override 34611308Santhony.gutierrez@amd.com { 34711308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 34811308Santhony.gutierrez@amd.com return((operandIndex == 0) ? dest.isVectorRegister() : 34911308Santhony.gutierrez@amd.com this->addr.isVectorRegister()); 35011308Santhony.gutierrez@amd.com } 35111347Sandreas.hansson@arm.com bool isCondRegister(int operandIndex) override 35211308Santhony.gutierrez@amd.com { 35311308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 35411308Santhony.gutierrez@amd.com return((operandIndex == 0) ? dest.isCondRegister() : 35511308Santhony.gutierrez@amd.com this->addr.isCondRegister()); 35611308Santhony.gutierrez@amd.com } 35711347Sandreas.hansson@arm.com bool isScalarRegister(int operandIndex) override 35811308Santhony.gutierrez@amd.com { 35911308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 36011308Santhony.gutierrez@amd.com return((operandIndex == 0) ? dest.isScalarRegister() : 36111308Santhony.gutierrez@amd.com this->addr.isScalarRegister()); 36211308Santhony.gutierrez@amd.com } 36311347Sandreas.hansson@arm.com bool isSrcOperand(int operandIndex) override 36411308Santhony.gutierrez@amd.com { 36511308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 36611308Santhony.gutierrez@amd.com if (operandIndex > 0) 36711308Santhony.gutierrez@amd.com return(this->addr.isVectorRegister()); 36811308Santhony.gutierrez@amd.com return false; 36911308Santhony.gutierrez@amd.com } 37011347Sandreas.hansson@arm.com bool isDstOperand(int operandIndex) override 37111308Santhony.gutierrez@amd.com { 37211308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 37311308Santhony.gutierrez@amd.com return(operandIndex == 0); 37411308Santhony.gutierrez@amd.com } 37511347Sandreas.hansson@arm.com int getOperandSize(int operandIndex) override 37611308Santhony.gutierrez@amd.com { 37711308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 37811308Santhony.gutierrez@amd.com return((operandIndex == 0) ? dest.opSize() : 37911308Santhony.gutierrez@amd.com this->addr.opSize()); 38011308Santhony.gutierrez@amd.com } 38111699Santhony.gutierrez@amd.com int 38211699Santhony.gutierrez@amd.com getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override 38311308Santhony.gutierrez@amd.com { 38411308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 38511308Santhony.gutierrez@amd.com return((operandIndex == 0) ? dest.regIndex() : 38611308Santhony.gutierrez@amd.com this->addr.regIndex()); 38711308Santhony.gutierrez@amd.com } 38811308Santhony.gutierrez@amd.com }; 38911308Santhony.gutierrez@amd.com 39011308Santhony.gutierrez@amd.com template<typename MemDataType, typename DestDataType, 39111308Santhony.gutierrez@amd.com typename AddrOperandType> 39211308Santhony.gutierrez@amd.com class LdInst : 39311308Santhony.gutierrez@amd.com public LdInstBase<typename MemDataType::CType, 39411308Santhony.gutierrez@amd.com typename DestDataType::OperandType, AddrOperandType>, 39511308Santhony.gutierrez@amd.com public MemInst 39611308Santhony.gutierrez@amd.com { 39711308Santhony.gutierrez@amd.com typename DestDataType::OperandType::DestOperand dest_vect[4]; 39811308Santhony.gutierrez@amd.com uint16_t num_dest_operands; 39911347Sandreas.hansson@arm.com void generateDisassembly() override; 40011308Santhony.gutierrez@amd.com 40111308Santhony.gutierrez@amd.com public: 40211308Santhony.gutierrez@amd.com LdInst(const Brig::BrigInstBase *ib, const BrigObject *obj, 40311308Santhony.gutierrez@amd.com const char *_opcode) 40411308Santhony.gutierrez@amd.com : LdInstBase<typename MemDataType::CType, 40511308Santhony.gutierrez@amd.com typename DestDataType::OperandType, 40611308Santhony.gutierrez@amd.com AddrOperandType>(ib, obj, _opcode), 40711308Santhony.gutierrez@amd.com MemInst(MemDataType::memType) 40811308Santhony.gutierrez@amd.com { 40911308Santhony.gutierrez@amd.com init_addr(&this->addr); 41011308Santhony.gutierrez@amd.com 41111308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands,0); 41211308Santhony.gutierrez@amd.com const Brig::BrigOperand *brigOp = obj->getOperand(op_offs); 41311308Santhony.gutierrez@amd.com 41411308Santhony.gutierrez@amd.com if (brigOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) { 41511308Santhony.gutierrez@amd.com const Brig::BrigOperandOperandList *brigRegVecOp = 41611308Santhony.gutierrez@amd.com (const Brig::BrigOperandOperandList*)brigOp; 41711308Santhony.gutierrez@amd.com 41811308Santhony.gutierrez@amd.com num_dest_operands = 41911308Santhony.gutierrez@amd.com *((unsigned*)obj->getData(brigRegVecOp->elements)) / 4; 42011308Santhony.gutierrez@amd.com 42111308Santhony.gutierrez@amd.com assert(num_dest_operands <= 4); 42211308Santhony.gutierrez@amd.com } else { 42311308Santhony.gutierrez@amd.com num_dest_operands = 1; 42411308Santhony.gutierrez@amd.com } 42511308Santhony.gutierrez@amd.com 42611308Santhony.gutierrez@amd.com if (num_dest_operands > 1) { 42711308Santhony.gutierrez@amd.com assert(brigOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST); 42811308Santhony.gutierrez@amd.com 42911308Santhony.gutierrez@amd.com for (int i = 0; i < num_dest_operands; ++i) { 43011308Santhony.gutierrez@amd.com dest_vect[i].init_from_vect(op_offs, obj, i); 43111308Santhony.gutierrez@amd.com } 43211308Santhony.gutierrez@amd.com } 43311308Santhony.gutierrez@amd.com } 43411308Santhony.gutierrez@amd.com 43511308Santhony.gutierrez@amd.com void 43611308Santhony.gutierrez@amd.com initiateAcc(GPUDynInstPtr gpuDynInst) override 43711308Santhony.gutierrez@amd.com { 43811308Santhony.gutierrez@amd.com typedef typename MemDataType::CType c0; 43911308Santhony.gutierrez@amd.com 44011308Santhony.gutierrez@amd.com gpuDynInst->statusBitVector = gpuDynInst->exec_mask; 44111308Santhony.gutierrez@amd.com 44211308Santhony.gutierrez@amd.com if (num_dest_operands > 1) { 44311534Sjohn.kalamatianos@amd.com for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) 44411308Santhony.gutierrez@amd.com if (gpuDynInst->exec_mask[i]) 44511308Santhony.gutierrez@amd.com gpuDynInst->statusVector.push_back(num_dest_operands); 44611308Santhony.gutierrez@amd.com else 44711308Santhony.gutierrez@amd.com gpuDynInst->statusVector.push_back(0); 44811308Santhony.gutierrez@amd.com } 44911308Santhony.gutierrez@amd.com 45011308Santhony.gutierrez@amd.com for (int k = 0; k < num_dest_operands; ++k) { 45111308Santhony.gutierrez@amd.com 45211534Sjohn.kalamatianos@amd.com c0 *d = &((c0*)gpuDynInst->d_data) 45311534Sjohn.kalamatianos@amd.com [k * gpuDynInst->computeUnit()->wfSize()]; 45411308Santhony.gutierrez@amd.com 45511534Sjohn.kalamatianos@amd.com for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) { 45611308Santhony.gutierrez@amd.com if (gpuDynInst->exec_mask[i]) { 45711308Santhony.gutierrez@amd.com Addr vaddr = gpuDynInst->addr[i] + k * sizeof(c0); 45811308Santhony.gutierrez@amd.com 45911692Santhony.gutierrez@amd.com if (this->isLocalMem()) { 46011308Santhony.gutierrez@amd.com // load from shared memory 46111308Santhony.gutierrez@amd.com *d = gpuDynInst->wavefront()->ldsChunk-> 46211308Santhony.gutierrez@amd.com read<c0>(vaddr); 46311308Santhony.gutierrez@amd.com } else { 46412749Sgiacomo.travaglini@arm.com RequestPtr req = std::make_shared<Request>(0, 46512748Sgiacomo.travaglini@arm.com vaddr, sizeof(c0), 0, 46612748Sgiacomo.travaglini@arm.com gpuDynInst->computeUnit()->masterId(), 46712748Sgiacomo.travaglini@arm.com 0, gpuDynInst->wfDynId); 46811308Santhony.gutierrez@amd.com 46911308Santhony.gutierrez@amd.com gpuDynInst->setRequestFlags(req); 47011308Santhony.gutierrez@amd.com PacketPtr pkt = new Packet(req, MemCmd::ReadReq); 47111308Santhony.gutierrez@amd.com pkt->dataStatic(d); 47211308Santhony.gutierrez@amd.com 47311308Santhony.gutierrez@amd.com if (gpuDynInst->computeUnit()->shader-> 47411308Santhony.gutierrez@amd.com separate_acquire_release && 47511692Santhony.gutierrez@amd.com gpuDynInst->isAcquire()) { 47611308Santhony.gutierrez@amd.com // if this load has acquire semantics, 47711308Santhony.gutierrez@amd.com // set the response continuation function 47811308Santhony.gutierrez@amd.com // to perform an Acquire request 47911308Santhony.gutierrez@amd.com gpuDynInst->execContinuation = 48011308Santhony.gutierrez@amd.com &GPUStaticInst::execLdAcq; 48111308Santhony.gutierrez@amd.com 48211308Santhony.gutierrez@amd.com gpuDynInst->useContinuation = true; 48311308Santhony.gutierrez@amd.com } else { 48411308Santhony.gutierrez@amd.com // the request will be finished when 48511308Santhony.gutierrez@amd.com // the load completes 48611308Santhony.gutierrez@amd.com gpuDynInst->useContinuation = false; 48711308Santhony.gutierrez@amd.com } 48811308Santhony.gutierrez@amd.com // translation is performed in sendRequest() 48911308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->sendRequest(gpuDynInst, 49011308Santhony.gutierrez@amd.com i, pkt); 49111308Santhony.gutierrez@amd.com } 49211308Santhony.gutierrez@amd.com } 49311308Santhony.gutierrez@amd.com ++d; 49411308Santhony.gutierrez@amd.com } 49511308Santhony.gutierrez@amd.com } 49611308Santhony.gutierrez@amd.com 49711308Santhony.gutierrez@amd.com gpuDynInst->updateStats(); 49811308Santhony.gutierrez@amd.com } 49911308Santhony.gutierrez@amd.com 50011693Santhony.gutierrez@amd.com void 50111693Santhony.gutierrez@amd.com completeAcc(GPUDynInstPtr gpuDynInst) override 50211693Santhony.gutierrez@amd.com { 50311693Santhony.gutierrez@amd.com typedef typename MemDataType::CType c1; 50411693Santhony.gutierrez@amd.com 50511693Santhony.gutierrez@amd.com constexpr bool is_vt_32 = DestDataType::vgprType == VT_32; 50611693Santhony.gutierrez@amd.com 50711693Santhony.gutierrez@amd.com /** 50811693Santhony.gutierrez@amd.com * this code essentially replaces the long if-else chain 50911693Santhony.gutierrez@amd.com * that was in used GlobalMemPipeline::exec() to infer the 51011693Santhony.gutierrez@amd.com * size (single/double) and type (floating point/integer) of 51111693Santhony.gutierrez@amd.com * the destination register. this is needed for load 51211693Santhony.gutierrez@amd.com * instructions because the loaded value and the 51311693Santhony.gutierrez@amd.com * destination type can be of different sizes, and we also 51411693Santhony.gutierrez@amd.com * need to know if the value we're writing back is floating 51511693Santhony.gutierrez@amd.com * point and signed/unsigned, so we can properly cast the 51611693Santhony.gutierrez@amd.com * writeback value 51711693Santhony.gutierrez@amd.com */ 51811693Santhony.gutierrez@amd.com typedef typename std::conditional<is_vt_32, 51911693Santhony.gutierrez@amd.com typename std::conditional<std::is_floating_point<c1>::value, 52011693Santhony.gutierrez@amd.com float, typename std::conditional<std::is_signed<c1>::value, 52111693Santhony.gutierrez@amd.com int32_t, uint32_t>::type>::type, 52211693Santhony.gutierrez@amd.com typename std::conditional<std::is_floating_point<c1>::value, 52311693Santhony.gutierrez@amd.com double, typename std::conditional<std::is_signed<c1>::value, 52411693Santhony.gutierrez@amd.com int64_t, uint64_t>::type>::type>::type c0; 52511693Santhony.gutierrez@amd.com 52611693Santhony.gutierrez@amd.com 52711693Santhony.gutierrez@amd.com Wavefront *w = gpuDynInst->wavefront(); 52811693Santhony.gutierrez@amd.com 52911693Santhony.gutierrez@amd.com std::vector<uint32_t> regVec; 53011693Santhony.gutierrez@amd.com // iterate over number of destination register operands since 53111693Santhony.gutierrez@amd.com // this is a load 53211693Santhony.gutierrez@amd.com for (int k = 0; k < num_dest_operands; ++k) { 53311693Santhony.gutierrez@amd.com assert((sizeof(c1) * num_dest_operands) 53411693Santhony.gutierrez@amd.com <= MAX_WIDTH_FOR_MEM_INST); 53511693Santhony.gutierrez@amd.com 53611693Santhony.gutierrez@amd.com int dst = this->dest.regIndex() + k; 53711693Santhony.gutierrez@amd.com if (num_dest_operands > MAX_REGS_FOR_NON_VEC_MEM_INST) 53811693Santhony.gutierrez@amd.com dst = dest_vect[k].regIndex(); 53911693Santhony.gutierrez@amd.com // virtual->physical VGPR mapping 54011693Santhony.gutierrez@amd.com int physVgpr = w->remap(dst, sizeof(c0), 1); 54111693Santhony.gutierrez@amd.com // save the physical VGPR index 54211693Santhony.gutierrez@amd.com regVec.push_back(physVgpr); 54311693Santhony.gutierrez@amd.com 54411693Santhony.gutierrez@amd.com c1 *p1 = 54511693Santhony.gutierrez@amd.com &((c1*)gpuDynInst->d_data)[k * w->computeUnit->wfSize()]; 54611693Santhony.gutierrez@amd.com 54711693Santhony.gutierrez@amd.com for (int i = 0; i < w->computeUnit->wfSize(); ++i) { 54811693Santhony.gutierrez@amd.com if (gpuDynInst->exec_mask[i]) { 54911693Santhony.gutierrez@amd.com DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: " 55011693Santhony.gutierrez@amd.com "$%s%d <- %d global ld done (src = wavefront " 55111693Santhony.gutierrez@amd.com "ld inst)\n", w->computeUnit->cu_id, w->simdId, 55211693Santhony.gutierrez@amd.com w->wfSlotId, i, sizeof(c0) == 4 ? "s" : "d", 55311693Santhony.gutierrez@amd.com dst, *p1); 55411693Santhony.gutierrez@amd.com // write the value into the physical VGPR. This is a 55511693Santhony.gutierrez@amd.com // purely functional operation. No timing is modeled. 55611693Santhony.gutierrez@amd.com w->computeUnit->vrf[w->simdId]->write<c0>(physVgpr, 55711693Santhony.gutierrez@amd.com *p1, i); 55811693Santhony.gutierrez@amd.com } 55911693Santhony.gutierrez@amd.com ++p1; 56011693Santhony.gutierrez@amd.com } 56111693Santhony.gutierrez@amd.com } 56211693Santhony.gutierrez@amd.com 56311693Santhony.gutierrez@amd.com // Schedule the write operation of the load data on the VRF. 56411693Santhony.gutierrez@amd.com // This simply models the timing aspect of the VRF write operation. 56511693Santhony.gutierrez@amd.com // It does not modify the physical VGPR. 56611693Santhony.gutierrez@amd.com int loadVrfBankConflictCycles = gpuDynInst->computeUnit()-> 56711693Santhony.gutierrez@amd.com vrf[w->simdId]->exec(gpuDynInst->seqNum(), w, regVec, 56811693Santhony.gutierrez@amd.com sizeof(c0), gpuDynInst->time); 56911693Santhony.gutierrez@amd.com 57011693Santhony.gutierrez@amd.com if (this->isGlobalMem()) { 57111693Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->globalMemoryPipe 57211693Santhony.gutierrez@amd.com .incLoadVRFBankConflictCycles(loadVrfBankConflictCycles); 57311693Santhony.gutierrez@amd.com } else { 57411693Santhony.gutierrez@amd.com assert(this->isLocalMem()); 57511693Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->localMemoryPipe 57611693Santhony.gutierrez@amd.com .incLoadVRFBankConflictCycles(loadVrfBankConflictCycles); 57711693Santhony.gutierrez@amd.com } 57811693Santhony.gutierrez@amd.com } 57911693Santhony.gutierrez@amd.com 58011308Santhony.gutierrez@amd.com private: 58111308Santhony.gutierrez@amd.com void 58211308Santhony.gutierrez@amd.com execLdAcq(GPUDynInstPtr gpuDynInst) override 58311308Santhony.gutierrez@amd.com { 58411308Santhony.gutierrez@amd.com // after the load has complete and if the load has acquire 58511308Santhony.gutierrez@amd.com // semantics, issue an acquire request. 58611692Santhony.gutierrez@amd.com if (!this->isLocalMem()) { 58711308Santhony.gutierrez@amd.com if (gpuDynInst->computeUnit()->shader->separate_acquire_release 58811692Santhony.gutierrez@amd.com && gpuDynInst->isAcquire()) { 58911308Santhony.gutierrez@amd.com gpuDynInst->statusBitVector = VectorMask(1); 59011308Santhony.gutierrez@amd.com gpuDynInst->useContinuation = false; 59111308Santhony.gutierrez@amd.com // create request 59212749Sgiacomo.travaglini@arm.com RequestPtr req = std::make_shared<Request>(0, 0, 0, 0, 59311308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->masterId(), 59411435Smitch.hayenga@arm.com 0, gpuDynInst->wfDynId); 59511308Santhony.gutierrez@amd.com req->setFlags(Request::ACQUIRE); 59611308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req); 59711308Santhony.gutierrez@amd.com } 59811308Santhony.gutierrez@amd.com } 59911308Santhony.gutierrez@amd.com } 60011308Santhony.gutierrez@amd.com 60111308Santhony.gutierrez@amd.com public: 60211347Sandreas.hansson@arm.com bool isVectorRegister(int operandIndex) override 60311308Santhony.gutierrez@amd.com { 60411308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 60511308Santhony.gutierrez@amd.com if ((num_dest_operands != getNumOperands()) && 60611308Santhony.gutierrez@amd.com (operandIndex == (getNumOperands()-1))) 60711308Santhony.gutierrez@amd.com return(this->addr.isVectorRegister()); 60811308Santhony.gutierrez@amd.com if (num_dest_operands > 1) { 60911308Santhony.gutierrez@amd.com return dest_vect[operandIndex].isVectorRegister(); 61011308Santhony.gutierrez@amd.com } 61111308Santhony.gutierrez@amd.com else if (num_dest_operands == 1) { 61211308Santhony.gutierrez@amd.com return LdInstBase<typename MemDataType::CType, 61311308Santhony.gutierrez@amd.com typename DestDataType::OperandType, 61411308Santhony.gutierrez@amd.com AddrOperandType>::dest.isVectorRegister(); 61511308Santhony.gutierrez@amd.com } 61611308Santhony.gutierrez@amd.com return false; 61711308Santhony.gutierrez@amd.com } 61811347Sandreas.hansson@arm.com bool isCondRegister(int operandIndex) override 61911308Santhony.gutierrez@amd.com { 62011308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 62111308Santhony.gutierrez@amd.com if ((num_dest_operands != getNumOperands()) && 62211308Santhony.gutierrez@amd.com (operandIndex == (getNumOperands()-1))) 62311308Santhony.gutierrez@amd.com return(this->addr.isCondRegister()); 62411308Santhony.gutierrez@amd.com if (num_dest_operands > 1) 62511308Santhony.gutierrez@amd.com return dest_vect[operandIndex].isCondRegister(); 62611308Santhony.gutierrez@amd.com else if (num_dest_operands == 1) 62711308Santhony.gutierrez@amd.com return LdInstBase<typename MemDataType::CType, 62811308Santhony.gutierrez@amd.com typename DestDataType::OperandType, 62911308Santhony.gutierrez@amd.com AddrOperandType>::dest.isCondRegister(); 63011308Santhony.gutierrez@amd.com return false; 63111308Santhony.gutierrez@amd.com } 63211347Sandreas.hansson@arm.com bool isScalarRegister(int operandIndex) override 63311308Santhony.gutierrez@amd.com { 63411308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 63511308Santhony.gutierrez@amd.com if ((num_dest_operands != getNumOperands()) && 63611308Santhony.gutierrez@amd.com (operandIndex == (getNumOperands()-1))) 63711308Santhony.gutierrez@amd.com return(this->addr.isScalarRegister()); 63811308Santhony.gutierrez@amd.com if (num_dest_operands > 1) 63911308Santhony.gutierrez@amd.com return dest_vect[operandIndex].isScalarRegister(); 64011308Santhony.gutierrez@amd.com else if (num_dest_operands == 1) 64111308Santhony.gutierrez@amd.com return LdInstBase<typename MemDataType::CType, 64211308Santhony.gutierrez@amd.com typename DestDataType::OperandType, 64311308Santhony.gutierrez@amd.com AddrOperandType>::dest.isScalarRegister(); 64411308Santhony.gutierrez@amd.com return false; 64511308Santhony.gutierrez@amd.com } 64611347Sandreas.hansson@arm.com bool isSrcOperand(int operandIndex) override 64711308Santhony.gutierrez@amd.com { 64811308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 64911308Santhony.gutierrez@amd.com if ((num_dest_operands != getNumOperands()) && 65011308Santhony.gutierrez@amd.com (operandIndex == (getNumOperands()-1))) 65111308Santhony.gutierrez@amd.com return(this->addr.isVectorRegister()); 65211308Santhony.gutierrez@amd.com return false; 65311308Santhony.gutierrez@amd.com } 65411347Sandreas.hansson@arm.com bool isDstOperand(int operandIndex) override 65511308Santhony.gutierrez@amd.com { 65611308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 65711308Santhony.gutierrez@amd.com if ((num_dest_operands != getNumOperands()) && 65811308Santhony.gutierrez@amd.com (operandIndex == (getNumOperands()-1))) 65911308Santhony.gutierrez@amd.com return false; 66011308Santhony.gutierrez@amd.com return true; 66111308Santhony.gutierrez@amd.com } 66211347Sandreas.hansson@arm.com int getOperandSize(int operandIndex) override 66311308Santhony.gutierrez@amd.com { 66411308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 66511308Santhony.gutierrez@amd.com if ((num_dest_operands != getNumOperands()) && 66611308Santhony.gutierrez@amd.com (operandIndex == (getNumOperands()-1))) 66711308Santhony.gutierrez@amd.com return(this->addr.opSize()); 66811308Santhony.gutierrez@amd.com if (num_dest_operands > 1) 66911308Santhony.gutierrez@amd.com return(dest_vect[operandIndex].opSize()); 67011308Santhony.gutierrez@amd.com else if (num_dest_operands == 1) 67111308Santhony.gutierrez@amd.com return(LdInstBase<typename MemDataType::CType, 67211308Santhony.gutierrez@amd.com typename DestDataType::OperandType, 67311308Santhony.gutierrez@amd.com AddrOperandType>::dest.opSize()); 67411308Santhony.gutierrez@amd.com return 0; 67511308Santhony.gutierrez@amd.com } 67611699Santhony.gutierrez@amd.com int 67711699Santhony.gutierrez@amd.com getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override 67811308Santhony.gutierrez@amd.com { 67911308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 68011308Santhony.gutierrez@amd.com if ((num_dest_operands != getNumOperands()) && 68111308Santhony.gutierrez@amd.com (operandIndex == (getNumOperands()-1))) 68211308Santhony.gutierrez@amd.com return(this->addr.regIndex()); 68311308Santhony.gutierrez@amd.com if (num_dest_operands > 1) 68411308Santhony.gutierrez@amd.com return(dest_vect[operandIndex].regIndex()); 68511308Santhony.gutierrez@amd.com else if (num_dest_operands == 1) 68611308Santhony.gutierrez@amd.com return(LdInstBase<typename MemDataType::CType, 68711308Santhony.gutierrez@amd.com typename DestDataType::OperandType, 68811308Santhony.gutierrez@amd.com AddrOperandType>::dest.regIndex()); 68911308Santhony.gutierrez@amd.com return -1; 69011308Santhony.gutierrez@amd.com } 69111347Sandreas.hansson@arm.com int getNumOperands() override 69211308Santhony.gutierrez@amd.com { 69311308Santhony.gutierrez@amd.com if (this->addr.isVectorRegister() || this->addr.isScalarRegister()) 69411308Santhony.gutierrez@amd.com return(num_dest_operands+1); 69511308Santhony.gutierrez@amd.com else 69611308Santhony.gutierrez@amd.com return(num_dest_operands); 69711308Santhony.gutierrez@amd.com } 69811347Sandreas.hansson@arm.com void execute(GPUDynInstPtr gpuDynInst) override; 69911308Santhony.gutierrez@amd.com }; 70011308Santhony.gutierrez@amd.com 70111308Santhony.gutierrez@amd.com template<typename MemDT, typename DestDT> 70211308Santhony.gutierrez@amd.com GPUStaticInst* 70311308Santhony.gutierrez@amd.com decodeLd2(const Brig::BrigInstBase *ib, const BrigObject *obj) 70411308Santhony.gutierrez@amd.com { 70511308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands,1); 70611308Santhony.gutierrez@amd.com BrigRegOperandInfo tmp = findRegDataType(op_offs, obj); 70711308Santhony.gutierrez@amd.com 70811308Santhony.gutierrez@amd.com if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) { 70911308Santhony.gutierrez@amd.com return new LdInst<MemDT, DestDT, NoRegAddrOperand>(ib, obj, "ld"); 71011308Santhony.gutierrez@amd.com } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER || 71111308Santhony.gutierrez@amd.com tmp.kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) { 71211308Santhony.gutierrez@amd.com switch (tmp.regKind) { 71311308Santhony.gutierrez@amd.com case Brig::BRIG_REGISTER_KIND_SINGLE: 71411308Santhony.gutierrez@amd.com return new LdInst<MemDT, DestDT, 71511308Santhony.gutierrez@amd.com SRegAddrOperand>(ib, obj, "ld"); 71611308Santhony.gutierrez@amd.com case Brig::BRIG_REGISTER_KIND_DOUBLE: 71711308Santhony.gutierrez@amd.com return new LdInst<MemDT, DestDT, 71811308Santhony.gutierrez@amd.com DRegAddrOperand>(ib, obj, "ld"); 71911308Santhony.gutierrez@amd.com default: 72011308Santhony.gutierrez@amd.com fatal("Bad ld register operand type %d\n", tmp.regKind); 72111308Santhony.gutierrez@amd.com } 72211308Santhony.gutierrez@amd.com } else { 72311308Santhony.gutierrez@amd.com fatal("Bad ld register operand kind %d\n", tmp.kind); 72411308Santhony.gutierrez@amd.com } 72511308Santhony.gutierrez@amd.com } 72611308Santhony.gutierrez@amd.com 72711308Santhony.gutierrez@amd.com template<typename MemDT> 72811308Santhony.gutierrez@amd.com GPUStaticInst* 72911308Santhony.gutierrez@amd.com decodeLd(const Brig::BrigInstBase *ib, const BrigObject *obj) 73011308Santhony.gutierrez@amd.com { 73111308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands,0); 73211308Santhony.gutierrez@amd.com BrigRegOperandInfo dest = findRegDataType(op_offs, obj); 73311308Santhony.gutierrez@amd.com 73411308Santhony.gutierrez@amd.com assert(dest.kind == Brig::BRIG_KIND_OPERAND_REGISTER || 73511308Santhony.gutierrez@amd.com dest.kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST); 73611308Santhony.gutierrez@amd.com switch(dest.regKind) { 73711308Santhony.gutierrez@amd.com case Brig::BRIG_REGISTER_KIND_SINGLE: 73811308Santhony.gutierrez@amd.com switch (ib->type) { 73911308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_B8: 74011308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_B16: 74111308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_B32: 74211308Santhony.gutierrez@amd.com return decodeLd2<MemDT, B32>(ib, obj); 74311308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_U8: 74411308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_U16: 74511308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_U32: 74611308Santhony.gutierrez@amd.com return decodeLd2<MemDT, U32>(ib, obj); 74711308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_S8: 74811308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_S16: 74911308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_S32: 75011308Santhony.gutierrez@amd.com return decodeLd2<MemDT, S32>(ib, obj); 75111308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_F16: 75211308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_F32: 75311308Santhony.gutierrez@amd.com return decodeLd2<MemDT, U32>(ib, obj); 75411308Santhony.gutierrez@amd.com default: 75511308Santhony.gutierrez@amd.com fatal("Bad ld register operand type %d, %d\n", 75611308Santhony.gutierrez@amd.com dest.regKind, ib->type); 75711308Santhony.gutierrez@amd.com }; 75811308Santhony.gutierrez@amd.com case Brig::BRIG_REGISTER_KIND_DOUBLE: 75911308Santhony.gutierrez@amd.com switch (ib->type) { 76011308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_B64: 76111308Santhony.gutierrez@amd.com return decodeLd2<MemDT, B64>(ib, obj); 76211308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_U64: 76311308Santhony.gutierrez@amd.com return decodeLd2<MemDT, U64>(ib, obj); 76411308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_S64: 76511308Santhony.gutierrez@amd.com return decodeLd2<MemDT, S64>(ib, obj); 76611308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_F64: 76711308Santhony.gutierrez@amd.com return decodeLd2<MemDT, U64>(ib, obj); 76811308Santhony.gutierrez@amd.com default: 76911308Santhony.gutierrez@amd.com fatal("Bad ld register operand type %d, %d\n", 77011308Santhony.gutierrez@amd.com dest.regKind, ib->type); 77111308Santhony.gutierrez@amd.com }; 77211308Santhony.gutierrez@amd.com default: 77311308Santhony.gutierrez@amd.com fatal("Bad ld register operand type %d, %d\n", dest.regKind, 77411308Santhony.gutierrez@amd.com ib->type); 77511308Santhony.gutierrez@amd.com } 77611308Santhony.gutierrez@amd.com } 77711308Santhony.gutierrez@amd.com 77811308Santhony.gutierrez@amd.com template<typename MemDataType, typename SrcOperandType, 77911308Santhony.gutierrez@amd.com typename AddrOperandType> 78011308Santhony.gutierrez@amd.com class StInstBase : public HsailGPUStaticInst 78111308Santhony.gutierrez@amd.com { 78211308Santhony.gutierrez@amd.com public: 78311308Santhony.gutierrez@amd.com typename SrcOperandType::SrcOperand src; 78411308Santhony.gutierrez@amd.com AddrOperandType addr; 78511308Santhony.gutierrez@amd.com 78611308Santhony.gutierrez@amd.com Brig::BrigSegment segment; 78711308Santhony.gutierrez@amd.com Brig::BrigMemoryScope memoryScope; 78811308Santhony.gutierrez@amd.com Brig::BrigMemoryOrder memoryOrder; 78911308Santhony.gutierrez@amd.com unsigned int equivClass; 79011308Santhony.gutierrez@amd.com 79111308Santhony.gutierrez@amd.com StInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj, 79211308Santhony.gutierrez@amd.com const char *_opcode) 79311308Santhony.gutierrez@amd.com : HsailGPUStaticInst(obj, _opcode) 79411308Santhony.gutierrez@amd.com { 79511308Santhony.gutierrez@amd.com using namespace Brig; 79611308Santhony.gutierrez@amd.com 79711692Santhony.gutierrez@amd.com setFlag(MemoryRef); 79811692Santhony.gutierrez@amd.com setFlag(Store); 79911692Santhony.gutierrez@amd.com 80011308Santhony.gutierrez@amd.com if (ib->opcode == BRIG_OPCODE_ST) { 80111692Santhony.gutierrez@amd.com const BrigInstMem *ldst = (const BrigInstMem*)ib; 80211692Santhony.gutierrez@amd.com 80311692Santhony.gutierrez@amd.com segment = (BrigSegment)ldst->segment; 80411692Santhony.gutierrez@amd.com memoryOrder = BRIG_MEMORY_ORDER_NONE; 80511692Santhony.gutierrez@amd.com memoryScope = BRIG_MEMORY_SCOPE_NONE; 80611692Santhony.gutierrez@amd.com equivClass = ldst->equivClass; 80711692Santhony.gutierrez@amd.com 80811692Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 80911692Santhony.gutierrez@amd.com const BrigOperand *baseOp = obj->getOperand(op_offs); 81011692Santhony.gutierrez@amd.com 81111692Santhony.gutierrez@amd.com if ((baseOp->kind == BRIG_KIND_OPERAND_CONSTANT_BYTES) || 81211692Santhony.gutierrez@amd.com (baseOp->kind == BRIG_KIND_OPERAND_REGISTER)) { 81311692Santhony.gutierrez@amd.com src.init(op_offs, obj); 81411692Santhony.gutierrez@amd.com } 81511692Santhony.gutierrez@amd.com 81611692Santhony.gutierrez@amd.com op_offs = obj->getOperandPtr(ib->operands, 1); 81711692Santhony.gutierrez@amd.com addr.init(op_offs, obj); 81811308Santhony.gutierrez@amd.com } else { 81911692Santhony.gutierrez@amd.com const BrigInstAtomic *at = (const BrigInstAtomic*)ib; 82011692Santhony.gutierrez@amd.com 82111692Santhony.gutierrez@amd.com segment = (BrigSegment)at->segment; 82211692Santhony.gutierrez@amd.com memoryScope = (BrigMemoryScope)at->memoryScope; 82311692Santhony.gutierrez@amd.com memoryOrder = (BrigMemoryOrder)at->memoryOrder; 82411692Santhony.gutierrez@amd.com equivClass = 0; 82511692Santhony.gutierrez@amd.com 82611692Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 82711692Santhony.gutierrez@amd.com addr.init(op_offs, obj); 82811692Santhony.gutierrez@amd.com 82911692Santhony.gutierrez@amd.com op_offs = obj->getOperandPtr(ib->operands, 1); 83011692Santhony.gutierrez@amd.com src.init(op_offs, obj); 83111692Santhony.gutierrez@amd.com } 83211692Santhony.gutierrez@amd.com 83311692Santhony.gutierrez@amd.com switch (memoryOrder) { 83411692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_NONE: 83511692Santhony.gutierrez@amd.com setFlag(NoOrder); 83611692Santhony.gutierrez@amd.com break; 83711692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_RELAXED: 83811692Santhony.gutierrez@amd.com setFlag(RelaxedOrder); 83911692Santhony.gutierrez@amd.com break; 84011692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_SC_ACQUIRE: 84111692Santhony.gutierrez@amd.com setFlag(Acquire); 84211692Santhony.gutierrez@amd.com break; 84311692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_SC_RELEASE: 84411692Santhony.gutierrez@amd.com setFlag(Release); 84511692Santhony.gutierrez@amd.com break; 84611692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE: 84711692Santhony.gutierrez@amd.com setFlag(AcquireRelease); 84811692Santhony.gutierrez@amd.com break; 84911692Santhony.gutierrez@amd.com default: 85011692Santhony.gutierrez@amd.com fatal("StInst has bad memory order type\n"); 85111692Santhony.gutierrez@amd.com } 85211692Santhony.gutierrez@amd.com 85311692Santhony.gutierrez@amd.com switch (memoryScope) { 85411692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_NONE: 85511692Santhony.gutierrez@amd.com setFlag(NoScope); 85611692Santhony.gutierrez@amd.com break; 85711692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_WORKITEM: 85811692Santhony.gutierrez@amd.com setFlag(WorkitemScope); 85911692Santhony.gutierrez@amd.com break; 86011692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_WORKGROUP: 86111692Santhony.gutierrez@amd.com setFlag(WorkgroupScope); 86211692Santhony.gutierrez@amd.com break; 86311692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_AGENT: 86411692Santhony.gutierrez@amd.com setFlag(DeviceScope); 86511692Santhony.gutierrez@amd.com break; 86611692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_SYSTEM: 86711692Santhony.gutierrez@amd.com setFlag(SystemScope); 86811692Santhony.gutierrez@amd.com break; 86911692Santhony.gutierrez@amd.com default: 87011692Santhony.gutierrez@amd.com fatal("StInst has bad memory scope type\n"); 87111692Santhony.gutierrez@amd.com } 87211692Santhony.gutierrez@amd.com 87311692Santhony.gutierrez@amd.com switch (segment) { 87411692Santhony.gutierrez@amd.com case BRIG_SEGMENT_GLOBAL: 87511692Santhony.gutierrez@amd.com setFlag(GlobalSegment); 87611692Santhony.gutierrez@amd.com break; 87711692Santhony.gutierrez@amd.com case BRIG_SEGMENT_GROUP: 87811692Santhony.gutierrez@amd.com setFlag(GroupSegment); 87911692Santhony.gutierrez@amd.com break; 88011692Santhony.gutierrez@amd.com case BRIG_SEGMENT_PRIVATE: 88111692Santhony.gutierrez@amd.com setFlag(PrivateSegment); 88211692Santhony.gutierrez@amd.com break; 88311692Santhony.gutierrez@amd.com case BRIG_SEGMENT_READONLY: 88411692Santhony.gutierrez@amd.com setFlag(ReadOnlySegment); 88511692Santhony.gutierrez@amd.com break; 88611692Santhony.gutierrez@amd.com case BRIG_SEGMENT_SPILL: 88711692Santhony.gutierrez@amd.com setFlag(SpillSegment); 88811692Santhony.gutierrez@amd.com break; 88911692Santhony.gutierrez@amd.com case BRIG_SEGMENT_FLAT: 89011692Santhony.gutierrez@amd.com setFlag(Flat); 89111692Santhony.gutierrez@amd.com break; 89211692Santhony.gutierrez@amd.com case BRIG_SEGMENT_ARG: 89311692Santhony.gutierrez@amd.com setFlag(ArgSegment); 89411692Santhony.gutierrez@amd.com break; 89511692Santhony.gutierrez@amd.com default: 89611692Santhony.gutierrez@amd.com panic("St: segment %d not supported\n", segment); 89711308Santhony.gutierrez@amd.com } 89811308Santhony.gutierrez@amd.com } 89911308Santhony.gutierrez@amd.com 90011347Sandreas.hansson@arm.com int numDstRegOperands() override { return 0; } 90111347Sandreas.hansson@arm.com int numSrcRegOperands() override 90211308Santhony.gutierrez@amd.com { 90311308Santhony.gutierrez@amd.com return src.isVectorRegister() + this->addr.isVectorRegister(); 90411308Santhony.gutierrez@amd.com } 90511347Sandreas.hansson@arm.com int getNumOperands() override 90611308Santhony.gutierrez@amd.com { 90711308Santhony.gutierrez@amd.com if (this->addr.isVectorRegister() || this->addr.isScalarRegister()) 90811308Santhony.gutierrez@amd.com return 2; 90911308Santhony.gutierrez@amd.com else 91011308Santhony.gutierrez@amd.com return 1; 91111308Santhony.gutierrez@amd.com } 91211347Sandreas.hansson@arm.com bool isVectorRegister(int operandIndex) override 91311308Santhony.gutierrez@amd.com { 91411308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 91511308Santhony.gutierrez@amd.com return !operandIndex ? src.isVectorRegister() : 91611308Santhony.gutierrez@amd.com this->addr.isVectorRegister(); 91711308Santhony.gutierrez@amd.com } 91811347Sandreas.hansson@arm.com bool isCondRegister(int operandIndex) override 91911308Santhony.gutierrez@amd.com { 92011308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 92111308Santhony.gutierrez@amd.com return !operandIndex ? src.isCondRegister() : 92211308Santhony.gutierrez@amd.com this->addr.isCondRegister(); 92311308Santhony.gutierrez@amd.com } 92411347Sandreas.hansson@arm.com bool isScalarRegister(int operandIndex) override 92511308Santhony.gutierrez@amd.com { 92611308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 92711308Santhony.gutierrez@amd.com return !operandIndex ? src.isScalarRegister() : 92811308Santhony.gutierrez@amd.com this->addr.isScalarRegister(); 92911308Santhony.gutierrez@amd.com } 93011347Sandreas.hansson@arm.com bool isSrcOperand(int operandIndex) override 93111308Santhony.gutierrez@amd.com { 93211308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 93311308Santhony.gutierrez@amd.com return true; 93411308Santhony.gutierrez@amd.com } 93511347Sandreas.hansson@arm.com bool isDstOperand(int operandIndex) override { return false; } 93611347Sandreas.hansson@arm.com int getOperandSize(int operandIndex) override 93711308Santhony.gutierrez@amd.com { 93811308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 93911308Santhony.gutierrez@amd.com return !operandIndex ? src.opSize() : this->addr.opSize(); 94011308Santhony.gutierrez@amd.com } 94111699Santhony.gutierrez@amd.com int 94211699Santhony.gutierrez@amd.com getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override 94311308Santhony.gutierrez@amd.com { 94411308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 94511308Santhony.gutierrez@amd.com return !operandIndex ? src.regIndex() : this->addr.regIndex(); 94611308Santhony.gutierrez@amd.com } 94711308Santhony.gutierrez@amd.com }; 94811308Santhony.gutierrez@amd.com 94911308Santhony.gutierrez@amd.com 95011308Santhony.gutierrez@amd.com template<typename MemDataType, typename SrcDataType, 95111308Santhony.gutierrez@amd.com typename AddrOperandType> 95211308Santhony.gutierrez@amd.com class StInst : 95311308Santhony.gutierrez@amd.com public StInstBase<MemDataType, typename SrcDataType::OperandType, 95411308Santhony.gutierrez@amd.com AddrOperandType>, 95511308Santhony.gutierrez@amd.com public MemInst 95611308Santhony.gutierrez@amd.com { 95711308Santhony.gutierrez@amd.com public: 95811308Santhony.gutierrez@amd.com typename SrcDataType::OperandType::SrcOperand src_vect[4]; 95911308Santhony.gutierrez@amd.com uint16_t num_src_operands; 96011347Sandreas.hansson@arm.com void generateDisassembly() override; 96111308Santhony.gutierrez@amd.com 96211308Santhony.gutierrez@amd.com StInst(const Brig::BrigInstBase *ib, const BrigObject *obj, 96311308Santhony.gutierrez@amd.com const char *_opcode, int srcIdx) 96411308Santhony.gutierrez@amd.com : StInstBase<MemDataType, typename SrcDataType::OperandType, 96511308Santhony.gutierrez@amd.com AddrOperandType>(ib, obj, _opcode), 96611308Santhony.gutierrez@amd.com MemInst(SrcDataType::memType) 96711308Santhony.gutierrez@amd.com { 96811308Santhony.gutierrez@amd.com init_addr(&this->addr); 96911308Santhony.gutierrez@amd.com 97011308Santhony.gutierrez@amd.com BrigRegOperandInfo rinfo; 97111308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands,srcIdx); 97211308Santhony.gutierrez@amd.com const Brig::BrigOperand *baseOp = obj->getOperand(op_offs); 97311308Santhony.gutierrez@amd.com 97411308Santhony.gutierrez@amd.com if (baseOp->kind == Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES) { 97511308Santhony.gutierrez@amd.com const Brig::BrigOperandConstantBytes *op = 97611308Santhony.gutierrez@amd.com (Brig::BrigOperandConstantBytes*)baseOp; 97711308Santhony.gutierrez@amd.com 97811308Santhony.gutierrez@amd.com rinfo = BrigRegOperandInfo((Brig::BrigKind16_t)op->base.kind, 97911308Santhony.gutierrez@amd.com Brig::BRIG_TYPE_NONE); 98011308Santhony.gutierrez@amd.com } else { 98111308Santhony.gutierrez@amd.com rinfo = findRegDataType(op_offs, obj); 98211308Santhony.gutierrez@amd.com } 98311308Santhony.gutierrez@amd.com 98411308Santhony.gutierrez@amd.com if (baseOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) { 98511308Santhony.gutierrez@amd.com const Brig::BrigOperandOperandList *brigRegVecOp = 98611308Santhony.gutierrez@amd.com (const Brig::BrigOperandOperandList*)baseOp; 98711308Santhony.gutierrez@amd.com 98811308Santhony.gutierrez@amd.com num_src_operands = 98911308Santhony.gutierrez@amd.com *((unsigned*)obj->getData(brigRegVecOp->elements)) / 4; 99011308Santhony.gutierrez@amd.com 99111308Santhony.gutierrez@amd.com assert(num_src_operands <= 4); 99211308Santhony.gutierrez@amd.com } else { 99311308Santhony.gutierrez@amd.com num_src_operands = 1; 99411308Santhony.gutierrez@amd.com } 99511308Santhony.gutierrez@amd.com 99611308Santhony.gutierrez@amd.com if (num_src_operands > 1) { 99711308Santhony.gutierrez@amd.com assert(baseOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST); 99811308Santhony.gutierrez@amd.com 99911308Santhony.gutierrez@amd.com for (int i = 0; i < num_src_operands; ++i) { 100011308Santhony.gutierrez@amd.com src_vect[i].init_from_vect(op_offs, obj, i); 100111308Santhony.gutierrez@amd.com } 100211308Santhony.gutierrez@amd.com } 100311308Santhony.gutierrez@amd.com } 100411308Santhony.gutierrez@amd.com 100511308Santhony.gutierrez@amd.com void 100611308Santhony.gutierrez@amd.com initiateAcc(GPUDynInstPtr gpuDynInst) override 100711308Santhony.gutierrez@amd.com { 100811308Santhony.gutierrez@amd.com // before performing a store, check if this store has 100911308Santhony.gutierrez@amd.com // release semantics, and if so issue a release first 101011692Santhony.gutierrez@amd.com if (!this->isLocalMem()) { 101111308Santhony.gutierrez@amd.com if (gpuDynInst->computeUnit()->shader->separate_acquire_release 101211692Santhony.gutierrez@amd.com && gpuDynInst->isRelease()) { 101311308Santhony.gutierrez@amd.com 101411308Santhony.gutierrez@amd.com gpuDynInst->statusBitVector = VectorMask(1); 101511308Santhony.gutierrez@amd.com gpuDynInst->execContinuation = &GPUStaticInst::execSt; 101611308Santhony.gutierrez@amd.com gpuDynInst->useContinuation = true; 101711308Santhony.gutierrez@amd.com // create request 101812749Sgiacomo.travaglini@arm.com RequestPtr req = std::make_shared<Request>(0, 0, 0, 0, 101911308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->masterId(), 102011435Smitch.hayenga@arm.com 0, gpuDynInst->wfDynId); 102111308Santhony.gutierrez@amd.com req->setFlags(Request::RELEASE); 102211308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req); 102311308Santhony.gutierrez@amd.com 102411308Santhony.gutierrez@amd.com return; 102511308Santhony.gutierrez@amd.com } 102611308Santhony.gutierrez@amd.com } 102711308Santhony.gutierrez@amd.com 102811308Santhony.gutierrez@amd.com // if there is no release semantic, perform stores immediately 102911308Santhony.gutierrez@amd.com execSt(gpuDynInst); 103011308Santhony.gutierrez@amd.com } 103111308Santhony.gutierrez@amd.com 103211693Santhony.gutierrez@amd.com // stores don't write anything back, so there is nothing 103311693Santhony.gutierrez@amd.com // to do here. we only override this method to avoid the 103411693Santhony.gutierrez@amd.com // fatal in the base class implementation 103511693Santhony.gutierrez@amd.com void completeAcc(GPUDynInstPtr gpuDynInst) override { } 103611693Santhony.gutierrez@amd.com 103711308Santhony.gutierrez@amd.com private: 103811308Santhony.gutierrez@amd.com // execSt may be called through a continuation 103911308Santhony.gutierrez@amd.com // if the store had release semantics. see comment for 104011308Santhony.gutierrez@amd.com // execSt in gpu_static_inst.hh 104111308Santhony.gutierrez@amd.com void 104211308Santhony.gutierrez@amd.com execSt(GPUDynInstPtr gpuDynInst) override 104311308Santhony.gutierrez@amd.com { 104411308Santhony.gutierrez@amd.com typedef typename MemDataType::CType c0; 104511308Santhony.gutierrez@amd.com 104611308Santhony.gutierrez@amd.com gpuDynInst->statusBitVector = gpuDynInst->exec_mask; 104711308Santhony.gutierrez@amd.com 104811308Santhony.gutierrez@amd.com if (num_src_operands > 1) { 104911534Sjohn.kalamatianos@amd.com for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) 105011308Santhony.gutierrez@amd.com if (gpuDynInst->exec_mask[i]) 105111308Santhony.gutierrez@amd.com gpuDynInst->statusVector.push_back(num_src_operands); 105211308Santhony.gutierrez@amd.com else 105311308Santhony.gutierrez@amd.com gpuDynInst->statusVector.push_back(0); 105411308Santhony.gutierrez@amd.com } 105511308Santhony.gutierrez@amd.com 105611308Santhony.gutierrez@amd.com for (int k = 0; k < num_src_operands; ++k) { 105711534Sjohn.kalamatianos@amd.com c0 *d = &((c0*)gpuDynInst->d_data) 105811534Sjohn.kalamatianos@amd.com [k * gpuDynInst->computeUnit()->wfSize()]; 105911308Santhony.gutierrez@amd.com 106011534Sjohn.kalamatianos@amd.com for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) { 106111308Santhony.gutierrez@amd.com if (gpuDynInst->exec_mask[i]) { 106211308Santhony.gutierrez@amd.com Addr vaddr = gpuDynInst->addr[i] + k * sizeof(c0); 106311308Santhony.gutierrez@amd.com 106411692Santhony.gutierrez@amd.com if (this->isLocalMem()) { 106511308Santhony.gutierrez@amd.com //store to shared memory 106611308Santhony.gutierrez@amd.com gpuDynInst->wavefront()->ldsChunk->write<c0>(vaddr, 106711308Santhony.gutierrez@amd.com *d); 106811308Santhony.gutierrez@amd.com } else { 106912749Sgiacomo.travaglini@arm.com RequestPtr req = std::make_shared<Request>( 107012749Sgiacomo.travaglini@arm.com 0, vaddr, sizeof(c0), 0, 107112749Sgiacomo.travaglini@arm.com gpuDynInst->computeUnit()->masterId(), 107212749Sgiacomo.travaglini@arm.com 0, gpuDynInst->wfDynId); 107311308Santhony.gutierrez@amd.com 107411308Santhony.gutierrez@amd.com gpuDynInst->setRequestFlags(req); 107511308Santhony.gutierrez@amd.com PacketPtr pkt = new Packet(req, MemCmd::WriteReq); 107611308Santhony.gutierrez@amd.com pkt->dataStatic<c0>(d); 107711308Santhony.gutierrez@amd.com 107811308Santhony.gutierrez@amd.com // translation is performed in sendRequest() 107911308Santhony.gutierrez@amd.com // the request will be finished when the store completes 108011308Santhony.gutierrez@amd.com gpuDynInst->useContinuation = false; 108111308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->sendRequest(gpuDynInst, 108211308Santhony.gutierrez@amd.com i, pkt); 108311308Santhony.gutierrez@amd.com 108411308Santhony.gutierrez@amd.com } 108511308Santhony.gutierrez@amd.com } 108611308Santhony.gutierrez@amd.com ++d; 108711308Santhony.gutierrez@amd.com } 108811308Santhony.gutierrez@amd.com } 108911308Santhony.gutierrez@amd.com 109011308Santhony.gutierrez@amd.com gpuDynInst->updateStats(); 109111308Santhony.gutierrez@amd.com } 109211308Santhony.gutierrez@amd.com 109311308Santhony.gutierrez@amd.com public: 109411347Sandreas.hansson@arm.com bool isVectorRegister(int operandIndex) override 109511308Santhony.gutierrez@amd.com { 109611308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 109711308Santhony.gutierrez@amd.com if (operandIndex == num_src_operands) 109811308Santhony.gutierrez@amd.com return this->addr.isVectorRegister(); 109911308Santhony.gutierrez@amd.com if (num_src_operands > 1) 110011308Santhony.gutierrez@amd.com return src_vect[operandIndex].isVectorRegister(); 110111308Santhony.gutierrez@amd.com else if (num_src_operands == 1) 110211308Santhony.gutierrez@amd.com return StInstBase<MemDataType, 110311308Santhony.gutierrez@amd.com typename SrcDataType::OperandType, 110411308Santhony.gutierrez@amd.com AddrOperandType>::src.isVectorRegister(); 110511308Santhony.gutierrez@amd.com return false; 110611308Santhony.gutierrez@amd.com } 110711347Sandreas.hansson@arm.com bool isCondRegister(int operandIndex) override 110811308Santhony.gutierrez@amd.com { 110911308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 111011308Santhony.gutierrez@amd.com if (operandIndex == num_src_operands) 111111308Santhony.gutierrez@amd.com return this->addr.isCondRegister(); 111211308Santhony.gutierrez@amd.com if (num_src_operands > 1) 111311308Santhony.gutierrez@amd.com return src_vect[operandIndex].isCondRegister(); 111411308Santhony.gutierrez@amd.com else if (num_src_operands == 1) 111511308Santhony.gutierrez@amd.com return StInstBase<MemDataType, 111611308Santhony.gutierrez@amd.com typename SrcDataType::OperandType, 111711308Santhony.gutierrez@amd.com AddrOperandType>::src.isCondRegister(); 111811308Santhony.gutierrez@amd.com return false; 111911308Santhony.gutierrez@amd.com } 112011347Sandreas.hansson@arm.com bool isScalarRegister(int operandIndex) override 112111308Santhony.gutierrez@amd.com { 112211308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 112311308Santhony.gutierrez@amd.com if (operandIndex == num_src_operands) 112411308Santhony.gutierrez@amd.com return this->addr.isScalarRegister(); 112511308Santhony.gutierrez@amd.com if (num_src_operands > 1) 112611308Santhony.gutierrez@amd.com return src_vect[operandIndex].isScalarRegister(); 112711308Santhony.gutierrez@amd.com else if (num_src_operands == 1) 112811308Santhony.gutierrez@amd.com return StInstBase<MemDataType, 112911308Santhony.gutierrez@amd.com typename SrcDataType::OperandType, 113011308Santhony.gutierrez@amd.com AddrOperandType>::src.isScalarRegister(); 113111308Santhony.gutierrez@amd.com return false; 113211308Santhony.gutierrez@amd.com } 113311347Sandreas.hansson@arm.com bool isSrcOperand(int operandIndex) override 113411308Santhony.gutierrez@amd.com { 113511308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 113611308Santhony.gutierrez@amd.com return true; 113711308Santhony.gutierrez@amd.com } 113811347Sandreas.hansson@arm.com bool isDstOperand(int operandIndex) override { return false; } 113911347Sandreas.hansson@arm.com int getOperandSize(int operandIndex) override 114011308Santhony.gutierrez@amd.com { 114111308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 114211308Santhony.gutierrez@amd.com if (operandIndex == num_src_operands) 114311308Santhony.gutierrez@amd.com return this->addr.opSize(); 114411308Santhony.gutierrez@amd.com if (num_src_operands > 1) 114511308Santhony.gutierrez@amd.com return src_vect[operandIndex].opSize(); 114611308Santhony.gutierrez@amd.com else if (num_src_operands == 1) 114711308Santhony.gutierrez@amd.com return StInstBase<MemDataType, 114811308Santhony.gutierrez@amd.com typename SrcDataType::OperandType, 114911308Santhony.gutierrez@amd.com AddrOperandType>::src.opSize(); 115011308Santhony.gutierrez@amd.com return 0; 115111308Santhony.gutierrez@amd.com } 115211699Santhony.gutierrez@amd.com int 115311699Santhony.gutierrez@amd.com getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override 115411308Santhony.gutierrez@amd.com { 115511308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 115611308Santhony.gutierrez@amd.com if (operandIndex == num_src_operands) 115711308Santhony.gutierrez@amd.com return this->addr.regIndex(); 115811308Santhony.gutierrez@amd.com if (num_src_operands > 1) 115911308Santhony.gutierrez@amd.com return src_vect[operandIndex].regIndex(); 116011308Santhony.gutierrez@amd.com else if (num_src_operands == 1) 116111308Santhony.gutierrez@amd.com return StInstBase<MemDataType, 116211308Santhony.gutierrez@amd.com typename SrcDataType::OperandType, 116311308Santhony.gutierrez@amd.com AddrOperandType>::src.regIndex(); 116411308Santhony.gutierrez@amd.com return -1; 116511308Santhony.gutierrez@amd.com } 116611347Sandreas.hansson@arm.com int getNumOperands() override 116711308Santhony.gutierrez@amd.com { 116811308Santhony.gutierrez@amd.com if (this->addr.isVectorRegister() || this->addr.isScalarRegister()) 116911308Santhony.gutierrez@amd.com return num_src_operands + 1; 117011308Santhony.gutierrez@amd.com else 117111308Santhony.gutierrez@amd.com return num_src_operands; 117211308Santhony.gutierrez@amd.com } 117311347Sandreas.hansson@arm.com void execute(GPUDynInstPtr gpuDynInst) override; 117411308Santhony.gutierrez@amd.com }; 117511308Santhony.gutierrez@amd.com 117611308Santhony.gutierrez@amd.com template<typename DataType, typename SrcDataType> 117711308Santhony.gutierrez@amd.com GPUStaticInst* 117811308Santhony.gutierrez@amd.com decodeSt(const Brig::BrigInstBase *ib, const BrigObject *obj) 117911308Santhony.gutierrez@amd.com { 118011308Santhony.gutierrez@amd.com int srcIdx = 0; 118111308Santhony.gutierrez@amd.com int destIdx = 1; 118211308Santhony.gutierrez@amd.com if (ib->opcode == Brig::BRIG_OPCODE_ATOMIC || 118311308Santhony.gutierrez@amd.com ib->opcode == Brig::BRIG_OPCODE_ATOMICNORET) { 118411308Santhony.gutierrez@amd.com srcIdx = 1; 118511308Santhony.gutierrez@amd.com destIdx = 0; 118611308Santhony.gutierrez@amd.com } 118711308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands,destIdx); 118811308Santhony.gutierrez@amd.com 118911308Santhony.gutierrez@amd.com BrigRegOperandInfo tmp = findRegDataType(op_offs, obj); 119011308Santhony.gutierrez@amd.com 119111308Santhony.gutierrez@amd.com if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) { 119211308Santhony.gutierrez@amd.com return new StInst<DataType, SrcDataType, 119311308Santhony.gutierrez@amd.com NoRegAddrOperand>(ib, obj, "st", srcIdx); 119411308Santhony.gutierrez@amd.com } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER) { 119511308Santhony.gutierrez@amd.com // V2/V4 not allowed 119611308Santhony.gutierrez@amd.com switch (tmp.regKind) { 119711308Santhony.gutierrez@amd.com case Brig::BRIG_REGISTER_KIND_SINGLE: 119811308Santhony.gutierrez@amd.com return new StInst<DataType, SrcDataType, 119911308Santhony.gutierrez@amd.com SRegAddrOperand>(ib, obj, "st", srcIdx); 120011308Santhony.gutierrez@amd.com case Brig::BRIG_REGISTER_KIND_DOUBLE: 120111308Santhony.gutierrez@amd.com return new StInst<DataType, SrcDataType, 120211308Santhony.gutierrez@amd.com DRegAddrOperand>(ib, obj, "st", srcIdx); 120311308Santhony.gutierrez@amd.com default: 120411308Santhony.gutierrez@amd.com fatal("Bad st register operand type %d\n", tmp.type); 120511308Santhony.gutierrez@amd.com } 120611308Santhony.gutierrez@amd.com } else { 120711308Santhony.gutierrez@amd.com fatal("Bad st register operand kind %d\n", tmp.kind); 120811308Santhony.gutierrez@amd.com } 120911308Santhony.gutierrez@amd.com } 121011308Santhony.gutierrez@amd.com 121111308Santhony.gutierrez@amd.com template<typename OperandType, typename AddrOperandType, int NumSrcOperands, 121211308Santhony.gutierrez@amd.com bool HasDst> 121311308Santhony.gutierrez@amd.com class AtomicInstBase : public HsailGPUStaticInst 121411308Santhony.gutierrez@amd.com { 121511308Santhony.gutierrez@amd.com public: 121611308Santhony.gutierrez@amd.com typename OperandType::DestOperand dest; 121711308Santhony.gutierrez@amd.com typename OperandType::SrcOperand src[NumSrcOperands]; 121811308Santhony.gutierrez@amd.com AddrOperandType addr; 121911308Santhony.gutierrez@amd.com 122011308Santhony.gutierrez@amd.com Brig::BrigSegment segment; 122111308Santhony.gutierrez@amd.com Brig::BrigMemoryOrder memoryOrder; 122211308Santhony.gutierrez@amd.com Brig::BrigAtomicOperation atomicOperation; 122311308Santhony.gutierrez@amd.com Brig::BrigMemoryScope memoryScope; 122411308Santhony.gutierrez@amd.com Brig::BrigOpcode opcode; 122511308Santhony.gutierrez@amd.com 122611308Santhony.gutierrez@amd.com AtomicInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj, 122711308Santhony.gutierrez@amd.com const char *_opcode) 122811308Santhony.gutierrez@amd.com : HsailGPUStaticInst(obj, _opcode) 122911308Santhony.gutierrez@amd.com { 123011308Santhony.gutierrez@amd.com using namespace Brig; 123111308Santhony.gutierrez@amd.com 123211308Santhony.gutierrez@amd.com const BrigInstAtomic *at = (const BrigInstAtomic*)ib; 123311308Santhony.gutierrez@amd.com 123411308Santhony.gutierrez@amd.com segment = (BrigSegment)at->segment; 123511308Santhony.gutierrez@amd.com memoryScope = (BrigMemoryScope)at->memoryScope; 123611308Santhony.gutierrez@amd.com memoryOrder = (BrigMemoryOrder)at->memoryOrder; 123711308Santhony.gutierrez@amd.com atomicOperation = (BrigAtomicOperation)at->atomicOperation; 123811308Santhony.gutierrez@amd.com opcode = (BrigOpcode)ib->opcode; 123911692Santhony.gutierrez@amd.com 124011692Santhony.gutierrez@amd.com assert(opcode == Brig::BRIG_OPCODE_ATOMICNORET || 124111692Santhony.gutierrez@amd.com opcode == Brig::BRIG_OPCODE_ATOMIC); 124211692Santhony.gutierrez@amd.com 124311692Santhony.gutierrez@amd.com setFlag(MemoryRef); 124411692Santhony.gutierrez@amd.com 124511692Santhony.gutierrez@amd.com if (opcode == Brig::BRIG_OPCODE_ATOMIC) { 124611692Santhony.gutierrez@amd.com setFlag(AtomicReturn); 124711692Santhony.gutierrez@amd.com } else { 124811692Santhony.gutierrez@amd.com setFlag(AtomicNoReturn); 124911692Santhony.gutierrez@amd.com } 125011692Santhony.gutierrez@amd.com 125111692Santhony.gutierrez@amd.com switch (memoryOrder) { 125211692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_NONE: 125311692Santhony.gutierrez@amd.com setFlag(NoOrder); 125411692Santhony.gutierrez@amd.com break; 125511692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_RELAXED: 125611692Santhony.gutierrez@amd.com setFlag(RelaxedOrder); 125711692Santhony.gutierrez@amd.com break; 125811692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_SC_ACQUIRE: 125911692Santhony.gutierrez@amd.com setFlag(Acquire); 126011692Santhony.gutierrez@amd.com break; 126111692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_SC_RELEASE: 126211692Santhony.gutierrez@amd.com setFlag(Release); 126311692Santhony.gutierrez@amd.com break; 126411692Santhony.gutierrez@amd.com case BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE: 126511692Santhony.gutierrez@amd.com setFlag(AcquireRelease); 126611692Santhony.gutierrez@amd.com break; 126711692Santhony.gutierrez@amd.com default: 126811692Santhony.gutierrez@amd.com fatal("AtomicInst has bad memory order type\n"); 126911692Santhony.gutierrez@amd.com } 127011692Santhony.gutierrez@amd.com 127111692Santhony.gutierrez@amd.com switch (memoryScope) { 127211692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_NONE: 127311692Santhony.gutierrez@amd.com setFlag(NoScope); 127411692Santhony.gutierrez@amd.com break; 127511692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_WORKITEM: 127611692Santhony.gutierrez@amd.com setFlag(WorkitemScope); 127711692Santhony.gutierrez@amd.com break; 127811692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_WORKGROUP: 127911692Santhony.gutierrez@amd.com setFlag(WorkgroupScope); 128011692Santhony.gutierrez@amd.com break; 128111692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_AGENT: 128211692Santhony.gutierrez@amd.com setFlag(DeviceScope); 128311692Santhony.gutierrez@amd.com break; 128411692Santhony.gutierrez@amd.com case BRIG_MEMORY_SCOPE_SYSTEM: 128511692Santhony.gutierrez@amd.com setFlag(SystemScope); 128611692Santhony.gutierrez@amd.com break; 128711692Santhony.gutierrez@amd.com default: 128811692Santhony.gutierrez@amd.com fatal("AtomicInst has bad memory scope type\n"); 128911692Santhony.gutierrez@amd.com } 129011692Santhony.gutierrez@amd.com 129111692Santhony.gutierrez@amd.com switch (atomicOperation) { 129211692Santhony.gutierrez@amd.com case Brig::BRIG_ATOMIC_AND: 129311692Santhony.gutierrez@amd.com setFlag(AtomicAnd); 129411692Santhony.gutierrez@amd.com break; 129511692Santhony.gutierrez@amd.com case Brig::BRIG_ATOMIC_OR: 129611692Santhony.gutierrez@amd.com setFlag(AtomicOr); 129711692Santhony.gutierrez@amd.com break; 129811692Santhony.gutierrez@amd.com case Brig::BRIG_ATOMIC_XOR: 129911692Santhony.gutierrez@amd.com setFlag(AtomicXor); 130011692Santhony.gutierrez@amd.com break; 130111692Santhony.gutierrez@amd.com case Brig::BRIG_ATOMIC_CAS: 130211692Santhony.gutierrez@amd.com setFlag(AtomicCAS); 130311692Santhony.gutierrez@amd.com break; 130411692Santhony.gutierrez@amd.com case Brig::BRIG_ATOMIC_EXCH: 130511692Santhony.gutierrez@amd.com setFlag(AtomicExch); 130611692Santhony.gutierrez@amd.com break; 130711692Santhony.gutierrez@amd.com case Brig::BRIG_ATOMIC_ADD: 130811692Santhony.gutierrez@amd.com setFlag(AtomicAdd); 130911692Santhony.gutierrez@amd.com break; 131011692Santhony.gutierrez@amd.com case Brig::BRIG_ATOMIC_WRAPINC: 131111692Santhony.gutierrez@amd.com setFlag(AtomicInc); 131211692Santhony.gutierrez@amd.com break; 131311692Santhony.gutierrez@amd.com case Brig::BRIG_ATOMIC_WRAPDEC: 131411692Santhony.gutierrez@amd.com setFlag(AtomicDec); 131511692Santhony.gutierrez@amd.com break; 131611692Santhony.gutierrez@amd.com case Brig::BRIG_ATOMIC_MIN: 131711692Santhony.gutierrez@amd.com setFlag(AtomicMin); 131811692Santhony.gutierrez@amd.com break; 131911692Santhony.gutierrez@amd.com case Brig::BRIG_ATOMIC_MAX: 132011692Santhony.gutierrez@amd.com setFlag(AtomicMax); 132111692Santhony.gutierrez@amd.com break; 132211692Santhony.gutierrez@amd.com case Brig::BRIG_ATOMIC_SUB: 132311692Santhony.gutierrez@amd.com setFlag(AtomicSub); 132411692Santhony.gutierrez@amd.com break; 132511692Santhony.gutierrez@amd.com default: 132611692Santhony.gutierrez@amd.com fatal("Bad BrigAtomicOperation code %d\n", atomicOperation); 132711692Santhony.gutierrez@amd.com } 132811308Santhony.gutierrez@amd.com 132911308Santhony.gutierrez@amd.com switch (segment) { 133011308Santhony.gutierrez@amd.com case BRIG_SEGMENT_GLOBAL: 133111692Santhony.gutierrez@amd.com setFlag(GlobalSegment); 133211308Santhony.gutierrez@amd.com break; 133311308Santhony.gutierrez@amd.com case BRIG_SEGMENT_GROUP: 133411692Santhony.gutierrez@amd.com setFlag(GroupSegment); 133511308Santhony.gutierrez@amd.com break; 133611308Santhony.gutierrez@amd.com case BRIG_SEGMENT_FLAT: 133711692Santhony.gutierrez@amd.com setFlag(Flat); 133811308Santhony.gutierrez@amd.com break; 133911308Santhony.gutierrez@amd.com default: 134011308Santhony.gutierrez@amd.com panic("Atomic: segment %d not supported\n", segment); 134111308Santhony.gutierrez@amd.com } 134211308Santhony.gutierrez@amd.com 134311308Santhony.gutierrez@amd.com if (HasDst) { 134411308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 134511308Santhony.gutierrez@amd.com dest.init(op_offs, obj); 134611308Santhony.gutierrez@amd.com 134711308Santhony.gutierrez@amd.com op_offs = obj->getOperandPtr(ib->operands, 1); 134811308Santhony.gutierrez@amd.com addr.init(op_offs, obj); 134911308Santhony.gutierrez@amd.com 135011308Santhony.gutierrez@amd.com for (int i = 0; i < NumSrcOperands; ++i) { 135111308Santhony.gutierrez@amd.com op_offs = obj->getOperandPtr(ib->operands, i + 2); 135211308Santhony.gutierrez@amd.com src[i].init(op_offs, obj); 135311308Santhony.gutierrez@amd.com } 135411308Santhony.gutierrez@amd.com } else { 135511308Santhony.gutierrez@amd.com 135611308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 135711308Santhony.gutierrez@amd.com addr.init(op_offs, obj); 135811308Santhony.gutierrez@amd.com 135911308Santhony.gutierrez@amd.com for (int i = 0; i < NumSrcOperands; ++i) { 136011308Santhony.gutierrez@amd.com op_offs = obj->getOperandPtr(ib->operands, i + 1); 136111308Santhony.gutierrez@amd.com src[i].init(op_offs, obj); 136211308Santhony.gutierrez@amd.com } 136311308Santhony.gutierrez@amd.com } 136411308Santhony.gutierrez@amd.com } 136511308Santhony.gutierrez@amd.com 136611308Santhony.gutierrez@amd.com int numSrcRegOperands() 136711308Santhony.gutierrez@amd.com { 136811308Santhony.gutierrez@amd.com int operands = 0; 136911308Santhony.gutierrez@amd.com for (int i = 0; i < NumSrcOperands; i++) { 137011325Ssteve.reinhardt@amd.com if (src[i].isVectorRegister()) { 137111308Santhony.gutierrez@amd.com operands++; 137211308Santhony.gutierrez@amd.com } 137311308Santhony.gutierrez@amd.com } 137411308Santhony.gutierrez@amd.com if (addr.isVectorRegister()) 137511308Santhony.gutierrez@amd.com operands++; 137611308Santhony.gutierrez@amd.com return operands; 137711308Santhony.gutierrez@amd.com } 137811308Santhony.gutierrez@amd.com int numDstRegOperands() { return dest.isVectorRegister(); } 137911308Santhony.gutierrez@amd.com int getNumOperands() 138011308Santhony.gutierrez@amd.com { 138111308Santhony.gutierrez@amd.com if (addr.isVectorRegister()) 138211308Santhony.gutierrez@amd.com return(NumSrcOperands + 2); 138311308Santhony.gutierrez@amd.com return(NumSrcOperands + 1); 138411308Santhony.gutierrez@amd.com } 138511308Santhony.gutierrez@amd.com bool isVectorRegister(int operandIndex) 138611308Santhony.gutierrez@amd.com { 138711308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 138811308Santhony.gutierrez@amd.com if (operandIndex < NumSrcOperands) 138911308Santhony.gutierrez@amd.com return src[operandIndex].isVectorRegister(); 139011308Santhony.gutierrez@amd.com else if (operandIndex == NumSrcOperands) 139111308Santhony.gutierrez@amd.com return(addr.isVectorRegister()); 139211308Santhony.gutierrez@amd.com else 139311308Santhony.gutierrez@amd.com return dest.isVectorRegister(); 139411308Santhony.gutierrez@amd.com } 139511308Santhony.gutierrez@amd.com bool isCondRegister(int operandIndex) 139611308Santhony.gutierrez@amd.com { 139711308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 139811308Santhony.gutierrez@amd.com if (operandIndex < NumSrcOperands) 139911308Santhony.gutierrez@amd.com return src[operandIndex].isCondRegister(); 140011308Santhony.gutierrez@amd.com else if (operandIndex == NumSrcOperands) 140111308Santhony.gutierrez@amd.com return(addr.isCondRegister()); 140211308Santhony.gutierrez@amd.com else 140311308Santhony.gutierrez@amd.com return dest.isCondRegister(); 140411308Santhony.gutierrez@amd.com } 140511308Santhony.gutierrez@amd.com bool isScalarRegister(int operandIndex) 140611308Santhony.gutierrez@amd.com { 140711308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 140811308Santhony.gutierrez@amd.com if (operandIndex < NumSrcOperands) 140911308Santhony.gutierrez@amd.com return src[operandIndex].isScalarRegister(); 141011308Santhony.gutierrez@amd.com else if (operandIndex == NumSrcOperands) 141111308Santhony.gutierrez@amd.com return(addr.isScalarRegister()); 141211308Santhony.gutierrez@amd.com else 141311308Santhony.gutierrez@amd.com return dest.isScalarRegister(); 141411308Santhony.gutierrez@amd.com } 141511308Santhony.gutierrez@amd.com bool isSrcOperand(int operandIndex) 141611308Santhony.gutierrez@amd.com { 141711308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 141811308Santhony.gutierrez@amd.com if (operandIndex < NumSrcOperands) 141911308Santhony.gutierrez@amd.com return true; 142011308Santhony.gutierrez@amd.com else if (operandIndex == NumSrcOperands) 142111308Santhony.gutierrez@amd.com return(addr.isVectorRegister()); 142211308Santhony.gutierrez@amd.com else 142311308Santhony.gutierrez@amd.com return false; 142411308Santhony.gutierrez@amd.com } 142511308Santhony.gutierrez@amd.com bool isDstOperand(int operandIndex) 142611308Santhony.gutierrez@amd.com { 142711308Santhony.gutierrez@amd.com if (operandIndex <= NumSrcOperands) 142811308Santhony.gutierrez@amd.com return false; 142911308Santhony.gutierrez@amd.com else 143011308Santhony.gutierrez@amd.com return true; 143111308Santhony.gutierrez@amd.com } 143211308Santhony.gutierrez@amd.com int getOperandSize(int operandIndex) 143311308Santhony.gutierrez@amd.com { 143411308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 143511308Santhony.gutierrez@amd.com if (operandIndex < NumSrcOperands) 143611308Santhony.gutierrez@amd.com return(src[operandIndex].opSize()); 143711308Santhony.gutierrez@amd.com else if (operandIndex == NumSrcOperands) 143811308Santhony.gutierrez@amd.com return(addr.opSize()); 143911308Santhony.gutierrez@amd.com else 144011308Santhony.gutierrez@amd.com return(dest.opSize()); 144111308Santhony.gutierrez@amd.com } 144211699Santhony.gutierrez@amd.com int 144311699Santhony.gutierrez@amd.com getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) 144411308Santhony.gutierrez@amd.com { 144511308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 144611308Santhony.gutierrez@amd.com if (operandIndex < NumSrcOperands) 144711308Santhony.gutierrez@amd.com return(src[operandIndex].regIndex()); 144811308Santhony.gutierrez@amd.com else if (operandIndex == NumSrcOperands) 144911308Santhony.gutierrez@amd.com return(addr.regIndex()); 145011308Santhony.gutierrez@amd.com else 145111308Santhony.gutierrez@amd.com return(dest.regIndex()); 145211308Santhony.gutierrez@amd.com return -1; 145311308Santhony.gutierrez@amd.com } 145411308Santhony.gutierrez@amd.com }; 145511308Santhony.gutierrez@amd.com 145611308Santhony.gutierrez@amd.com template<typename MemDataType, typename AddrOperandType, int NumSrcOperands, 145711308Santhony.gutierrez@amd.com bool HasDst> 145811308Santhony.gutierrez@amd.com class AtomicInst : 145911308Santhony.gutierrez@amd.com public AtomicInstBase<typename MemDataType::OperandType, 146011308Santhony.gutierrez@amd.com AddrOperandType, NumSrcOperands, HasDst>, 146111308Santhony.gutierrez@amd.com public MemInst 146211308Santhony.gutierrez@amd.com { 146311308Santhony.gutierrez@amd.com public: 146411347Sandreas.hansson@arm.com void generateDisassembly() override; 146511308Santhony.gutierrez@amd.com 146611308Santhony.gutierrez@amd.com AtomicInst(const Brig::BrigInstBase *ib, const BrigObject *obj, 146711308Santhony.gutierrez@amd.com const char *_opcode) 146811308Santhony.gutierrez@amd.com : AtomicInstBase<typename MemDataType::OperandType, AddrOperandType, 146911308Santhony.gutierrez@amd.com NumSrcOperands, HasDst> 147011308Santhony.gutierrez@amd.com (ib, obj, _opcode), 147111308Santhony.gutierrez@amd.com MemInst(MemDataType::memType) 147211308Santhony.gutierrez@amd.com { 147311308Santhony.gutierrez@amd.com init_addr(&this->addr); 147411308Santhony.gutierrez@amd.com } 147511308Santhony.gutierrez@amd.com 147611308Santhony.gutierrez@amd.com void 147711308Santhony.gutierrez@amd.com initiateAcc(GPUDynInstPtr gpuDynInst) override 147811308Santhony.gutierrez@amd.com { 147911308Santhony.gutierrez@amd.com // before doing the RMW, check if this atomic has 148011308Santhony.gutierrez@amd.com // release semantics, and if so issue a release first 148111692Santhony.gutierrez@amd.com if (!this->isLocalMem()) { 148211308Santhony.gutierrez@amd.com if (gpuDynInst->computeUnit()->shader->separate_acquire_release 148311692Santhony.gutierrez@amd.com && (gpuDynInst->isRelease() 148411692Santhony.gutierrez@amd.com || gpuDynInst->isAcquireRelease())) { 148511308Santhony.gutierrez@amd.com 148611308Santhony.gutierrez@amd.com gpuDynInst->statusBitVector = VectorMask(1); 148711308Santhony.gutierrez@amd.com 148811308Santhony.gutierrez@amd.com gpuDynInst->execContinuation = &GPUStaticInst::execAtomic; 148911308Santhony.gutierrez@amd.com gpuDynInst->useContinuation = true; 149011308Santhony.gutierrez@amd.com 149111308Santhony.gutierrez@amd.com // create request 149212749Sgiacomo.travaglini@arm.com RequestPtr req = std::make_shared<Request>(0, 0, 0, 0, 149311308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->masterId(), 149411435Smitch.hayenga@arm.com 0, gpuDynInst->wfDynId); 149511308Santhony.gutierrez@amd.com req->setFlags(Request::RELEASE); 149611308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req); 149711308Santhony.gutierrez@amd.com 149811308Santhony.gutierrez@amd.com return; 149911308Santhony.gutierrez@amd.com } 150011308Santhony.gutierrez@amd.com } 150111308Santhony.gutierrez@amd.com 150211308Santhony.gutierrez@amd.com // if there is no release semantic, execute the RMW immediately 150311308Santhony.gutierrez@amd.com execAtomic(gpuDynInst); 150411308Santhony.gutierrez@amd.com 150511308Santhony.gutierrez@amd.com } 150611308Santhony.gutierrez@amd.com 150711693Santhony.gutierrez@amd.com void 150811693Santhony.gutierrez@amd.com completeAcc(GPUDynInstPtr gpuDynInst) override 150911693Santhony.gutierrez@amd.com { 151011693Santhony.gutierrez@amd.com // if this is not an atomic return op, then we 151111693Santhony.gutierrez@amd.com // have nothing more to do. 151211693Santhony.gutierrez@amd.com if (this->isAtomicRet()) { 151311693Santhony.gutierrez@amd.com // the size of the src operands and the 151411693Santhony.gutierrez@amd.com // memory being operated on must match 151511693Santhony.gutierrez@amd.com // for HSAIL atomics - this assumption may 151611693Santhony.gutierrez@amd.com // not apply to all ISAs 151711693Santhony.gutierrez@amd.com typedef typename MemDataType::CType CType; 151811693Santhony.gutierrez@amd.com 151911693Santhony.gutierrez@amd.com Wavefront *w = gpuDynInst->wavefront(); 152011693Santhony.gutierrez@amd.com int dst = this->dest.regIndex(); 152111693Santhony.gutierrez@amd.com std::vector<uint32_t> regVec; 152211693Santhony.gutierrez@amd.com // virtual->physical VGPR mapping 152311693Santhony.gutierrez@amd.com int physVgpr = w->remap(dst, sizeof(CType), 1); 152411693Santhony.gutierrez@amd.com regVec.push_back(physVgpr); 152511693Santhony.gutierrez@amd.com CType *p1 = &((CType*)gpuDynInst->d_data)[0]; 152611693Santhony.gutierrez@amd.com 152711693Santhony.gutierrez@amd.com for (int i = 0; i < w->computeUnit->wfSize(); ++i) { 152811693Santhony.gutierrez@amd.com if (gpuDynInst->exec_mask[i]) { 152911693Santhony.gutierrez@amd.com DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: " 153011693Santhony.gutierrez@amd.com "$%s%d <- %d global ld done (src = wavefront " 153111693Santhony.gutierrez@amd.com "ld inst)\n", w->computeUnit->cu_id, w->simdId, 153211693Santhony.gutierrez@amd.com w->wfSlotId, i, sizeof(CType) == 4 ? "s" : "d", 153311693Santhony.gutierrez@amd.com dst, *p1); 153411693Santhony.gutierrez@amd.com // write the value into the physical VGPR. This is a 153511693Santhony.gutierrez@amd.com // purely functional operation. No timing is modeled. 153611693Santhony.gutierrez@amd.com w->computeUnit->vrf[w->simdId]->write<CType>(physVgpr, *p1, i); 153711693Santhony.gutierrez@amd.com } 153811693Santhony.gutierrez@amd.com ++p1; 153911693Santhony.gutierrez@amd.com } 154011693Santhony.gutierrez@amd.com 154111693Santhony.gutierrez@amd.com // Schedule the write operation of the load data on the VRF. 154211693Santhony.gutierrez@amd.com // This simply models the timing aspect of the VRF write operation. 154311693Santhony.gutierrez@amd.com // It does not modify the physical VGPR. 154411693Santhony.gutierrez@amd.com int loadVrfBankConflictCycles = gpuDynInst->computeUnit()-> 154511693Santhony.gutierrez@amd.com vrf[w->simdId]->exec(gpuDynInst->seqNum(), w, regVec, 154611693Santhony.gutierrez@amd.com sizeof(CType), gpuDynInst->time); 154711693Santhony.gutierrez@amd.com 154811693Santhony.gutierrez@amd.com if (this->isGlobalMem()) { 154911693Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->globalMemoryPipe 155011693Santhony.gutierrez@amd.com .incLoadVRFBankConflictCycles(loadVrfBankConflictCycles); 155111693Santhony.gutierrez@amd.com } else { 155211693Santhony.gutierrez@amd.com assert(this->isLocalMem()); 155311693Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->localMemoryPipe 155411693Santhony.gutierrez@amd.com .incLoadVRFBankConflictCycles(loadVrfBankConflictCycles); 155511693Santhony.gutierrez@amd.com } 155611693Santhony.gutierrez@amd.com } 155711693Santhony.gutierrez@amd.com } 155811693Santhony.gutierrez@amd.com 155911347Sandreas.hansson@arm.com void execute(GPUDynInstPtr gpuDynInst) override; 156011308Santhony.gutierrez@amd.com 156111308Santhony.gutierrez@amd.com private: 156211308Santhony.gutierrez@amd.com // execAtomic may be called through a continuation 156311308Santhony.gutierrez@amd.com // if the RMW had release semantics. see comment for 156411308Santhony.gutierrez@amd.com // execContinuation in gpu_dyn_inst.hh 156511308Santhony.gutierrez@amd.com void 156611308Santhony.gutierrez@amd.com execAtomic(GPUDynInstPtr gpuDynInst) override 156711308Santhony.gutierrez@amd.com { 156811308Santhony.gutierrez@amd.com gpuDynInst->statusBitVector = gpuDynInst->exec_mask; 156911308Santhony.gutierrez@amd.com 157011308Santhony.gutierrez@amd.com typedef typename MemDataType::CType c0; 157111308Santhony.gutierrez@amd.com 157211308Santhony.gutierrez@amd.com c0 *d = &((c0*) gpuDynInst->d_data)[0]; 157311308Santhony.gutierrez@amd.com c0 *e = &((c0*) gpuDynInst->a_data)[0]; 157411308Santhony.gutierrez@amd.com c0 *f = &((c0*) gpuDynInst->x_data)[0]; 157511308Santhony.gutierrez@amd.com 157611534Sjohn.kalamatianos@amd.com for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) { 157711308Santhony.gutierrez@amd.com if (gpuDynInst->exec_mask[i]) { 157811308Santhony.gutierrez@amd.com Addr vaddr = gpuDynInst->addr[i]; 157911308Santhony.gutierrez@amd.com 158011692Santhony.gutierrez@amd.com if (this->isLocalMem()) { 158111308Santhony.gutierrez@amd.com Wavefront *wavefront = gpuDynInst->wavefront(); 158211308Santhony.gutierrez@amd.com *d = wavefront->ldsChunk->read<c0>(vaddr); 158311308Santhony.gutierrez@amd.com 158411692Santhony.gutierrez@amd.com if (this->isAtomicAdd()) { 158511308Santhony.gutierrez@amd.com wavefront->ldsChunk->write<c0>(vaddr, 158611308Santhony.gutierrez@amd.com wavefront->ldsChunk->read<c0>(vaddr) + (*e)); 158711692Santhony.gutierrez@amd.com } else if (this->isAtomicSub()) { 158811308Santhony.gutierrez@amd.com wavefront->ldsChunk->write<c0>(vaddr, 158911308Santhony.gutierrez@amd.com wavefront->ldsChunk->read<c0>(vaddr) - (*e)); 159011692Santhony.gutierrez@amd.com } else if (this->isAtomicMax()) { 159111308Santhony.gutierrez@amd.com wavefront->ldsChunk->write<c0>(vaddr, 159211308Santhony.gutierrez@amd.com std::max(wavefront->ldsChunk->read<c0>(vaddr), 159311308Santhony.gutierrez@amd.com (*e))); 159411692Santhony.gutierrez@amd.com } else if (this->isAtomicMin()) { 159511308Santhony.gutierrez@amd.com wavefront->ldsChunk->write<c0>(vaddr, 159611308Santhony.gutierrez@amd.com std::min(wavefront->ldsChunk->read<c0>(vaddr), 159711308Santhony.gutierrez@amd.com (*e))); 159811692Santhony.gutierrez@amd.com } else if (this->isAtomicAnd()) { 159911308Santhony.gutierrez@amd.com wavefront->ldsChunk->write<c0>(vaddr, 160011308Santhony.gutierrez@amd.com wavefront->ldsChunk->read<c0>(vaddr) & (*e)); 160111692Santhony.gutierrez@amd.com } else if (this->isAtomicOr()) { 160211308Santhony.gutierrez@amd.com wavefront->ldsChunk->write<c0>(vaddr, 160311308Santhony.gutierrez@amd.com wavefront->ldsChunk->read<c0>(vaddr) | (*e)); 160411692Santhony.gutierrez@amd.com } else if (this->isAtomicXor()) { 160511308Santhony.gutierrez@amd.com wavefront->ldsChunk->write<c0>(vaddr, 160611308Santhony.gutierrez@amd.com wavefront->ldsChunk->read<c0>(vaddr) ^ (*e)); 160711692Santhony.gutierrez@amd.com } else if (this->isAtomicInc()) { 160811308Santhony.gutierrez@amd.com wavefront->ldsChunk->write<c0>(vaddr, 160911308Santhony.gutierrez@amd.com wavefront->ldsChunk->read<c0>(vaddr) + 1); 161011692Santhony.gutierrez@amd.com } else if (this->isAtomicDec()) { 161111308Santhony.gutierrez@amd.com wavefront->ldsChunk->write<c0>(vaddr, 161211308Santhony.gutierrez@amd.com wavefront->ldsChunk->read<c0>(vaddr) - 1); 161311692Santhony.gutierrez@amd.com } else if (this->isAtomicExch()) { 161411308Santhony.gutierrez@amd.com wavefront->ldsChunk->write<c0>(vaddr, (*e)); 161511692Santhony.gutierrez@amd.com } else if (this->isAtomicCAS()) { 161611308Santhony.gutierrez@amd.com wavefront->ldsChunk->write<c0>(vaddr, 161711308Santhony.gutierrez@amd.com (wavefront->ldsChunk->read<c0>(vaddr) == (*e)) ? 161811308Santhony.gutierrez@amd.com (*f) : wavefront->ldsChunk->read<c0>(vaddr)); 161911692Santhony.gutierrez@amd.com } else { 162011308Santhony.gutierrez@amd.com fatal("Unrecognized or invalid HSAIL atomic op " 162111308Santhony.gutierrez@amd.com "type.\n"); 162211308Santhony.gutierrez@amd.com } 162311308Santhony.gutierrez@amd.com } else { 162412748Sgiacomo.travaglini@arm.com RequestPtr req = 162512749Sgiacomo.travaglini@arm.com std::make_shared<Request>(0, vaddr, sizeof(c0), 0, 162611308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->masterId(), 162711435Smitch.hayenga@arm.com 0, gpuDynInst->wfDynId, 162811308Santhony.gutierrez@amd.com gpuDynInst->makeAtomicOpFunctor<c0>(e, 162911692Santhony.gutierrez@amd.com f)); 163011308Santhony.gutierrez@amd.com 163111308Santhony.gutierrez@amd.com gpuDynInst->setRequestFlags(req); 163211308Santhony.gutierrez@amd.com PacketPtr pkt = new Packet(req, MemCmd::SwapReq); 163311308Santhony.gutierrez@amd.com pkt->dataStatic(d); 163411308Santhony.gutierrez@amd.com 163511308Santhony.gutierrez@amd.com if (gpuDynInst->computeUnit()->shader-> 163611308Santhony.gutierrez@amd.com separate_acquire_release && 163711692Santhony.gutierrez@amd.com (gpuDynInst->isAcquire())) { 163811308Santhony.gutierrez@amd.com // if this atomic has acquire semantics, 163911308Santhony.gutierrez@amd.com // schedule the continuation to perform an 164011308Santhony.gutierrez@amd.com // acquire after the RMW completes 164111308Santhony.gutierrez@amd.com gpuDynInst->execContinuation = 164211308Santhony.gutierrez@amd.com &GPUStaticInst::execAtomicAcq; 164311308Santhony.gutierrez@amd.com 164411308Santhony.gutierrez@amd.com gpuDynInst->useContinuation = true; 164511308Santhony.gutierrez@amd.com } else { 164611308Santhony.gutierrez@amd.com // the request will be finished when the RMW completes 164711308Santhony.gutierrez@amd.com gpuDynInst->useContinuation = false; 164811308Santhony.gutierrez@amd.com } 164911308Santhony.gutierrez@amd.com // translation is performed in sendRequest() 165011308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->sendRequest(gpuDynInst, i, 165111308Santhony.gutierrez@amd.com pkt); 165211308Santhony.gutierrez@amd.com } 165311308Santhony.gutierrez@amd.com } 165411308Santhony.gutierrez@amd.com 165511308Santhony.gutierrez@amd.com ++d; 165611308Santhony.gutierrez@amd.com ++e; 165711308Santhony.gutierrez@amd.com ++f; 165811308Santhony.gutierrez@amd.com } 165911308Santhony.gutierrez@amd.com 166011308Santhony.gutierrez@amd.com gpuDynInst->updateStats(); 166111308Santhony.gutierrez@amd.com } 166211308Santhony.gutierrez@amd.com 166311308Santhony.gutierrez@amd.com // execAtomicACq will always be called through a continuation. 166411308Santhony.gutierrez@amd.com // see comment for execContinuation in gpu_dyn_inst.hh 166511308Santhony.gutierrez@amd.com void 166611308Santhony.gutierrez@amd.com execAtomicAcq(GPUDynInstPtr gpuDynInst) override 166711308Santhony.gutierrez@amd.com { 166811308Santhony.gutierrez@amd.com // after performing the RMW, check to see if this instruction 166911308Santhony.gutierrez@amd.com // has acquire semantics, and if so, issue an acquire 167011692Santhony.gutierrez@amd.com if (!this->isLocalMem()) { 167111308Santhony.gutierrez@amd.com if (gpuDynInst->computeUnit()->shader->separate_acquire_release 167211692Santhony.gutierrez@amd.com && gpuDynInst->isAcquire()) { 167311308Santhony.gutierrez@amd.com gpuDynInst->statusBitVector = VectorMask(1); 167411308Santhony.gutierrez@amd.com 167511308Santhony.gutierrez@amd.com // the request will be finished when 167611308Santhony.gutierrez@amd.com // the acquire completes 167711308Santhony.gutierrez@amd.com gpuDynInst->useContinuation = false; 167811308Santhony.gutierrez@amd.com // create request 167912749Sgiacomo.travaglini@arm.com RequestPtr req = std::make_shared<Request>(0, 0, 0, 0, 168011308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->masterId(), 168111435Smitch.hayenga@arm.com 0, gpuDynInst->wfDynId); 168211308Santhony.gutierrez@amd.com req->setFlags(Request::ACQUIRE); 168311308Santhony.gutierrez@amd.com gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req); 168411308Santhony.gutierrez@amd.com } 168511308Santhony.gutierrez@amd.com } 168611308Santhony.gutierrez@amd.com } 168711308Santhony.gutierrez@amd.com }; 168811308Santhony.gutierrez@amd.com 168911308Santhony.gutierrez@amd.com template<typename DataType, typename AddrOperandType, int NumSrcOperands> 169011308Santhony.gutierrez@amd.com GPUStaticInst* 169111308Santhony.gutierrez@amd.com constructAtomic(const Brig::BrigInstBase *ib, const BrigObject *obj) 169211308Santhony.gutierrez@amd.com { 169311308Santhony.gutierrez@amd.com const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib; 169411308Santhony.gutierrez@amd.com 169511308Santhony.gutierrez@amd.com if (at->atomicOperation == Brig::BRIG_ATOMIC_LD) { 169611308Santhony.gutierrez@amd.com return decodeLd<DataType>(ib, obj); 169711308Santhony.gutierrez@amd.com } else if (at->atomicOperation == Brig::BRIG_ATOMIC_ST) { 169811308Santhony.gutierrez@amd.com switch (ib->type) { 169911308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_B8: 170011308Santhony.gutierrez@amd.com return decodeSt<S8,S8>(ib, obj); 170111308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_B16: 170211536Staquangtuan1992@gmail.com return decodeSt<S16,S16>(ib, obj); 170311308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_B32: 170411536Staquangtuan1992@gmail.com return decodeSt<S32,S32>(ib, obj); 170511308Santhony.gutierrez@amd.com case Brig::BRIG_TYPE_B64: 170611536Staquangtuan1992@gmail.com return decodeSt<S64,S64>(ib, obj); 170711308Santhony.gutierrez@amd.com default: fatal("AtomicSt: Operand type mismatch %d\n", ib->type); 170811308Santhony.gutierrez@amd.com } 170911308Santhony.gutierrez@amd.com } else { 171011308Santhony.gutierrez@amd.com if ((Brig::BrigOpcode)ib->opcode == Brig::BRIG_OPCODE_ATOMICNORET) 171111308Santhony.gutierrez@amd.com return new AtomicInst<DataType, AddrOperandType, 171211308Santhony.gutierrez@amd.com NumSrcOperands, false>(ib, obj, "atomicnoret"); 171311308Santhony.gutierrez@amd.com else 171411308Santhony.gutierrez@amd.com return new AtomicInst<DataType, AddrOperandType, 171511308Santhony.gutierrez@amd.com NumSrcOperands, true>(ib, obj, "atomic"); 171611308Santhony.gutierrez@amd.com } 171711308Santhony.gutierrez@amd.com } 171811308Santhony.gutierrez@amd.com 171911308Santhony.gutierrez@amd.com template<typename DataType, int NumSrcOperands> 172011308Santhony.gutierrez@amd.com GPUStaticInst* 172111308Santhony.gutierrez@amd.com decodeAtomicHelper(const Brig::BrigInstBase *ib, const BrigObject *obj) 172211308Santhony.gutierrez@amd.com { 172311308Santhony.gutierrez@amd.com unsigned addrIndex = (Brig::BrigOpcode)ib->opcode == 172411308Santhony.gutierrez@amd.com Brig::BRIG_OPCODE_ATOMICNORET ? 0 : 1; 172511308Santhony.gutierrez@amd.com 172611308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands,addrIndex); 172711308Santhony.gutierrez@amd.com 172811308Santhony.gutierrez@amd.com BrigRegOperandInfo tmp = findRegDataType(op_offs, obj); 172911308Santhony.gutierrez@amd.com 173011308Santhony.gutierrez@amd.com if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) { 173111308Santhony.gutierrez@amd.com return constructAtomic<DataType, NoRegAddrOperand, 173211308Santhony.gutierrez@amd.com NumSrcOperands>(ib, obj); 173311308Santhony.gutierrez@amd.com } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER) { 173411308Santhony.gutierrez@amd.com // V2/V4 not allowed 173511308Santhony.gutierrez@amd.com switch (tmp.regKind) { 173611308Santhony.gutierrez@amd.com case Brig::BRIG_REGISTER_KIND_SINGLE: 173711308Santhony.gutierrez@amd.com return constructAtomic<DataType, SRegAddrOperand, 173811308Santhony.gutierrez@amd.com NumSrcOperands>(ib, obj); 173911308Santhony.gutierrez@amd.com case Brig::BRIG_REGISTER_KIND_DOUBLE: 174011308Santhony.gutierrez@amd.com return constructAtomic<DataType, DRegAddrOperand, 174111308Santhony.gutierrez@amd.com NumSrcOperands>(ib, obj); 174211308Santhony.gutierrez@amd.com default: 174311308Santhony.gutierrez@amd.com fatal("Bad atomic register operand type %d\n", tmp.type); 174411308Santhony.gutierrez@amd.com } 174511308Santhony.gutierrez@amd.com } else { 174611308Santhony.gutierrez@amd.com fatal("Bad atomic register operand kind %d\n", tmp.kind); 174711308Santhony.gutierrez@amd.com } 174811308Santhony.gutierrez@amd.com } 174911308Santhony.gutierrez@amd.com 175011308Santhony.gutierrez@amd.com 175111308Santhony.gutierrez@amd.com template<typename DataType> 175211308Santhony.gutierrez@amd.com GPUStaticInst* 175311308Santhony.gutierrez@amd.com decodeAtomic(const Brig::BrigInstBase *ib, const BrigObject *obj) 175411308Santhony.gutierrez@amd.com { 175511308Santhony.gutierrez@amd.com const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib; 175611308Santhony.gutierrez@amd.com 175711308Santhony.gutierrez@amd.com if (at->atomicOperation == Brig::BRIG_ATOMIC_CAS) { 175811308Santhony.gutierrez@amd.com return decodeAtomicHelper<DataType, 2>(ib, obj); 175911308Santhony.gutierrez@amd.com } else { 176011308Santhony.gutierrez@amd.com return decodeAtomicHelper<DataType, 1>(ib, obj); 176111308Santhony.gutierrez@amd.com } 176211308Santhony.gutierrez@amd.com } 176311308Santhony.gutierrez@amd.com 176411308Santhony.gutierrez@amd.com template<typename DataType> 176511308Santhony.gutierrez@amd.com GPUStaticInst* 176611308Santhony.gutierrez@amd.com decodeAtomicNoRet(const Brig::BrigInstBase *ib, const BrigObject *obj) 176711308Santhony.gutierrez@amd.com { 176811308Santhony.gutierrez@amd.com const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib; 176911308Santhony.gutierrez@amd.com if (at->atomicOperation == Brig::BRIG_ATOMIC_CAS) { 177011308Santhony.gutierrez@amd.com return decodeAtomicHelper<DataType, 2>(ib, obj); 177111308Santhony.gutierrez@amd.com } else { 177211308Santhony.gutierrez@amd.com return decodeAtomicHelper<DataType, 1>(ib, obj); 177311308Santhony.gutierrez@amd.com } 177411308Santhony.gutierrez@amd.com } 177511308Santhony.gutierrez@amd.com} // namespace HsailISA 177611308Santhony.gutierrez@amd.com 177711308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_MEM_HH__ 1778