mem.hh revision 11693
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        }
14911347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
15011308Santhony.gutierrez@amd.com        {
15111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
15211308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.regIndex() :
15311308Santhony.gutierrez@amd.com                   this->addr.regIndex());
15411308Santhony.gutierrez@amd.com        }
15511347Sandreas.hansson@arm.com        int getNumOperands() override
15611308Santhony.gutierrez@amd.com        {
15711308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister())
15811308Santhony.gutierrez@amd.com                return 2;
15911308Santhony.gutierrez@amd.com            return 1;
16011308Santhony.gutierrez@amd.com        }
16111308Santhony.gutierrez@amd.com    };
16211308Santhony.gutierrez@amd.com
16311308Santhony.gutierrez@amd.com    template<typename DestDataType, typename AddrOperandType>
16411308Santhony.gutierrez@amd.com    class LdaInst :
16511308Santhony.gutierrez@amd.com        public LdaInstBase<typename DestDataType::OperandType, AddrOperandType>,
16611308Santhony.gutierrez@amd.com        public MemInst
16711308Santhony.gutierrez@amd.com    {
16811308Santhony.gutierrez@amd.com      public:
16911308Santhony.gutierrez@amd.com        void generateDisassembly();
17011308Santhony.gutierrez@amd.com
17111308Santhony.gutierrez@amd.com        LdaInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
17211308Santhony.gutierrez@amd.com                        const char *_opcode)
17311308Santhony.gutierrez@amd.com            : LdaInstBase<typename DestDataType::OperandType,
17411308Santhony.gutierrez@amd.com                          AddrOperandType>(ib, obj, _opcode)
17511308Santhony.gutierrez@amd.com        {
17611308Santhony.gutierrez@amd.com            init_addr(&this->addr);
17711308Santhony.gutierrez@amd.com        }
17811308Santhony.gutierrez@amd.com
17911308Santhony.gutierrez@amd.com        void execute(GPUDynInstPtr gpuDynInst);
18011308Santhony.gutierrez@amd.com    };
18111308Santhony.gutierrez@amd.com
18211308Santhony.gutierrez@amd.com    template<typename DataType>
18311308Santhony.gutierrez@amd.com    GPUStaticInst*
18411308Santhony.gutierrez@amd.com    decodeLda(const Brig::BrigInstBase *ib, const BrigObject *obj)
18511308Santhony.gutierrez@amd.com    {
18611308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands, 1);
18711308Santhony.gutierrez@amd.com        BrigRegOperandInfo regDataType = findRegDataType(op_offs, obj);
18811308Santhony.gutierrez@amd.com
18911308Santhony.gutierrez@amd.com        if (regDataType.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
19011308Santhony.gutierrez@amd.com            return new LdaInst<DataType, NoRegAddrOperand>(ib, obj, "ldas");
19111308Santhony.gutierrez@amd.com        } else if (regDataType.kind == Brig::BRIG_KIND_OPERAND_REGISTER) {
19211308Santhony.gutierrez@amd.com            // V2/V4 not allowed
19311308Santhony.gutierrez@amd.com            switch (regDataType.regKind) {
19411308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
19511308Santhony.gutierrez@amd.com                return new LdaInst<DataType, SRegAddrOperand>(ib, obj, "ldas");
19611308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
19711308Santhony.gutierrez@amd.com                return new LdaInst<DataType, DRegAddrOperand>(ib, obj, "ldas");
19811308Santhony.gutierrez@amd.com              default:
19911308Santhony.gutierrez@amd.com                fatal("Bad ldas register operand type %d\n", regDataType.type);
20011308Santhony.gutierrez@amd.com            }
20111308Santhony.gutierrez@amd.com        } else {
20211308Santhony.gutierrez@amd.com            fatal("Bad ldas register operand kind %d\n", regDataType.kind);
20311308Santhony.gutierrez@amd.com        }
20411308Santhony.gutierrez@amd.com    }
20511308Santhony.gutierrez@amd.com
20611308Santhony.gutierrez@amd.com    template<typename MemOperandType, typename DestOperandType,
20711308Santhony.gutierrez@amd.com             typename AddrOperandType>
20811308Santhony.gutierrez@amd.com    class LdInstBase : public HsailGPUStaticInst
20911308Santhony.gutierrez@amd.com    {
21011308Santhony.gutierrez@amd.com      public:
21111308Santhony.gutierrez@amd.com        Brig::BrigWidth8_t width;
21211308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
21311308Santhony.gutierrez@amd.com        AddrOperandType addr;
21411308Santhony.gutierrez@amd.com
21511308Santhony.gutierrez@amd.com        Brig::BrigSegment segment;
21611308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memoryOrder;
21711308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memoryScope;
21811308Santhony.gutierrez@amd.com        unsigned int equivClass;
21911308Santhony.gutierrez@amd.com
22011308Santhony.gutierrez@amd.com        LdInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
22111308Santhony.gutierrez@amd.com                   const char *_opcode)
22211308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
22311308Santhony.gutierrez@amd.com        {
22411308Santhony.gutierrez@amd.com            using namespace Brig;
22511308Santhony.gutierrez@amd.com
22611692Santhony.gutierrez@amd.com            setFlag(MemoryRef);
22711692Santhony.gutierrez@amd.com            setFlag(Load);
22811692Santhony.gutierrez@amd.com
22911308Santhony.gutierrez@amd.com            if (ib->opcode == BRIG_OPCODE_LD) {
23011692Santhony.gutierrez@amd.com                const BrigInstMem *ldst = (const BrigInstMem*)ib;
23111692Santhony.gutierrez@amd.com
23211692Santhony.gutierrez@amd.com                segment = (BrigSegment)ldst->segment;
23311692Santhony.gutierrez@amd.com                memoryOrder = BRIG_MEMORY_ORDER_NONE;
23411692Santhony.gutierrez@amd.com                memoryScope = BRIG_MEMORY_SCOPE_NONE;
23511692Santhony.gutierrez@amd.com                equivClass = ldst->equivClass;
23611692Santhony.gutierrez@amd.com
23711692Santhony.gutierrez@amd.com                width = ldst->width;
23811692Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
23911692Santhony.gutierrez@amd.com                const Brig::BrigOperand *brigOp = obj->getOperand(op_offs);
24011692Santhony.gutierrez@amd.com                if (brigOp->kind == BRIG_KIND_OPERAND_REGISTER)
24111692Santhony.gutierrez@amd.com                    dest.init(op_offs, obj);
24211692Santhony.gutierrez@amd.com
24311692Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands, 1);
24411692Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
24511308Santhony.gutierrez@amd.com            } else {
24611692Santhony.gutierrez@amd.com                const BrigInstAtomic *at = (const BrigInstAtomic*)ib;
24711692Santhony.gutierrez@amd.com
24811692Santhony.gutierrez@amd.com                segment = (BrigSegment)at->segment;
24911692Santhony.gutierrez@amd.com                memoryOrder = (BrigMemoryOrder)at->memoryOrder;
25011692Santhony.gutierrez@amd.com                memoryScope = (BrigMemoryScope)at->memoryScope;
25111692Santhony.gutierrez@amd.com                equivClass = 0;
25211692Santhony.gutierrez@amd.com
25311692Santhony.gutierrez@amd.com                width = BRIG_WIDTH_1;
25411692Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
25511692Santhony.gutierrez@amd.com                const Brig::BrigOperand *brigOp = obj->getOperand(op_offs);
25611692Santhony.gutierrez@amd.com
25711692Santhony.gutierrez@amd.com                if (brigOp->kind == BRIG_KIND_OPERAND_REGISTER)
25811692Santhony.gutierrez@amd.com                    dest.init(op_offs, obj);
25911692Santhony.gutierrez@amd.com
26011692Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands,1);
26111692Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
26211692Santhony.gutierrez@amd.com            }
26311692Santhony.gutierrez@amd.com
26411692Santhony.gutierrez@amd.com            switch (memoryOrder) {
26511692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_NONE:
26611692Santhony.gutierrez@amd.com                setFlag(NoOrder);
26711692Santhony.gutierrez@amd.com                break;
26811692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_RELAXED:
26911692Santhony.gutierrez@amd.com                setFlag(RelaxedOrder);
27011692Santhony.gutierrez@amd.com                break;
27111692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE:
27211692Santhony.gutierrez@amd.com                setFlag(Acquire);
27311692Santhony.gutierrez@amd.com                break;
27411692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_RELEASE:
27511692Santhony.gutierrez@amd.com                setFlag(Release);
27611692Santhony.gutierrez@amd.com                break;
27711692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE:
27811692Santhony.gutierrez@amd.com                setFlag(AcquireRelease);
27911692Santhony.gutierrez@amd.com                break;
28011692Santhony.gutierrez@amd.com              default:
28111692Santhony.gutierrez@amd.com                fatal("LdInst has bad memory order type\n");
28211692Santhony.gutierrez@amd.com            }
28311692Santhony.gutierrez@amd.com
28411692Santhony.gutierrez@amd.com            switch (memoryScope) {
28511692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_NONE:
28611692Santhony.gutierrez@amd.com                setFlag(NoScope);
28711692Santhony.gutierrez@amd.com                break;
28811692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKITEM:
28911692Santhony.gutierrez@amd.com                setFlag(WorkitemScope);
29011692Santhony.gutierrez@amd.com                break;
29111692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKGROUP:
29211692Santhony.gutierrez@amd.com                setFlag(WorkgroupScope);
29311692Santhony.gutierrez@amd.com                break;
29411692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_AGENT:
29511692Santhony.gutierrez@amd.com                setFlag(DeviceScope);
29611692Santhony.gutierrez@amd.com                break;
29711692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_SYSTEM:
29811692Santhony.gutierrez@amd.com                setFlag(SystemScope);
29911692Santhony.gutierrez@amd.com                break;
30011692Santhony.gutierrez@amd.com              default:
30111692Santhony.gutierrez@amd.com                fatal("LdInst has bad memory scope type\n");
30211692Santhony.gutierrez@amd.com            }
30311692Santhony.gutierrez@amd.com
30411692Santhony.gutierrez@amd.com            switch (segment) {
30511692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
30611692Santhony.gutierrez@amd.com                setFlag(GlobalSegment);
30711692Santhony.gutierrez@amd.com                break;
30811692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
30911692Santhony.gutierrez@amd.com                setFlag(GroupSegment);
31011692Santhony.gutierrez@amd.com                break;
31111692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_PRIVATE:
31211692Santhony.gutierrez@amd.com                setFlag(PrivateSegment);
31311692Santhony.gutierrez@amd.com                break;
31411692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_READONLY:
31511692Santhony.gutierrez@amd.com                setFlag(ReadOnlySegment);
31611692Santhony.gutierrez@amd.com                break;
31711692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_SPILL:
31811692Santhony.gutierrez@amd.com                setFlag(SpillSegment);
31911692Santhony.gutierrez@amd.com                break;
32011692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
32111692Santhony.gutierrez@amd.com                setFlag(Flat);
32211692Santhony.gutierrez@amd.com                break;
32311692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_KERNARG:
32411692Santhony.gutierrez@amd.com                setFlag(KernArgSegment);
32511692Santhony.gutierrez@amd.com                break;
32611692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_ARG:
32711692Santhony.gutierrez@amd.com                setFlag(ArgSegment);
32811692Santhony.gutierrez@amd.com                break;
32911692Santhony.gutierrez@amd.com              default:
33011692Santhony.gutierrez@amd.com                panic("Ld: segment %d not supported\n", segment);
33111308Santhony.gutierrez@amd.com            }
33211308Santhony.gutierrez@amd.com        }
33311308Santhony.gutierrez@amd.com
33411347Sandreas.hansson@arm.com        int numSrcRegOperands() override
33511347Sandreas.hansson@arm.com        { return(this->addr.isVectorRegister()); }
33611347Sandreas.hansson@arm.com        int numDstRegOperands() override { return dest.isVectorRegister(); }
33711347Sandreas.hansson@arm.com        int getNumOperands() override
33811308Santhony.gutierrez@amd.com        {
33911308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister())
34011308Santhony.gutierrez@amd.com                return 2;
34111308Santhony.gutierrez@amd.com            else
34211308Santhony.gutierrez@amd.com                return 1;
34311308Santhony.gutierrez@amd.com        }
34411347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
34511308Santhony.gutierrez@amd.com        {
34611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
34711308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isVectorRegister() :
34811308Santhony.gutierrez@amd.com                   this->addr.isVectorRegister());
34911308Santhony.gutierrez@amd.com        }
35011347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
35111308Santhony.gutierrez@amd.com        {
35211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
35311308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isCondRegister() :
35411308Santhony.gutierrez@amd.com                   this->addr.isCondRegister());
35511308Santhony.gutierrez@amd.com        }
35611347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
35711308Santhony.gutierrez@amd.com        {
35811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
35911308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isScalarRegister() :
36011308Santhony.gutierrez@amd.com                   this->addr.isScalarRegister());
36111308Santhony.gutierrez@amd.com        }
36211347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
36311308Santhony.gutierrez@amd.com        {
36411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
36511308Santhony.gutierrez@amd.com            if (operandIndex > 0)
36611308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
36711308Santhony.gutierrez@amd.com            return false;
36811308Santhony.gutierrez@amd.com        }
36911347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override
37011308Santhony.gutierrez@amd.com        {
37111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
37211308Santhony.gutierrez@amd.com            return(operandIndex == 0);
37311308Santhony.gutierrez@amd.com        }
37411347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
37511308Santhony.gutierrez@amd.com        {
37611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
37711308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.opSize() :
37811308Santhony.gutierrez@amd.com                   this->addr.opSize());
37911308Santhony.gutierrez@amd.com        }
38011347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
38111308Santhony.gutierrez@amd.com        {
38211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
38311308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.regIndex() :
38411308Santhony.gutierrez@amd.com                   this->addr.regIndex());
38511308Santhony.gutierrez@amd.com        }
38611308Santhony.gutierrez@amd.com    };
38711308Santhony.gutierrez@amd.com
38811308Santhony.gutierrez@amd.com    template<typename MemDataType, typename DestDataType,
38911308Santhony.gutierrez@amd.com             typename AddrOperandType>
39011308Santhony.gutierrez@amd.com    class LdInst :
39111308Santhony.gutierrez@amd.com        public LdInstBase<typename MemDataType::CType,
39211308Santhony.gutierrez@amd.com                          typename DestDataType::OperandType, AddrOperandType>,
39311308Santhony.gutierrez@amd.com        public MemInst
39411308Santhony.gutierrez@amd.com    {
39511308Santhony.gutierrez@amd.com        typename DestDataType::OperandType::DestOperand dest_vect[4];
39611308Santhony.gutierrez@amd.com        uint16_t num_dest_operands;
39711347Sandreas.hansson@arm.com        void generateDisassembly() override;
39811308Santhony.gutierrez@amd.com
39911308Santhony.gutierrez@amd.com      public:
40011308Santhony.gutierrez@amd.com        LdInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
40111308Santhony.gutierrez@amd.com               const char *_opcode)
40211308Santhony.gutierrez@amd.com            : LdInstBase<typename MemDataType::CType,
40311308Santhony.gutierrez@amd.com                         typename DestDataType::OperandType,
40411308Santhony.gutierrez@amd.com                         AddrOperandType>(ib, obj, _opcode),
40511308Santhony.gutierrez@amd.com              MemInst(MemDataType::memType)
40611308Santhony.gutierrez@amd.com        {
40711308Santhony.gutierrez@amd.com            init_addr(&this->addr);
40811308Santhony.gutierrez@amd.com
40911308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands,0);
41011308Santhony.gutierrez@amd.com            const Brig::BrigOperand *brigOp = obj->getOperand(op_offs);
41111308Santhony.gutierrez@amd.com
41211308Santhony.gutierrez@amd.com            if (brigOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
41311308Santhony.gutierrez@amd.com                const Brig::BrigOperandOperandList *brigRegVecOp =
41411308Santhony.gutierrez@amd.com                    (const Brig::BrigOperandOperandList*)brigOp;
41511308Santhony.gutierrez@amd.com
41611308Santhony.gutierrez@amd.com                num_dest_operands =
41711308Santhony.gutierrez@amd.com                    *((unsigned*)obj->getData(brigRegVecOp->elements)) / 4;
41811308Santhony.gutierrez@amd.com
41911308Santhony.gutierrez@amd.com                assert(num_dest_operands <= 4);
42011308Santhony.gutierrez@amd.com            } else {
42111308Santhony.gutierrez@amd.com                num_dest_operands = 1;
42211308Santhony.gutierrez@amd.com            }
42311308Santhony.gutierrez@amd.com
42411308Santhony.gutierrez@amd.com            if (num_dest_operands > 1) {
42511308Santhony.gutierrez@amd.com                assert(brigOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST);
42611308Santhony.gutierrez@amd.com
42711308Santhony.gutierrez@amd.com                for (int i = 0; i < num_dest_operands; ++i) {
42811308Santhony.gutierrez@amd.com                    dest_vect[i].init_from_vect(op_offs, obj, i);
42911308Santhony.gutierrez@amd.com                }
43011308Santhony.gutierrez@amd.com            }
43111308Santhony.gutierrez@amd.com        }
43211308Santhony.gutierrez@amd.com
43311308Santhony.gutierrez@amd.com        void
43411308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst) override
43511308Santhony.gutierrez@amd.com        {
43611308Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c0;
43711308Santhony.gutierrez@amd.com
43811308Santhony.gutierrez@amd.com            gpuDynInst->statusBitVector = gpuDynInst->exec_mask;
43911308Santhony.gutierrez@amd.com
44011308Santhony.gutierrez@amd.com            if (num_dest_operands > 1) {
44111534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i)
44211308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i])
44311308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(num_dest_operands);
44411308Santhony.gutierrez@amd.com                    else
44511308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(0);
44611308Santhony.gutierrez@amd.com            }
44711308Santhony.gutierrez@amd.com
44811308Santhony.gutierrez@amd.com            for (int k = 0; k < num_dest_operands; ++k) {
44911308Santhony.gutierrez@amd.com
45011534Sjohn.kalamatianos@amd.com                c0 *d = &((c0*)gpuDynInst->d_data)
45111534Sjohn.kalamatianos@amd.com                    [k * gpuDynInst->computeUnit()->wfSize()];
45211308Santhony.gutierrez@amd.com
45311534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) {
45411308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i]) {
45511308Santhony.gutierrez@amd.com                        Addr vaddr = gpuDynInst->addr[i] + k * sizeof(c0);
45611308Santhony.gutierrez@amd.com
45711692Santhony.gutierrez@amd.com                        if (this->isLocalMem()) {
45811308Santhony.gutierrez@amd.com                            // load from shared memory
45911308Santhony.gutierrez@amd.com                            *d = gpuDynInst->wavefront()->ldsChunk->
46011308Santhony.gutierrez@amd.com                                read<c0>(vaddr);
46111308Santhony.gutierrez@amd.com                        } else {
46211308Santhony.gutierrez@amd.com                            Request *req = new Request(0, vaddr, sizeof(c0), 0,
46311308Santhony.gutierrez@amd.com                                          gpuDynInst->computeUnit()->masterId(),
46411435Smitch.hayenga@arm.com                                          0, gpuDynInst->wfDynId);
46511308Santhony.gutierrez@amd.com
46611308Santhony.gutierrez@amd.com                            gpuDynInst->setRequestFlags(req);
46711308Santhony.gutierrez@amd.com                            PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
46811308Santhony.gutierrez@amd.com                            pkt->dataStatic(d);
46911308Santhony.gutierrez@amd.com
47011308Santhony.gutierrez@amd.com                            if (gpuDynInst->computeUnit()->shader->
47111308Santhony.gutierrez@amd.com                                separate_acquire_release &&
47211692Santhony.gutierrez@amd.com                                gpuDynInst->isAcquire()) {
47311308Santhony.gutierrez@amd.com                                // if this load has acquire semantics,
47411308Santhony.gutierrez@amd.com                                // set the response continuation function
47511308Santhony.gutierrez@amd.com                                // to perform an Acquire request
47611308Santhony.gutierrez@amd.com                                gpuDynInst->execContinuation =
47711308Santhony.gutierrez@amd.com                                    &GPUStaticInst::execLdAcq;
47811308Santhony.gutierrez@amd.com
47911308Santhony.gutierrez@amd.com                                gpuDynInst->useContinuation = true;
48011308Santhony.gutierrez@amd.com                            } else {
48111308Santhony.gutierrez@amd.com                                // the request will be finished when
48211308Santhony.gutierrez@amd.com                                // the load completes
48311308Santhony.gutierrez@amd.com                                gpuDynInst->useContinuation = false;
48411308Santhony.gutierrez@amd.com                            }
48511308Santhony.gutierrez@amd.com                            // translation is performed in sendRequest()
48611308Santhony.gutierrez@amd.com                            gpuDynInst->computeUnit()->sendRequest(gpuDynInst,
48711308Santhony.gutierrez@amd.com                                                                   i, pkt);
48811308Santhony.gutierrez@amd.com                        }
48911308Santhony.gutierrez@amd.com                    }
49011308Santhony.gutierrez@amd.com                    ++d;
49111308Santhony.gutierrez@amd.com                }
49211308Santhony.gutierrez@amd.com            }
49311308Santhony.gutierrez@amd.com
49411308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
49511308Santhony.gutierrez@amd.com        }
49611308Santhony.gutierrez@amd.com
49711693Santhony.gutierrez@amd.com        void
49811693Santhony.gutierrez@amd.com        completeAcc(GPUDynInstPtr gpuDynInst) override
49911693Santhony.gutierrez@amd.com        {
50011693Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c1;
50111693Santhony.gutierrez@amd.com
50211693Santhony.gutierrez@amd.com            constexpr bool is_vt_32 = DestDataType::vgprType == VT_32;
50311693Santhony.gutierrez@amd.com
50411693Santhony.gutierrez@amd.com            /**
50511693Santhony.gutierrez@amd.com              * this code essentially replaces the long if-else chain
50611693Santhony.gutierrez@amd.com              * that was in used GlobalMemPipeline::exec() to infer the
50711693Santhony.gutierrez@amd.com              * size (single/double) and type (floating point/integer) of
50811693Santhony.gutierrez@amd.com              * the destination register. this is needed for load
50911693Santhony.gutierrez@amd.com              * instructions because the loaded value and the
51011693Santhony.gutierrez@amd.com              * destination type can be of different sizes, and we also
51111693Santhony.gutierrez@amd.com              * need to know if the value we're writing back is floating
51211693Santhony.gutierrez@amd.com              * point and signed/unsigned, so we can properly cast the
51311693Santhony.gutierrez@amd.com              * writeback value
51411693Santhony.gutierrez@amd.com              */
51511693Santhony.gutierrez@amd.com            typedef typename std::conditional<is_vt_32,
51611693Santhony.gutierrez@amd.com                typename std::conditional<std::is_floating_point<c1>::value,
51711693Santhony.gutierrez@amd.com                    float, typename std::conditional<std::is_signed<c1>::value,
51811693Santhony.gutierrez@amd.com                    int32_t, uint32_t>::type>::type,
51911693Santhony.gutierrez@amd.com                typename std::conditional<std::is_floating_point<c1>::value,
52011693Santhony.gutierrez@amd.com                    double, typename std::conditional<std::is_signed<c1>::value,
52111693Santhony.gutierrez@amd.com                    int64_t, uint64_t>::type>::type>::type c0;
52211693Santhony.gutierrez@amd.com
52311693Santhony.gutierrez@amd.com
52411693Santhony.gutierrez@amd.com            Wavefront *w = gpuDynInst->wavefront();
52511693Santhony.gutierrez@amd.com
52611693Santhony.gutierrez@amd.com            std::vector<uint32_t> regVec;
52711693Santhony.gutierrez@amd.com            // iterate over number of destination register operands since
52811693Santhony.gutierrez@amd.com            // this is a load
52911693Santhony.gutierrez@amd.com            for (int k = 0; k < num_dest_operands; ++k) {
53011693Santhony.gutierrez@amd.com                assert((sizeof(c1) * num_dest_operands)
53111693Santhony.gutierrez@amd.com                       <= MAX_WIDTH_FOR_MEM_INST);
53211693Santhony.gutierrez@amd.com
53311693Santhony.gutierrez@amd.com                int dst = this->dest.regIndex() + k;
53411693Santhony.gutierrez@amd.com                if (num_dest_operands > MAX_REGS_FOR_NON_VEC_MEM_INST)
53511693Santhony.gutierrez@amd.com                    dst = dest_vect[k].regIndex();
53611693Santhony.gutierrez@amd.com                // virtual->physical VGPR mapping
53711693Santhony.gutierrez@amd.com                int physVgpr = w->remap(dst, sizeof(c0), 1);
53811693Santhony.gutierrez@amd.com                // save the physical VGPR index
53911693Santhony.gutierrez@amd.com                regVec.push_back(physVgpr);
54011693Santhony.gutierrez@amd.com
54111693Santhony.gutierrez@amd.com                c1 *p1 =
54211693Santhony.gutierrez@amd.com                    &((c1*)gpuDynInst->d_data)[k * w->computeUnit->wfSize()];
54311693Santhony.gutierrez@amd.com
54411693Santhony.gutierrez@amd.com                for (int i = 0; i < w->computeUnit->wfSize(); ++i) {
54511693Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i]) {
54611693Santhony.gutierrez@amd.com                        DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: "
54711693Santhony.gutierrez@amd.com                                "$%s%d <- %d global ld done (src = wavefront "
54811693Santhony.gutierrez@amd.com                                "ld inst)\n", w->computeUnit->cu_id, w->simdId,
54911693Santhony.gutierrez@amd.com                                w->wfSlotId, i, sizeof(c0) == 4 ? "s" : "d",
55011693Santhony.gutierrez@amd.com                                dst, *p1);
55111693Santhony.gutierrez@amd.com                        // write the value into the physical VGPR. This is a
55211693Santhony.gutierrez@amd.com                        // purely functional operation. No timing is modeled.
55311693Santhony.gutierrez@amd.com                        w->computeUnit->vrf[w->simdId]->write<c0>(physVgpr,
55411693Santhony.gutierrez@amd.com                                                                    *p1, i);
55511693Santhony.gutierrez@amd.com                    }
55611693Santhony.gutierrez@amd.com                    ++p1;
55711693Santhony.gutierrez@amd.com                }
55811693Santhony.gutierrez@amd.com            }
55911693Santhony.gutierrez@amd.com
56011693Santhony.gutierrez@amd.com            // Schedule the write operation of the load data on the VRF.
56111693Santhony.gutierrez@amd.com            // This simply models the timing aspect of the VRF write operation.
56211693Santhony.gutierrez@amd.com            // It does not modify the physical VGPR.
56311693Santhony.gutierrez@amd.com            int loadVrfBankConflictCycles = gpuDynInst->computeUnit()->
56411693Santhony.gutierrez@amd.com                vrf[w->simdId]->exec(gpuDynInst->seqNum(), w, regVec,
56511693Santhony.gutierrez@amd.com                                     sizeof(c0), gpuDynInst->time);
56611693Santhony.gutierrez@amd.com
56711693Santhony.gutierrez@amd.com            if (this->isGlobalMem()) {
56811693Santhony.gutierrez@amd.com                gpuDynInst->computeUnit()->globalMemoryPipe
56911693Santhony.gutierrez@amd.com                    .incLoadVRFBankConflictCycles(loadVrfBankConflictCycles);
57011693Santhony.gutierrez@amd.com            } else {
57111693Santhony.gutierrez@amd.com                assert(this->isLocalMem());
57211693Santhony.gutierrez@amd.com                gpuDynInst->computeUnit()->localMemoryPipe
57311693Santhony.gutierrez@amd.com                    .incLoadVRFBankConflictCycles(loadVrfBankConflictCycles);
57411693Santhony.gutierrez@amd.com            }
57511693Santhony.gutierrez@amd.com        }
57611693Santhony.gutierrez@amd.com
57711308Santhony.gutierrez@amd.com      private:
57811308Santhony.gutierrez@amd.com        void
57911308Santhony.gutierrez@amd.com        execLdAcq(GPUDynInstPtr gpuDynInst) override
58011308Santhony.gutierrez@amd.com        {
58111308Santhony.gutierrez@amd.com            // after the load has complete and if the load has acquire
58211308Santhony.gutierrez@amd.com            // semantics, issue an acquire request.
58311692Santhony.gutierrez@amd.com            if (!this->isLocalMem()) {
58411308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
58511692Santhony.gutierrez@amd.com                    && gpuDynInst->isAcquire()) {
58611308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
58711308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = false;
58811308Santhony.gutierrez@amd.com                    // create request
58911308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
59011308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
59111435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
59211308Santhony.gutierrez@amd.com                    req->setFlags(Request::ACQUIRE);
59311308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
59411308Santhony.gutierrez@amd.com                }
59511308Santhony.gutierrez@amd.com            }
59611308Santhony.gutierrez@amd.com        }
59711308Santhony.gutierrez@amd.com
59811308Santhony.gutierrez@amd.com      public:
59911347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
60011308Santhony.gutierrez@amd.com        {
60111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
60211308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
60311308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
60411308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
60511308Santhony.gutierrez@amd.com            if (num_dest_operands > 1) {
60611308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isVectorRegister();
60711308Santhony.gutierrez@amd.com            }
60811308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1) {
60911308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
61011308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
61111308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isVectorRegister();
61211308Santhony.gutierrez@amd.com            }
61311308Santhony.gutierrez@amd.com            return false;
61411308Santhony.gutierrez@amd.com        }
61511347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
61611308Santhony.gutierrez@amd.com        {
61711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
61811308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
61911308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
62011308Santhony.gutierrez@amd.com                return(this->addr.isCondRegister());
62111308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
62211308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isCondRegister();
62311308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
62411308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
62511308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
62611308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isCondRegister();
62711308Santhony.gutierrez@amd.com            return false;
62811308Santhony.gutierrez@amd.com        }
62911347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
63011308Santhony.gutierrez@amd.com        {
63111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
63211308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
63311308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
63411308Santhony.gutierrez@amd.com                return(this->addr.isScalarRegister());
63511308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
63611308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isScalarRegister();
63711308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
63811308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
63911308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
64011308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isScalarRegister();
64111308Santhony.gutierrez@amd.com            return false;
64211308Santhony.gutierrez@amd.com        }
64311347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
64411308Santhony.gutierrez@amd.com        {
64511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
64611308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
64711308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
64811308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
64911308Santhony.gutierrez@amd.com            return false;
65011308Santhony.gutierrez@amd.com        }
65111347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override
65211308Santhony.gutierrez@amd.com        {
65311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
65411308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
65511308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
65611308Santhony.gutierrez@amd.com                return false;
65711308Santhony.gutierrez@amd.com            return true;
65811308Santhony.gutierrez@amd.com        }
65911347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
66011308Santhony.gutierrez@amd.com        {
66111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
66211308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
66311308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
66411308Santhony.gutierrez@amd.com                return(this->addr.opSize());
66511308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
66611308Santhony.gutierrez@amd.com                return(dest_vect[operandIndex].opSize());
66711308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
66811308Santhony.gutierrez@amd.com                return(LdInstBase<typename MemDataType::CType,
66911308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
67011308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.opSize());
67111308Santhony.gutierrez@amd.com            return 0;
67211308Santhony.gutierrez@amd.com        }
67311347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
67411308Santhony.gutierrez@amd.com        {
67511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
67611308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
67711308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
67811308Santhony.gutierrez@amd.com                return(this->addr.regIndex());
67911308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
68011308Santhony.gutierrez@amd.com                return(dest_vect[operandIndex].regIndex());
68111308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
68211308Santhony.gutierrez@amd.com                return(LdInstBase<typename MemDataType::CType,
68311308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
68411308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.regIndex());
68511308Santhony.gutierrez@amd.com            return -1;
68611308Santhony.gutierrez@amd.com        }
68711347Sandreas.hansson@arm.com        int getNumOperands() override
68811308Santhony.gutierrez@amd.com        {
68911308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
69011308Santhony.gutierrez@amd.com                return(num_dest_operands+1);
69111308Santhony.gutierrez@amd.com            else
69211308Santhony.gutierrez@amd.com                return(num_dest_operands);
69311308Santhony.gutierrez@amd.com        }
69411347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
69511308Santhony.gutierrez@amd.com    };
69611308Santhony.gutierrez@amd.com
69711308Santhony.gutierrez@amd.com    template<typename MemDT, typename DestDT>
69811308Santhony.gutierrez@amd.com    GPUStaticInst*
69911308Santhony.gutierrez@amd.com    decodeLd2(const Brig::BrigInstBase *ib, const BrigObject *obj)
70011308Santhony.gutierrez@amd.com    {
70111308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,1);
70211308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
70311308Santhony.gutierrez@amd.com
70411308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
70511308Santhony.gutierrez@amd.com            return new LdInst<MemDT, DestDT, NoRegAddrOperand>(ib, obj, "ld");
70611308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER ||
70711308Santhony.gutierrez@amd.com                   tmp.kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
70811308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
70911308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
71011308Santhony.gutierrez@amd.com                return new LdInst<MemDT, DestDT,
71111308Santhony.gutierrez@amd.com                                  SRegAddrOperand>(ib, obj, "ld");
71211308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
71311308Santhony.gutierrez@amd.com                return new LdInst<MemDT, DestDT,
71411308Santhony.gutierrez@amd.com                                  DRegAddrOperand>(ib, obj, "ld");
71511308Santhony.gutierrez@amd.com              default:
71611308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d\n", tmp.regKind);
71711308Santhony.gutierrez@amd.com            }
71811308Santhony.gutierrez@amd.com        } else {
71911308Santhony.gutierrez@amd.com            fatal("Bad ld register operand kind %d\n", tmp.kind);
72011308Santhony.gutierrez@amd.com        }
72111308Santhony.gutierrez@amd.com    }
72211308Santhony.gutierrez@amd.com
72311308Santhony.gutierrez@amd.com    template<typename MemDT>
72411308Santhony.gutierrez@amd.com    GPUStaticInst*
72511308Santhony.gutierrez@amd.com    decodeLd(const Brig::BrigInstBase *ib, const BrigObject *obj)
72611308Santhony.gutierrez@amd.com    {
72711308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,0);
72811308Santhony.gutierrez@amd.com        BrigRegOperandInfo dest = findRegDataType(op_offs, obj);
72911308Santhony.gutierrez@amd.com
73011308Santhony.gutierrez@amd.com        assert(dest.kind == Brig::BRIG_KIND_OPERAND_REGISTER ||
73111308Santhony.gutierrez@amd.com               dest.kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST);
73211308Santhony.gutierrez@amd.com        switch(dest.regKind) {
73311308Santhony.gutierrez@amd.com          case Brig::BRIG_REGISTER_KIND_SINGLE:
73411308Santhony.gutierrez@amd.com            switch (ib->type) {
73511308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B8:
73611308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B16:
73711308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B32:
73811308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, B32>(ib, obj);
73911308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U8:
74011308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U16:
74111308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U32:
74211308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U32>(ib, obj);
74311308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S8:
74411308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S16:
74511308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S32:
74611308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, S32>(ib, obj);
74711308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F16:
74811308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F32:
74911308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U32>(ib, obj);
75011308Santhony.gutierrez@amd.com              default:
75111308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d, %d\n",
75211308Santhony.gutierrez@amd.com                      dest.regKind, ib->type);
75311308Santhony.gutierrez@amd.com            };
75411308Santhony.gutierrez@amd.com          case Brig::BRIG_REGISTER_KIND_DOUBLE:
75511308Santhony.gutierrez@amd.com            switch (ib->type) {
75611308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B64:
75711308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, B64>(ib, obj);
75811308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U64:
75911308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U64>(ib, obj);
76011308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S64:
76111308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, S64>(ib, obj);
76211308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F64:
76311308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U64>(ib, obj);
76411308Santhony.gutierrez@amd.com              default:
76511308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d, %d\n",
76611308Santhony.gutierrez@amd.com                      dest.regKind, ib->type);
76711308Santhony.gutierrez@amd.com            };
76811308Santhony.gutierrez@amd.com          default:
76911308Santhony.gutierrez@amd.com            fatal("Bad ld register operand type %d, %d\n", dest.regKind,
77011308Santhony.gutierrez@amd.com                  ib->type);
77111308Santhony.gutierrez@amd.com        }
77211308Santhony.gutierrez@amd.com    }
77311308Santhony.gutierrez@amd.com
77411308Santhony.gutierrez@amd.com    template<typename MemDataType, typename SrcOperandType,
77511308Santhony.gutierrez@amd.com             typename AddrOperandType>
77611308Santhony.gutierrez@amd.com    class StInstBase : public HsailGPUStaticInst
77711308Santhony.gutierrez@amd.com    {
77811308Santhony.gutierrez@amd.com      public:
77911308Santhony.gutierrez@amd.com        typename SrcOperandType::SrcOperand src;
78011308Santhony.gutierrez@amd.com        AddrOperandType addr;
78111308Santhony.gutierrez@amd.com
78211308Santhony.gutierrez@amd.com        Brig::BrigSegment segment;
78311308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memoryScope;
78411308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memoryOrder;
78511308Santhony.gutierrez@amd.com        unsigned int equivClass;
78611308Santhony.gutierrez@amd.com
78711308Santhony.gutierrez@amd.com        StInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
78811308Santhony.gutierrez@amd.com                   const char *_opcode)
78911308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
79011308Santhony.gutierrez@amd.com        {
79111308Santhony.gutierrez@amd.com            using namespace Brig;
79211308Santhony.gutierrez@amd.com
79311692Santhony.gutierrez@amd.com            setFlag(MemoryRef);
79411692Santhony.gutierrez@amd.com            setFlag(Store);
79511692Santhony.gutierrez@amd.com
79611308Santhony.gutierrez@amd.com            if (ib->opcode == BRIG_OPCODE_ST) {
79711692Santhony.gutierrez@amd.com                const BrigInstMem *ldst = (const BrigInstMem*)ib;
79811692Santhony.gutierrez@amd.com
79911692Santhony.gutierrez@amd.com                segment = (BrigSegment)ldst->segment;
80011692Santhony.gutierrez@amd.com                memoryOrder = BRIG_MEMORY_ORDER_NONE;
80111692Santhony.gutierrez@amd.com                memoryScope = BRIG_MEMORY_SCOPE_NONE;
80211692Santhony.gutierrez@amd.com                equivClass = ldst->equivClass;
80311692Santhony.gutierrez@amd.com
80411692Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
80511692Santhony.gutierrez@amd.com                const BrigOperand *baseOp = obj->getOperand(op_offs);
80611692Santhony.gutierrez@amd.com
80711692Santhony.gutierrez@amd.com                if ((baseOp->kind == BRIG_KIND_OPERAND_CONSTANT_BYTES) ||
80811692Santhony.gutierrez@amd.com                    (baseOp->kind == BRIG_KIND_OPERAND_REGISTER)) {
80911692Santhony.gutierrez@amd.com                    src.init(op_offs, obj);
81011692Santhony.gutierrez@amd.com                }
81111692Santhony.gutierrez@amd.com
81211692Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands, 1);
81311692Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
81411308Santhony.gutierrez@amd.com            } else {
81511692Santhony.gutierrez@amd.com                const BrigInstAtomic *at = (const BrigInstAtomic*)ib;
81611692Santhony.gutierrez@amd.com
81711692Santhony.gutierrez@amd.com                segment = (BrigSegment)at->segment;
81811692Santhony.gutierrez@amd.com                memoryScope = (BrigMemoryScope)at->memoryScope;
81911692Santhony.gutierrez@amd.com                memoryOrder = (BrigMemoryOrder)at->memoryOrder;
82011692Santhony.gutierrez@amd.com                equivClass = 0;
82111692Santhony.gutierrez@amd.com
82211692Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
82311692Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
82411692Santhony.gutierrez@amd.com
82511692Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands, 1);
82611692Santhony.gutierrez@amd.com                src.init(op_offs, obj);
82711692Santhony.gutierrez@amd.com            }
82811692Santhony.gutierrez@amd.com
82911692Santhony.gutierrez@amd.com            switch (memoryOrder) {
83011692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_NONE:
83111692Santhony.gutierrez@amd.com                setFlag(NoOrder);
83211692Santhony.gutierrez@amd.com                break;
83311692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_RELAXED:
83411692Santhony.gutierrez@amd.com                setFlag(RelaxedOrder);
83511692Santhony.gutierrez@amd.com                break;
83611692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE:
83711692Santhony.gutierrez@amd.com                setFlag(Acquire);
83811692Santhony.gutierrez@amd.com                break;
83911692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_RELEASE:
84011692Santhony.gutierrez@amd.com                setFlag(Release);
84111692Santhony.gutierrez@amd.com                break;
84211692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE:
84311692Santhony.gutierrez@amd.com                setFlag(AcquireRelease);
84411692Santhony.gutierrez@amd.com                break;
84511692Santhony.gutierrez@amd.com              default:
84611692Santhony.gutierrez@amd.com                fatal("StInst has bad memory order type\n");
84711692Santhony.gutierrez@amd.com            }
84811692Santhony.gutierrez@amd.com
84911692Santhony.gutierrez@amd.com            switch (memoryScope) {
85011692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_NONE:
85111692Santhony.gutierrez@amd.com                setFlag(NoScope);
85211692Santhony.gutierrez@amd.com                break;
85311692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKITEM:
85411692Santhony.gutierrez@amd.com                setFlag(WorkitemScope);
85511692Santhony.gutierrez@amd.com                break;
85611692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKGROUP:
85711692Santhony.gutierrez@amd.com                setFlag(WorkgroupScope);
85811692Santhony.gutierrez@amd.com                break;
85911692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_AGENT:
86011692Santhony.gutierrez@amd.com                setFlag(DeviceScope);
86111692Santhony.gutierrez@amd.com                break;
86211692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_SYSTEM:
86311692Santhony.gutierrez@amd.com                setFlag(SystemScope);
86411692Santhony.gutierrez@amd.com                break;
86511692Santhony.gutierrez@amd.com              default:
86611692Santhony.gutierrez@amd.com                fatal("StInst has bad memory scope type\n");
86711692Santhony.gutierrez@amd.com            }
86811692Santhony.gutierrez@amd.com
86911692Santhony.gutierrez@amd.com            switch (segment) {
87011692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
87111692Santhony.gutierrez@amd.com                setFlag(GlobalSegment);
87211692Santhony.gutierrez@amd.com                break;
87311692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
87411692Santhony.gutierrez@amd.com                setFlag(GroupSegment);
87511692Santhony.gutierrez@amd.com                break;
87611692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_PRIVATE:
87711692Santhony.gutierrez@amd.com                setFlag(PrivateSegment);
87811692Santhony.gutierrez@amd.com                break;
87911692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_READONLY:
88011692Santhony.gutierrez@amd.com                setFlag(ReadOnlySegment);
88111692Santhony.gutierrez@amd.com                break;
88211692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_SPILL:
88311692Santhony.gutierrez@amd.com                setFlag(SpillSegment);
88411692Santhony.gutierrez@amd.com                break;
88511692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
88611692Santhony.gutierrez@amd.com                setFlag(Flat);
88711692Santhony.gutierrez@amd.com                break;
88811692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_ARG:
88911692Santhony.gutierrez@amd.com                setFlag(ArgSegment);
89011692Santhony.gutierrez@amd.com                break;
89111692Santhony.gutierrez@amd.com              default:
89211692Santhony.gutierrez@amd.com                panic("St: segment %d not supported\n", segment);
89311308Santhony.gutierrez@amd.com            }
89411308Santhony.gutierrez@amd.com        }
89511308Santhony.gutierrez@amd.com
89611347Sandreas.hansson@arm.com        int numDstRegOperands() override { return 0; }
89711347Sandreas.hansson@arm.com        int numSrcRegOperands() override
89811308Santhony.gutierrez@amd.com        {
89911308Santhony.gutierrez@amd.com            return src.isVectorRegister() + this->addr.isVectorRegister();
90011308Santhony.gutierrez@amd.com        }
90111347Sandreas.hansson@arm.com        int getNumOperands() override
90211308Santhony.gutierrez@amd.com        {
90311308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
90411308Santhony.gutierrez@amd.com                return 2;
90511308Santhony.gutierrez@amd.com            else
90611308Santhony.gutierrez@amd.com                return 1;
90711308Santhony.gutierrez@amd.com        }
90811347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
90911308Santhony.gutierrez@amd.com        {
91011308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
91111308Santhony.gutierrez@amd.com            return !operandIndex ? src.isVectorRegister() :
91211308Santhony.gutierrez@amd.com                   this->addr.isVectorRegister();
91311308Santhony.gutierrez@amd.com        }
91411347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
91511308Santhony.gutierrez@amd.com        {
91611308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
91711308Santhony.gutierrez@amd.com            return !operandIndex ? src.isCondRegister() :
91811308Santhony.gutierrez@amd.com                   this->addr.isCondRegister();
91911308Santhony.gutierrez@amd.com        }
92011347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
92111308Santhony.gutierrez@amd.com        {
92211308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
92311308Santhony.gutierrez@amd.com            return !operandIndex ? src.isScalarRegister() :
92411308Santhony.gutierrez@amd.com                   this->addr.isScalarRegister();
92511308Santhony.gutierrez@amd.com        }
92611347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
92711308Santhony.gutierrez@amd.com        {
92811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
92911308Santhony.gutierrez@amd.com            return true;
93011308Santhony.gutierrez@amd.com        }
93111347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override { return false; }
93211347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
93311308Santhony.gutierrez@amd.com        {
93411308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
93511308Santhony.gutierrez@amd.com            return !operandIndex ? src.opSize() : this->addr.opSize();
93611308Santhony.gutierrez@amd.com        }
93711347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
93811308Santhony.gutierrez@amd.com        {
93911308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
94011308Santhony.gutierrez@amd.com            return !operandIndex ? src.regIndex() : this->addr.regIndex();
94111308Santhony.gutierrez@amd.com        }
94211308Santhony.gutierrez@amd.com    };
94311308Santhony.gutierrez@amd.com
94411308Santhony.gutierrez@amd.com
94511308Santhony.gutierrez@amd.com    template<typename MemDataType, typename SrcDataType,
94611308Santhony.gutierrez@amd.com             typename AddrOperandType>
94711308Santhony.gutierrez@amd.com    class StInst :
94811308Santhony.gutierrez@amd.com        public StInstBase<MemDataType, typename SrcDataType::OperandType,
94911308Santhony.gutierrez@amd.com                          AddrOperandType>,
95011308Santhony.gutierrez@amd.com        public MemInst
95111308Santhony.gutierrez@amd.com    {
95211308Santhony.gutierrez@amd.com      public:
95311308Santhony.gutierrez@amd.com        typename SrcDataType::OperandType::SrcOperand src_vect[4];
95411308Santhony.gutierrez@amd.com        uint16_t num_src_operands;
95511347Sandreas.hansson@arm.com        void generateDisassembly() override;
95611308Santhony.gutierrez@amd.com
95711308Santhony.gutierrez@amd.com        StInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
95811308Santhony.gutierrez@amd.com                        const char *_opcode, int srcIdx)
95911308Santhony.gutierrez@amd.com            : StInstBase<MemDataType, typename SrcDataType::OperandType,
96011308Santhony.gutierrez@amd.com                         AddrOperandType>(ib, obj, _opcode),
96111308Santhony.gutierrez@amd.com              MemInst(SrcDataType::memType)
96211308Santhony.gutierrez@amd.com        {
96311308Santhony.gutierrez@amd.com            init_addr(&this->addr);
96411308Santhony.gutierrez@amd.com
96511308Santhony.gutierrez@amd.com            BrigRegOperandInfo rinfo;
96611308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands,srcIdx);
96711308Santhony.gutierrez@amd.com            const Brig::BrigOperand *baseOp = obj->getOperand(op_offs);
96811308Santhony.gutierrez@amd.com
96911308Santhony.gutierrez@amd.com            if (baseOp->kind == Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES) {
97011308Santhony.gutierrez@amd.com                const Brig::BrigOperandConstantBytes *op =
97111308Santhony.gutierrez@amd.com                    (Brig::BrigOperandConstantBytes*)baseOp;
97211308Santhony.gutierrez@amd.com
97311308Santhony.gutierrez@amd.com                rinfo = BrigRegOperandInfo((Brig::BrigKind16_t)op->base.kind,
97411308Santhony.gutierrez@amd.com                                           Brig::BRIG_TYPE_NONE);
97511308Santhony.gutierrez@amd.com            } else {
97611308Santhony.gutierrez@amd.com                rinfo = findRegDataType(op_offs, obj);
97711308Santhony.gutierrez@amd.com            }
97811308Santhony.gutierrez@amd.com
97911308Santhony.gutierrez@amd.com            if (baseOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
98011308Santhony.gutierrez@amd.com                const Brig::BrigOperandOperandList *brigRegVecOp =
98111308Santhony.gutierrez@amd.com                    (const Brig::BrigOperandOperandList*)baseOp;
98211308Santhony.gutierrez@amd.com
98311308Santhony.gutierrez@amd.com                num_src_operands =
98411308Santhony.gutierrez@amd.com                    *((unsigned*)obj->getData(brigRegVecOp->elements)) / 4;
98511308Santhony.gutierrez@amd.com
98611308Santhony.gutierrez@amd.com                assert(num_src_operands <= 4);
98711308Santhony.gutierrez@amd.com            } else {
98811308Santhony.gutierrez@amd.com                num_src_operands = 1;
98911308Santhony.gutierrez@amd.com            }
99011308Santhony.gutierrez@amd.com
99111308Santhony.gutierrez@amd.com            if (num_src_operands > 1) {
99211308Santhony.gutierrez@amd.com                assert(baseOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST);
99311308Santhony.gutierrez@amd.com
99411308Santhony.gutierrez@amd.com                for (int i = 0; i < num_src_operands; ++i) {
99511308Santhony.gutierrez@amd.com                    src_vect[i].init_from_vect(op_offs, obj, i);
99611308Santhony.gutierrez@amd.com                }
99711308Santhony.gutierrez@amd.com            }
99811308Santhony.gutierrez@amd.com        }
99911308Santhony.gutierrez@amd.com
100011308Santhony.gutierrez@amd.com        void
100111308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst) override
100211308Santhony.gutierrez@amd.com        {
100311308Santhony.gutierrez@amd.com            // before performing a store, check if this store has
100411308Santhony.gutierrez@amd.com            // release semantics, and if so issue a release first
100511692Santhony.gutierrez@amd.com            if (!this->isLocalMem()) {
100611308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
100711692Santhony.gutierrez@amd.com                    && gpuDynInst->isRelease()) {
100811308Santhony.gutierrez@amd.com
100911308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
101011308Santhony.gutierrez@amd.com                    gpuDynInst->execContinuation = &GPUStaticInst::execSt;
101111308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = true;
101211308Santhony.gutierrez@amd.com                    // create request
101311308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
101411308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
101511435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
101611308Santhony.gutierrez@amd.com                    req->setFlags(Request::RELEASE);
101711308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
101811308Santhony.gutierrez@amd.com
101911308Santhony.gutierrez@amd.com                    return;
102011308Santhony.gutierrez@amd.com                }
102111308Santhony.gutierrez@amd.com            }
102211308Santhony.gutierrez@amd.com
102311308Santhony.gutierrez@amd.com            // if there is no release semantic, perform stores immediately
102411308Santhony.gutierrez@amd.com            execSt(gpuDynInst);
102511308Santhony.gutierrez@amd.com        }
102611308Santhony.gutierrez@amd.com
102711693Santhony.gutierrez@amd.com        // stores don't write anything back, so there is nothing
102811693Santhony.gutierrez@amd.com        // to do here. we only override this method to avoid the
102911693Santhony.gutierrez@amd.com        // fatal in the base class implementation
103011693Santhony.gutierrez@amd.com        void completeAcc(GPUDynInstPtr gpuDynInst) override { }
103111693Santhony.gutierrez@amd.com
103211308Santhony.gutierrez@amd.com      private:
103311308Santhony.gutierrez@amd.com        // execSt may be called through a continuation
103411308Santhony.gutierrez@amd.com        // if the store had release semantics. see comment for
103511308Santhony.gutierrez@amd.com        // execSt in gpu_static_inst.hh
103611308Santhony.gutierrez@amd.com        void
103711308Santhony.gutierrez@amd.com        execSt(GPUDynInstPtr gpuDynInst) override
103811308Santhony.gutierrez@amd.com        {
103911308Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c0;
104011308Santhony.gutierrez@amd.com
104111308Santhony.gutierrez@amd.com            gpuDynInst->statusBitVector = gpuDynInst->exec_mask;
104211308Santhony.gutierrez@amd.com
104311308Santhony.gutierrez@amd.com            if (num_src_operands > 1) {
104411534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i)
104511308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i])
104611308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(num_src_operands);
104711308Santhony.gutierrez@amd.com                    else
104811308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(0);
104911308Santhony.gutierrez@amd.com            }
105011308Santhony.gutierrez@amd.com
105111308Santhony.gutierrez@amd.com            for (int k = 0; k < num_src_operands; ++k) {
105211534Sjohn.kalamatianos@amd.com                c0 *d = &((c0*)gpuDynInst->d_data)
105311534Sjohn.kalamatianos@amd.com                    [k * gpuDynInst->computeUnit()->wfSize()];
105411308Santhony.gutierrez@amd.com
105511534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) {
105611308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i]) {
105711308Santhony.gutierrez@amd.com                        Addr vaddr = gpuDynInst->addr[i] + k * sizeof(c0);
105811308Santhony.gutierrez@amd.com
105911692Santhony.gutierrez@amd.com                        if (this->isLocalMem()) {
106011308Santhony.gutierrez@amd.com                            //store to shared memory
106111308Santhony.gutierrez@amd.com                            gpuDynInst->wavefront()->ldsChunk->write<c0>(vaddr,
106211308Santhony.gutierrez@amd.com                                                                         *d);
106311308Santhony.gutierrez@amd.com                        } else {
106411308Santhony.gutierrez@amd.com                            Request *req =
106511308Santhony.gutierrez@amd.com                              new Request(0, vaddr, sizeof(c0), 0,
106611308Santhony.gutierrez@amd.com                                          gpuDynInst->computeUnit()->masterId(),
106711435Smitch.hayenga@arm.com                                          0, gpuDynInst->wfDynId);
106811308Santhony.gutierrez@amd.com
106911308Santhony.gutierrez@amd.com                            gpuDynInst->setRequestFlags(req);
107011308Santhony.gutierrez@amd.com                            PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
107111308Santhony.gutierrez@amd.com                            pkt->dataStatic<c0>(d);
107211308Santhony.gutierrez@amd.com
107311308Santhony.gutierrez@amd.com                            // translation is performed in sendRequest()
107411308Santhony.gutierrez@amd.com                            // the request will be finished when the store completes
107511308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = false;
107611308Santhony.gutierrez@amd.com                            gpuDynInst->computeUnit()->sendRequest(gpuDynInst,
107711308Santhony.gutierrez@amd.com                                                                   i, pkt);
107811308Santhony.gutierrez@amd.com
107911308Santhony.gutierrez@amd.com                        }
108011308Santhony.gutierrez@amd.com                    }
108111308Santhony.gutierrez@amd.com                    ++d;
108211308Santhony.gutierrez@amd.com                }
108311308Santhony.gutierrez@amd.com            }
108411308Santhony.gutierrez@amd.com
108511308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
108611308Santhony.gutierrez@amd.com        }
108711308Santhony.gutierrez@amd.com
108811308Santhony.gutierrez@amd.com      public:
108911347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
109011308Santhony.gutierrez@amd.com        {
109111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
109211308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
109311308Santhony.gutierrez@amd.com                return this->addr.isVectorRegister();
109411308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
109511308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isVectorRegister();
109611308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
109711308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
109811308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
109911308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isVectorRegister();
110011308Santhony.gutierrez@amd.com            return false;
110111308Santhony.gutierrez@amd.com        }
110211347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
110311308Santhony.gutierrez@amd.com        {
110411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
110511308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
110611308Santhony.gutierrez@amd.com                return this->addr.isCondRegister();
110711308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
110811308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isCondRegister();
110911308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
111011308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
111111308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
111211308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isCondRegister();
111311308Santhony.gutierrez@amd.com            return false;
111411308Santhony.gutierrez@amd.com        }
111511347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
111611308Santhony.gutierrez@amd.com        {
111711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
111811308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
111911308Santhony.gutierrez@amd.com                return this->addr.isScalarRegister();
112011308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
112111308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isScalarRegister();
112211308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
112311308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
112411308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
112511308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isScalarRegister();
112611308Santhony.gutierrez@amd.com            return false;
112711308Santhony.gutierrez@amd.com        }
112811347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
112911308Santhony.gutierrez@amd.com        {
113011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
113111308Santhony.gutierrez@amd.com            return true;
113211308Santhony.gutierrez@amd.com        }
113311347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override { return false; }
113411347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
113511308Santhony.gutierrez@amd.com        {
113611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
113711308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
113811308Santhony.gutierrez@amd.com                return this->addr.opSize();
113911308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
114011308Santhony.gutierrez@amd.com                return src_vect[operandIndex].opSize();
114111308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
114211308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
114311308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
114411308Santhony.gutierrez@amd.com                       AddrOperandType>::src.opSize();
114511308Santhony.gutierrez@amd.com            return 0;
114611308Santhony.gutierrez@amd.com        }
114711347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
114811308Santhony.gutierrez@amd.com        {
114911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
115011308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
115111308Santhony.gutierrez@amd.com                return this->addr.regIndex();
115211308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
115311308Santhony.gutierrez@amd.com                return src_vect[operandIndex].regIndex();
115411308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
115511308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
115611308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
115711308Santhony.gutierrez@amd.com                       AddrOperandType>::src.regIndex();
115811308Santhony.gutierrez@amd.com            return -1;
115911308Santhony.gutierrez@amd.com        }
116011347Sandreas.hansson@arm.com        int getNumOperands() override
116111308Santhony.gutierrez@amd.com        {
116211308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
116311308Santhony.gutierrez@amd.com                return num_src_operands + 1;
116411308Santhony.gutierrez@amd.com            else
116511308Santhony.gutierrez@amd.com                return num_src_operands;
116611308Santhony.gutierrez@amd.com        }
116711347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
116811308Santhony.gutierrez@amd.com    };
116911308Santhony.gutierrez@amd.com
117011308Santhony.gutierrez@amd.com    template<typename DataType, typename SrcDataType>
117111308Santhony.gutierrez@amd.com    GPUStaticInst*
117211308Santhony.gutierrez@amd.com    decodeSt(const Brig::BrigInstBase *ib, const BrigObject *obj)
117311308Santhony.gutierrez@amd.com    {
117411308Santhony.gutierrez@amd.com        int srcIdx = 0;
117511308Santhony.gutierrez@amd.com        int destIdx = 1;
117611308Santhony.gutierrez@amd.com        if (ib->opcode == Brig::BRIG_OPCODE_ATOMIC ||
117711308Santhony.gutierrez@amd.com            ib->opcode == Brig::BRIG_OPCODE_ATOMICNORET) {
117811308Santhony.gutierrez@amd.com            srcIdx = 1;
117911308Santhony.gutierrez@amd.com            destIdx = 0;
118011308Santhony.gutierrez@amd.com        }
118111308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,destIdx);
118211308Santhony.gutierrez@amd.com
118311308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
118411308Santhony.gutierrez@amd.com
118511308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
118611308Santhony.gutierrez@amd.com            return new StInst<DataType, SrcDataType,
118711308Santhony.gutierrez@amd.com                              NoRegAddrOperand>(ib, obj, "st", srcIdx);
118811308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER) {
118911308Santhony.gutierrez@amd.com            // V2/V4 not allowed
119011308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
119111308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
119211308Santhony.gutierrez@amd.com                return new StInst<DataType, SrcDataType,
119311308Santhony.gutierrez@amd.com                                  SRegAddrOperand>(ib, obj, "st", srcIdx);
119411308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
119511308Santhony.gutierrez@amd.com                return new StInst<DataType, SrcDataType,
119611308Santhony.gutierrez@amd.com                                  DRegAddrOperand>(ib, obj, "st", srcIdx);
119711308Santhony.gutierrez@amd.com              default:
119811308Santhony.gutierrez@amd.com                fatal("Bad st register operand type %d\n", tmp.type);
119911308Santhony.gutierrez@amd.com            }
120011308Santhony.gutierrez@amd.com        } else {
120111308Santhony.gutierrez@amd.com            fatal("Bad st register operand kind %d\n", tmp.kind);
120211308Santhony.gutierrez@amd.com        }
120311308Santhony.gutierrez@amd.com    }
120411308Santhony.gutierrez@amd.com
120511308Santhony.gutierrez@amd.com    template<typename OperandType, typename AddrOperandType, int NumSrcOperands,
120611308Santhony.gutierrez@amd.com             bool HasDst>
120711308Santhony.gutierrez@amd.com    class AtomicInstBase : public HsailGPUStaticInst
120811308Santhony.gutierrez@amd.com    {
120911308Santhony.gutierrez@amd.com      public:
121011308Santhony.gutierrez@amd.com        typename OperandType::DestOperand dest;
121111308Santhony.gutierrez@amd.com        typename OperandType::SrcOperand src[NumSrcOperands];
121211308Santhony.gutierrez@amd.com        AddrOperandType addr;
121311308Santhony.gutierrez@amd.com
121411308Santhony.gutierrez@amd.com        Brig::BrigSegment segment;
121511308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memoryOrder;
121611308Santhony.gutierrez@amd.com        Brig::BrigAtomicOperation atomicOperation;
121711308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memoryScope;
121811308Santhony.gutierrez@amd.com        Brig::BrigOpcode opcode;
121911308Santhony.gutierrez@amd.com
122011308Santhony.gutierrez@amd.com        AtomicInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
122111308Santhony.gutierrez@amd.com                       const char *_opcode)
122211308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
122311308Santhony.gutierrez@amd.com        {
122411308Santhony.gutierrez@amd.com            using namespace Brig;
122511308Santhony.gutierrez@amd.com
122611308Santhony.gutierrez@amd.com            const BrigInstAtomic *at = (const BrigInstAtomic*)ib;
122711308Santhony.gutierrez@amd.com
122811308Santhony.gutierrez@amd.com            segment = (BrigSegment)at->segment;
122911308Santhony.gutierrez@amd.com            memoryScope = (BrigMemoryScope)at->memoryScope;
123011308Santhony.gutierrez@amd.com            memoryOrder = (BrigMemoryOrder)at->memoryOrder;
123111308Santhony.gutierrez@amd.com            atomicOperation = (BrigAtomicOperation)at->atomicOperation;
123211308Santhony.gutierrez@amd.com            opcode = (BrigOpcode)ib->opcode;
123311692Santhony.gutierrez@amd.com
123411692Santhony.gutierrez@amd.com            assert(opcode == Brig::BRIG_OPCODE_ATOMICNORET ||
123511692Santhony.gutierrez@amd.com                   opcode == Brig::BRIG_OPCODE_ATOMIC);
123611692Santhony.gutierrez@amd.com
123711692Santhony.gutierrez@amd.com            setFlag(MemoryRef);
123811692Santhony.gutierrez@amd.com
123911692Santhony.gutierrez@amd.com            if (opcode == Brig::BRIG_OPCODE_ATOMIC) {
124011692Santhony.gutierrez@amd.com                setFlag(AtomicReturn);
124111692Santhony.gutierrez@amd.com            } else {
124211692Santhony.gutierrez@amd.com                setFlag(AtomicNoReturn);
124311692Santhony.gutierrez@amd.com            }
124411692Santhony.gutierrez@amd.com
124511692Santhony.gutierrez@amd.com            switch (memoryOrder) {
124611692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_NONE:
124711692Santhony.gutierrez@amd.com                setFlag(NoOrder);
124811692Santhony.gutierrez@amd.com                break;
124911692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_RELAXED:
125011692Santhony.gutierrez@amd.com                setFlag(RelaxedOrder);
125111692Santhony.gutierrez@amd.com                break;
125211692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE:
125311692Santhony.gutierrez@amd.com                setFlag(Acquire);
125411692Santhony.gutierrez@amd.com                break;
125511692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_RELEASE:
125611692Santhony.gutierrez@amd.com                setFlag(Release);
125711692Santhony.gutierrez@amd.com                break;
125811692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE:
125911692Santhony.gutierrez@amd.com                setFlag(AcquireRelease);
126011692Santhony.gutierrez@amd.com                break;
126111692Santhony.gutierrez@amd.com              default:
126211692Santhony.gutierrez@amd.com                fatal("AtomicInst has bad memory order type\n");
126311692Santhony.gutierrez@amd.com            }
126411692Santhony.gutierrez@amd.com
126511692Santhony.gutierrez@amd.com            switch (memoryScope) {
126611692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_NONE:
126711692Santhony.gutierrez@amd.com                setFlag(NoScope);
126811692Santhony.gutierrez@amd.com                break;
126911692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKITEM:
127011692Santhony.gutierrez@amd.com                setFlag(WorkitemScope);
127111692Santhony.gutierrez@amd.com                break;
127211692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKGROUP:
127311692Santhony.gutierrez@amd.com                setFlag(WorkgroupScope);
127411692Santhony.gutierrez@amd.com                break;
127511692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_AGENT:
127611692Santhony.gutierrez@amd.com                setFlag(DeviceScope);
127711692Santhony.gutierrez@amd.com                break;
127811692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_SYSTEM:
127911692Santhony.gutierrez@amd.com                setFlag(SystemScope);
128011692Santhony.gutierrez@amd.com                break;
128111692Santhony.gutierrez@amd.com              default:
128211692Santhony.gutierrez@amd.com                fatal("AtomicInst has bad memory scope type\n");
128311692Santhony.gutierrez@amd.com            }
128411692Santhony.gutierrez@amd.com
128511692Santhony.gutierrez@amd.com            switch (atomicOperation) {
128611692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_AND:
128711692Santhony.gutierrez@amd.com                setFlag(AtomicAnd);
128811692Santhony.gutierrez@amd.com                break;
128911692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_OR:
129011692Santhony.gutierrez@amd.com                setFlag(AtomicOr);
129111692Santhony.gutierrez@amd.com                break;
129211692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_XOR:
129311692Santhony.gutierrez@amd.com                setFlag(AtomicXor);
129411692Santhony.gutierrez@amd.com                break;
129511692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_CAS:
129611692Santhony.gutierrez@amd.com                setFlag(AtomicCAS);
129711692Santhony.gutierrez@amd.com                break;
129811692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_EXCH:
129911692Santhony.gutierrez@amd.com                setFlag(AtomicExch);
130011692Santhony.gutierrez@amd.com                break;
130111692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_ADD:
130211692Santhony.gutierrez@amd.com                setFlag(AtomicAdd);
130311692Santhony.gutierrez@amd.com                break;
130411692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_WRAPINC:
130511692Santhony.gutierrez@amd.com                setFlag(AtomicInc);
130611692Santhony.gutierrez@amd.com                break;
130711692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_WRAPDEC:
130811692Santhony.gutierrez@amd.com                setFlag(AtomicDec);
130911692Santhony.gutierrez@amd.com                break;
131011692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_MIN:
131111692Santhony.gutierrez@amd.com                setFlag(AtomicMin);
131211692Santhony.gutierrez@amd.com                break;
131311692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_MAX:
131411692Santhony.gutierrez@amd.com                setFlag(AtomicMax);
131511692Santhony.gutierrez@amd.com                break;
131611692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_SUB:
131711692Santhony.gutierrez@amd.com                setFlag(AtomicSub);
131811692Santhony.gutierrez@amd.com                break;
131911692Santhony.gutierrez@amd.com              default:
132011692Santhony.gutierrez@amd.com                fatal("Bad BrigAtomicOperation code %d\n", atomicOperation);
132111692Santhony.gutierrez@amd.com            }
132211308Santhony.gutierrez@amd.com
132311308Santhony.gutierrez@amd.com            switch (segment) {
132411308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
132511692Santhony.gutierrez@amd.com                setFlag(GlobalSegment);
132611308Santhony.gutierrez@amd.com                break;
132711308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
132811692Santhony.gutierrez@amd.com                setFlag(GroupSegment);
132911308Santhony.gutierrez@amd.com                break;
133011308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
133111692Santhony.gutierrez@amd.com                setFlag(Flat);
133211308Santhony.gutierrez@amd.com                break;
133311308Santhony.gutierrez@amd.com              default:
133411308Santhony.gutierrez@amd.com                panic("Atomic: segment %d not supported\n", segment);
133511308Santhony.gutierrez@amd.com            }
133611308Santhony.gutierrez@amd.com
133711308Santhony.gutierrez@amd.com            if (HasDst) {
133811308Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
133911308Santhony.gutierrez@amd.com                dest.init(op_offs, obj);
134011308Santhony.gutierrez@amd.com
134111308Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands, 1);
134211308Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
134311308Santhony.gutierrez@amd.com
134411308Santhony.gutierrez@amd.com                for (int i = 0; i < NumSrcOperands; ++i) {
134511308Santhony.gutierrez@amd.com                    op_offs = obj->getOperandPtr(ib->operands, i + 2);
134611308Santhony.gutierrez@amd.com                    src[i].init(op_offs, obj);
134711308Santhony.gutierrez@amd.com                }
134811308Santhony.gutierrez@amd.com            } else {
134911308Santhony.gutierrez@amd.com
135011308Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
135111308Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
135211308Santhony.gutierrez@amd.com
135311308Santhony.gutierrez@amd.com                for (int i = 0; i < NumSrcOperands; ++i) {
135411308Santhony.gutierrez@amd.com                    op_offs = obj->getOperandPtr(ib->operands, i + 1);
135511308Santhony.gutierrez@amd.com                    src[i].init(op_offs, obj);
135611308Santhony.gutierrez@amd.com                }
135711308Santhony.gutierrez@amd.com            }
135811308Santhony.gutierrez@amd.com        }
135911308Santhony.gutierrez@amd.com
136011308Santhony.gutierrez@amd.com        int numSrcRegOperands()
136111308Santhony.gutierrez@amd.com        {
136211308Santhony.gutierrez@amd.com            int operands = 0;
136311308Santhony.gutierrez@amd.com            for (int i = 0; i < NumSrcOperands; i++) {
136411325Ssteve.reinhardt@amd.com                if (src[i].isVectorRegister()) {
136511308Santhony.gutierrez@amd.com                    operands++;
136611308Santhony.gutierrez@amd.com                }
136711308Santhony.gutierrez@amd.com            }
136811308Santhony.gutierrez@amd.com            if (addr.isVectorRegister())
136911308Santhony.gutierrez@amd.com                operands++;
137011308Santhony.gutierrez@amd.com            return operands;
137111308Santhony.gutierrez@amd.com        }
137211308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
137311308Santhony.gutierrez@amd.com        int getNumOperands()
137411308Santhony.gutierrez@amd.com        {
137511308Santhony.gutierrez@amd.com            if (addr.isVectorRegister())
137611308Santhony.gutierrez@amd.com                return(NumSrcOperands + 2);
137711308Santhony.gutierrez@amd.com            return(NumSrcOperands + 1);
137811308Santhony.gutierrez@amd.com        }
137911308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex)
138011308Santhony.gutierrez@amd.com        {
138111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
138211308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
138311308Santhony.gutierrez@amd.com                return src[operandIndex].isVectorRegister();
138411308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
138511308Santhony.gutierrez@amd.com                return(addr.isVectorRegister());
138611308Santhony.gutierrez@amd.com            else
138711308Santhony.gutierrez@amd.com                return dest.isVectorRegister();
138811308Santhony.gutierrez@amd.com        }
138911308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex)
139011308Santhony.gutierrez@amd.com        {
139111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
139211308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
139311308Santhony.gutierrez@amd.com                return src[operandIndex].isCondRegister();
139411308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
139511308Santhony.gutierrez@amd.com                return(addr.isCondRegister());
139611308Santhony.gutierrez@amd.com            else
139711308Santhony.gutierrez@amd.com                return dest.isCondRegister();
139811308Santhony.gutierrez@amd.com        }
139911308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex)
140011308Santhony.gutierrez@amd.com        {
140111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
140211308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
140311308Santhony.gutierrez@amd.com                return src[operandIndex].isScalarRegister();
140411308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
140511308Santhony.gutierrez@amd.com                return(addr.isScalarRegister());
140611308Santhony.gutierrez@amd.com            else
140711308Santhony.gutierrez@amd.com                return dest.isScalarRegister();
140811308Santhony.gutierrez@amd.com        }
140911308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex)
141011308Santhony.gutierrez@amd.com        {
141111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
141211308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
141311308Santhony.gutierrez@amd.com                return true;
141411308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
141511308Santhony.gutierrez@amd.com                return(addr.isVectorRegister());
141611308Santhony.gutierrez@amd.com            else
141711308Santhony.gutierrez@amd.com                return false;
141811308Santhony.gutierrez@amd.com        }
141911308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex)
142011308Santhony.gutierrez@amd.com        {
142111308Santhony.gutierrez@amd.com            if (operandIndex <= NumSrcOperands)
142211308Santhony.gutierrez@amd.com                return false;
142311308Santhony.gutierrez@amd.com            else
142411308Santhony.gutierrez@amd.com                return true;
142511308Santhony.gutierrez@amd.com        }
142611308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex)
142711308Santhony.gutierrez@amd.com        {
142811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
142911308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
143011308Santhony.gutierrez@amd.com                return(src[operandIndex].opSize());
143111308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
143211308Santhony.gutierrez@amd.com                return(addr.opSize());
143311308Santhony.gutierrez@amd.com            else
143411308Santhony.gutierrez@amd.com                return(dest.opSize());
143511308Santhony.gutierrez@amd.com        }
143611308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex)
143711308Santhony.gutierrez@amd.com        {
143811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
143911308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
144011308Santhony.gutierrez@amd.com                return(src[operandIndex].regIndex());
144111308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
144211308Santhony.gutierrez@amd.com                return(addr.regIndex());
144311308Santhony.gutierrez@amd.com            else
144411308Santhony.gutierrez@amd.com                return(dest.regIndex());
144511308Santhony.gutierrez@amd.com            return -1;
144611308Santhony.gutierrez@amd.com        }
144711308Santhony.gutierrez@amd.com    };
144811308Santhony.gutierrez@amd.com
144911308Santhony.gutierrez@amd.com    template<typename MemDataType, typename AddrOperandType, int NumSrcOperands,
145011308Santhony.gutierrez@amd.com             bool HasDst>
145111308Santhony.gutierrez@amd.com    class AtomicInst :
145211308Santhony.gutierrez@amd.com        public AtomicInstBase<typename MemDataType::OperandType,
145311308Santhony.gutierrez@amd.com                              AddrOperandType, NumSrcOperands, HasDst>,
145411308Santhony.gutierrez@amd.com        public MemInst
145511308Santhony.gutierrez@amd.com    {
145611308Santhony.gutierrez@amd.com      public:
145711347Sandreas.hansson@arm.com        void generateDisassembly() override;
145811308Santhony.gutierrez@amd.com
145911308Santhony.gutierrez@amd.com        AtomicInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
146011308Santhony.gutierrez@amd.com                   const char *_opcode)
146111308Santhony.gutierrez@amd.com            : AtomicInstBase<typename MemDataType::OperandType, AddrOperandType,
146211308Santhony.gutierrez@amd.com                             NumSrcOperands, HasDst>
146311308Santhony.gutierrez@amd.com                (ib, obj, _opcode),
146411308Santhony.gutierrez@amd.com              MemInst(MemDataType::memType)
146511308Santhony.gutierrez@amd.com        {
146611308Santhony.gutierrez@amd.com            init_addr(&this->addr);
146711308Santhony.gutierrez@amd.com        }
146811308Santhony.gutierrez@amd.com
146911308Santhony.gutierrez@amd.com        void
147011308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst) override
147111308Santhony.gutierrez@amd.com        {
147211308Santhony.gutierrez@amd.com            // before doing the RMW, check if this atomic has
147311308Santhony.gutierrez@amd.com            // release semantics, and if so issue a release first
147411692Santhony.gutierrez@amd.com            if (!this->isLocalMem()) {
147511308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
147611692Santhony.gutierrez@amd.com                    && (gpuDynInst->isRelease()
147711692Santhony.gutierrez@amd.com                    || gpuDynInst->isAcquireRelease())) {
147811308Santhony.gutierrez@amd.com
147911308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
148011308Santhony.gutierrez@amd.com
148111308Santhony.gutierrez@amd.com                    gpuDynInst->execContinuation = &GPUStaticInst::execAtomic;
148211308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = true;
148311308Santhony.gutierrez@amd.com
148411308Santhony.gutierrez@amd.com                    // create request
148511308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
148611308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
148711435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
148811308Santhony.gutierrez@amd.com                    req->setFlags(Request::RELEASE);
148911308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
149011308Santhony.gutierrez@amd.com
149111308Santhony.gutierrez@amd.com                    return;
149211308Santhony.gutierrez@amd.com                }
149311308Santhony.gutierrez@amd.com            }
149411308Santhony.gutierrez@amd.com
149511308Santhony.gutierrez@amd.com            // if there is no release semantic, execute the RMW immediately
149611308Santhony.gutierrez@amd.com            execAtomic(gpuDynInst);
149711308Santhony.gutierrez@amd.com
149811308Santhony.gutierrez@amd.com        }
149911308Santhony.gutierrez@amd.com
150011693Santhony.gutierrez@amd.com        void
150111693Santhony.gutierrez@amd.com        completeAcc(GPUDynInstPtr gpuDynInst) override
150211693Santhony.gutierrez@amd.com        {
150311693Santhony.gutierrez@amd.com            // if this is not an atomic return op, then we
150411693Santhony.gutierrez@amd.com            // have nothing more to do.
150511693Santhony.gutierrez@amd.com            if (this->isAtomicRet()) {
150611693Santhony.gutierrez@amd.com                // the size of the src operands and the
150711693Santhony.gutierrez@amd.com                // memory being operated on must match
150811693Santhony.gutierrez@amd.com                // for HSAIL atomics - this assumption may
150911693Santhony.gutierrez@amd.com                // not apply to all ISAs
151011693Santhony.gutierrez@amd.com                typedef typename MemDataType::CType CType;
151111693Santhony.gutierrez@amd.com
151211693Santhony.gutierrez@amd.com                Wavefront *w = gpuDynInst->wavefront();
151311693Santhony.gutierrez@amd.com                int dst = this->dest.regIndex();
151411693Santhony.gutierrez@amd.com                std::vector<uint32_t> regVec;
151511693Santhony.gutierrez@amd.com                // virtual->physical VGPR mapping
151611693Santhony.gutierrez@amd.com                int physVgpr = w->remap(dst, sizeof(CType), 1);
151711693Santhony.gutierrez@amd.com                regVec.push_back(physVgpr);
151811693Santhony.gutierrez@amd.com                CType *p1 = &((CType*)gpuDynInst->d_data)[0];
151911693Santhony.gutierrez@amd.com
152011693Santhony.gutierrez@amd.com                for (int i = 0; i < w->computeUnit->wfSize(); ++i) {
152111693Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i]) {
152211693Santhony.gutierrez@amd.com                        DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: "
152311693Santhony.gutierrez@amd.com                                "$%s%d <- %d global ld done (src = wavefront "
152411693Santhony.gutierrez@amd.com                                "ld inst)\n", w->computeUnit->cu_id, w->simdId,
152511693Santhony.gutierrez@amd.com                                w->wfSlotId, i, sizeof(CType) == 4 ? "s" : "d",
152611693Santhony.gutierrez@amd.com                                dst, *p1);
152711693Santhony.gutierrez@amd.com                        // write the value into the physical VGPR. This is a
152811693Santhony.gutierrez@amd.com                        // purely functional operation. No timing is modeled.
152911693Santhony.gutierrez@amd.com                        w->computeUnit->vrf[w->simdId]->write<CType>(physVgpr, *p1, i);
153011693Santhony.gutierrez@amd.com                    }
153111693Santhony.gutierrez@amd.com                    ++p1;
153211693Santhony.gutierrez@amd.com                }
153311693Santhony.gutierrez@amd.com
153411693Santhony.gutierrez@amd.com                // Schedule the write operation of the load data on the VRF.
153511693Santhony.gutierrez@amd.com                // This simply models the timing aspect of the VRF write operation.
153611693Santhony.gutierrez@amd.com                // It does not modify the physical VGPR.
153711693Santhony.gutierrez@amd.com                int loadVrfBankConflictCycles = gpuDynInst->computeUnit()->
153811693Santhony.gutierrez@amd.com                    vrf[w->simdId]->exec(gpuDynInst->seqNum(), w, regVec,
153911693Santhony.gutierrez@amd.com                                         sizeof(CType), gpuDynInst->time);
154011693Santhony.gutierrez@amd.com
154111693Santhony.gutierrez@amd.com                if (this->isGlobalMem()) {
154211693Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->globalMemoryPipe
154311693Santhony.gutierrez@amd.com                        .incLoadVRFBankConflictCycles(loadVrfBankConflictCycles);
154411693Santhony.gutierrez@amd.com                } else {
154511693Santhony.gutierrez@amd.com                    assert(this->isLocalMem());
154611693Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->localMemoryPipe
154711693Santhony.gutierrez@amd.com                        .incLoadVRFBankConflictCycles(loadVrfBankConflictCycles);
154811693Santhony.gutierrez@amd.com                }
154911693Santhony.gutierrez@amd.com            }
155011693Santhony.gutierrez@amd.com        }
155111693Santhony.gutierrez@amd.com
155211347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
155311308Santhony.gutierrez@amd.com
155411308Santhony.gutierrez@amd.com      private:
155511308Santhony.gutierrez@amd.com        // execAtomic may be called through a continuation
155611308Santhony.gutierrez@amd.com        // if the RMW had release semantics. see comment for
155711308Santhony.gutierrez@amd.com        // execContinuation in gpu_dyn_inst.hh
155811308Santhony.gutierrez@amd.com        void
155911308Santhony.gutierrez@amd.com        execAtomic(GPUDynInstPtr gpuDynInst) override
156011308Santhony.gutierrez@amd.com        {
156111308Santhony.gutierrez@amd.com            gpuDynInst->statusBitVector = gpuDynInst->exec_mask;
156211308Santhony.gutierrez@amd.com
156311308Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c0;
156411308Santhony.gutierrez@amd.com
156511308Santhony.gutierrez@amd.com            c0 *d = &((c0*) gpuDynInst->d_data)[0];
156611308Santhony.gutierrez@amd.com            c0 *e = &((c0*) gpuDynInst->a_data)[0];
156711308Santhony.gutierrez@amd.com            c0 *f = &((c0*) gpuDynInst->x_data)[0];
156811308Santhony.gutierrez@amd.com
156911534Sjohn.kalamatianos@amd.com            for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) {
157011308Santhony.gutierrez@amd.com                if (gpuDynInst->exec_mask[i]) {
157111308Santhony.gutierrez@amd.com                    Addr vaddr = gpuDynInst->addr[i];
157211308Santhony.gutierrez@amd.com
157311692Santhony.gutierrez@amd.com                    if (this->isLocalMem()) {
157411308Santhony.gutierrez@amd.com                        Wavefront *wavefront = gpuDynInst->wavefront();
157511308Santhony.gutierrez@amd.com                        *d = wavefront->ldsChunk->read<c0>(vaddr);
157611308Santhony.gutierrez@amd.com
157711692Santhony.gutierrez@amd.com                        if (this->isAtomicAdd()) {
157811308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
157911308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) + (*e));
158011692Santhony.gutierrez@amd.com                        } else if (this->isAtomicSub()) {
158111308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
158211308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) - (*e));
158311692Santhony.gutierrez@amd.com                        } else if (this->isAtomicMax()) {
158411308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
158511308Santhony.gutierrez@amd.com                            std::max(wavefront->ldsChunk->read<c0>(vaddr),
158611308Santhony.gutierrez@amd.com                            (*e)));
158711692Santhony.gutierrez@amd.com                        } else if (this->isAtomicMin()) {
158811308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
158911308Santhony.gutierrez@amd.com                            std::min(wavefront->ldsChunk->read<c0>(vaddr),
159011308Santhony.gutierrez@amd.com                            (*e)));
159111692Santhony.gutierrez@amd.com                        } else if (this->isAtomicAnd()) {
159211308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
159311308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) & (*e));
159411692Santhony.gutierrez@amd.com                        } else if (this->isAtomicOr()) {
159511308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
159611308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) | (*e));
159711692Santhony.gutierrez@amd.com                        } else if (this->isAtomicXor()) {
159811308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
159911308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) ^ (*e));
160011692Santhony.gutierrez@amd.com                        } else if (this->isAtomicInc()) {
160111308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
160211308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) + 1);
160311692Santhony.gutierrez@amd.com                        } else if (this->isAtomicDec()) {
160411308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
160511308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) - 1);
160611692Santhony.gutierrez@amd.com                        } else if (this->isAtomicExch()) {
160711308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr, (*e));
160811692Santhony.gutierrez@amd.com                        } else if (this->isAtomicCAS()) {
160911308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
161011308Santhony.gutierrez@amd.com                            (wavefront->ldsChunk->read<c0>(vaddr) == (*e)) ?
161111308Santhony.gutierrez@amd.com                            (*f) : wavefront->ldsChunk->read<c0>(vaddr));
161211692Santhony.gutierrez@amd.com                        } else {
161311308Santhony.gutierrez@amd.com                            fatal("Unrecognized or invalid HSAIL atomic op "
161411308Santhony.gutierrez@amd.com                                  "type.\n");
161511308Santhony.gutierrez@amd.com                        }
161611308Santhony.gutierrez@amd.com                    } else {
161711308Santhony.gutierrez@amd.com                        Request *req =
161811308Santhony.gutierrez@amd.com                            new Request(0, vaddr, sizeof(c0), 0,
161911308Santhony.gutierrez@amd.com                                        gpuDynInst->computeUnit()->masterId(),
162011435Smitch.hayenga@arm.com                                        0, gpuDynInst->wfDynId,
162111308Santhony.gutierrez@amd.com                                        gpuDynInst->makeAtomicOpFunctor<c0>(e,
162211692Santhony.gutierrez@amd.com                                        f));
162311308Santhony.gutierrez@amd.com
162411308Santhony.gutierrez@amd.com                        gpuDynInst->setRequestFlags(req);
162511308Santhony.gutierrez@amd.com                        PacketPtr pkt = new Packet(req, MemCmd::SwapReq);
162611308Santhony.gutierrez@amd.com                        pkt->dataStatic(d);
162711308Santhony.gutierrez@amd.com
162811308Santhony.gutierrez@amd.com                        if (gpuDynInst->computeUnit()->shader->
162911308Santhony.gutierrez@amd.com                            separate_acquire_release &&
163011692Santhony.gutierrez@amd.com                            (gpuDynInst->isAcquire())) {
163111308Santhony.gutierrez@amd.com                            // if this atomic has acquire semantics,
163211308Santhony.gutierrez@amd.com                            // schedule the continuation to perform an
163311308Santhony.gutierrez@amd.com                            // acquire after the RMW completes
163411308Santhony.gutierrez@amd.com                            gpuDynInst->execContinuation =
163511308Santhony.gutierrez@amd.com                                &GPUStaticInst::execAtomicAcq;
163611308Santhony.gutierrez@amd.com
163711308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = true;
163811308Santhony.gutierrez@amd.com                        } else {
163911308Santhony.gutierrez@amd.com                            // the request will be finished when the RMW completes
164011308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = false;
164111308Santhony.gutierrez@amd.com                        }
164211308Santhony.gutierrez@amd.com                        // translation is performed in sendRequest()
164311308Santhony.gutierrez@amd.com                        gpuDynInst->computeUnit()->sendRequest(gpuDynInst, i,
164411308Santhony.gutierrez@amd.com                                                               pkt);
164511308Santhony.gutierrez@amd.com                    }
164611308Santhony.gutierrez@amd.com                }
164711308Santhony.gutierrez@amd.com
164811308Santhony.gutierrez@amd.com                ++d;
164911308Santhony.gutierrez@amd.com                ++e;
165011308Santhony.gutierrez@amd.com                ++f;
165111308Santhony.gutierrez@amd.com            }
165211308Santhony.gutierrez@amd.com
165311308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
165411308Santhony.gutierrez@amd.com        }
165511308Santhony.gutierrez@amd.com
165611308Santhony.gutierrez@amd.com        // execAtomicACq will always be called through a continuation.
165711308Santhony.gutierrez@amd.com        // see comment for execContinuation in gpu_dyn_inst.hh
165811308Santhony.gutierrez@amd.com        void
165911308Santhony.gutierrez@amd.com        execAtomicAcq(GPUDynInstPtr gpuDynInst) override
166011308Santhony.gutierrez@amd.com        {
166111308Santhony.gutierrez@amd.com            // after performing the RMW, check to see if this instruction
166211308Santhony.gutierrez@amd.com            // has acquire semantics, and if so, issue an acquire
166311692Santhony.gutierrez@amd.com            if (!this->isLocalMem()) {
166411308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
166511692Santhony.gutierrez@amd.com                     && gpuDynInst->isAcquire()) {
166611308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
166711308Santhony.gutierrez@amd.com
166811308Santhony.gutierrez@amd.com                    // the request will be finished when
166911308Santhony.gutierrez@amd.com                    // the acquire completes
167011308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = false;
167111308Santhony.gutierrez@amd.com                    // create request
167211308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
167311308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
167411435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
167511308Santhony.gutierrez@amd.com                    req->setFlags(Request::ACQUIRE);
167611308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
167711308Santhony.gutierrez@amd.com                }
167811308Santhony.gutierrez@amd.com            }
167911308Santhony.gutierrez@amd.com        }
168011308Santhony.gutierrez@amd.com    };
168111308Santhony.gutierrez@amd.com
168211308Santhony.gutierrez@amd.com    template<typename DataType, typename AddrOperandType, int NumSrcOperands>
168311308Santhony.gutierrez@amd.com    GPUStaticInst*
168411308Santhony.gutierrez@amd.com    constructAtomic(const Brig::BrigInstBase *ib, const BrigObject *obj)
168511308Santhony.gutierrez@amd.com    {
168611308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
168711308Santhony.gutierrez@amd.com
168811308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_LD) {
168911308Santhony.gutierrez@amd.com            return decodeLd<DataType>(ib, obj);
169011308Santhony.gutierrez@amd.com        } else if (at->atomicOperation == Brig::BRIG_ATOMIC_ST) {
169111308Santhony.gutierrez@amd.com            switch (ib->type) {
169211308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B8:
169311308Santhony.gutierrez@amd.com                return decodeSt<S8,S8>(ib, obj);
169411308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B16:
169511536Staquangtuan1992@gmail.com                return decodeSt<S16,S16>(ib, obj);
169611308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B32:
169711536Staquangtuan1992@gmail.com                return decodeSt<S32,S32>(ib, obj);
169811308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B64:
169911536Staquangtuan1992@gmail.com                return decodeSt<S64,S64>(ib, obj);
170011308Santhony.gutierrez@amd.com              default: fatal("AtomicSt: Operand type mismatch %d\n", ib->type);
170111308Santhony.gutierrez@amd.com            }
170211308Santhony.gutierrez@amd.com        } else {
170311308Santhony.gutierrez@amd.com            if ((Brig::BrigOpcode)ib->opcode == Brig::BRIG_OPCODE_ATOMICNORET)
170411308Santhony.gutierrez@amd.com                return new AtomicInst<DataType, AddrOperandType,
170511308Santhony.gutierrez@amd.com                    NumSrcOperands, false>(ib, obj, "atomicnoret");
170611308Santhony.gutierrez@amd.com            else
170711308Santhony.gutierrez@amd.com                return new AtomicInst<DataType, AddrOperandType,
170811308Santhony.gutierrez@amd.com                    NumSrcOperands, true>(ib, obj, "atomic");
170911308Santhony.gutierrez@amd.com        }
171011308Santhony.gutierrez@amd.com    }
171111308Santhony.gutierrez@amd.com
171211308Santhony.gutierrez@amd.com    template<typename DataType, int NumSrcOperands>
171311308Santhony.gutierrez@amd.com    GPUStaticInst*
171411308Santhony.gutierrez@amd.com    decodeAtomicHelper(const Brig::BrigInstBase *ib, const BrigObject *obj)
171511308Santhony.gutierrez@amd.com    {
171611308Santhony.gutierrez@amd.com        unsigned addrIndex = (Brig::BrigOpcode)ib->opcode ==
171711308Santhony.gutierrez@amd.com            Brig::BRIG_OPCODE_ATOMICNORET ? 0 : 1;
171811308Santhony.gutierrez@amd.com
171911308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,addrIndex);
172011308Santhony.gutierrez@amd.com
172111308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
172211308Santhony.gutierrez@amd.com
172311308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
172411308Santhony.gutierrez@amd.com            return constructAtomic<DataType, NoRegAddrOperand,
172511308Santhony.gutierrez@amd.com                                   NumSrcOperands>(ib, obj);
172611308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER) {
172711308Santhony.gutierrez@amd.com            // V2/V4 not allowed
172811308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
172911308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
173011308Santhony.gutierrez@amd.com                  return constructAtomic<DataType, SRegAddrOperand,
173111308Santhony.gutierrez@amd.com                                         NumSrcOperands>(ib, obj);
173211308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
173311308Santhony.gutierrez@amd.com                return constructAtomic<DataType, DRegAddrOperand,
173411308Santhony.gutierrez@amd.com                                       NumSrcOperands>(ib, obj);
173511308Santhony.gutierrez@amd.com              default:
173611308Santhony.gutierrez@amd.com                fatal("Bad atomic register operand type %d\n", tmp.type);
173711308Santhony.gutierrez@amd.com            }
173811308Santhony.gutierrez@amd.com        } else {
173911308Santhony.gutierrez@amd.com            fatal("Bad atomic register operand kind %d\n", tmp.kind);
174011308Santhony.gutierrez@amd.com        }
174111308Santhony.gutierrez@amd.com    }
174211308Santhony.gutierrez@amd.com
174311308Santhony.gutierrez@amd.com
174411308Santhony.gutierrez@amd.com    template<typename DataType>
174511308Santhony.gutierrez@amd.com    GPUStaticInst*
174611308Santhony.gutierrez@amd.com    decodeAtomic(const Brig::BrigInstBase *ib, const BrigObject *obj)
174711308Santhony.gutierrez@amd.com    {
174811308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
174911308Santhony.gutierrez@amd.com
175011308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_CAS) {
175111308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 2>(ib, obj);
175211308Santhony.gutierrez@amd.com        } else {
175311308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 1>(ib, obj);
175411308Santhony.gutierrez@amd.com        }
175511308Santhony.gutierrez@amd.com    }
175611308Santhony.gutierrez@amd.com
175711308Santhony.gutierrez@amd.com    template<typename DataType>
175811308Santhony.gutierrez@amd.com    GPUStaticInst*
175911308Santhony.gutierrez@amd.com    decodeAtomicNoRet(const Brig::BrigInstBase *ib, const BrigObject *obj)
176011308Santhony.gutierrez@amd.com    {
176111308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
176211308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_CAS) {
176311308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 2>(ib, obj);
176411308Santhony.gutierrez@amd.com        } else {
176511308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 1>(ib, obj);
176611308Santhony.gutierrez@amd.com        }
176711308Santhony.gutierrez@amd.com    }
176811308Santhony.gutierrez@amd.com} // namespace HsailISA
176911308Santhony.gutierrez@amd.com
177011308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_MEM_HH__
1771