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