mem.hh revision 11692
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
3911308Santhony.gutierrez@amd.com#include "arch/hsail/insts/decl.hh"
4011308Santhony.gutierrez@amd.com#include "arch/hsail/insts/gpu_static_inst.hh"
4111308Santhony.gutierrez@amd.com#include "arch/hsail/operand.hh"
4211308Santhony.gutierrez@amd.com
4311308Santhony.gutierrez@amd.comnamespace HsailISA
4411308Santhony.gutierrez@amd.com{
4511308Santhony.gutierrez@amd.com    class MemInst
4611308Santhony.gutierrez@amd.com    {
4711308Santhony.gutierrez@amd.com      public:
4811308Santhony.gutierrez@amd.com        MemInst() : size(0), addr_operand(nullptr) { }
4911308Santhony.gutierrez@amd.com
5011308Santhony.gutierrez@amd.com        MemInst(Enums::MemType m_type)
5111308Santhony.gutierrez@amd.com        {
5211308Santhony.gutierrez@amd.com            if (m_type == Enums::M_U64 ||
5311308Santhony.gutierrez@amd.com                m_type == Enums::M_S64 ||
5411308Santhony.gutierrez@amd.com                m_type == Enums::M_F64) {
5511308Santhony.gutierrez@amd.com                size = 8;
5611308Santhony.gutierrez@amd.com            } else if (m_type == Enums::M_U32 ||
5711308Santhony.gutierrez@amd.com                       m_type == Enums::M_S32 ||
5811308Santhony.gutierrez@amd.com                       m_type == Enums::M_F32) {
5911308Santhony.gutierrez@amd.com                size = 4;
6011308Santhony.gutierrez@amd.com            } else if (m_type == Enums::M_U16 ||
6111308Santhony.gutierrez@amd.com                       m_type == Enums::M_S16 ||
6211308Santhony.gutierrez@amd.com                       m_type == Enums::M_F16) {
6311308Santhony.gutierrez@amd.com                size = 2;
6411308Santhony.gutierrez@amd.com            } else {
6511308Santhony.gutierrez@amd.com                size = 1;
6611308Santhony.gutierrez@amd.com            }
6711308Santhony.gutierrez@amd.com
6811308Santhony.gutierrez@amd.com            addr_operand = nullptr;
6911308Santhony.gutierrez@amd.com        }
7011308Santhony.gutierrez@amd.com
7111308Santhony.gutierrez@amd.com        void
7211308Santhony.gutierrez@amd.com        init_addr(AddrOperandBase *_addr_operand)
7311308Santhony.gutierrez@amd.com        {
7411308Santhony.gutierrez@amd.com            addr_operand = _addr_operand;
7511308Santhony.gutierrez@amd.com        }
7611308Santhony.gutierrez@amd.com
7711308Santhony.gutierrez@amd.com      private:
7811308Santhony.gutierrez@amd.com        int size;
7911308Santhony.gutierrez@amd.com        AddrOperandBase *addr_operand;
8011308Santhony.gutierrez@amd.com
8111308Santhony.gutierrez@amd.com      public:
8211308Santhony.gutierrez@amd.com        int getMemOperandSize() { return size; }
8311308Santhony.gutierrez@amd.com        AddrOperandBase *getAddressOperand() { return addr_operand; }
8411308Santhony.gutierrez@amd.com    };
8511308Santhony.gutierrez@amd.com
8611308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename AddrOperandType>
8711308Santhony.gutierrez@amd.com    class LdaInstBase : public HsailGPUStaticInst
8811308Santhony.gutierrez@amd.com    {
8911308Santhony.gutierrez@amd.com      public:
9011308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
9111308Santhony.gutierrez@amd.com        AddrOperandType addr;
9211308Santhony.gutierrez@amd.com
9311308Santhony.gutierrez@amd.com        LdaInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
9411308Santhony.gutierrez@amd.com                    const char *_opcode)
9511308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
9611308Santhony.gutierrez@amd.com        {
9711308Santhony.gutierrez@amd.com            using namespace Brig;
9811308Santhony.gutierrez@amd.com
9911692Santhony.gutierrez@amd.com            setFlag(ALU);
10011692Santhony.gutierrez@amd.com
10111308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
10211308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
10311308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
10411308Santhony.gutierrez@amd.com            addr.init(op_offs, obj);
10511308Santhony.gutierrez@amd.com        }
10611308Santhony.gutierrez@amd.com
10711347Sandreas.hansson@arm.com        int numSrcRegOperands() override
10811347Sandreas.hansson@arm.com        { return(this->addr.isVectorRegister()); }
10911347Sandreas.hansson@arm.com        int numDstRegOperands() override
11011347Sandreas.hansson@arm.com        { return dest.isVectorRegister(); }
11111347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
11211308Santhony.gutierrez@amd.com        {
11311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
11411308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isVectorRegister() :
11511308Santhony.gutierrez@amd.com                   this->addr.isVectorRegister());
11611308Santhony.gutierrez@amd.com        }
11711347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
11811308Santhony.gutierrez@amd.com        {
11911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
12011308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isCondRegister() :
12111308Santhony.gutierrez@amd.com                   this->addr.isCondRegister());
12211308Santhony.gutierrez@amd.com        }
12311347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
12411308Santhony.gutierrez@amd.com        {
12511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
12611308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isScalarRegister() :
12711308Santhony.gutierrez@amd.com                   this->addr.isScalarRegister());
12811308Santhony.gutierrez@amd.com        }
12911347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
13011308Santhony.gutierrez@amd.com        {
13111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
13211308Santhony.gutierrez@amd.com            if (operandIndex > 0)
13311308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
13411308Santhony.gutierrez@amd.com            return false;
13511308Santhony.gutierrez@amd.com        }
13611347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override {
13711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
13811308Santhony.gutierrez@amd.com            return(operandIndex == 0);
13911308Santhony.gutierrez@amd.com        }
14011347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
14111308Santhony.gutierrez@amd.com        {
14211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
14311308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.opSize() :
14411308Santhony.gutierrez@amd.com                   this->addr.opSize());
14511308Santhony.gutierrez@amd.com        }
14611347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
14711308Santhony.gutierrez@amd.com        {
14811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
14911308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.regIndex() :
15011308Santhony.gutierrez@amd.com                   this->addr.regIndex());
15111308Santhony.gutierrez@amd.com        }
15211347Sandreas.hansson@arm.com        int getNumOperands() override
15311308Santhony.gutierrez@amd.com        {
15411308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister())
15511308Santhony.gutierrez@amd.com                return 2;
15611308Santhony.gutierrez@amd.com            return 1;
15711308Santhony.gutierrez@amd.com        }
15811308Santhony.gutierrez@amd.com    };
15911308Santhony.gutierrez@amd.com
16011308Santhony.gutierrez@amd.com    template<typename DestDataType, typename AddrOperandType>
16111308Santhony.gutierrez@amd.com    class LdaInst :
16211308Santhony.gutierrez@amd.com        public LdaInstBase<typename DestDataType::OperandType, AddrOperandType>,
16311308Santhony.gutierrez@amd.com        public MemInst
16411308Santhony.gutierrez@amd.com    {
16511308Santhony.gutierrez@amd.com      public:
16611308Santhony.gutierrez@amd.com        void generateDisassembly();
16711308Santhony.gutierrez@amd.com
16811308Santhony.gutierrez@amd.com        LdaInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
16911308Santhony.gutierrez@amd.com                        const char *_opcode)
17011308Santhony.gutierrez@amd.com            : LdaInstBase<typename DestDataType::OperandType,
17111308Santhony.gutierrez@amd.com                          AddrOperandType>(ib, obj, _opcode)
17211308Santhony.gutierrez@amd.com        {
17311308Santhony.gutierrez@amd.com            init_addr(&this->addr);
17411308Santhony.gutierrez@amd.com        }
17511308Santhony.gutierrez@amd.com
17611308Santhony.gutierrez@amd.com        void execute(GPUDynInstPtr gpuDynInst);
17711308Santhony.gutierrez@amd.com    };
17811308Santhony.gutierrez@amd.com
17911308Santhony.gutierrez@amd.com    template<typename DataType>
18011308Santhony.gutierrez@amd.com    GPUStaticInst*
18111308Santhony.gutierrez@amd.com    decodeLda(const Brig::BrigInstBase *ib, const BrigObject *obj)
18211308Santhony.gutierrez@amd.com    {
18311308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands, 1);
18411308Santhony.gutierrez@amd.com        BrigRegOperandInfo regDataType = findRegDataType(op_offs, obj);
18511308Santhony.gutierrez@amd.com
18611308Santhony.gutierrez@amd.com        if (regDataType.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
18711308Santhony.gutierrez@amd.com            return new LdaInst<DataType, NoRegAddrOperand>(ib, obj, "ldas");
18811308Santhony.gutierrez@amd.com        } else if (regDataType.kind == Brig::BRIG_KIND_OPERAND_REGISTER) {
18911308Santhony.gutierrez@amd.com            // V2/V4 not allowed
19011308Santhony.gutierrez@amd.com            switch (regDataType.regKind) {
19111308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
19211308Santhony.gutierrez@amd.com                return new LdaInst<DataType, SRegAddrOperand>(ib, obj, "ldas");
19311308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
19411308Santhony.gutierrez@amd.com                return new LdaInst<DataType, DRegAddrOperand>(ib, obj, "ldas");
19511308Santhony.gutierrez@amd.com              default:
19611308Santhony.gutierrez@amd.com                fatal("Bad ldas register operand type %d\n", regDataType.type);
19711308Santhony.gutierrez@amd.com            }
19811308Santhony.gutierrez@amd.com        } else {
19911308Santhony.gutierrez@amd.com            fatal("Bad ldas register operand kind %d\n", regDataType.kind);
20011308Santhony.gutierrez@amd.com        }
20111308Santhony.gutierrez@amd.com    }
20211308Santhony.gutierrez@amd.com
20311308Santhony.gutierrez@amd.com    template<typename MemOperandType, typename DestOperandType,
20411308Santhony.gutierrez@amd.com             typename AddrOperandType>
20511308Santhony.gutierrez@amd.com    class LdInstBase : public HsailGPUStaticInst
20611308Santhony.gutierrez@amd.com    {
20711308Santhony.gutierrez@amd.com      public:
20811308Santhony.gutierrez@amd.com        Brig::BrigWidth8_t width;
20911308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
21011308Santhony.gutierrez@amd.com        AddrOperandType addr;
21111308Santhony.gutierrez@amd.com
21211308Santhony.gutierrez@amd.com        Brig::BrigSegment segment;
21311308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memoryOrder;
21411308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memoryScope;
21511308Santhony.gutierrez@amd.com        unsigned int equivClass;
21611308Santhony.gutierrez@amd.com
21711308Santhony.gutierrez@amd.com        LdInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
21811308Santhony.gutierrez@amd.com                   const char *_opcode)
21911308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
22011308Santhony.gutierrez@amd.com        {
22111308Santhony.gutierrez@amd.com            using namespace Brig;
22211308Santhony.gutierrez@amd.com
22311692Santhony.gutierrez@amd.com            setFlag(MemoryRef);
22411692Santhony.gutierrez@amd.com            setFlag(Load);
22511692Santhony.gutierrez@amd.com
22611308Santhony.gutierrez@amd.com            if (ib->opcode == BRIG_OPCODE_LD) {
22711692Santhony.gutierrez@amd.com                const BrigInstMem *ldst = (const BrigInstMem*)ib;
22811692Santhony.gutierrez@amd.com
22911692Santhony.gutierrez@amd.com                segment = (BrigSegment)ldst->segment;
23011692Santhony.gutierrez@amd.com                memoryOrder = BRIG_MEMORY_ORDER_NONE;
23111692Santhony.gutierrez@amd.com                memoryScope = BRIG_MEMORY_SCOPE_NONE;
23211692Santhony.gutierrez@amd.com                equivClass = ldst->equivClass;
23311692Santhony.gutierrez@amd.com
23411692Santhony.gutierrez@amd.com                width = ldst->width;
23511692Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
23611692Santhony.gutierrez@amd.com                const Brig::BrigOperand *brigOp = obj->getOperand(op_offs);
23711692Santhony.gutierrez@amd.com                if (brigOp->kind == BRIG_KIND_OPERAND_REGISTER)
23811692Santhony.gutierrez@amd.com                    dest.init(op_offs, obj);
23911692Santhony.gutierrez@amd.com
24011692Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands, 1);
24111692Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
24211308Santhony.gutierrez@amd.com            } else {
24311692Santhony.gutierrez@amd.com                const BrigInstAtomic *at = (const BrigInstAtomic*)ib;
24411692Santhony.gutierrez@amd.com
24511692Santhony.gutierrez@amd.com                segment = (BrigSegment)at->segment;
24611692Santhony.gutierrez@amd.com                memoryOrder = (BrigMemoryOrder)at->memoryOrder;
24711692Santhony.gutierrez@amd.com                memoryScope = (BrigMemoryScope)at->memoryScope;
24811692Santhony.gutierrez@amd.com                equivClass = 0;
24911692Santhony.gutierrez@amd.com
25011692Santhony.gutierrez@amd.com                width = BRIG_WIDTH_1;
25111692Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
25211692Santhony.gutierrez@amd.com                const Brig::BrigOperand *brigOp = obj->getOperand(op_offs);
25311692Santhony.gutierrez@amd.com
25411692Santhony.gutierrez@amd.com                if (brigOp->kind == BRIG_KIND_OPERAND_REGISTER)
25511692Santhony.gutierrez@amd.com                    dest.init(op_offs, obj);
25611692Santhony.gutierrez@amd.com
25711692Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands,1);
25811692Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
25911692Santhony.gutierrez@amd.com            }
26011692Santhony.gutierrez@amd.com
26111692Santhony.gutierrez@amd.com            switch (memoryOrder) {
26211692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_NONE:
26311692Santhony.gutierrez@amd.com                setFlag(NoOrder);
26411692Santhony.gutierrez@amd.com                break;
26511692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_RELAXED:
26611692Santhony.gutierrez@amd.com                setFlag(RelaxedOrder);
26711692Santhony.gutierrez@amd.com                break;
26811692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE:
26911692Santhony.gutierrez@amd.com                setFlag(Acquire);
27011692Santhony.gutierrez@amd.com                break;
27111692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_RELEASE:
27211692Santhony.gutierrez@amd.com                setFlag(Release);
27311692Santhony.gutierrez@amd.com                break;
27411692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE:
27511692Santhony.gutierrez@amd.com                setFlag(AcquireRelease);
27611692Santhony.gutierrez@amd.com                break;
27711692Santhony.gutierrez@amd.com              default:
27811692Santhony.gutierrez@amd.com                fatal("LdInst has bad memory order type\n");
27911692Santhony.gutierrez@amd.com            }
28011692Santhony.gutierrez@amd.com
28111692Santhony.gutierrez@amd.com            switch (memoryScope) {
28211692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_NONE:
28311692Santhony.gutierrez@amd.com                setFlag(NoScope);
28411692Santhony.gutierrez@amd.com                break;
28511692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKITEM:
28611692Santhony.gutierrez@amd.com                setFlag(WorkitemScope);
28711692Santhony.gutierrez@amd.com                break;
28811692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKGROUP:
28911692Santhony.gutierrez@amd.com                setFlag(WorkgroupScope);
29011692Santhony.gutierrez@amd.com                break;
29111692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_AGENT:
29211692Santhony.gutierrez@amd.com                setFlag(DeviceScope);
29311692Santhony.gutierrez@amd.com                break;
29411692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_SYSTEM:
29511692Santhony.gutierrez@amd.com                setFlag(SystemScope);
29611692Santhony.gutierrez@amd.com                break;
29711692Santhony.gutierrez@amd.com              default:
29811692Santhony.gutierrez@amd.com                fatal("LdInst has bad memory scope type\n");
29911692Santhony.gutierrez@amd.com            }
30011692Santhony.gutierrez@amd.com
30111692Santhony.gutierrez@amd.com            switch (segment) {
30211692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
30311692Santhony.gutierrez@amd.com                setFlag(GlobalSegment);
30411692Santhony.gutierrez@amd.com                break;
30511692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
30611692Santhony.gutierrez@amd.com                setFlag(GroupSegment);
30711692Santhony.gutierrez@amd.com                break;
30811692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_PRIVATE:
30911692Santhony.gutierrez@amd.com                setFlag(PrivateSegment);
31011692Santhony.gutierrez@amd.com                break;
31111692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_READONLY:
31211692Santhony.gutierrez@amd.com                setFlag(ReadOnlySegment);
31311692Santhony.gutierrez@amd.com                break;
31411692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_SPILL:
31511692Santhony.gutierrez@amd.com                setFlag(SpillSegment);
31611692Santhony.gutierrez@amd.com                break;
31711692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
31811692Santhony.gutierrez@amd.com                setFlag(Flat);
31911692Santhony.gutierrez@amd.com                break;
32011692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_KERNARG:
32111692Santhony.gutierrez@amd.com                setFlag(KernArgSegment);
32211692Santhony.gutierrez@amd.com                break;
32311692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_ARG:
32411692Santhony.gutierrez@amd.com                setFlag(ArgSegment);
32511692Santhony.gutierrez@amd.com                break;
32611692Santhony.gutierrez@amd.com              default:
32711692Santhony.gutierrez@amd.com                panic("Ld: segment %d not supported\n", segment);
32811308Santhony.gutierrez@amd.com            }
32911308Santhony.gutierrez@amd.com        }
33011308Santhony.gutierrez@amd.com
33111347Sandreas.hansson@arm.com        int numSrcRegOperands() override
33211347Sandreas.hansson@arm.com        { return(this->addr.isVectorRegister()); }
33311347Sandreas.hansson@arm.com        int numDstRegOperands() override { return dest.isVectorRegister(); }
33411347Sandreas.hansson@arm.com        int getNumOperands() override
33511308Santhony.gutierrez@amd.com        {
33611308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister())
33711308Santhony.gutierrez@amd.com                return 2;
33811308Santhony.gutierrez@amd.com            else
33911308Santhony.gutierrez@amd.com                return 1;
34011308Santhony.gutierrez@amd.com        }
34111347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
34211308Santhony.gutierrez@amd.com        {
34311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
34411308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isVectorRegister() :
34511308Santhony.gutierrez@amd.com                   this->addr.isVectorRegister());
34611308Santhony.gutierrez@amd.com        }
34711347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
34811308Santhony.gutierrez@amd.com        {
34911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
35011308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isCondRegister() :
35111308Santhony.gutierrez@amd.com                   this->addr.isCondRegister());
35211308Santhony.gutierrez@amd.com        }
35311347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
35411308Santhony.gutierrez@amd.com        {
35511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
35611308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isScalarRegister() :
35711308Santhony.gutierrez@amd.com                   this->addr.isScalarRegister());
35811308Santhony.gutierrez@amd.com        }
35911347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
36011308Santhony.gutierrez@amd.com        {
36111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
36211308Santhony.gutierrez@amd.com            if (operandIndex > 0)
36311308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
36411308Santhony.gutierrez@amd.com            return false;
36511308Santhony.gutierrez@amd.com        }
36611347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override
36711308Santhony.gutierrez@amd.com        {
36811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
36911308Santhony.gutierrez@amd.com            return(operandIndex == 0);
37011308Santhony.gutierrez@amd.com        }
37111347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
37211308Santhony.gutierrez@amd.com        {
37311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
37411308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.opSize() :
37511308Santhony.gutierrez@amd.com                   this->addr.opSize());
37611308Santhony.gutierrez@amd.com        }
37711347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
37811308Santhony.gutierrez@amd.com        {
37911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
38011308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.regIndex() :
38111308Santhony.gutierrez@amd.com                   this->addr.regIndex());
38211308Santhony.gutierrez@amd.com        }
38311308Santhony.gutierrez@amd.com    };
38411308Santhony.gutierrez@amd.com
38511308Santhony.gutierrez@amd.com    template<typename MemDataType, typename DestDataType,
38611308Santhony.gutierrez@amd.com             typename AddrOperandType>
38711308Santhony.gutierrez@amd.com    class LdInst :
38811308Santhony.gutierrez@amd.com        public LdInstBase<typename MemDataType::CType,
38911308Santhony.gutierrez@amd.com                          typename DestDataType::OperandType, AddrOperandType>,
39011308Santhony.gutierrez@amd.com        public MemInst
39111308Santhony.gutierrez@amd.com    {
39211308Santhony.gutierrez@amd.com        typename DestDataType::OperandType::DestOperand dest_vect[4];
39311308Santhony.gutierrez@amd.com        uint16_t num_dest_operands;
39411347Sandreas.hansson@arm.com        void generateDisassembly() override;
39511308Santhony.gutierrez@amd.com
39611308Santhony.gutierrez@amd.com      public:
39711308Santhony.gutierrez@amd.com        LdInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
39811308Santhony.gutierrez@amd.com               const char *_opcode)
39911308Santhony.gutierrez@amd.com            : LdInstBase<typename MemDataType::CType,
40011308Santhony.gutierrez@amd.com                         typename DestDataType::OperandType,
40111308Santhony.gutierrez@amd.com                         AddrOperandType>(ib, obj, _opcode),
40211308Santhony.gutierrez@amd.com              MemInst(MemDataType::memType)
40311308Santhony.gutierrez@amd.com        {
40411308Santhony.gutierrez@amd.com            init_addr(&this->addr);
40511308Santhony.gutierrez@amd.com
40611308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands,0);
40711308Santhony.gutierrez@amd.com            const Brig::BrigOperand *brigOp = obj->getOperand(op_offs);
40811308Santhony.gutierrez@amd.com
40911308Santhony.gutierrez@amd.com            if (brigOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
41011308Santhony.gutierrez@amd.com                const Brig::BrigOperandOperandList *brigRegVecOp =
41111308Santhony.gutierrez@amd.com                    (const Brig::BrigOperandOperandList*)brigOp;
41211308Santhony.gutierrez@amd.com
41311308Santhony.gutierrez@amd.com                num_dest_operands =
41411308Santhony.gutierrez@amd.com                    *((unsigned*)obj->getData(brigRegVecOp->elements)) / 4;
41511308Santhony.gutierrez@amd.com
41611308Santhony.gutierrez@amd.com                assert(num_dest_operands <= 4);
41711308Santhony.gutierrez@amd.com            } else {
41811308Santhony.gutierrez@amd.com                num_dest_operands = 1;
41911308Santhony.gutierrez@amd.com            }
42011308Santhony.gutierrez@amd.com
42111308Santhony.gutierrez@amd.com            if (num_dest_operands > 1) {
42211308Santhony.gutierrez@amd.com                assert(brigOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST);
42311308Santhony.gutierrez@amd.com
42411308Santhony.gutierrez@amd.com                for (int i = 0; i < num_dest_operands; ++i) {
42511308Santhony.gutierrez@amd.com                    dest_vect[i].init_from_vect(op_offs, obj, i);
42611308Santhony.gutierrez@amd.com                }
42711308Santhony.gutierrez@amd.com            }
42811308Santhony.gutierrez@amd.com        }
42911308Santhony.gutierrez@amd.com
43011308Santhony.gutierrez@amd.com        void
43111308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst) override
43211308Santhony.gutierrez@amd.com        {
43311308Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c0;
43411308Santhony.gutierrez@amd.com
43511308Santhony.gutierrez@amd.com            gpuDynInst->statusBitVector = gpuDynInst->exec_mask;
43611308Santhony.gutierrez@amd.com
43711308Santhony.gutierrez@amd.com            if (num_dest_operands > 1) {
43811534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i)
43911308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i])
44011308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(num_dest_operands);
44111308Santhony.gutierrez@amd.com                    else
44211308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(0);
44311308Santhony.gutierrez@amd.com            }
44411308Santhony.gutierrez@amd.com
44511308Santhony.gutierrez@amd.com            for (int k = 0; k < num_dest_operands; ++k) {
44611308Santhony.gutierrez@amd.com
44711534Sjohn.kalamatianos@amd.com                c0 *d = &((c0*)gpuDynInst->d_data)
44811534Sjohn.kalamatianos@amd.com                    [k * gpuDynInst->computeUnit()->wfSize()];
44911308Santhony.gutierrez@amd.com
45011534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) {
45111308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i]) {
45211308Santhony.gutierrez@amd.com                        Addr vaddr = gpuDynInst->addr[i] + k * sizeof(c0);
45311308Santhony.gutierrez@amd.com
45411692Santhony.gutierrez@amd.com                        if (this->isLocalMem()) {
45511308Santhony.gutierrez@amd.com                            // load from shared memory
45611308Santhony.gutierrez@amd.com                            *d = gpuDynInst->wavefront()->ldsChunk->
45711308Santhony.gutierrez@amd.com                                read<c0>(vaddr);
45811308Santhony.gutierrez@amd.com                        } else {
45911308Santhony.gutierrez@amd.com                            Request *req = new Request(0, vaddr, sizeof(c0), 0,
46011308Santhony.gutierrez@amd.com                                          gpuDynInst->computeUnit()->masterId(),
46111435Smitch.hayenga@arm.com                                          0, gpuDynInst->wfDynId);
46211308Santhony.gutierrez@amd.com
46311308Santhony.gutierrez@amd.com                            gpuDynInst->setRequestFlags(req);
46411308Santhony.gutierrez@amd.com                            PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
46511308Santhony.gutierrez@amd.com                            pkt->dataStatic(d);
46611308Santhony.gutierrez@amd.com
46711308Santhony.gutierrez@amd.com                            if (gpuDynInst->computeUnit()->shader->
46811308Santhony.gutierrez@amd.com                                separate_acquire_release &&
46911692Santhony.gutierrez@amd.com                                gpuDynInst->isAcquire()) {
47011308Santhony.gutierrez@amd.com                                // if this load has acquire semantics,
47111308Santhony.gutierrez@amd.com                                // set the response continuation function
47211308Santhony.gutierrez@amd.com                                // to perform an Acquire request
47311308Santhony.gutierrez@amd.com                                gpuDynInst->execContinuation =
47411308Santhony.gutierrez@amd.com                                    &GPUStaticInst::execLdAcq;
47511308Santhony.gutierrez@amd.com
47611308Santhony.gutierrez@amd.com                                gpuDynInst->useContinuation = true;
47711308Santhony.gutierrez@amd.com                            } else {
47811308Santhony.gutierrez@amd.com                                // the request will be finished when
47911308Santhony.gutierrez@amd.com                                // the load completes
48011308Santhony.gutierrez@amd.com                                gpuDynInst->useContinuation = false;
48111308Santhony.gutierrez@amd.com                            }
48211308Santhony.gutierrez@amd.com                            // translation is performed in sendRequest()
48311308Santhony.gutierrez@amd.com                            gpuDynInst->computeUnit()->sendRequest(gpuDynInst,
48411308Santhony.gutierrez@amd.com                                                                   i, pkt);
48511308Santhony.gutierrez@amd.com                        }
48611308Santhony.gutierrez@amd.com                    }
48711308Santhony.gutierrez@amd.com                    ++d;
48811308Santhony.gutierrez@amd.com                }
48911308Santhony.gutierrez@amd.com            }
49011308Santhony.gutierrez@amd.com
49111308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
49211308Santhony.gutierrez@amd.com        }
49311308Santhony.gutierrez@amd.com
49411308Santhony.gutierrez@amd.com      private:
49511308Santhony.gutierrez@amd.com        void
49611308Santhony.gutierrez@amd.com        execLdAcq(GPUDynInstPtr gpuDynInst) override
49711308Santhony.gutierrez@amd.com        {
49811308Santhony.gutierrez@amd.com            // after the load has complete and if the load has acquire
49911308Santhony.gutierrez@amd.com            // semantics, issue an acquire request.
50011692Santhony.gutierrez@amd.com            if (!this->isLocalMem()) {
50111308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
50211692Santhony.gutierrez@amd.com                    && gpuDynInst->isAcquire()) {
50311308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
50411308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = false;
50511308Santhony.gutierrez@amd.com                    // create request
50611308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
50711308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
50811435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
50911308Santhony.gutierrez@amd.com                    req->setFlags(Request::ACQUIRE);
51011308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
51111308Santhony.gutierrez@amd.com                }
51211308Santhony.gutierrez@amd.com            }
51311308Santhony.gutierrez@amd.com        }
51411308Santhony.gutierrez@amd.com
51511308Santhony.gutierrez@amd.com      public:
51611347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
51711308Santhony.gutierrez@amd.com        {
51811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
51911308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
52011308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
52111308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
52211308Santhony.gutierrez@amd.com            if (num_dest_operands > 1) {
52311308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isVectorRegister();
52411308Santhony.gutierrez@amd.com            }
52511308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1) {
52611308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
52711308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
52811308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isVectorRegister();
52911308Santhony.gutierrez@amd.com            }
53011308Santhony.gutierrez@amd.com            return false;
53111308Santhony.gutierrez@amd.com        }
53211347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
53311308Santhony.gutierrez@amd.com        {
53411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
53511308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
53611308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
53711308Santhony.gutierrez@amd.com                return(this->addr.isCondRegister());
53811308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
53911308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isCondRegister();
54011308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
54111308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
54211308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
54311308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isCondRegister();
54411308Santhony.gutierrez@amd.com            return false;
54511308Santhony.gutierrez@amd.com        }
54611347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
54711308Santhony.gutierrez@amd.com        {
54811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
54911308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
55011308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
55111308Santhony.gutierrez@amd.com                return(this->addr.isScalarRegister());
55211308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
55311308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isScalarRegister();
55411308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
55511308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
55611308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
55711308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isScalarRegister();
55811308Santhony.gutierrez@amd.com            return false;
55911308Santhony.gutierrez@amd.com        }
56011347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
56111308Santhony.gutierrez@amd.com        {
56211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
56311308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
56411308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
56511308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
56611308Santhony.gutierrez@amd.com            return false;
56711308Santhony.gutierrez@amd.com        }
56811347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override
56911308Santhony.gutierrez@amd.com        {
57011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
57111308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
57211308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
57311308Santhony.gutierrez@amd.com                return false;
57411308Santhony.gutierrez@amd.com            return true;
57511308Santhony.gutierrez@amd.com        }
57611347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
57711308Santhony.gutierrez@amd.com        {
57811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
57911308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
58011308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
58111308Santhony.gutierrez@amd.com                return(this->addr.opSize());
58211308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
58311308Santhony.gutierrez@amd.com                return(dest_vect[operandIndex].opSize());
58411308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
58511308Santhony.gutierrez@amd.com                return(LdInstBase<typename MemDataType::CType,
58611308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
58711308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.opSize());
58811308Santhony.gutierrez@amd.com            return 0;
58911308Santhony.gutierrez@amd.com        }
59011347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
59111308Santhony.gutierrez@amd.com        {
59211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
59311308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
59411308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
59511308Santhony.gutierrez@amd.com                return(this->addr.regIndex());
59611308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
59711308Santhony.gutierrez@amd.com                return(dest_vect[operandIndex].regIndex());
59811308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
59911308Santhony.gutierrez@amd.com                return(LdInstBase<typename MemDataType::CType,
60011308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
60111308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.regIndex());
60211308Santhony.gutierrez@amd.com            return -1;
60311308Santhony.gutierrez@amd.com        }
60411347Sandreas.hansson@arm.com        int getNumOperands() override
60511308Santhony.gutierrez@amd.com        {
60611308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
60711308Santhony.gutierrez@amd.com                return(num_dest_operands+1);
60811308Santhony.gutierrez@amd.com            else
60911308Santhony.gutierrez@amd.com                return(num_dest_operands);
61011308Santhony.gutierrez@amd.com        }
61111347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
61211308Santhony.gutierrez@amd.com    };
61311308Santhony.gutierrez@amd.com
61411308Santhony.gutierrez@amd.com    template<typename MemDT, typename DestDT>
61511308Santhony.gutierrez@amd.com    GPUStaticInst*
61611308Santhony.gutierrez@amd.com    decodeLd2(const Brig::BrigInstBase *ib, const BrigObject *obj)
61711308Santhony.gutierrez@amd.com    {
61811308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,1);
61911308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
62011308Santhony.gutierrez@amd.com
62111308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
62211308Santhony.gutierrez@amd.com            return new LdInst<MemDT, DestDT, NoRegAddrOperand>(ib, obj, "ld");
62311308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER ||
62411308Santhony.gutierrez@amd.com                   tmp.kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
62511308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
62611308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
62711308Santhony.gutierrez@amd.com                return new LdInst<MemDT, DestDT,
62811308Santhony.gutierrez@amd.com                                  SRegAddrOperand>(ib, obj, "ld");
62911308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
63011308Santhony.gutierrez@amd.com                return new LdInst<MemDT, DestDT,
63111308Santhony.gutierrez@amd.com                                  DRegAddrOperand>(ib, obj, "ld");
63211308Santhony.gutierrez@amd.com              default:
63311308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d\n", tmp.regKind);
63411308Santhony.gutierrez@amd.com            }
63511308Santhony.gutierrez@amd.com        } else {
63611308Santhony.gutierrez@amd.com            fatal("Bad ld register operand kind %d\n", tmp.kind);
63711308Santhony.gutierrez@amd.com        }
63811308Santhony.gutierrez@amd.com    }
63911308Santhony.gutierrez@amd.com
64011308Santhony.gutierrez@amd.com    template<typename MemDT>
64111308Santhony.gutierrez@amd.com    GPUStaticInst*
64211308Santhony.gutierrez@amd.com    decodeLd(const Brig::BrigInstBase *ib, const BrigObject *obj)
64311308Santhony.gutierrez@amd.com    {
64411308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,0);
64511308Santhony.gutierrez@amd.com        BrigRegOperandInfo dest = findRegDataType(op_offs, obj);
64611308Santhony.gutierrez@amd.com
64711308Santhony.gutierrez@amd.com        assert(dest.kind == Brig::BRIG_KIND_OPERAND_REGISTER ||
64811308Santhony.gutierrez@amd.com               dest.kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST);
64911308Santhony.gutierrez@amd.com        switch(dest.regKind) {
65011308Santhony.gutierrez@amd.com          case Brig::BRIG_REGISTER_KIND_SINGLE:
65111308Santhony.gutierrez@amd.com            switch (ib->type) {
65211308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B8:
65311308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B16:
65411308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B32:
65511308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, B32>(ib, obj);
65611308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U8:
65711308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U16:
65811308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U32:
65911308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U32>(ib, obj);
66011308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S8:
66111308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S16:
66211308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S32:
66311308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, S32>(ib, obj);
66411308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F16:
66511308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F32:
66611308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U32>(ib, obj);
66711308Santhony.gutierrez@amd.com              default:
66811308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d, %d\n",
66911308Santhony.gutierrez@amd.com                      dest.regKind, ib->type);
67011308Santhony.gutierrez@amd.com            };
67111308Santhony.gutierrez@amd.com          case Brig::BRIG_REGISTER_KIND_DOUBLE:
67211308Santhony.gutierrez@amd.com            switch (ib->type) {
67311308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B64:
67411308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, B64>(ib, obj);
67511308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U64:
67611308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U64>(ib, obj);
67711308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S64:
67811308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, S64>(ib, obj);
67911308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F64:
68011308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U64>(ib, obj);
68111308Santhony.gutierrez@amd.com              default:
68211308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d, %d\n",
68311308Santhony.gutierrez@amd.com                      dest.regKind, ib->type);
68411308Santhony.gutierrez@amd.com            };
68511308Santhony.gutierrez@amd.com          default:
68611308Santhony.gutierrez@amd.com            fatal("Bad ld register operand type %d, %d\n", dest.regKind,
68711308Santhony.gutierrez@amd.com                  ib->type);
68811308Santhony.gutierrez@amd.com        }
68911308Santhony.gutierrez@amd.com    }
69011308Santhony.gutierrez@amd.com
69111308Santhony.gutierrez@amd.com    template<typename MemDataType, typename SrcOperandType,
69211308Santhony.gutierrez@amd.com             typename AddrOperandType>
69311308Santhony.gutierrez@amd.com    class StInstBase : public HsailGPUStaticInst
69411308Santhony.gutierrez@amd.com    {
69511308Santhony.gutierrez@amd.com      public:
69611308Santhony.gutierrez@amd.com        typename SrcOperandType::SrcOperand src;
69711308Santhony.gutierrez@amd.com        AddrOperandType addr;
69811308Santhony.gutierrez@amd.com
69911308Santhony.gutierrez@amd.com        Brig::BrigSegment segment;
70011308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memoryScope;
70111308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memoryOrder;
70211308Santhony.gutierrez@amd.com        unsigned int equivClass;
70311308Santhony.gutierrez@amd.com
70411308Santhony.gutierrez@amd.com        StInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
70511308Santhony.gutierrez@amd.com                   const char *_opcode)
70611308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
70711308Santhony.gutierrez@amd.com        {
70811308Santhony.gutierrez@amd.com            using namespace Brig;
70911308Santhony.gutierrez@amd.com
71011692Santhony.gutierrez@amd.com            setFlag(MemoryRef);
71111692Santhony.gutierrez@amd.com            setFlag(Store);
71211692Santhony.gutierrez@amd.com
71311308Santhony.gutierrez@amd.com            if (ib->opcode == BRIG_OPCODE_ST) {
71411692Santhony.gutierrez@amd.com                const BrigInstMem *ldst = (const BrigInstMem*)ib;
71511692Santhony.gutierrez@amd.com
71611692Santhony.gutierrez@amd.com                segment = (BrigSegment)ldst->segment;
71711692Santhony.gutierrez@amd.com                memoryOrder = BRIG_MEMORY_ORDER_NONE;
71811692Santhony.gutierrez@amd.com                memoryScope = BRIG_MEMORY_SCOPE_NONE;
71911692Santhony.gutierrez@amd.com                equivClass = ldst->equivClass;
72011692Santhony.gutierrez@amd.com
72111692Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
72211692Santhony.gutierrez@amd.com                const BrigOperand *baseOp = obj->getOperand(op_offs);
72311692Santhony.gutierrez@amd.com
72411692Santhony.gutierrez@amd.com                if ((baseOp->kind == BRIG_KIND_OPERAND_CONSTANT_BYTES) ||
72511692Santhony.gutierrez@amd.com                    (baseOp->kind == BRIG_KIND_OPERAND_REGISTER)) {
72611692Santhony.gutierrez@amd.com                    src.init(op_offs, obj);
72711692Santhony.gutierrez@amd.com                }
72811692Santhony.gutierrez@amd.com
72911692Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands, 1);
73011692Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
73111308Santhony.gutierrez@amd.com            } else {
73211692Santhony.gutierrez@amd.com                const BrigInstAtomic *at = (const BrigInstAtomic*)ib;
73311692Santhony.gutierrez@amd.com
73411692Santhony.gutierrez@amd.com                segment = (BrigSegment)at->segment;
73511692Santhony.gutierrez@amd.com                memoryScope = (BrigMemoryScope)at->memoryScope;
73611692Santhony.gutierrez@amd.com                memoryOrder = (BrigMemoryOrder)at->memoryOrder;
73711692Santhony.gutierrez@amd.com                equivClass = 0;
73811692Santhony.gutierrez@amd.com
73911692Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
74011692Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
74111692Santhony.gutierrez@amd.com
74211692Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands, 1);
74311692Santhony.gutierrez@amd.com                src.init(op_offs, obj);
74411692Santhony.gutierrez@amd.com            }
74511692Santhony.gutierrez@amd.com
74611692Santhony.gutierrez@amd.com            switch (memoryOrder) {
74711692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_NONE:
74811692Santhony.gutierrez@amd.com                setFlag(NoOrder);
74911692Santhony.gutierrez@amd.com                break;
75011692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_RELAXED:
75111692Santhony.gutierrez@amd.com                setFlag(RelaxedOrder);
75211692Santhony.gutierrez@amd.com                break;
75311692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE:
75411692Santhony.gutierrez@amd.com                setFlag(Acquire);
75511692Santhony.gutierrez@amd.com                break;
75611692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_RELEASE:
75711692Santhony.gutierrez@amd.com                setFlag(Release);
75811692Santhony.gutierrez@amd.com                break;
75911692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE:
76011692Santhony.gutierrez@amd.com                setFlag(AcquireRelease);
76111692Santhony.gutierrez@amd.com                break;
76211692Santhony.gutierrez@amd.com              default:
76311692Santhony.gutierrez@amd.com                fatal("StInst has bad memory order type\n");
76411692Santhony.gutierrez@amd.com            }
76511692Santhony.gutierrez@amd.com
76611692Santhony.gutierrez@amd.com            switch (memoryScope) {
76711692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_NONE:
76811692Santhony.gutierrez@amd.com                setFlag(NoScope);
76911692Santhony.gutierrez@amd.com                break;
77011692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKITEM:
77111692Santhony.gutierrez@amd.com                setFlag(WorkitemScope);
77211692Santhony.gutierrez@amd.com                break;
77311692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKGROUP:
77411692Santhony.gutierrez@amd.com                setFlag(WorkgroupScope);
77511692Santhony.gutierrez@amd.com                break;
77611692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_AGENT:
77711692Santhony.gutierrez@amd.com                setFlag(DeviceScope);
77811692Santhony.gutierrez@amd.com                break;
77911692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_SYSTEM:
78011692Santhony.gutierrez@amd.com                setFlag(SystemScope);
78111692Santhony.gutierrez@amd.com                break;
78211692Santhony.gutierrez@amd.com              default:
78311692Santhony.gutierrez@amd.com                fatal("StInst has bad memory scope type\n");
78411692Santhony.gutierrez@amd.com            }
78511692Santhony.gutierrez@amd.com
78611692Santhony.gutierrez@amd.com            switch (segment) {
78711692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
78811692Santhony.gutierrez@amd.com                setFlag(GlobalSegment);
78911692Santhony.gutierrez@amd.com                break;
79011692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
79111692Santhony.gutierrez@amd.com                setFlag(GroupSegment);
79211692Santhony.gutierrez@amd.com                break;
79311692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_PRIVATE:
79411692Santhony.gutierrez@amd.com                setFlag(PrivateSegment);
79511692Santhony.gutierrez@amd.com                break;
79611692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_READONLY:
79711692Santhony.gutierrez@amd.com                setFlag(ReadOnlySegment);
79811692Santhony.gutierrez@amd.com                break;
79911692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_SPILL:
80011692Santhony.gutierrez@amd.com                setFlag(SpillSegment);
80111692Santhony.gutierrez@amd.com                break;
80211692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
80311692Santhony.gutierrez@amd.com                setFlag(Flat);
80411692Santhony.gutierrez@amd.com                break;
80511692Santhony.gutierrez@amd.com              case BRIG_SEGMENT_ARG:
80611692Santhony.gutierrez@amd.com                setFlag(ArgSegment);
80711692Santhony.gutierrez@amd.com                break;
80811692Santhony.gutierrez@amd.com              default:
80911692Santhony.gutierrez@amd.com                panic("St: segment %d not supported\n", segment);
81011308Santhony.gutierrez@amd.com            }
81111308Santhony.gutierrez@amd.com        }
81211308Santhony.gutierrez@amd.com
81311347Sandreas.hansson@arm.com        int numDstRegOperands() override { return 0; }
81411347Sandreas.hansson@arm.com        int numSrcRegOperands() override
81511308Santhony.gutierrez@amd.com        {
81611308Santhony.gutierrez@amd.com            return src.isVectorRegister() + this->addr.isVectorRegister();
81711308Santhony.gutierrez@amd.com        }
81811347Sandreas.hansson@arm.com        int getNumOperands() override
81911308Santhony.gutierrez@amd.com        {
82011308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
82111308Santhony.gutierrez@amd.com                return 2;
82211308Santhony.gutierrez@amd.com            else
82311308Santhony.gutierrez@amd.com                return 1;
82411308Santhony.gutierrez@amd.com        }
82511347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
82611308Santhony.gutierrez@amd.com        {
82711308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
82811308Santhony.gutierrez@amd.com            return !operandIndex ? src.isVectorRegister() :
82911308Santhony.gutierrez@amd.com                   this->addr.isVectorRegister();
83011308Santhony.gutierrez@amd.com        }
83111347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
83211308Santhony.gutierrez@amd.com        {
83311308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
83411308Santhony.gutierrez@amd.com            return !operandIndex ? src.isCondRegister() :
83511308Santhony.gutierrez@amd.com                   this->addr.isCondRegister();
83611308Santhony.gutierrez@amd.com        }
83711347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
83811308Santhony.gutierrez@amd.com        {
83911308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
84011308Santhony.gutierrez@amd.com            return !operandIndex ? src.isScalarRegister() :
84111308Santhony.gutierrez@amd.com                   this->addr.isScalarRegister();
84211308Santhony.gutierrez@amd.com        }
84311347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
84411308Santhony.gutierrez@amd.com        {
84511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
84611308Santhony.gutierrez@amd.com            return true;
84711308Santhony.gutierrez@amd.com        }
84811347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override { return false; }
84911347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
85011308Santhony.gutierrez@amd.com        {
85111308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
85211308Santhony.gutierrez@amd.com            return !operandIndex ? src.opSize() : this->addr.opSize();
85311308Santhony.gutierrez@amd.com        }
85411347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
85511308Santhony.gutierrez@amd.com        {
85611308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
85711308Santhony.gutierrez@amd.com            return !operandIndex ? src.regIndex() : this->addr.regIndex();
85811308Santhony.gutierrez@amd.com        }
85911308Santhony.gutierrez@amd.com    };
86011308Santhony.gutierrez@amd.com
86111308Santhony.gutierrez@amd.com
86211308Santhony.gutierrez@amd.com    template<typename MemDataType, typename SrcDataType,
86311308Santhony.gutierrez@amd.com             typename AddrOperandType>
86411308Santhony.gutierrez@amd.com    class StInst :
86511308Santhony.gutierrez@amd.com        public StInstBase<MemDataType, typename SrcDataType::OperandType,
86611308Santhony.gutierrez@amd.com                          AddrOperandType>,
86711308Santhony.gutierrez@amd.com        public MemInst
86811308Santhony.gutierrez@amd.com    {
86911308Santhony.gutierrez@amd.com      public:
87011308Santhony.gutierrez@amd.com        typename SrcDataType::OperandType::SrcOperand src_vect[4];
87111308Santhony.gutierrez@amd.com        uint16_t num_src_operands;
87211347Sandreas.hansson@arm.com        void generateDisassembly() override;
87311308Santhony.gutierrez@amd.com
87411308Santhony.gutierrez@amd.com        StInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
87511308Santhony.gutierrez@amd.com                        const char *_opcode, int srcIdx)
87611308Santhony.gutierrez@amd.com            : StInstBase<MemDataType, typename SrcDataType::OperandType,
87711308Santhony.gutierrez@amd.com                         AddrOperandType>(ib, obj, _opcode),
87811308Santhony.gutierrez@amd.com              MemInst(SrcDataType::memType)
87911308Santhony.gutierrez@amd.com        {
88011308Santhony.gutierrez@amd.com            init_addr(&this->addr);
88111308Santhony.gutierrez@amd.com
88211308Santhony.gutierrez@amd.com            BrigRegOperandInfo rinfo;
88311308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands,srcIdx);
88411308Santhony.gutierrez@amd.com            const Brig::BrigOperand *baseOp = obj->getOperand(op_offs);
88511308Santhony.gutierrez@amd.com
88611308Santhony.gutierrez@amd.com            if (baseOp->kind == Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES) {
88711308Santhony.gutierrez@amd.com                const Brig::BrigOperandConstantBytes *op =
88811308Santhony.gutierrez@amd.com                    (Brig::BrigOperandConstantBytes*)baseOp;
88911308Santhony.gutierrez@amd.com
89011308Santhony.gutierrez@amd.com                rinfo = BrigRegOperandInfo((Brig::BrigKind16_t)op->base.kind,
89111308Santhony.gutierrez@amd.com                                           Brig::BRIG_TYPE_NONE);
89211308Santhony.gutierrez@amd.com            } else {
89311308Santhony.gutierrez@amd.com                rinfo = findRegDataType(op_offs, obj);
89411308Santhony.gutierrez@amd.com            }
89511308Santhony.gutierrez@amd.com
89611308Santhony.gutierrez@amd.com            if (baseOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
89711308Santhony.gutierrez@amd.com                const Brig::BrigOperandOperandList *brigRegVecOp =
89811308Santhony.gutierrez@amd.com                    (const Brig::BrigOperandOperandList*)baseOp;
89911308Santhony.gutierrez@amd.com
90011308Santhony.gutierrez@amd.com                num_src_operands =
90111308Santhony.gutierrez@amd.com                    *((unsigned*)obj->getData(brigRegVecOp->elements)) / 4;
90211308Santhony.gutierrez@amd.com
90311308Santhony.gutierrez@amd.com                assert(num_src_operands <= 4);
90411308Santhony.gutierrez@amd.com            } else {
90511308Santhony.gutierrez@amd.com                num_src_operands = 1;
90611308Santhony.gutierrez@amd.com            }
90711308Santhony.gutierrez@amd.com
90811308Santhony.gutierrez@amd.com            if (num_src_operands > 1) {
90911308Santhony.gutierrez@amd.com                assert(baseOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST);
91011308Santhony.gutierrez@amd.com
91111308Santhony.gutierrez@amd.com                for (int i = 0; i < num_src_operands; ++i) {
91211308Santhony.gutierrez@amd.com                    src_vect[i].init_from_vect(op_offs, obj, i);
91311308Santhony.gutierrez@amd.com                }
91411308Santhony.gutierrez@amd.com            }
91511308Santhony.gutierrez@amd.com        }
91611308Santhony.gutierrez@amd.com
91711308Santhony.gutierrez@amd.com        void
91811308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst) override
91911308Santhony.gutierrez@amd.com        {
92011308Santhony.gutierrez@amd.com            // before performing a store, check if this store has
92111308Santhony.gutierrez@amd.com            // release semantics, and if so issue a release first
92211692Santhony.gutierrez@amd.com            if (!this->isLocalMem()) {
92311308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
92411692Santhony.gutierrez@amd.com                    && gpuDynInst->isRelease()) {
92511308Santhony.gutierrez@amd.com
92611308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
92711308Santhony.gutierrez@amd.com                    gpuDynInst->execContinuation = &GPUStaticInst::execSt;
92811308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = true;
92911308Santhony.gutierrez@amd.com                    // create request
93011308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
93111308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
93211435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
93311308Santhony.gutierrez@amd.com                    req->setFlags(Request::RELEASE);
93411308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
93511308Santhony.gutierrez@amd.com
93611308Santhony.gutierrez@amd.com                    return;
93711308Santhony.gutierrez@amd.com                }
93811308Santhony.gutierrez@amd.com            }
93911308Santhony.gutierrez@amd.com
94011308Santhony.gutierrez@amd.com            // if there is no release semantic, perform stores immediately
94111308Santhony.gutierrez@amd.com            execSt(gpuDynInst);
94211308Santhony.gutierrez@amd.com        }
94311308Santhony.gutierrez@amd.com
94411308Santhony.gutierrez@amd.com      private:
94511308Santhony.gutierrez@amd.com        // execSt may be called through a continuation
94611308Santhony.gutierrez@amd.com        // if the store had release semantics. see comment for
94711308Santhony.gutierrez@amd.com        // execSt in gpu_static_inst.hh
94811308Santhony.gutierrez@amd.com        void
94911308Santhony.gutierrez@amd.com        execSt(GPUDynInstPtr gpuDynInst) override
95011308Santhony.gutierrez@amd.com        {
95111308Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c0;
95211308Santhony.gutierrez@amd.com
95311308Santhony.gutierrez@amd.com            gpuDynInst->statusBitVector = gpuDynInst->exec_mask;
95411308Santhony.gutierrez@amd.com
95511308Santhony.gutierrez@amd.com            if (num_src_operands > 1) {
95611534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i)
95711308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i])
95811308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(num_src_operands);
95911308Santhony.gutierrez@amd.com                    else
96011308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(0);
96111308Santhony.gutierrez@amd.com            }
96211308Santhony.gutierrez@amd.com
96311308Santhony.gutierrez@amd.com            for (int k = 0; k < num_src_operands; ++k) {
96411534Sjohn.kalamatianos@amd.com                c0 *d = &((c0*)gpuDynInst->d_data)
96511534Sjohn.kalamatianos@amd.com                    [k * gpuDynInst->computeUnit()->wfSize()];
96611308Santhony.gutierrez@amd.com
96711534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) {
96811308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i]) {
96911308Santhony.gutierrez@amd.com                        Addr vaddr = gpuDynInst->addr[i] + k * sizeof(c0);
97011308Santhony.gutierrez@amd.com
97111692Santhony.gutierrez@amd.com                        if (this->isLocalMem()) {
97211308Santhony.gutierrez@amd.com                            //store to shared memory
97311308Santhony.gutierrez@amd.com                            gpuDynInst->wavefront()->ldsChunk->write<c0>(vaddr,
97411308Santhony.gutierrez@amd.com                                                                         *d);
97511308Santhony.gutierrez@amd.com                        } else {
97611308Santhony.gutierrez@amd.com                            Request *req =
97711308Santhony.gutierrez@amd.com                              new Request(0, vaddr, sizeof(c0), 0,
97811308Santhony.gutierrez@amd.com                                          gpuDynInst->computeUnit()->masterId(),
97911435Smitch.hayenga@arm.com                                          0, gpuDynInst->wfDynId);
98011308Santhony.gutierrez@amd.com
98111308Santhony.gutierrez@amd.com                            gpuDynInst->setRequestFlags(req);
98211308Santhony.gutierrez@amd.com                            PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
98311308Santhony.gutierrez@amd.com                            pkt->dataStatic<c0>(d);
98411308Santhony.gutierrez@amd.com
98511308Santhony.gutierrez@amd.com                            // translation is performed in sendRequest()
98611308Santhony.gutierrez@amd.com                            // the request will be finished when the store completes
98711308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = false;
98811308Santhony.gutierrez@amd.com                            gpuDynInst->computeUnit()->sendRequest(gpuDynInst,
98911308Santhony.gutierrez@amd.com                                                                   i, pkt);
99011308Santhony.gutierrez@amd.com
99111308Santhony.gutierrez@amd.com                        }
99211308Santhony.gutierrez@amd.com                    }
99311308Santhony.gutierrez@amd.com                    ++d;
99411308Santhony.gutierrez@amd.com                }
99511308Santhony.gutierrez@amd.com            }
99611308Santhony.gutierrez@amd.com
99711308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
99811308Santhony.gutierrez@amd.com        }
99911308Santhony.gutierrez@amd.com
100011308Santhony.gutierrez@amd.com      public:
100111347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
100211308Santhony.gutierrez@amd.com        {
100311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
100411308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
100511308Santhony.gutierrez@amd.com                return this->addr.isVectorRegister();
100611308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
100711308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isVectorRegister();
100811308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
100911308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
101011308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
101111308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isVectorRegister();
101211308Santhony.gutierrez@amd.com            return false;
101311308Santhony.gutierrez@amd.com        }
101411347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
101511308Santhony.gutierrez@amd.com        {
101611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
101711308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
101811308Santhony.gutierrez@amd.com                return this->addr.isCondRegister();
101911308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
102011308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isCondRegister();
102111308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
102211308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
102311308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
102411308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isCondRegister();
102511308Santhony.gutierrez@amd.com            return false;
102611308Santhony.gutierrez@amd.com        }
102711347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
102811308Santhony.gutierrez@amd.com        {
102911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
103011308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
103111308Santhony.gutierrez@amd.com                return this->addr.isScalarRegister();
103211308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
103311308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isScalarRegister();
103411308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
103511308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
103611308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
103711308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isScalarRegister();
103811308Santhony.gutierrez@amd.com            return false;
103911308Santhony.gutierrez@amd.com        }
104011347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
104111308Santhony.gutierrez@amd.com        {
104211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
104311308Santhony.gutierrez@amd.com            return true;
104411308Santhony.gutierrez@amd.com        }
104511347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override { return false; }
104611347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
104711308Santhony.gutierrez@amd.com        {
104811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
104911308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
105011308Santhony.gutierrez@amd.com                return this->addr.opSize();
105111308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
105211308Santhony.gutierrez@amd.com                return src_vect[operandIndex].opSize();
105311308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
105411308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
105511308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
105611308Santhony.gutierrez@amd.com                       AddrOperandType>::src.opSize();
105711308Santhony.gutierrez@amd.com            return 0;
105811308Santhony.gutierrez@amd.com        }
105911347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
106011308Santhony.gutierrez@amd.com        {
106111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
106211308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
106311308Santhony.gutierrez@amd.com                return this->addr.regIndex();
106411308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
106511308Santhony.gutierrez@amd.com                return src_vect[operandIndex].regIndex();
106611308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
106711308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
106811308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
106911308Santhony.gutierrez@amd.com                       AddrOperandType>::src.regIndex();
107011308Santhony.gutierrez@amd.com            return -1;
107111308Santhony.gutierrez@amd.com        }
107211347Sandreas.hansson@arm.com        int getNumOperands() override
107311308Santhony.gutierrez@amd.com        {
107411308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
107511308Santhony.gutierrez@amd.com                return num_src_operands + 1;
107611308Santhony.gutierrez@amd.com            else
107711308Santhony.gutierrez@amd.com                return num_src_operands;
107811308Santhony.gutierrez@amd.com        }
107911347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
108011308Santhony.gutierrez@amd.com    };
108111308Santhony.gutierrez@amd.com
108211308Santhony.gutierrez@amd.com    template<typename DataType, typename SrcDataType>
108311308Santhony.gutierrez@amd.com    GPUStaticInst*
108411308Santhony.gutierrez@amd.com    decodeSt(const Brig::BrigInstBase *ib, const BrigObject *obj)
108511308Santhony.gutierrez@amd.com    {
108611308Santhony.gutierrez@amd.com        int srcIdx = 0;
108711308Santhony.gutierrez@amd.com        int destIdx = 1;
108811308Santhony.gutierrez@amd.com        if (ib->opcode == Brig::BRIG_OPCODE_ATOMIC ||
108911308Santhony.gutierrez@amd.com            ib->opcode == Brig::BRIG_OPCODE_ATOMICNORET) {
109011308Santhony.gutierrez@amd.com            srcIdx = 1;
109111308Santhony.gutierrez@amd.com            destIdx = 0;
109211308Santhony.gutierrez@amd.com        }
109311308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,destIdx);
109411308Santhony.gutierrez@amd.com
109511308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
109611308Santhony.gutierrez@amd.com
109711308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
109811308Santhony.gutierrez@amd.com            return new StInst<DataType, SrcDataType,
109911308Santhony.gutierrez@amd.com                              NoRegAddrOperand>(ib, obj, "st", srcIdx);
110011308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER) {
110111308Santhony.gutierrez@amd.com            // V2/V4 not allowed
110211308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
110311308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
110411308Santhony.gutierrez@amd.com                return new StInst<DataType, SrcDataType,
110511308Santhony.gutierrez@amd.com                                  SRegAddrOperand>(ib, obj, "st", srcIdx);
110611308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
110711308Santhony.gutierrez@amd.com                return new StInst<DataType, SrcDataType,
110811308Santhony.gutierrez@amd.com                                  DRegAddrOperand>(ib, obj, "st", srcIdx);
110911308Santhony.gutierrez@amd.com              default:
111011308Santhony.gutierrez@amd.com                fatal("Bad st register operand type %d\n", tmp.type);
111111308Santhony.gutierrez@amd.com            }
111211308Santhony.gutierrez@amd.com        } else {
111311308Santhony.gutierrez@amd.com            fatal("Bad st register operand kind %d\n", tmp.kind);
111411308Santhony.gutierrez@amd.com        }
111511308Santhony.gutierrez@amd.com    }
111611308Santhony.gutierrez@amd.com
111711308Santhony.gutierrez@amd.com    template<typename OperandType, typename AddrOperandType, int NumSrcOperands,
111811308Santhony.gutierrez@amd.com             bool HasDst>
111911308Santhony.gutierrez@amd.com    class AtomicInstBase : public HsailGPUStaticInst
112011308Santhony.gutierrez@amd.com    {
112111308Santhony.gutierrez@amd.com      public:
112211308Santhony.gutierrez@amd.com        typename OperandType::DestOperand dest;
112311308Santhony.gutierrez@amd.com        typename OperandType::SrcOperand src[NumSrcOperands];
112411308Santhony.gutierrez@amd.com        AddrOperandType addr;
112511308Santhony.gutierrez@amd.com
112611308Santhony.gutierrez@amd.com        Brig::BrigSegment segment;
112711308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memoryOrder;
112811308Santhony.gutierrez@amd.com        Brig::BrigAtomicOperation atomicOperation;
112911308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memoryScope;
113011308Santhony.gutierrez@amd.com        Brig::BrigOpcode opcode;
113111308Santhony.gutierrez@amd.com
113211308Santhony.gutierrez@amd.com        AtomicInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
113311308Santhony.gutierrez@amd.com                       const char *_opcode)
113411308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
113511308Santhony.gutierrez@amd.com        {
113611308Santhony.gutierrez@amd.com            using namespace Brig;
113711308Santhony.gutierrez@amd.com
113811308Santhony.gutierrez@amd.com            const BrigInstAtomic *at = (const BrigInstAtomic*)ib;
113911308Santhony.gutierrez@amd.com
114011308Santhony.gutierrez@amd.com            segment = (BrigSegment)at->segment;
114111308Santhony.gutierrez@amd.com            memoryScope = (BrigMemoryScope)at->memoryScope;
114211308Santhony.gutierrez@amd.com            memoryOrder = (BrigMemoryOrder)at->memoryOrder;
114311308Santhony.gutierrez@amd.com            atomicOperation = (BrigAtomicOperation)at->atomicOperation;
114411308Santhony.gutierrez@amd.com            opcode = (BrigOpcode)ib->opcode;
114511692Santhony.gutierrez@amd.com
114611692Santhony.gutierrez@amd.com            assert(opcode == Brig::BRIG_OPCODE_ATOMICNORET ||
114711692Santhony.gutierrez@amd.com                   opcode == Brig::BRIG_OPCODE_ATOMIC);
114811692Santhony.gutierrez@amd.com
114911692Santhony.gutierrez@amd.com            setFlag(MemoryRef);
115011692Santhony.gutierrez@amd.com
115111692Santhony.gutierrez@amd.com            if (opcode == Brig::BRIG_OPCODE_ATOMIC) {
115211692Santhony.gutierrez@amd.com                setFlag(AtomicReturn);
115311692Santhony.gutierrez@amd.com            } else {
115411692Santhony.gutierrez@amd.com                setFlag(AtomicNoReturn);
115511692Santhony.gutierrez@amd.com            }
115611692Santhony.gutierrez@amd.com
115711692Santhony.gutierrez@amd.com            switch (memoryOrder) {
115811692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_NONE:
115911692Santhony.gutierrez@amd.com                setFlag(NoOrder);
116011692Santhony.gutierrez@amd.com                break;
116111692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_RELAXED:
116211692Santhony.gutierrez@amd.com                setFlag(RelaxedOrder);
116311692Santhony.gutierrez@amd.com                break;
116411692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE:
116511692Santhony.gutierrez@amd.com                setFlag(Acquire);
116611692Santhony.gutierrez@amd.com                break;
116711692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_RELEASE:
116811692Santhony.gutierrez@amd.com                setFlag(Release);
116911692Santhony.gutierrez@amd.com                break;
117011692Santhony.gutierrez@amd.com              case BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE:
117111692Santhony.gutierrez@amd.com                setFlag(AcquireRelease);
117211692Santhony.gutierrez@amd.com                break;
117311692Santhony.gutierrez@amd.com              default:
117411692Santhony.gutierrez@amd.com                fatal("AtomicInst has bad memory order type\n");
117511692Santhony.gutierrez@amd.com            }
117611692Santhony.gutierrez@amd.com
117711692Santhony.gutierrez@amd.com            switch (memoryScope) {
117811692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_NONE:
117911692Santhony.gutierrez@amd.com                setFlag(NoScope);
118011692Santhony.gutierrez@amd.com                break;
118111692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKITEM:
118211692Santhony.gutierrez@amd.com                setFlag(WorkitemScope);
118311692Santhony.gutierrez@amd.com                break;
118411692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_WORKGROUP:
118511692Santhony.gutierrez@amd.com                setFlag(WorkgroupScope);
118611692Santhony.gutierrez@amd.com                break;
118711692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_AGENT:
118811692Santhony.gutierrez@amd.com                setFlag(DeviceScope);
118911692Santhony.gutierrez@amd.com                break;
119011692Santhony.gutierrez@amd.com              case BRIG_MEMORY_SCOPE_SYSTEM:
119111692Santhony.gutierrez@amd.com                setFlag(SystemScope);
119211692Santhony.gutierrez@amd.com                break;
119311692Santhony.gutierrez@amd.com              default:
119411692Santhony.gutierrez@amd.com                fatal("AtomicInst has bad memory scope type\n");
119511692Santhony.gutierrez@amd.com            }
119611692Santhony.gutierrez@amd.com
119711692Santhony.gutierrez@amd.com            switch (atomicOperation) {
119811692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_AND:
119911692Santhony.gutierrez@amd.com                setFlag(AtomicAnd);
120011692Santhony.gutierrez@amd.com                break;
120111692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_OR:
120211692Santhony.gutierrez@amd.com                setFlag(AtomicOr);
120311692Santhony.gutierrez@amd.com                break;
120411692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_XOR:
120511692Santhony.gutierrez@amd.com                setFlag(AtomicXor);
120611692Santhony.gutierrez@amd.com                break;
120711692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_CAS:
120811692Santhony.gutierrez@amd.com                setFlag(AtomicCAS);
120911692Santhony.gutierrez@amd.com                break;
121011692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_EXCH:
121111692Santhony.gutierrez@amd.com                setFlag(AtomicExch);
121211692Santhony.gutierrez@amd.com                break;
121311692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_ADD:
121411692Santhony.gutierrez@amd.com                setFlag(AtomicAdd);
121511692Santhony.gutierrez@amd.com                break;
121611692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_WRAPINC:
121711692Santhony.gutierrez@amd.com                setFlag(AtomicInc);
121811692Santhony.gutierrez@amd.com                break;
121911692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_WRAPDEC:
122011692Santhony.gutierrez@amd.com                setFlag(AtomicDec);
122111692Santhony.gutierrez@amd.com                break;
122211692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_MIN:
122311692Santhony.gutierrez@amd.com                setFlag(AtomicMin);
122411692Santhony.gutierrez@amd.com                break;
122511692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_MAX:
122611692Santhony.gutierrez@amd.com                setFlag(AtomicMax);
122711692Santhony.gutierrez@amd.com                break;
122811692Santhony.gutierrez@amd.com              case Brig::BRIG_ATOMIC_SUB:
122911692Santhony.gutierrez@amd.com                setFlag(AtomicSub);
123011692Santhony.gutierrez@amd.com                break;
123111692Santhony.gutierrez@amd.com              default:
123211692Santhony.gutierrez@amd.com                fatal("Bad BrigAtomicOperation code %d\n", atomicOperation);
123311692Santhony.gutierrez@amd.com            }
123411308Santhony.gutierrez@amd.com
123511308Santhony.gutierrez@amd.com            switch (segment) {
123611308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
123711692Santhony.gutierrez@amd.com                setFlag(GlobalSegment);
123811308Santhony.gutierrez@amd.com                break;
123911308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
124011692Santhony.gutierrez@amd.com                setFlag(GroupSegment);
124111308Santhony.gutierrez@amd.com                break;
124211308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
124311692Santhony.gutierrez@amd.com                setFlag(Flat);
124411308Santhony.gutierrez@amd.com                break;
124511308Santhony.gutierrez@amd.com              default:
124611308Santhony.gutierrez@amd.com                panic("Atomic: segment %d not supported\n", segment);
124711308Santhony.gutierrez@amd.com            }
124811308Santhony.gutierrez@amd.com
124911308Santhony.gutierrez@amd.com            if (HasDst) {
125011308Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
125111308Santhony.gutierrez@amd.com                dest.init(op_offs, obj);
125211308Santhony.gutierrez@amd.com
125311308Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands, 1);
125411308Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
125511308Santhony.gutierrez@amd.com
125611308Santhony.gutierrez@amd.com                for (int i = 0; i < NumSrcOperands; ++i) {
125711308Santhony.gutierrez@amd.com                    op_offs = obj->getOperandPtr(ib->operands, i + 2);
125811308Santhony.gutierrez@amd.com                    src[i].init(op_offs, obj);
125911308Santhony.gutierrez@amd.com                }
126011308Santhony.gutierrez@amd.com            } else {
126111308Santhony.gutierrez@amd.com
126211308Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
126311308Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
126411308Santhony.gutierrez@amd.com
126511308Santhony.gutierrez@amd.com                for (int i = 0; i < NumSrcOperands; ++i) {
126611308Santhony.gutierrez@amd.com                    op_offs = obj->getOperandPtr(ib->operands, i + 1);
126711308Santhony.gutierrez@amd.com                    src[i].init(op_offs, obj);
126811308Santhony.gutierrez@amd.com                }
126911308Santhony.gutierrez@amd.com            }
127011308Santhony.gutierrez@amd.com        }
127111308Santhony.gutierrez@amd.com
127211308Santhony.gutierrez@amd.com        int numSrcRegOperands()
127311308Santhony.gutierrez@amd.com        {
127411308Santhony.gutierrez@amd.com            int operands = 0;
127511308Santhony.gutierrez@amd.com            for (int i = 0; i < NumSrcOperands; i++) {
127611325Ssteve.reinhardt@amd.com                if (src[i].isVectorRegister()) {
127711308Santhony.gutierrez@amd.com                    operands++;
127811308Santhony.gutierrez@amd.com                }
127911308Santhony.gutierrez@amd.com            }
128011308Santhony.gutierrez@amd.com            if (addr.isVectorRegister())
128111308Santhony.gutierrez@amd.com                operands++;
128211308Santhony.gutierrez@amd.com            return operands;
128311308Santhony.gutierrez@amd.com        }
128411308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
128511308Santhony.gutierrez@amd.com        int getNumOperands()
128611308Santhony.gutierrez@amd.com        {
128711308Santhony.gutierrez@amd.com            if (addr.isVectorRegister())
128811308Santhony.gutierrez@amd.com                return(NumSrcOperands + 2);
128911308Santhony.gutierrez@amd.com            return(NumSrcOperands + 1);
129011308Santhony.gutierrez@amd.com        }
129111308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex)
129211308Santhony.gutierrez@amd.com        {
129311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
129411308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
129511308Santhony.gutierrez@amd.com                return src[operandIndex].isVectorRegister();
129611308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
129711308Santhony.gutierrez@amd.com                return(addr.isVectorRegister());
129811308Santhony.gutierrez@amd.com            else
129911308Santhony.gutierrez@amd.com                return dest.isVectorRegister();
130011308Santhony.gutierrez@amd.com        }
130111308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex)
130211308Santhony.gutierrez@amd.com        {
130311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
130411308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
130511308Santhony.gutierrez@amd.com                return src[operandIndex].isCondRegister();
130611308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
130711308Santhony.gutierrez@amd.com                return(addr.isCondRegister());
130811308Santhony.gutierrez@amd.com            else
130911308Santhony.gutierrez@amd.com                return dest.isCondRegister();
131011308Santhony.gutierrez@amd.com        }
131111308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex)
131211308Santhony.gutierrez@amd.com        {
131311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
131411308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
131511308Santhony.gutierrez@amd.com                return src[operandIndex].isScalarRegister();
131611308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
131711308Santhony.gutierrez@amd.com                return(addr.isScalarRegister());
131811308Santhony.gutierrez@amd.com            else
131911308Santhony.gutierrez@amd.com                return dest.isScalarRegister();
132011308Santhony.gutierrez@amd.com        }
132111308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex)
132211308Santhony.gutierrez@amd.com        {
132311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
132411308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
132511308Santhony.gutierrez@amd.com                return true;
132611308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
132711308Santhony.gutierrez@amd.com                return(addr.isVectorRegister());
132811308Santhony.gutierrez@amd.com            else
132911308Santhony.gutierrez@amd.com                return false;
133011308Santhony.gutierrez@amd.com        }
133111308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex)
133211308Santhony.gutierrez@amd.com        {
133311308Santhony.gutierrez@amd.com            if (operandIndex <= NumSrcOperands)
133411308Santhony.gutierrez@amd.com                return false;
133511308Santhony.gutierrez@amd.com            else
133611308Santhony.gutierrez@amd.com                return true;
133711308Santhony.gutierrez@amd.com        }
133811308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex)
133911308Santhony.gutierrez@amd.com        {
134011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
134111308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
134211308Santhony.gutierrez@amd.com                return(src[operandIndex].opSize());
134311308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
134411308Santhony.gutierrez@amd.com                return(addr.opSize());
134511308Santhony.gutierrez@amd.com            else
134611308Santhony.gutierrez@amd.com                return(dest.opSize());
134711308Santhony.gutierrez@amd.com        }
134811308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex)
134911308Santhony.gutierrez@amd.com        {
135011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
135111308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
135211308Santhony.gutierrez@amd.com                return(src[operandIndex].regIndex());
135311308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
135411308Santhony.gutierrez@amd.com                return(addr.regIndex());
135511308Santhony.gutierrez@amd.com            else
135611308Santhony.gutierrez@amd.com                return(dest.regIndex());
135711308Santhony.gutierrez@amd.com            return -1;
135811308Santhony.gutierrez@amd.com        }
135911308Santhony.gutierrez@amd.com    };
136011308Santhony.gutierrez@amd.com
136111308Santhony.gutierrez@amd.com    template<typename MemDataType, typename AddrOperandType, int NumSrcOperands,
136211308Santhony.gutierrez@amd.com             bool HasDst>
136311308Santhony.gutierrez@amd.com    class AtomicInst :
136411308Santhony.gutierrez@amd.com        public AtomicInstBase<typename MemDataType::OperandType,
136511308Santhony.gutierrez@amd.com                              AddrOperandType, NumSrcOperands, HasDst>,
136611308Santhony.gutierrez@amd.com        public MemInst
136711308Santhony.gutierrez@amd.com    {
136811308Santhony.gutierrez@amd.com      public:
136911347Sandreas.hansson@arm.com        void generateDisassembly() override;
137011308Santhony.gutierrez@amd.com
137111308Santhony.gutierrez@amd.com        AtomicInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
137211308Santhony.gutierrez@amd.com                   const char *_opcode)
137311308Santhony.gutierrez@amd.com            : AtomicInstBase<typename MemDataType::OperandType, AddrOperandType,
137411308Santhony.gutierrez@amd.com                             NumSrcOperands, HasDst>
137511308Santhony.gutierrez@amd.com                (ib, obj, _opcode),
137611308Santhony.gutierrez@amd.com              MemInst(MemDataType::memType)
137711308Santhony.gutierrez@amd.com        {
137811308Santhony.gutierrez@amd.com            init_addr(&this->addr);
137911308Santhony.gutierrez@amd.com        }
138011308Santhony.gutierrez@amd.com
138111308Santhony.gutierrez@amd.com        void
138211308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst) override
138311308Santhony.gutierrez@amd.com        {
138411308Santhony.gutierrez@amd.com            // before doing the RMW, check if this atomic has
138511308Santhony.gutierrez@amd.com            // release semantics, and if so issue a release first
138611692Santhony.gutierrez@amd.com            if (!this->isLocalMem()) {
138711308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
138811692Santhony.gutierrez@amd.com                    && (gpuDynInst->isRelease()
138911692Santhony.gutierrez@amd.com                    || gpuDynInst->isAcquireRelease())) {
139011308Santhony.gutierrez@amd.com
139111308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
139211308Santhony.gutierrez@amd.com
139311308Santhony.gutierrez@amd.com                    gpuDynInst->execContinuation = &GPUStaticInst::execAtomic;
139411308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = true;
139511308Santhony.gutierrez@amd.com
139611308Santhony.gutierrez@amd.com                    // create request
139711308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
139811308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
139911435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
140011308Santhony.gutierrez@amd.com                    req->setFlags(Request::RELEASE);
140111308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
140211308Santhony.gutierrez@amd.com
140311308Santhony.gutierrez@amd.com                    return;
140411308Santhony.gutierrez@amd.com                }
140511308Santhony.gutierrez@amd.com            }
140611308Santhony.gutierrez@amd.com
140711308Santhony.gutierrez@amd.com            // if there is no release semantic, execute the RMW immediately
140811308Santhony.gutierrez@amd.com            execAtomic(gpuDynInst);
140911308Santhony.gutierrez@amd.com
141011308Santhony.gutierrez@amd.com        }
141111308Santhony.gutierrez@amd.com
141211347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
141311308Santhony.gutierrez@amd.com
141411308Santhony.gutierrez@amd.com      private:
141511308Santhony.gutierrez@amd.com        // execAtomic may be called through a continuation
141611308Santhony.gutierrez@amd.com        // if the RMW had release semantics. see comment for
141711308Santhony.gutierrez@amd.com        // execContinuation in gpu_dyn_inst.hh
141811308Santhony.gutierrez@amd.com        void
141911308Santhony.gutierrez@amd.com        execAtomic(GPUDynInstPtr gpuDynInst) override
142011308Santhony.gutierrez@amd.com        {
142111308Santhony.gutierrez@amd.com            gpuDynInst->statusBitVector = gpuDynInst->exec_mask;
142211308Santhony.gutierrez@amd.com
142311308Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c0;
142411308Santhony.gutierrez@amd.com
142511308Santhony.gutierrez@amd.com            c0 *d = &((c0*) gpuDynInst->d_data)[0];
142611308Santhony.gutierrez@amd.com            c0 *e = &((c0*) gpuDynInst->a_data)[0];
142711308Santhony.gutierrez@amd.com            c0 *f = &((c0*) gpuDynInst->x_data)[0];
142811308Santhony.gutierrez@amd.com
142911534Sjohn.kalamatianos@amd.com            for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) {
143011308Santhony.gutierrez@amd.com                if (gpuDynInst->exec_mask[i]) {
143111308Santhony.gutierrez@amd.com                    Addr vaddr = gpuDynInst->addr[i];
143211308Santhony.gutierrez@amd.com
143311692Santhony.gutierrez@amd.com                    if (this->isLocalMem()) {
143411308Santhony.gutierrez@amd.com                        Wavefront *wavefront = gpuDynInst->wavefront();
143511308Santhony.gutierrez@amd.com                        *d = wavefront->ldsChunk->read<c0>(vaddr);
143611308Santhony.gutierrez@amd.com
143711692Santhony.gutierrez@amd.com                        if (this->isAtomicAdd()) {
143811308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
143911308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) + (*e));
144011692Santhony.gutierrez@amd.com                        } else if (this->isAtomicSub()) {
144111308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
144211308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) - (*e));
144311692Santhony.gutierrez@amd.com                        } else if (this->isAtomicMax()) {
144411308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
144511308Santhony.gutierrez@amd.com                            std::max(wavefront->ldsChunk->read<c0>(vaddr),
144611308Santhony.gutierrez@amd.com                            (*e)));
144711692Santhony.gutierrez@amd.com                        } else if (this->isAtomicMin()) {
144811308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
144911308Santhony.gutierrez@amd.com                            std::min(wavefront->ldsChunk->read<c0>(vaddr),
145011308Santhony.gutierrez@amd.com                            (*e)));
145111692Santhony.gutierrez@amd.com                        } else if (this->isAtomicAnd()) {
145211308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
145311308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) & (*e));
145411692Santhony.gutierrez@amd.com                        } else if (this->isAtomicOr()) {
145511308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
145611308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) | (*e));
145711692Santhony.gutierrez@amd.com                        } else if (this->isAtomicXor()) {
145811308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
145911308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) ^ (*e));
146011692Santhony.gutierrez@amd.com                        } else if (this->isAtomicInc()) {
146111308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
146211308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) + 1);
146311692Santhony.gutierrez@amd.com                        } else if (this->isAtomicDec()) {
146411308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
146511308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) - 1);
146611692Santhony.gutierrez@amd.com                        } else if (this->isAtomicExch()) {
146711308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr, (*e));
146811692Santhony.gutierrez@amd.com                        } else if (this->isAtomicCAS()) {
146911308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
147011308Santhony.gutierrez@amd.com                            (wavefront->ldsChunk->read<c0>(vaddr) == (*e)) ?
147111308Santhony.gutierrez@amd.com                            (*f) : wavefront->ldsChunk->read<c0>(vaddr));
147211692Santhony.gutierrez@amd.com                        } else {
147311308Santhony.gutierrez@amd.com                            fatal("Unrecognized or invalid HSAIL atomic op "
147411308Santhony.gutierrez@amd.com                                  "type.\n");
147511308Santhony.gutierrez@amd.com                        }
147611308Santhony.gutierrez@amd.com                    } else {
147711308Santhony.gutierrez@amd.com                        Request *req =
147811308Santhony.gutierrez@amd.com                            new Request(0, vaddr, sizeof(c0), 0,
147911308Santhony.gutierrez@amd.com                                        gpuDynInst->computeUnit()->masterId(),
148011435Smitch.hayenga@arm.com                                        0, gpuDynInst->wfDynId,
148111308Santhony.gutierrez@amd.com                                        gpuDynInst->makeAtomicOpFunctor<c0>(e,
148211692Santhony.gutierrez@amd.com                                        f));
148311308Santhony.gutierrez@amd.com
148411308Santhony.gutierrez@amd.com                        gpuDynInst->setRequestFlags(req);
148511308Santhony.gutierrez@amd.com                        PacketPtr pkt = new Packet(req, MemCmd::SwapReq);
148611308Santhony.gutierrez@amd.com                        pkt->dataStatic(d);
148711308Santhony.gutierrez@amd.com
148811308Santhony.gutierrez@amd.com                        if (gpuDynInst->computeUnit()->shader->
148911308Santhony.gutierrez@amd.com                            separate_acquire_release &&
149011692Santhony.gutierrez@amd.com                            (gpuDynInst->isAcquire())) {
149111308Santhony.gutierrez@amd.com                            // if this atomic has acquire semantics,
149211308Santhony.gutierrez@amd.com                            // schedule the continuation to perform an
149311308Santhony.gutierrez@amd.com                            // acquire after the RMW completes
149411308Santhony.gutierrez@amd.com                            gpuDynInst->execContinuation =
149511308Santhony.gutierrez@amd.com                                &GPUStaticInst::execAtomicAcq;
149611308Santhony.gutierrez@amd.com
149711308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = true;
149811308Santhony.gutierrez@amd.com                        } else {
149911308Santhony.gutierrez@amd.com                            // the request will be finished when the RMW completes
150011308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = false;
150111308Santhony.gutierrez@amd.com                        }
150211308Santhony.gutierrez@amd.com                        // translation is performed in sendRequest()
150311308Santhony.gutierrez@amd.com                        gpuDynInst->computeUnit()->sendRequest(gpuDynInst, i,
150411308Santhony.gutierrez@amd.com                                                               pkt);
150511308Santhony.gutierrez@amd.com                    }
150611308Santhony.gutierrez@amd.com                }
150711308Santhony.gutierrez@amd.com
150811308Santhony.gutierrez@amd.com                ++d;
150911308Santhony.gutierrez@amd.com                ++e;
151011308Santhony.gutierrez@amd.com                ++f;
151111308Santhony.gutierrez@amd.com            }
151211308Santhony.gutierrez@amd.com
151311308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
151411308Santhony.gutierrez@amd.com        }
151511308Santhony.gutierrez@amd.com
151611308Santhony.gutierrez@amd.com        // execAtomicACq will always be called through a continuation.
151711308Santhony.gutierrez@amd.com        // see comment for execContinuation in gpu_dyn_inst.hh
151811308Santhony.gutierrez@amd.com        void
151911308Santhony.gutierrez@amd.com        execAtomicAcq(GPUDynInstPtr gpuDynInst) override
152011308Santhony.gutierrez@amd.com        {
152111308Santhony.gutierrez@amd.com            // after performing the RMW, check to see if this instruction
152211308Santhony.gutierrez@amd.com            // has acquire semantics, and if so, issue an acquire
152311692Santhony.gutierrez@amd.com            if (!this->isLocalMem()) {
152411308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
152511692Santhony.gutierrez@amd.com                     && gpuDynInst->isAcquire()) {
152611308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
152711308Santhony.gutierrez@amd.com
152811308Santhony.gutierrez@amd.com                    // the request will be finished when
152911308Santhony.gutierrez@amd.com                    // the acquire completes
153011308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = false;
153111308Santhony.gutierrez@amd.com                    // create request
153211308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
153311308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
153411435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
153511308Santhony.gutierrez@amd.com                    req->setFlags(Request::ACQUIRE);
153611308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
153711308Santhony.gutierrez@amd.com                }
153811308Santhony.gutierrez@amd.com            }
153911308Santhony.gutierrez@amd.com        }
154011308Santhony.gutierrez@amd.com    };
154111308Santhony.gutierrez@amd.com
154211308Santhony.gutierrez@amd.com    template<typename DataType, typename AddrOperandType, int NumSrcOperands>
154311308Santhony.gutierrez@amd.com    GPUStaticInst*
154411308Santhony.gutierrez@amd.com    constructAtomic(const Brig::BrigInstBase *ib, const BrigObject *obj)
154511308Santhony.gutierrez@amd.com    {
154611308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
154711308Santhony.gutierrez@amd.com
154811308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_LD) {
154911308Santhony.gutierrez@amd.com            return decodeLd<DataType>(ib, obj);
155011308Santhony.gutierrez@amd.com        } else if (at->atomicOperation == Brig::BRIG_ATOMIC_ST) {
155111308Santhony.gutierrez@amd.com            switch (ib->type) {
155211308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B8:
155311308Santhony.gutierrez@amd.com                return decodeSt<S8,S8>(ib, obj);
155411308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B16:
155511536Staquangtuan1992@gmail.com                return decodeSt<S16,S16>(ib, obj);
155611308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B32:
155711536Staquangtuan1992@gmail.com                return decodeSt<S32,S32>(ib, obj);
155811308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B64:
155911536Staquangtuan1992@gmail.com                return decodeSt<S64,S64>(ib, obj);
156011308Santhony.gutierrez@amd.com              default: fatal("AtomicSt: Operand type mismatch %d\n", ib->type);
156111308Santhony.gutierrez@amd.com            }
156211308Santhony.gutierrez@amd.com        } else {
156311308Santhony.gutierrez@amd.com            if ((Brig::BrigOpcode)ib->opcode == Brig::BRIG_OPCODE_ATOMICNORET)
156411308Santhony.gutierrez@amd.com                return new AtomicInst<DataType, AddrOperandType,
156511308Santhony.gutierrez@amd.com                    NumSrcOperands, false>(ib, obj, "atomicnoret");
156611308Santhony.gutierrez@amd.com            else
156711308Santhony.gutierrez@amd.com                return new AtomicInst<DataType, AddrOperandType,
156811308Santhony.gutierrez@amd.com                    NumSrcOperands, true>(ib, obj, "atomic");
156911308Santhony.gutierrez@amd.com        }
157011308Santhony.gutierrez@amd.com    }
157111308Santhony.gutierrez@amd.com
157211308Santhony.gutierrez@amd.com    template<typename DataType, int NumSrcOperands>
157311308Santhony.gutierrez@amd.com    GPUStaticInst*
157411308Santhony.gutierrez@amd.com    decodeAtomicHelper(const Brig::BrigInstBase *ib, const BrigObject *obj)
157511308Santhony.gutierrez@amd.com    {
157611308Santhony.gutierrez@amd.com        unsigned addrIndex = (Brig::BrigOpcode)ib->opcode ==
157711308Santhony.gutierrez@amd.com            Brig::BRIG_OPCODE_ATOMICNORET ? 0 : 1;
157811308Santhony.gutierrez@amd.com
157911308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,addrIndex);
158011308Santhony.gutierrez@amd.com
158111308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
158211308Santhony.gutierrez@amd.com
158311308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
158411308Santhony.gutierrez@amd.com            return constructAtomic<DataType, NoRegAddrOperand,
158511308Santhony.gutierrez@amd.com                                   NumSrcOperands>(ib, obj);
158611308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER) {
158711308Santhony.gutierrez@amd.com            // V2/V4 not allowed
158811308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
158911308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
159011308Santhony.gutierrez@amd.com                  return constructAtomic<DataType, SRegAddrOperand,
159111308Santhony.gutierrez@amd.com                                         NumSrcOperands>(ib, obj);
159211308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
159311308Santhony.gutierrez@amd.com                return constructAtomic<DataType, DRegAddrOperand,
159411308Santhony.gutierrez@amd.com                                       NumSrcOperands>(ib, obj);
159511308Santhony.gutierrez@amd.com              default:
159611308Santhony.gutierrez@amd.com                fatal("Bad atomic register operand type %d\n", tmp.type);
159711308Santhony.gutierrez@amd.com            }
159811308Santhony.gutierrez@amd.com        } else {
159911308Santhony.gutierrez@amd.com            fatal("Bad atomic register operand kind %d\n", tmp.kind);
160011308Santhony.gutierrez@amd.com        }
160111308Santhony.gutierrez@amd.com    }
160211308Santhony.gutierrez@amd.com
160311308Santhony.gutierrez@amd.com
160411308Santhony.gutierrez@amd.com    template<typename DataType>
160511308Santhony.gutierrez@amd.com    GPUStaticInst*
160611308Santhony.gutierrez@amd.com    decodeAtomic(const Brig::BrigInstBase *ib, const BrigObject *obj)
160711308Santhony.gutierrez@amd.com    {
160811308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
160911308Santhony.gutierrez@amd.com
161011308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_CAS) {
161111308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 2>(ib, obj);
161211308Santhony.gutierrez@amd.com        } else {
161311308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 1>(ib, obj);
161411308Santhony.gutierrez@amd.com        }
161511308Santhony.gutierrez@amd.com    }
161611308Santhony.gutierrez@amd.com
161711308Santhony.gutierrez@amd.com    template<typename DataType>
161811308Santhony.gutierrez@amd.com    GPUStaticInst*
161911308Santhony.gutierrez@amd.com    decodeAtomicNoRet(const Brig::BrigInstBase *ib, const BrigObject *obj)
162011308Santhony.gutierrez@amd.com    {
162111308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
162211308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_CAS) {
162311308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 2>(ib, obj);
162411308Santhony.gutierrez@amd.com        } else {
162511308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 1>(ib, obj);
162611308Santhony.gutierrez@amd.com        }
162711308Santhony.gutierrez@amd.com    }
162811308Santhony.gutierrez@amd.com} // namespace HsailISA
162911308Santhony.gutierrez@amd.com
163011308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_MEM_HH__
1631