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