mem.hh revision 11534
111308Santhony.gutierrez@amd.com/*
211308Santhony.gutierrez@amd.com * Copyright (c) 2012-2015 Advanced Micro Devices, Inc.
311308Santhony.gutierrez@amd.com * All rights reserved.
411308Santhony.gutierrez@amd.com *
511308Santhony.gutierrez@amd.com * For use for simulation and test purposes only
611308Santhony.gutierrez@amd.com *
711308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without
811308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are met:
911308Santhony.gutierrez@amd.com *
1011308Santhony.gutierrez@amd.com * 1. Redistributions of source code must retain the above copyright notice,
1111308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer.
1211308Santhony.gutierrez@amd.com *
1311308Santhony.gutierrez@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice,
1411308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer in the documentation
1511308Santhony.gutierrez@amd.com * and/or other materials provided with the distribution.
1611308Santhony.gutierrez@amd.com *
1711308Santhony.gutierrez@amd.com * 3. Neither the name of the copyright holder nor the names of its contributors
1811308Santhony.gutierrez@amd.com * may be used to endorse or promote products derived from this software
1911308Santhony.gutierrez@amd.com * without specific prior written permission.
2011308Santhony.gutierrez@amd.com *
2111308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2211308Santhony.gutierrez@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2311308Santhony.gutierrez@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2411308Santhony.gutierrez@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2511308Santhony.gutierrez@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2611308Santhony.gutierrez@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2711308Santhony.gutierrez@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2811308Santhony.gutierrez@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2911308Santhony.gutierrez@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3011308Santhony.gutierrez@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3111308Santhony.gutierrez@amd.com * POSSIBILITY OF SUCH DAMAGE.
3211308Santhony.gutierrez@amd.com *
3311308Santhony.gutierrez@amd.com * Author: Steve Reinhardt
3411308Santhony.gutierrez@amd.com */
3511308Santhony.gutierrez@amd.com
3611308Santhony.gutierrez@amd.com#ifndef __ARCH_HSAIL_INSTS_MEM_HH__
3711308Santhony.gutierrez@amd.com#define __ARCH_HSAIL_INSTS_MEM_HH__
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.com#include "arch/hsail/insts/decl.hh"
4011308Santhony.gutierrez@amd.com#include "arch/hsail/insts/gpu_static_inst.hh"
4111308Santhony.gutierrez@amd.com#include "arch/hsail/operand.hh"
4211308Santhony.gutierrez@amd.com
4311308Santhony.gutierrez@amd.comnamespace HsailISA
4411308Santhony.gutierrez@amd.com{
4511308Santhony.gutierrez@amd.com    class MemInst
4611308Santhony.gutierrez@amd.com    {
4711308Santhony.gutierrez@amd.com      public:
4811308Santhony.gutierrez@amd.com        MemInst() : size(0), addr_operand(nullptr) { }
4911308Santhony.gutierrez@amd.com
5011308Santhony.gutierrez@amd.com        MemInst(Enums::MemType m_type)
5111308Santhony.gutierrez@amd.com        {
5211308Santhony.gutierrez@amd.com            if (m_type == Enums::M_U64 ||
5311308Santhony.gutierrez@amd.com                m_type == Enums::M_S64 ||
5411308Santhony.gutierrez@amd.com                m_type == Enums::M_F64) {
5511308Santhony.gutierrez@amd.com                size = 8;
5611308Santhony.gutierrez@amd.com            } else if (m_type == Enums::M_U32 ||
5711308Santhony.gutierrez@amd.com                       m_type == Enums::M_S32 ||
5811308Santhony.gutierrez@amd.com                       m_type == Enums::M_F32) {
5911308Santhony.gutierrez@amd.com                size = 4;
6011308Santhony.gutierrez@amd.com            } else if (m_type == Enums::M_U16 ||
6111308Santhony.gutierrez@amd.com                       m_type == Enums::M_S16 ||
6211308Santhony.gutierrez@amd.com                       m_type == Enums::M_F16) {
6311308Santhony.gutierrez@amd.com                size = 2;
6411308Santhony.gutierrez@amd.com            } else {
6511308Santhony.gutierrez@amd.com                size = 1;
6611308Santhony.gutierrez@amd.com            }
6711308Santhony.gutierrez@amd.com
6811308Santhony.gutierrez@amd.com            addr_operand = nullptr;
6911308Santhony.gutierrez@amd.com        }
7011308Santhony.gutierrez@amd.com
7111308Santhony.gutierrez@amd.com        void
7211308Santhony.gutierrez@amd.com        init_addr(AddrOperandBase *_addr_operand)
7311308Santhony.gutierrez@amd.com        {
7411308Santhony.gutierrez@amd.com            addr_operand = _addr_operand;
7511308Santhony.gutierrez@amd.com        }
7611308Santhony.gutierrez@amd.com
7711308Santhony.gutierrez@amd.com      private:
7811308Santhony.gutierrez@amd.com        int size;
7911308Santhony.gutierrez@amd.com        AddrOperandBase *addr_operand;
8011308Santhony.gutierrez@amd.com
8111308Santhony.gutierrez@amd.com      public:
8211308Santhony.gutierrez@amd.com        int getMemOperandSize() { return size; }
8311308Santhony.gutierrez@amd.com        AddrOperandBase *getAddressOperand() { return addr_operand; }
8411308Santhony.gutierrez@amd.com    };
8511308Santhony.gutierrez@amd.com
8611308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename AddrOperandType>
8711308Santhony.gutierrez@amd.com    class LdaInstBase : public HsailGPUStaticInst
8811308Santhony.gutierrez@amd.com    {
8911308Santhony.gutierrez@amd.com      public:
9011308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
9111308Santhony.gutierrez@amd.com        AddrOperandType addr;
9211308Santhony.gutierrez@amd.com
9311308Santhony.gutierrez@amd.com        LdaInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
9411308Santhony.gutierrez@amd.com                    const char *_opcode)
9511308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
9611308Santhony.gutierrez@amd.com        {
9711308Santhony.gutierrez@amd.com            using namespace Brig;
9811308Santhony.gutierrez@amd.com
9911308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
10011308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
10111308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
10211308Santhony.gutierrez@amd.com            addr.init(op_offs, obj);
10311308Santhony.gutierrez@amd.com        }
10411308Santhony.gutierrez@amd.com
10511347Sandreas.hansson@arm.com        int numSrcRegOperands() override
10611347Sandreas.hansson@arm.com        { return(this->addr.isVectorRegister()); }
10711347Sandreas.hansson@arm.com        int numDstRegOperands() override
10811347Sandreas.hansson@arm.com        { return dest.isVectorRegister(); }
10911347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
11011308Santhony.gutierrez@amd.com        {
11111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
11211308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isVectorRegister() :
11311308Santhony.gutierrez@amd.com                   this->addr.isVectorRegister());
11411308Santhony.gutierrez@amd.com        }
11511347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
11611308Santhony.gutierrez@amd.com        {
11711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
11811308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isCondRegister() :
11911308Santhony.gutierrez@amd.com                   this->addr.isCondRegister());
12011308Santhony.gutierrez@amd.com        }
12111347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
12211308Santhony.gutierrez@amd.com        {
12311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
12411308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isScalarRegister() :
12511308Santhony.gutierrez@amd.com                   this->addr.isScalarRegister());
12611308Santhony.gutierrez@amd.com        }
12711347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
12811308Santhony.gutierrez@amd.com        {
12911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
13011308Santhony.gutierrez@amd.com            if (operandIndex > 0)
13111308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
13211308Santhony.gutierrez@amd.com            return false;
13311308Santhony.gutierrez@amd.com        }
13411347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override {
13511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
13611308Santhony.gutierrez@amd.com            return(operandIndex == 0);
13711308Santhony.gutierrez@amd.com        }
13811347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
13911308Santhony.gutierrez@amd.com        {
14011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
14111308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.opSize() :
14211308Santhony.gutierrez@amd.com                   this->addr.opSize());
14311308Santhony.gutierrez@amd.com        }
14411347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
14511308Santhony.gutierrez@amd.com        {
14611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
14711308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.regIndex() :
14811308Santhony.gutierrez@amd.com                   this->addr.regIndex());
14911308Santhony.gutierrez@amd.com        }
15011347Sandreas.hansson@arm.com        int getNumOperands() override
15111308Santhony.gutierrez@amd.com        {
15211308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister())
15311308Santhony.gutierrez@amd.com                return 2;
15411308Santhony.gutierrez@amd.com            return 1;
15511308Santhony.gutierrez@amd.com        }
15611308Santhony.gutierrez@amd.com    };
15711308Santhony.gutierrez@amd.com
15811308Santhony.gutierrez@amd.com    template<typename DestDataType, typename AddrOperandType>
15911308Santhony.gutierrez@amd.com    class LdaInst :
16011308Santhony.gutierrez@amd.com        public LdaInstBase<typename DestDataType::OperandType, AddrOperandType>,
16111308Santhony.gutierrez@amd.com        public MemInst
16211308Santhony.gutierrez@amd.com    {
16311308Santhony.gutierrez@amd.com      public:
16411308Santhony.gutierrez@amd.com        void generateDisassembly();
16511308Santhony.gutierrez@amd.com
16611308Santhony.gutierrez@amd.com        LdaInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
16711308Santhony.gutierrez@amd.com                        const char *_opcode)
16811308Santhony.gutierrez@amd.com            : LdaInstBase<typename DestDataType::OperandType,
16911308Santhony.gutierrez@amd.com                          AddrOperandType>(ib, obj, _opcode)
17011308Santhony.gutierrez@amd.com        {
17111308Santhony.gutierrez@amd.com            init_addr(&this->addr);
17211308Santhony.gutierrez@amd.com        }
17311308Santhony.gutierrez@amd.com
17411308Santhony.gutierrez@amd.com        void execute(GPUDynInstPtr gpuDynInst);
17511308Santhony.gutierrez@amd.com    };
17611308Santhony.gutierrez@amd.com
17711308Santhony.gutierrez@amd.com    template<typename DataType>
17811308Santhony.gutierrez@amd.com    GPUStaticInst*
17911308Santhony.gutierrez@amd.com    decodeLda(const Brig::BrigInstBase *ib, const BrigObject *obj)
18011308Santhony.gutierrez@amd.com    {
18111308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands, 1);
18211308Santhony.gutierrez@amd.com        BrigRegOperandInfo regDataType = findRegDataType(op_offs, obj);
18311308Santhony.gutierrez@amd.com
18411308Santhony.gutierrez@amd.com        if (regDataType.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
18511308Santhony.gutierrez@amd.com            return new LdaInst<DataType, NoRegAddrOperand>(ib, obj, "ldas");
18611308Santhony.gutierrez@amd.com        } else if (regDataType.kind == Brig::BRIG_KIND_OPERAND_REGISTER) {
18711308Santhony.gutierrez@amd.com            // V2/V4 not allowed
18811308Santhony.gutierrez@amd.com            switch (regDataType.regKind) {
18911308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
19011308Santhony.gutierrez@amd.com                return new LdaInst<DataType, SRegAddrOperand>(ib, obj, "ldas");
19111308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
19211308Santhony.gutierrez@amd.com                return new LdaInst<DataType, DRegAddrOperand>(ib, obj, "ldas");
19311308Santhony.gutierrez@amd.com              default:
19411308Santhony.gutierrez@amd.com                fatal("Bad ldas register operand type %d\n", regDataType.type);
19511308Santhony.gutierrez@amd.com            }
19611308Santhony.gutierrez@amd.com        } else {
19711308Santhony.gutierrez@amd.com            fatal("Bad ldas register operand kind %d\n", regDataType.kind);
19811308Santhony.gutierrez@amd.com        }
19911308Santhony.gutierrez@amd.com    }
20011308Santhony.gutierrez@amd.com
20111308Santhony.gutierrez@amd.com    template<typename MemOperandType, typename DestOperandType,
20211308Santhony.gutierrez@amd.com             typename AddrOperandType>
20311308Santhony.gutierrez@amd.com    class LdInstBase : public HsailGPUStaticInst
20411308Santhony.gutierrez@amd.com    {
20511308Santhony.gutierrez@amd.com      public:
20611308Santhony.gutierrez@amd.com        Brig::BrigWidth8_t width;
20711308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
20811308Santhony.gutierrez@amd.com        AddrOperandType addr;
20911308Santhony.gutierrez@amd.com
21011308Santhony.gutierrez@amd.com        Brig::BrigSegment segment;
21111308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memoryOrder;
21211308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memoryScope;
21311308Santhony.gutierrez@amd.com        unsigned int equivClass;
21411308Santhony.gutierrez@amd.com        bool isArgLoad()
21511308Santhony.gutierrez@amd.com        {
21611308Santhony.gutierrez@amd.com            return segment == Brig::BRIG_SEGMENT_KERNARG ||
21711308Santhony.gutierrez@amd.com                   segment == Brig::BRIG_SEGMENT_ARG;
21811308Santhony.gutierrez@amd.com        }
21911308Santhony.gutierrez@amd.com        void
22011308Santhony.gutierrez@amd.com        initLd(const Brig::BrigInstBase *ib, const BrigObject *obj,
22111308Santhony.gutierrez@amd.com               const char *_opcode)
22211308Santhony.gutierrez@amd.com        {
22311308Santhony.gutierrez@amd.com            using namespace Brig;
22411308Santhony.gutierrez@amd.com
22511308Santhony.gutierrez@amd.com            const BrigInstMem *ldst = (const BrigInstMem*)ib;
22611308Santhony.gutierrez@amd.com
22711308Santhony.gutierrez@amd.com            segment = (BrigSegment)ldst->segment;
22811308Santhony.gutierrez@amd.com            memoryOrder = BRIG_MEMORY_ORDER_NONE;
22911308Santhony.gutierrez@amd.com            memoryScope = BRIG_MEMORY_SCOPE_NONE;
23011308Santhony.gutierrez@amd.com            equivClass = ldst->equivClass;
23111308Santhony.gutierrez@amd.com
23211308Santhony.gutierrez@amd.com            switch (segment) {
23311308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
23411308Santhony.gutierrez@amd.com                o_type = Enums::OT_GLOBAL_READ;
23511308Santhony.gutierrez@amd.com                break;
23611308Santhony.gutierrez@amd.com
23711308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
23811308Santhony.gutierrez@amd.com                o_type = Enums::OT_SHARED_READ;
23911308Santhony.gutierrez@amd.com                break;
24011308Santhony.gutierrez@amd.com
24111308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_PRIVATE:
24211308Santhony.gutierrez@amd.com                o_type = Enums::OT_PRIVATE_READ;
24311308Santhony.gutierrez@amd.com                break;
24411308Santhony.gutierrez@amd.com
24511308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_READONLY:
24611308Santhony.gutierrez@amd.com                o_type = Enums::OT_READONLY_READ;
24711308Santhony.gutierrez@amd.com                break;
24811308Santhony.gutierrez@amd.com
24911308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_SPILL:
25011308Santhony.gutierrez@amd.com                o_type = Enums::OT_SPILL_READ;
25111308Santhony.gutierrez@amd.com                break;
25211308Santhony.gutierrez@amd.com
25311308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
25411308Santhony.gutierrez@amd.com                o_type = Enums::OT_FLAT_READ;
25511308Santhony.gutierrez@amd.com                break;
25611308Santhony.gutierrez@amd.com
25711308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_KERNARG:
25811308Santhony.gutierrez@amd.com                o_type = Enums::OT_KERN_READ;
25911308Santhony.gutierrez@amd.com                break;
26011308Santhony.gutierrez@amd.com
26111308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_ARG:
26211308Santhony.gutierrez@amd.com                o_type = Enums::OT_ARG;
26311308Santhony.gutierrez@amd.com                break;
26411308Santhony.gutierrez@amd.com
26511308Santhony.gutierrez@amd.com              default:
26611308Santhony.gutierrez@amd.com                panic("Ld: segment %d not supported\n", segment);
26711308Santhony.gutierrez@amd.com            }
26811308Santhony.gutierrez@amd.com
26911308Santhony.gutierrez@amd.com            width = ldst->width;
27011308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
27111308Santhony.gutierrez@amd.com            const Brig::BrigOperand *brigOp = obj->getOperand(op_offs);
27211308Santhony.gutierrez@amd.com            if (brigOp->kind == BRIG_KIND_OPERAND_REGISTER)
27311308Santhony.gutierrez@amd.com                dest.init(op_offs, obj);
27411308Santhony.gutierrez@amd.com
27511308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
27611308Santhony.gutierrez@amd.com            addr.init(op_offs, obj);
27711308Santhony.gutierrez@amd.com        }
27811308Santhony.gutierrez@amd.com
27911308Santhony.gutierrez@amd.com        void
28011308Santhony.gutierrez@amd.com        initAtomicLd(const Brig::BrigInstBase *ib, const BrigObject *obj,
28111308Santhony.gutierrez@amd.com                     const char *_opcode)
28211308Santhony.gutierrez@amd.com        {
28311308Santhony.gutierrez@amd.com            using namespace Brig;
28411308Santhony.gutierrez@amd.com
28511308Santhony.gutierrez@amd.com            const BrigInstAtomic *at = (const BrigInstAtomic*)ib;
28611308Santhony.gutierrez@amd.com
28711308Santhony.gutierrez@amd.com            segment = (BrigSegment)at->segment;
28811308Santhony.gutierrez@amd.com            memoryOrder = (BrigMemoryOrder)at->memoryOrder;
28911308Santhony.gutierrez@amd.com            memoryScope = (BrigMemoryScope)at->memoryScope;
29011308Santhony.gutierrez@amd.com            equivClass = 0;
29111308Santhony.gutierrez@amd.com
29211308Santhony.gutierrez@amd.com            switch (segment) {
29311308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
29411308Santhony.gutierrez@amd.com                o_type = Enums::OT_GLOBAL_READ;
29511308Santhony.gutierrez@amd.com                break;
29611308Santhony.gutierrez@amd.com
29711308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
29811308Santhony.gutierrez@amd.com                o_type = Enums::OT_SHARED_READ;
29911308Santhony.gutierrez@amd.com                break;
30011308Santhony.gutierrez@amd.com
30111308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_PRIVATE:
30211308Santhony.gutierrez@amd.com                o_type = Enums::OT_PRIVATE_READ;
30311308Santhony.gutierrez@amd.com                break;
30411308Santhony.gutierrez@amd.com
30511308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_READONLY:
30611308Santhony.gutierrez@amd.com                o_type = Enums::OT_READONLY_READ;
30711308Santhony.gutierrez@amd.com                break;
30811308Santhony.gutierrez@amd.com
30911308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_SPILL:
31011308Santhony.gutierrez@amd.com                o_type = Enums::OT_SPILL_READ;
31111308Santhony.gutierrez@amd.com                break;
31211308Santhony.gutierrez@amd.com
31311308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
31411308Santhony.gutierrez@amd.com                o_type = Enums::OT_FLAT_READ;
31511308Santhony.gutierrez@amd.com                break;
31611308Santhony.gutierrez@amd.com
31711308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_KERNARG:
31811308Santhony.gutierrez@amd.com                o_type = Enums::OT_KERN_READ;
31911308Santhony.gutierrez@amd.com                break;
32011308Santhony.gutierrez@amd.com
32111308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_ARG:
32211308Santhony.gutierrez@amd.com                o_type = Enums::OT_ARG;
32311308Santhony.gutierrez@amd.com                break;
32411308Santhony.gutierrez@amd.com
32511308Santhony.gutierrez@amd.com              default:
32611308Santhony.gutierrez@amd.com                panic("Ld: segment %d not supported\n", segment);
32711308Santhony.gutierrez@amd.com            }
32811308Santhony.gutierrez@amd.com
32911308Santhony.gutierrez@amd.com            width = BRIG_WIDTH_1;
33011308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
33111308Santhony.gutierrez@amd.com            const Brig::BrigOperand *brigOp = obj->getOperand(op_offs);
33211308Santhony.gutierrez@amd.com
33311308Santhony.gutierrez@amd.com            if (brigOp->kind == BRIG_KIND_OPERAND_REGISTER)
33411308Santhony.gutierrez@amd.com                dest.init(op_offs, obj);
33511308Santhony.gutierrez@amd.com
33611308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands,1);
33711308Santhony.gutierrez@amd.com            addr.init(op_offs, obj);
33811308Santhony.gutierrez@amd.com        }
33911308Santhony.gutierrez@amd.com
34011308Santhony.gutierrez@amd.com        LdInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
34111308Santhony.gutierrez@amd.com                   const char *_opcode)
34211308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
34311308Santhony.gutierrez@amd.com        {
34411308Santhony.gutierrez@amd.com            using namespace Brig;
34511308Santhony.gutierrez@amd.com
34611308Santhony.gutierrez@amd.com            if (ib->opcode == BRIG_OPCODE_LD) {
34711308Santhony.gutierrez@amd.com                initLd(ib, obj, _opcode);
34811308Santhony.gutierrez@amd.com            } else {
34911308Santhony.gutierrez@amd.com                initAtomicLd(ib, obj, _opcode);
35011308Santhony.gutierrez@amd.com            }
35111308Santhony.gutierrez@amd.com        }
35211308Santhony.gutierrez@amd.com
35311347Sandreas.hansson@arm.com        int numSrcRegOperands() override
35411347Sandreas.hansson@arm.com        { return(this->addr.isVectorRegister()); }
35511347Sandreas.hansson@arm.com        int numDstRegOperands() override { return dest.isVectorRegister(); }
35611347Sandreas.hansson@arm.com        int getNumOperands() override
35711308Santhony.gutierrez@amd.com        {
35811308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister())
35911308Santhony.gutierrez@amd.com                return 2;
36011308Santhony.gutierrez@amd.com            else
36111308Santhony.gutierrez@amd.com                return 1;
36211308Santhony.gutierrez@amd.com        }
36311347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
36411308Santhony.gutierrez@amd.com        {
36511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
36611308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isVectorRegister() :
36711308Santhony.gutierrez@amd.com                   this->addr.isVectorRegister());
36811308Santhony.gutierrez@amd.com        }
36911347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
37011308Santhony.gutierrez@amd.com        {
37111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
37211308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isCondRegister() :
37311308Santhony.gutierrez@amd.com                   this->addr.isCondRegister());
37411308Santhony.gutierrez@amd.com        }
37511347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
37611308Santhony.gutierrez@amd.com        {
37711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
37811308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.isScalarRegister() :
37911308Santhony.gutierrez@amd.com                   this->addr.isScalarRegister());
38011308Santhony.gutierrez@amd.com        }
38111347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
38211308Santhony.gutierrez@amd.com        {
38311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
38411308Santhony.gutierrez@amd.com            if (operandIndex > 0)
38511308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
38611308Santhony.gutierrez@amd.com            return false;
38711308Santhony.gutierrez@amd.com        }
38811347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override
38911308Santhony.gutierrez@amd.com        {
39011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
39111308Santhony.gutierrez@amd.com            return(operandIndex == 0);
39211308Santhony.gutierrez@amd.com        }
39311347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
39411308Santhony.gutierrez@amd.com        {
39511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
39611308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.opSize() :
39711308Santhony.gutierrez@amd.com                   this->addr.opSize());
39811308Santhony.gutierrez@amd.com        }
39911347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
40011308Santhony.gutierrez@amd.com        {
40111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
40211308Santhony.gutierrez@amd.com            return((operandIndex == 0) ? dest.regIndex() :
40311308Santhony.gutierrez@amd.com                   this->addr.regIndex());
40411308Santhony.gutierrez@amd.com        }
40511308Santhony.gutierrez@amd.com    };
40611308Santhony.gutierrez@amd.com
40711308Santhony.gutierrez@amd.com    template<typename MemDataType, typename DestDataType,
40811308Santhony.gutierrez@amd.com             typename AddrOperandType>
40911308Santhony.gutierrez@amd.com    class LdInst :
41011308Santhony.gutierrez@amd.com        public LdInstBase<typename MemDataType::CType,
41111308Santhony.gutierrez@amd.com                          typename DestDataType::OperandType, AddrOperandType>,
41211308Santhony.gutierrez@amd.com        public MemInst
41311308Santhony.gutierrez@amd.com    {
41411308Santhony.gutierrez@amd.com        typename DestDataType::OperandType::DestOperand dest_vect[4];
41511308Santhony.gutierrez@amd.com        uint16_t num_dest_operands;
41611347Sandreas.hansson@arm.com        void generateDisassembly() override;
41711308Santhony.gutierrez@amd.com
41811308Santhony.gutierrez@amd.com      public:
41911308Santhony.gutierrez@amd.com        LdInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
42011308Santhony.gutierrez@amd.com               const char *_opcode)
42111308Santhony.gutierrez@amd.com            : LdInstBase<typename MemDataType::CType,
42211308Santhony.gutierrez@amd.com                         typename DestDataType::OperandType,
42311308Santhony.gutierrez@amd.com                         AddrOperandType>(ib, obj, _opcode),
42411308Santhony.gutierrez@amd.com              MemInst(MemDataType::memType)
42511308Santhony.gutierrez@amd.com        {
42611308Santhony.gutierrez@amd.com            init_addr(&this->addr);
42711308Santhony.gutierrez@amd.com
42811308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands,0);
42911308Santhony.gutierrez@amd.com            const Brig::BrigOperand *brigOp = obj->getOperand(op_offs);
43011308Santhony.gutierrez@amd.com
43111308Santhony.gutierrez@amd.com            if (brigOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
43211308Santhony.gutierrez@amd.com                const Brig::BrigOperandOperandList *brigRegVecOp =
43311308Santhony.gutierrez@amd.com                    (const Brig::BrigOperandOperandList*)brigOp;
43411308Santhony.gutierrez@amd.com
43511308Santhony.gutierrez@amd.com                num_dest_operands =
43611308Santhony.gutierrez@amd.com                    *((unsigned*)obj->getData(brigRegVecOp->elements)) / 4;
43711308Santhony.gutierrez@amd.com
43811308Santhony.gutierrez@amd.com                assert(num_dest_operands <= 4);
43911308Santhony.gutierrez@amd.com            } else {
44011308Santhony.gutierrez@amd.com                num_dest_operands = 1;
44111308Santhony.gutierrez@amd.com            }
44211308Santhony.gutierrez@amd.com
44311308Santhony.gutierrez@amd.com            if (num_dest_operands > 1) {
44411308Santhony.gutierrez@amd.com                assert(brigOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST);
44511308Santhony.gutierrez@amd.com
44611308Santhony.gutierrez@amd.com                for (int i = 0; i < num_dest_operands; ++i) {
44711308Santhony.gutierrez@amd.com                    dest_vect[i].init_from_vect(op_offs, obj, i);
44811308Santhony.gutierrez@amd.com                }
44911308Santhony.gutierrez@amd.com            }
45011308Santhony.gutierrez@amd.com        }
45111308Santhony.gutierrez@amd.com
45211308Santhony.gutierrez@amd.com        void
45311308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst) override
45411308Santhony.gutierrez@amd.com        {
45511308Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c0;
45611308Santhony.gutierrez@amd.com
45711308Santhony.gutierrez@amd.com            gpuDynInst->statusBitVector = gpuDynInst->exec_mask;
45811308Santhony.gutierrez@amd.com
45911308Santhony.gutierrez@amd.com            if (num_dest_operands > 1) {
46011534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i)
46111308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i])
46211308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(num_dest_operands);
46311308Santhony.gutierrez@amd.com                    else
46411308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(0);
46511308Santhony.gutierrez@amd.com            }
46611308Santhony.gutierrez@amd.com
46711308Santhony.gutierrez@amd.com            for (int k = 0; k < num_dest_operands; ++k) {
46811308Santhony.gutierrez@amd.com
46911534Sjohn.kalamatianos@amd.com                c0 *d = &((c0*)gpuDynInst->d_data)
47011534Sjohn.kalamatianos@amd.com                    [k * gpuDynInst->computeUnit()->wfSize()];
47111308Santhony.gutierrez@amd.com
47211534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) {
47311308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i]) {
47411308Santhony.gutierrez@amd.com                        Addr vaddr = gpuDynInst->addr[i] + k * sizeof(c0);
47511308Santhony.gutierrez@amd.com
47611308Santhony.gutierrez@amd.com                        if (isLocalMem()) {
47711308Santhony.gutierrez@amd.com                            // load from shared memory
47811308Santhony.gutierrez@amd.com                            *d = gpuDynInst->wavefront()->ldsChunk->
47911308Santhony.gutierrez@amd.com                                read<c0>(vaddr);
48011308Santhony.gutierrez@amd.com                        } else {
48111308Santhony.gutierrez@amd.com                            Request *req = new Request(0, vaddr, sizeof(c0), 0,
48211308Santhony.gutierrez@amd.com                                          gpuDynInst->computeUnit()->masterId(),
48311435Smitch.hayenga@arm.com                                          0, gpuDynInst->wfDynId);
48411308Santhony.gutierrez@amd.com
48511308Santhony.gutierrez@amd.com                            gpuDynInst->setRequestFlags(req);
48611308Santhony.gutierrez@amd.com                            PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
48711308Santhony.gutierrez@amd.com                            pkt->dataStatic(d);
48811308Santhony.gutierrez@amd.com
48911308Santhony.gutierrez@amd.com                            if (gpuDynInst->computeUnit()->shader->
49011308Santhony.gutierrez@amd.com                                separate_acquire_release &&
49111308Santhony.gutierrez@amd.com                                gpuDynInst->memoryOrder ==
49211308Santhony.gutierrez@amd.com                                Enums::MEMORY_ORDER_SC_ACQUIRE) {
49311308Santhony.gutierrez@amd.com                                // if this load has acquire semantics,
49411308Santhony.gutierrez@amd.com                                // set the response continuation function
49511308Santhony.gutierrez@amd.com                                // to perform an Acquire request
49611308Santhony.gutierrez@amd.com                                gpuDynInst->execContinuation =
49711308Santhony.gutierrez@amd.com                                    &GPUStaticInst::execLdAcq;
49811308Santhony.gutierrez@amd.com
49911308Santhony.gutierrez@amd.com                                gpuDynInst->useContinuation = true;
50011308Santhony.gutierrez@amd.com                            } else {
50111308Santhony.gutierrez@amd.com                                // the request will be finished when
50211308Santhony.gutierrez@amd.com                                // the load completes
50311308Santhony.gutierrez@amd.com                                gpuDynInst->useContinuation = false;
50411308Santhony.gutierrez@amd.com                            }
50511308Santhony.gutierrez@amd.com                            // translation is performed in sendRequest()
50611308Santhony.gutierrez@amd.com                            gpuDynInst->computeUnit()->sendRequest(gpuDynInst,
50711308Santhony.gutierrez@amd.com                                                                   i, pkt);
50811308Santhony.gutierrez@amd.com                        }
50911308Santhony.gutierrez@amd.com                    }
51011308Santhony.gutierrez@amd.com                    ++d;
51111308Santhony.gutierrez@amd.com                }
51211308Santhony.gutierrez@amd.com            }
51311308Santhony.gutierrez@amd.com
51411308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
51511308Santhony.gutierrez@amd.com        }
51611308Santhony.gutierrez@amd.com
51711308Santhony.gutierrez@amd.com      private:
51811308Santhony.gutierrez@amd.com        void
51911308Santhony.gutierrez@amd.com        execLdAcq(GPUDynInstPtr gpuDynInst) override
52011308Santhony.gutierrez@amd.com        {
52111308Santhony.gutierrez@amd.com            // after the load has complete and if the load has acquire
52211308Santhony.gutierrez@amd.com            // semantics, issue an acquire request.
52311308Santhony.gutierrez@amd.com            if (!isLocalMem()) {
52411308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
52511308Santhony.gutierrez@amd.com                    && gpuDynInst->memoryOrder ==
52611308Santhony.gutierrez@amd.com                    Enums::MEMORY_ORDER_SC_ACQUIRE) {
52711308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
52811308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = false;
52911308Santhony.gutierrez@amd.com                    // create request
53011308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
53111308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
53211435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
53311308Santhony.gutierrez@amd.com                    req->setFlags(Request::ACQUIRE);
53411308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
53511308Santhony.gutierrez@amd.com                }
53611308Santhony.gutierrez@amd.com            }
53711308Santhony.gutierrez@amd.com        }
53811308Santhony.gutierrez@amd.com
53911308Santhony.gutierrez@amd.com      public:
54011308Santhony.gutierrez@amd.com        bool
54111308Santhony.gutierrez@amd.com        isLocalMem() const override
54211308Santhony.gutierrez@amd.com        {
54311308Santhony.gutierrez@amd.com            return this->segment == Brig::BRIG_SEGMENT_GROUP;
54411308Santhony.gutierrez@amd.com        }
54511308Santhony.gutierrez@amd.com
54611347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
54711308Santhony.gutierrez@amd.com        {
54811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
54911308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
55011308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
55111308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
55211308Santhony.gutierrez@amd.com            if (num_dest_operands > 1) {
55311308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isVectorRegister();
55411308Santhony.gutierrez@amd.com            }
55511308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1) {
55611308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
55711308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
55811308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isVectorRegister();
55911308Santhony.gutierrez@amd.com            }
56011308Santhony.gutierrez@amd.com            return false;
56111308Santhony.gutierrez@amd.com        }
56211347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
56311308Santhony.gutierrez@amd.com        {
56411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
56511308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
56611308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
56711308Santhony.gutierrez@amd.com                return(this->addr.isCondRegister());
56811308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
56911308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isCondRegister();
57011308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
57111308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
57211308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
57311308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isCondRegister();
57411308Santhony.gutierrez@amd.com            return false;
57511308Santhony.gutierrez@amd.com        }
57611347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
57711308Santhony.gutierrez@amd.com        {
57811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
57911308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
58011308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
58111308Santhony.gutierrez@amd.com                return(this->addr.isScalarRegister());
58211308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
58311308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isScalarRegister();
58411308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
58511308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
58611308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
58711308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isScalarRegister();
58811308Santhony.gutierrez@amd.com            return false;
58911308Santhony.gutierrez@amd.com        }
59011347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
59111308Santhony.gutierrez@amd.com        {
59211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
59311308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
59411308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
59511308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
59611308Santhony.gutierrez@amd.com            return false;
59711308Santhony.gutierrez@amd.com        }
59811347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override
59911308Santhony.gutierrez@amd.com        {
60011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
60111308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
60211308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
60311308Santhony.gutierrez@amd.com                return false;
60411308Santhony.gutierrez@amd.com            return true;
60511308Santhony.gutierrez@amd.com        }
60611347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
60711308Santhony.gutierrez@amd.com        {
60811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
60911308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
61011308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
61111308Santhony.gutierrez@amd.com                return(this->addr.opSize());
61211308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
61311308Santhony.gutierrez@amd.com                return(dest_vect[operandIndex].opSize());
61411308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
61511308Santhony.gutierrez@amd.com                return(LdInstBase<typename MemDataType::CType,
61611308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
61711308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.opSize());
61811308Santhony.gutierrez@amd.com            return 0;
61911308Santhony.gutierrez@amd.com        }
62011347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
62111308Santhony.gutierrez@amd.com        {
62211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
62311308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
62411308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
62511308Santhony.gutierrez@amd.com                return(this->addr.regIndex());
62611308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
62711308Santhony.gutierrez@amd.com                return(dest_vect[operandIndex].regIndex());
62811308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
62911308Santhony.gutierrez@amd.com                return(LdInstBase<typename MemDataType::CType,
63011308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
63111308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.regIndex());
63211308Santhony.gutierrez@amd.com            return -1;
63311308Santhony.gutierrez@amd.com        }
63411347Sandreas.hansson@arm.com        int getNumOperands() override
63511308Santhony.gutierrez@amd.com        {
63611308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
63711308Santhony.gutierrez@amd.com                return(num_dest_operands+1);
63811308Santhony.gutierrez@amd.com            else
63911308Santhony.gutierrez@amd.com                return(num_dest_operands);
64011308Santhony.gutierrez@amd.com        }
64111347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
64211308Santhony.gutierrez@amd.com    };
64311308Santhony.gutierrez@amd.com
64411308Santhony.gutierrez@amd.com    template<typename MemDT, typename DestDT>
64511308Santhony.gutierrez@amd.com    GPUStaticInst*
64611308Santhony.gutierrez@amd.com    decodeLd2(const Brig::BrigInstBase *ib, const BrigObject *obj)
64711308Santhony.gutierrez@amd.com    {
64811308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,1);
64911308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
65011308Santhony.gutierrez@amd.com
65111308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
65211308Santhony.gutierrez@amd.com            return new LdInst<MemDT, DestDT, NoRegAddrOperand>(ib, obj, "ld");
65311308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER ||
65411308Santhony.gutierrez@amd.com                   tmp.kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
65511308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
65611308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
65711308Santhony.gutierrez@amd.com                return new LdInst<MemDT, DestDT,
65811308Santhony.gutierrez@amd.com                                  SRegAddrOperand>(ib, obj, "ld");
65911308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
66011308Santhony.gutierrez@amd.com                return new LdInst<MemDT, DestDT,
66111308Santhony.gutierrez@amd.com                                  DRegAddrOperand>(ib, obj, "ld");
66211308Santhony.gutierrez@amd.com              default:
66311308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d\n", tmp.regKind);
66411308Santhony.gutierrez@amd.com            }
66511308Santhony.gutierrez@amd.com        } else {
66611308Santhony.gutierrez@amd.com            fatal("Bad ld register operand kind %d\n", tmp.kind);
66711308Santhony.gutierrez@amd.com        }
66811308Santhony.gutierrez@amd.com    }
66911308Santhony.gutierrez@amd.com
67011308Santhony.gutierrez@amd.com    template<typename MemDT>
67111308Santhony.gutierrez@amd.com    GPUStaticInst*
67211308Santhony.gutierrez@amd.com    decodeLd(const Brig::BrigInstBase *ib, const BrigObject *obj)
67311308Santhony.gutierrez@amd.com    {
67411308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,0);
67511308Santhony.gutierrez@amd.com        BrigRegOperandInfo dest = findRegDataType(op_offs, obj);
67611308Santhony.gutierrez@amd.com
67711308Santhony.gutierrez@amd.com        assert(dest.kind == Brig::BRIG_KIND_OPERAND_REGISTER ||
67811308Santhony.gutierrez@amd.com               dest.kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST);
67911308Santhony.gutierrez@amd.com        switch(dest.regKind) {
68011308Santhony.gutierrez@amd.com          case Brig::BRIG_REGISTER_KIND_SINGLE:
68111308Santhony.gutierrez@amd.com            switch (ib->type) {
68211308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B8:
68311308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B16:
68411308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B32:
68511308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, B32>(ib, obj);
68611308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U8:
68711308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U16:
68811308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U32:
68911308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U32>(ib, obj);
69011308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S8:
69111308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S16:
69211308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S32:
69311308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, S32>(ib, obj);
69411308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F16:
69511308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F32:
69611308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U32>(ib, obj);
69711308Santhony.gutierrez@amd.com              default:
69811308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d, %d\n",
69911308Santhony.gutierrez@amd.com                      dest.regKind, ib->type);
70011308Santhony.gutierrez@amd.com            };
70111308Santhony.gutierrez@amd.com          case Brig::BRIG_REGISTER_KIND_DOUBLE:
70211308Santhony.gutierrez@amd.com            switch (ib->type) {
70311308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B64:
70411308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, B64>(ib, obj);
70511308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U64:
70611308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U64>(ib, obj);
70711308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S64:
70811308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, S64>(ib, obj);
70911308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F64:
71011308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U64>(ib, obj);
71111308Santhony.gutierrez@amd.com              default:
71211308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d, %d\n",
71311308Santhony.gutierrez@amd.com                      dest.regKind, ib->type);
71411308Santhony.gutierrez@amd.com            };
71511308Santhony.gutierrez@amd.com          default:
71611308Santhony.gutierrez@amd.com            fatal("Bad ld register operand type %d, %d\n", dest.regKind,
71711308Santhony.gutierrez@amd.com                  ib->type);
71811308Santhony.gutierrez@amd.com        }
71911308Santhony.gutierrez@amd.com    }
72011308Santhony.gutierrez@amd.com
72111308Santhony.gutierrez@amd.com    template<typename MemDataType, typename SrcOperandType,
72211308Santhony.gutierrez@amd.com             typename AddrOperandType>
72311308Santhony.gutierrez@amd.com    class StInstBase : public HsailGPUStaticInst
72411308Santhony.gutierrez@amd.com    {
72511308Santhony.gutierrez@amd.com      public:
72611308Santhony.gutierrez@amd.com        typename SrcOperandType::SrcOperand src;
72711308Santhony.gutierrez@amd.com        AddrOperandType addr;
72811308Santhony.gutierrez@amd.com
72911308Santhony.gutierrez@amd.com        Brig::BrigSegment segment;
73011308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memoryScope;
73111308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memoryOrder;
73211308Santhony.gutierrez@amd.com        unsigned int equivClass;
73311308Santhony.gutierrez@amd.com
73411308Santhony.gutierrez@amd.com        void
73511308Santhony.gutierrez@amd.com        initSt(const Brig::BrigInstBase *ib, const BrigObject *obj,
73611308Santhony.gutierrez@amd.com               const char *_opcode)
73711308Santhony.gutierrez@amd.com        {
73811308Santhony.gutierrez@amd.com            using namespace Brig;
73911308Santhony.gutierrez@amd.com
74011308Santhony.gutierrez@amd.com            const BrigInstMem *ldst = (const BrigInstMem*)ib;
74111308Santhony.gutierrez@amd.com
74211308Santhony.gutierrez@amd.com            segment = (BrigSegment)ldst->segment;
74311308Santhony.gutierrez@amd.com            memoryOrder = BRIG_MEMORY_ORDER_NONE;
74411308Santhony.gutierrez@amd.com            memoryScope = BRIG_MEMORY_SCOPE_NONE;
74511308Santhony.gutierrez@amd.com            equivClass = ldst->equivClass;
74611308Santhony.gutierrez@amd.com
74711308Santhony.gutierrez@amd.com            switch (segment) {
74811308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
74911308Santhony.gutierrez@amd.com                o_type = Enums::OT_GLOBAL_WRITE;
75011308Santhony.gutierrez@amd.com                break;
75111308Santhony.gutierrez@amd.com
75211308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
75311308Santhony.gutierrez@amd.com                o_type = Enums::OT_SHARED_WRITE;
75411308Santhony.gutierrez@amd.com                break;
75511308Santhony.gutierrez@amd.com
75611308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_PRIVATE:
75711308Santhony.gutierrez@amd.com                o_type = Enums::OT_PRIVATE_WRITE;
75811308Santhony.gutierrez@amd.com                break;
75911308Santhony.gutierrez@amd.com
76011308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_READONLY:
76111308Santhony.gutierrez@amd.com                o_type = Enums::OT_READONLY_WRITE;
76211308Santhony.gutierrez@amd.com                break;
76311308Santhony.gutierrez@amd.com
76411308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_SPILL:
76511308Santhony.gutierrez@amd.com                o_type = Enums::OT_SPILL_WRITE;
76611308Santhony.gutierrez@amd.com                break;
76711308Santhony.gutierrez@amd.com
76811308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
76911308Santhony.gutierrez@amd.com                o_type = Enums::OT_FLAT_WRITE;
77011308Santhony.gutierrez@amd.com                break;
77111308Santhony.gutierrez@amd.com
77211308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_ARG:
77311308Santhony.gutierrez@amd.com                o_type = Enums::OT_ARG;
77411308Santhony.gutierrez@amd.com                break;
77511308Santhony.gutierrez@amd.com
77611308Santhony.gutierrez@amd.com              default:
77711308Santhony.gutierrez@amd.com                panic("St: segment %d not supported\n", segment);
77811308Santhony.gutierrez@amd.com            }
77911308Santhony.gutierrez@amd.com
78011308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
78111308Santhony.gutierrez@amd.com            const BrigOperand *baseOp = obj->getOperand(op_offs);
78211308Santhony.gutierrez@amd.com
78311308Santhony.gutierrez@amd.com            if ((baseOp->kind == BRIG_KIND_OPERAND_CONSTANT_BYTES) ||
78411308Santhony.gutierrez@amd.com                (baseOp->kind == BRIG_KIND_OPERAND_REGISTER)) {
78511308Santhony.gutierrez@amd.com                src.init(op_offs, obj);
78611308Santhony.gutierrez@amd.com            }
78711308Santhony.gutierrez@amd.com
78811308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
78911308Santhony.gutierrez@amd.com            addr.init(op_offs, obj);
79011308Santhony.gutierrez@amd.com        }
79111308Santhony.gutierrez@amd.com
79211308Santhony.gutierrez@amd.com        void
79311308Santhony.gutierrez@amd.com        initAtomicSt(const Brig::BrigInstBase *ib, const BrigObject *obj,
79411308Santhony.gutierrez@amd.com                     const char *_opcode)
79511308Santhony.gutierrez@amd.com        {
79611308Santhony.gutierrez@amd.com            using namespace Brig;
79711308Santhony.gutierrez@amd.com
79811308Santhony.gutierrez@amd.com            const BrigInstAtomic *at = (const BrigInstAtomic*)ib;
79911308Santhony.gutierrez@amd.com
80011308Santhony.gutierrez@amd.com            segment = (BrigSegment)at->segment;
80111308Santhony.gutierrez@amd.com            memoryScope = (BrigMemoryScope)at->memoryScope;
80211308Santhony.gutierrez@amd.com            memoryOrder = (BrigMemoryOrder)at->memoryOrder;
80311308Santhony.gutierrez@amd.com            equivClass = 0;
80411308Santhony.gutierrez@amd.com
80511308Santhony.gutierrez@amd.com            switch (segment) {
80611308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
80711308Santhony.gutierrez@amd.com                o_type = Enums::OT_GLOBAL_WRITE;
80811308Santhony.gutierrez@amd.com                break;
80911308Santhony.gutierrez@amd.com
81011308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
81111308Santhony.gutierrez@amd.com                o_type = Enums::OT_SHARED_WRITE;
81211308Santhony.gutierrez@amd.com                break;
81311308Santhony.gutierrez@amd.com
81411308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_PRIVATE:
81511308Santhony.gutierrez@amd.com                o_type = Enums::OT_PRIVATE_WRITE;
81611308Santhony.gutierrez@amd.com                break;
81711308Santhony.gutierrez@amd.com
81811308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_READONLY:
81911308Santhony.gutierrez@amd.com                o_type = Enums::OT_READONLY_WRITE;
82011308Santhony.gutierrez@amd.com                break;
82111308Santhony.gutierrez@amd.com
82211308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_SPILL:
82311308Santhony.gutierrez@amd.com                o_type = Enums::OT_SPILL_WRITE;
82411308Santhony.gutierrez@amd.com                break;
82511308Santhony.gutierrez@amd.com
82611308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
82711308Santhony.gutierrez@amd.com                o_type = Enums::OT_FLAT_WRITE;
82811308Santhony.gutierrez@amd.com                break;
82911308Santhony.gutierrez@amd.com
83011308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_ARG:
83111308Santhony.gutierrez@amd.com                o_type = Enums::OT_ARG;
83211308Santhony.gutierrez@amd.com                break;
83311308Santhony.gutierrez@amd.com
83411308Santhony.gutierrez@amd.com              default:
83511308Santhony.gutierrez@amd.com                panic("St: segment %d not supported\n", segment);
83611308Santhony.gutierrez@amd.com            }
83711308Santhony.gutierrez@amd.com
83811308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
83911308Santhony.gutierrez@amd.com            addr.init(op_offs, obj);
84011308Santhony.gutierrez@amd.com
84111308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
84211308Santhony.gutierrez@amd.com            src.init(op_offs, obj);
84311308Santhony.gutierrez@amd.com        }
84411308Santhony.gutierrez@amd.com
84511308Santhony.gutierrez@amd.com        StInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
84611308Santhony.gutierrez@amd.com                   const char *_opcode)
84711308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
84811308Santhony.gutierrez@amd.com        {
84911308Santhony.gutierrez@amd.com            using namespace Brig;
85011308Santhony.gutierrez@amd.com
85111308Santhony.gutierrez@amd.com            if (ib->opcode == BRIG_OPCODE_ST) {
85211308Santhony.gutierrez@amd.com                initSt(ib, obj, _opcode);
85311308Santhony.gutierrez@amd.com            } else {
85411308Santhony.gutierrez@amd.com                initAtomicSt(ib, obj, _opcode);
85511308Santhony.gutierrez@amd.com            }
85611308Santhony.gutierrez@amd.com        }
85711308Santhony.gutierrez@amd.com
85811347Sandreas.hansson@arm.com        int numDstRegOperands() override { return 0; }
85911347Sandreas.hansson@arm.com        int numSrcRegOperands() override
86011308Santhony.gutierrez@amd.com        {
86111308Santhony.gutierrez@amd.com            return src.isVectorRegister() + this->addr.isVectorRegister();
86211308Santhony.gutierrez@amd.com        }
86311347Sandreas.hansson@arm.com        int getNumOperands() override
86411308Santhony.gutierrez@amd.com        {
86511308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
86611308Santhony.gutierrez@amd.com                return 2;
86711308Santhony.gutierrez@amd.com            else
86811308Santhony.gutierrez@amd.com                return 1;
86911308Santhony.gutierrez@amd.com        }
87011347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
87111308Santhony.gutierrez@amd.com        {
87211308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
87311308Santhony.gutierrez@amd.com            return !operandIndex ? src.isVectorRegister() :
87411308Santhony.gutierrez@amd.com                   this->addr.isVectorRegister();
87511308Santhony.gutierrez@amd.com        }
87611347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
87711308Santhony.gutierrez@amd.com        {
87811308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
87911308Santhony.gutierrez@amd.com            return !operandIndex ? src.isCondRegister() :
88011308Santhony.gutierrez@amd.com                   this->addr.isCondRegister();
88111308Santhony.gutierrez@amd.com        }
88211347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
88311308Santhony.gutierrez@amd.com        {
88411308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
88511308Santhony.gutierrez@amd.com            return !operandIndex ? src.isScalarRegister() :
88611308Santhony.gutierrez@amd.com                   this->addr.isScalarRegister();
88711308Santhony.gutierrez@amd.com        }
88811347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
88911308Santhony.gutierrez@amd.com        {
89011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
89111308Santhony.gutierrez@amd.com            return true;
89211308Santhony.gutierrez@amd.com        }
89311347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override { return false; }
89411347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
89511308Santhony.gutierrez@amd.com        {
89611308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
89711308Santhony.gutierrez@amd.com            return !operandIndex ? src.opSize() : this->addr.opSize();
89811308Santhony.gutierrez@amd.com        }
89911347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
90011308Santhony.gutierrez@amd.com        {
90111308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
90211308Santhony.gutierrez@amd.com            return !operandIndex ? src.regIndex() : this->addr.regIndex();
90311308Santhony.gutierrez@amd.com        }
90411308Santhony.gutierrez@amd.com    };
90511308Santhony.gutierrez@amd.com
90611308Santhony.gutierrez@amd.com
90711308Santhony.gutierrez@amd.com    template<typename MemDataType, typename SrcDataType,
90811308Santhony.gutierrez@amd.com             typename AddrOperandType>
90911308Santhony.gutierrez@amd.com    class StInst :
91011308Santhony.gutierrez@amd.com        public StInstBase<MemDataType, typename SrcDataType::OperandType,
91111308Santhony.gutierrez@amd.com                          AddrOperandType>,
91211308Santhony.gutierrez@amd.com        public MemInst
91311308Santhony.gutierrez@amd.com    {
91411308Santhony.gutierrez@amd.com      public:
91511308Santhony.gutierrez@amd.com        typename SrcDataType::OperandType::SrcOperand src_vect[4];
91611308Santhony.gutierrez@amd.com        uint16_t num_src_operands;
91711347Sandreas.hansson@arm.com        void generateDisassembly() override;
91811308Santhony.gutierrez@amd.com
91911308Santhony.gutierrez@amd.com        StInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
92011308Santhony.gutierrez@amd.com                        const char *_opcode, int srcIdx)
92111308Santhony.gutierrez@amd.com            : StInstBase<MemDataType, typename SrcDataType::OperandType,
92211308Santhony.gutierrez@amd.com                         AddrOperandType>(ib, obj, _opcode),
92311308Santhony.gutierrez@amd.com              MemInst(SrcDataType::memType)
92411308Santhony.gutierrez@amd.com        {
92511308Santhony.gutierrez@amd.com            init_addr(&this->addr);
92611308Santhony.gutierrez@amd.com
92711308Santhony.gutierrez@amd.com            BrigRegOperandInfo rinfo;
92811308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands,srcIdx);
92911308Santhony.gutierrez@amd.com            const Brig::BrigOperand *baseOp = obj->getOperand(op_offs);
93011308Santhony.gutierrez@amd.com
93111308Santhony.gutierrez@amd.com            if (baseOp->kind == Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES) {
93211308Santhony.gutierrez@amd.com                const Brig::BrigOperandConstantBytes *op =
93311308Santhony.gutierrez@amd.com                    (Brig::BrigOperandConstantBytes*)baseOp;
93411308Santhony.gutierrez@amd.com
93511308Santhony.gutierrez@amd.com                rinfo = BrigRegOperandInfo((Brig::BrigKind16_t)op->base.kind,
93611308Santhony.gutierrez@amd.com                                           Brig::BRIG_TYPE_NONE);
93711308Santhony.gutierrez@amd.com            } else {
93811308Santhony.gutierrez@amd.com                rinfo = findRegDataType(op_offs, obj);
93911308Santhony.gutierrez@amd.com            }
94011308Santhony.gutierrez@amd.com
94111308Santhony.gutierrez@amd.com            if (baseOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
94211308Santhony.gutierrez@amd.com                const Brig::BrigOperandOperandList *brigRegVecOp =
94311308Santhony.gutierrez@amd.com                    (const Brig::BrigOperandOperandList*)baseOp;
94411308Santhony.gutierrez@amd.com
94511308Santhony.gutierrez@amd.com                num_src_operands =
94611308Santhony.gutierrez@amd.com                    *((unsigned*)obj->getData(brigRegVecOp->elements)) / 4;
94711308Santhony.gutierrez@amd.com
94811308Santhony.gutierrez@amd.com                assert(num_src_operands <= 4);
94911308Santhony.gutierrez@amd.com            } else {
95011308Santhony.gutierrez@amd.com                num_src_operands = 1;
95111308Santhony.gutierrez@amd.com            }
95211308Santhony.gutierrez@amd.com
95311308Santhony.gutierrez@amd.com            if (num_src_operands > 1) {
95411308Santhony.gutierrez@amd.com                assert(baseOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST);
95511308Santhony.gutierrez@amd.com
95611308Santhony.gutierrez@amd.com                for (int i = 0; i < num_src_operands; ++i) {
95711308Santhony.gutierrez@amd.com                    src_vect[i].init_from_vect(op_offs, obj, i);
95811308Santhony.gutierrez@amd.com                }
95911308Santhony.gutierrez@amd.com            }
96011308Santhony.gutierrez@amd.com        }
96111308Santhony.gutierrez@amd.com
96211308Santhony.gutierrez@amd.com        void
96311308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst) override
96411308Santhony.gutierrez@amd.com        {
96511308Santhony.gutierrez@amd.com            // before performing a store, check if this store has
96611308Santhony.gutierrez@amd.com            // release semantics, and if so issue a release first
96711308Santhony.gutierrez@amd.com            if (!isLocalMem()) {
96811308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
96911308Santhony.gutierrez@amd.com                    && gpuDynInst->memoryOrder ==
97011308Santhony.gutierrez@amd.com                    Enums::MEMORY_ORDER_SC_RELEASE) {
97111308Santhony.gutierrez@amd.com
97211308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
97311308Santhony.gutierrez@amd.com                    gpuDynInst->execContinuation = &GPUStaticInst::execSt;
97411308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = true;
97511308Santhony.gutierrez@amd.com                    // create request
97611308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
97711308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
97811435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
97911308Santhony.gutierrez@amd.com                    req->setFlags(Request::RELEASE);
98011308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
98111308Santhony.gutierrez@amd.com
98211308Santhony.gutierrez@amd.com                    return;
98311308Santhony.gutierrez@amd.com                }
98411308Santhony.gutierrez@amd.com            }
98511308Santhony.gutierrez@amd.com
98611308Santhony.gutierrez@amd.com            // if there is no release semantic, perform stores immediately
98711308Santhony.gutierrez@amd.com            execSt(gpuDynInst);
98811308Santhony.gutierrez@amd.com        }
98911308Santhony.gutierrez@amd.com
99011308Santhony.gutierrez@amd.com        bool
99111308Santhony.gutierrez@amd.com        isLocalMem() const override
99211308Santhony.gutierrez@amd.com        {
99311308Santhony.gutierrez@amd.com            return this->segment == Brig::BRIG_SEGMENT_GROUP;
99411308Santhony.gutierrez@amd.com        }
99511308Santhony.gutierrez@amd.com
99611308Santhony.gutierrez@amd.com      private:
99711308Santhony.gutierrez@amd.com        // execSt may be called through a continuation
99811308Santhony.gutierrez@amd.com        // if the store had release semantics. see comment for
99911308Santhony.gutierrez@amd.com        // execSt in gpu_static_inst.hh
100011308Santhony.gutierrez@amd.com        void
100111308Santhony.gutierrez@amd.com        execSt(GPUDynInstPtr gpuDynInst) override
100211308Santhony.gutierrez@amd.com        {
100311308Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c0;
100411308Santhony.gutierrez@amd.com
100511308Santhony.gutierrez@amd.com            gpuDynInst->statusBitVector = gpuDynInst->exec_mask;
100611308Santhony.gutierrez@amd.com
100711308Santhony.gutierrez@amd.com            if (num_src_operands > 1) {
100811534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i)
100911308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i])
101011308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(num_src_operands);
101111308Santhony.gutierrez@amd.com                    else
101211308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(0);
101311308Santhony.gutierrez@amd.com            }
101411308Santhony.gutierrez@amd.com
101511308Santhony.gutierrez@amd.com            for (int k = 0; k < num_src_operands; ++k) {
101611534Sjohn.kalamatianos@amd.com                c0 *d = &((c0*)gpuDynInst->d_data)
101711534Sjohn.kalamatianos@amd.com                    [k * gpuDynInst->computeUnit()->wfSize()];
101811308Santhony.gutierrez@amd.com
101911534Sjohn.kalamatianos@amd.com                for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) {
102011308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i]) {
102111308Santhony.gutierrez@amd.com                        Addr vaddr = gpuDynInst->addr[i] + k * sizeof(c0);
102211308Santhony.gutierrez@amd.com
102311308Santhony.gutierrez@amd.com                        if (isLocalMem()) {
102411308Santhony.gutierrez@amd.com                            //store to shared memory
102511308Santhony.gutierrez@amd.com                            gpuDynInst->wavefront()->ldsChunk->write<c0>(vaddr,
102611308Santhony.gutierrez@amd.com                                                                         *d);
102711308Santhony.gutierrez@amd.com                        } else {
102811308Santhony.gutierrez@amd.com                            Request *req =
102911308Santhony.gutierrez@amd.com                              new Request(0, vaddr, sizeof(c0), 0,
103011308Santhony.gutierrez@amd.com                                          gpuDynInst->computeUnit()->masterId(),
103111435Smitch.hayenga@arm.com                                          0, gpuDynInst->wfDynId);
103211308Santhony.gutierrez@amd.com
103311308Santhony.gutierrez@amd.com                            gpuDynInst->setRequestFlags(req);
103411308Santhony.gutierrez@amd.com                            PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
103511308Santhony.gutierrez@amd.com                            pkt->dataStatic<c0>(d);
103611308Santhony.gutierrez@amd.com
103711308Santhony.gutierrez@amd.com                            // translation is performed in sendRequest()
103811308Santhony.gutierrez@amd.com                            // the request will be finished when the store completes
103911308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = false;
104011308Santhony.gutierrez@amd.com                            gpuDynInst->computeUnit()->sendRequest(gpuDynInst,
104111308Santhony.gutierrez@amd.com                                                                   i, pkt);
104211308Santhony.gutierrez@amd.com
104311308Santhony.gutierrez@amd.com                        }
104411308Santhony.gutierrez@amd.com                    }
104511308Santhony.gutierrez@amd.com                    ++d;
104611308Santhony.gutierrez@amd.com                }
104711308Santhony.gutierrez@amd.com            }
104811308Santhony.gutierrez@amd.com
104911308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
105011308Santhony.gutierrez@amd.com        }
105111308Santhony.gutierrez@amd.com
105211308Santhony.gutierrez@amd.com      public:
105311347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
105411308Santhony.gutierrez@amd.com        {
105511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
105611308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
105711308Santhony.gutierrez@amd.com                return this->addr.isVectorRegister();
105811308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
105911308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isVectorRegister();
106011308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
106111308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
106211308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
106311308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isVectorRegister();
106411308Santhony.gutierrez@amd.com            return false;
106511308Santhony.gutierrez@amd.com        }
106611347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
106711308Santhony.gutierrez@amd.com        {
106811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
106911308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
107011308Santhony.gutierrez@amd.com                return this->addr.isCondRegister();
107111308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
107211308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isCondRegister();
107311308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
107411308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
107511308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
107611308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isCondRegister();
107711308Santhony.gutierrez@amd.com            return false;
107811308Santhony.gutierrez@amd.com        }
107911347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
108011308Santhony.gutierrez@amd.com        {
108111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
108211308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
108311308Santhony.gutierrez@amd.com                return this->addr.isScalarRegister();
108411308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
108511308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isScalarRegister();
108611308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
108711308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
108811308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
108911308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isScalarRegister();
109011308Santhony.gutierrez@amd.com            return false;
109111308Santhony.gutierrez@amd.com        }
109211347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
109311308Santhony.gutierrez@amd.com        {
109411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
109511308Santhony.gutierrez@amd.com            return true;
109611308Santhony.gutierrez@amd.com        }
109711347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override { return false; }
109811347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
109911308Santhony.gutierrez@amd.com        {
110011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
110111308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
110211308Santhony.gutierrez@amd.com                return this->addr.opSize();
110311308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
110411308Santhony.gutierrez@amd.com                return src_vect[operandIndex].opSize();
110511308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
110611308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
110711308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
110811308Santhony.gutierrez@amd.com                       AddrOperandType>::src.opSize();
110911308Santhony.gutierrez@amd.com            return 0;
111011308Santhony.gutierrez@amd.com        }
111111347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
111211308Santhony.gutierrez@amd.com        {
111311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
111411308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
111511308Santhony.gutierrez@amd.com                return this->addr.regIndex();
111611308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
111711308Santhony.gutierrez@amd.com                return src_vect[operandIndex].regIndex();
111811308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
111911308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
112011308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
112111308Santhony.gutierrez@amd.com                       AddrOperandType>::src.regIndex();
112211308Santhony.gutierrez@amd.com            return -1;
112311308Santhony.gutierrez@amd.com        }
112411347Sandreas.hansson@arm.com        int getNumOperands() override
112511308Santhony.gutierrez@amd.com        {
112611308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
112711308Santhony.gutierrez@amd.com                return num_src_operands + 1;
112811308Santhony.gutierrez@amd.com            else
112911308Santhony.gutierrez@amd.com                return num_src_operands;
113011308Santhony.gutierrez@amd.com        }
113111347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
113211308Santhony.gutierrez@amd.com    };
113311308Santhony.gutierrez@amd.com
113411308Santhony.gutierrez@amd.com    template<typename DataType, typename SrcDataType>
113511308Santhony.gutierrez@amd.com    GPUStaticInst*
113611308Santhony.gutierrez@amd.com    decodeSt(const Brig::BrigInstBase *ib, const BrigObject *obj)
113711308Santhony.gutierrez@amd.com    {
113811308Santhony.gutierrez@amd.com        int srcIdx = 0;
113911308Santhony.gutierrez@amd.com        int destIdx = 1;
114011308Santhony.gutierrez@amd.com        if (ib->opcode == Brig::BRIG_OPCODE_ATOMIC ||
114111308Santhony.gutierrez@amd.com            ib->opcode == Brig::BRIG_OPCODE_ATOMICNORET) {
114211308Santhony.gutierrez@amd.com            srcIdx = 1;
114311308Santhony.gutierrez@amd.com            destIdx = 0;
114411308Santhony.gutierrez@amd.com        }
114511308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,destIdx);
114611308Santhony.gutierrez@amd.com
114711308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
114811308Santhony.gutierrez@amd.com
114911308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
115011308Santhony.gutierrez@amd.com            return new StInst<DataType, SrcDataType,
115111308Santhony.gutierrez@amd.com                              NoRegAddrOperand>(ib, obj, "st", srcIdx);
115211308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER) {
115311308Santhony.gutierrez@amd.com            // V2/V4 not allowed
115411308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
115511308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
115611308Santhony.gutierrez@amd.com                return new StInst<DataType, SrcDataType,
115711308Santhony.gutierrez@amd.com                                  SRegAddrOperand>(ib, obj, "st", srcIdx);
115811308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
115911308Santhony.gutierrez@amd.com                return new StInst<DataType, SrcDataType,
116011308Santhony.gutierrez@amd.com                                  DRegAddrOperand>(ib, obj, "st", srcIdx);
116111308Santhony.gutierrez@amd.com              default:
116211308Santhony.gutierrez@amd.com                fatal("Bad st register operand type %d\n", tmp.type);
116311308Santhony.gutierrez@amd.com            }
116411308Santhony.gutierrez@amd.com        } else {
116511308Santhony.gutierrez@amd.com            fatal("Bad st register operand kind %d\n", tmp.kind);
116611308Santhony.gutierrez@amd.com        }
116711308Santhony.gutierrez@amd.com    }
116811308Santhony.gutierrez@amd.com
116911308Santhony.gutierrez@amd.com    Enums::MemOpType brigAtomicToMemOpType(Brig::BrigOpcode brigOpCode,
117011308Santhony.gutierrez@amd.com                                           Brig::BrigAtomicOperation brigOp);
117111308Santhony.gutierrez@amd.com
117211308Santhony.gutierrez@amd.com    template<typename OperandType, typename AddrOperandType, int NumSrcOperands,
117311308Santhony.gutierrez@amd.com             bool HasDst>
117411308Santhony.gutierrez@amd.com    class AtomicInstBase : public HsailGPUStaticInst
117511308Santhony.gutierrez@amd.com    {
117611308Santhony.gutierrez@amd.com      public:
117711308Santhony.gutierrez@amd.com        typename OperandType::DestOperand dest;
117811308Santhony.gutierrez@amd.com        typename OperandType::SrcOperand src[NumSrcOperands];
117911308Santhony.gutierrez@amd.com        AddrOperandType addr;
118011308Santhony.gutierrez@amd.com
118111308Santhony.gutierrez@amd.com        Brig::BrigSegment segment;
118211308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memoryOrder;
118311308Santhony.gutierrez@amd.com        Brig::BrigAtomicOperation atomicOperation;
118411308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memoryScope;
118511308Santhony.gutierrez@amd.com        Brig::BrigOpcode opcode;
118611308Santhony.gutierrez@amd.com        Enums::MemOpType opType;
118711308Santhony.gutierrez@amd.com
118811308Santhony.gutierrez@amd.com        AtomicInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
118911308Santhony.gutierrez@amd.com                       const char *_opcode)
119011308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
119111308Santhony.gutierrez@amd.com        {
119211308Santhony.gutierrez@amd.com            using namespace Brig;
119311308Santhony.gutierrez@amd.com
119411308Santhony.gutierrez@amd.com            const BrigInstAtomic *at = (const BrigInstAtomic*)ib;
119511308Santhony.gutierrez@amd.com
119611308Santhony.gutierrez@amd.com            segment = (BrigSegment)at->segment;
119711308Santhony.gutierrez@amd.com            memoryScope = (BrigMemoryScope)at->memoryScope;
119811308Santhony.gutierrez@amd.com            memoryOrder = (BrigMemoryOrder)at->memoryOrder;
119911308Santhony.gutierrez@amd.com            atomicOperation = (BrigAtomicOperation)at->atomicOperation;
120011308Santhony.gutierrez@amd.com            opcode = (BrigOpcode)ib->opcode;
120111308Santhony.gutierrez@amd.com            opType = brigAtomicToMemOpType(opcode, atomicOperation);
120211308Santhony.gutierrez@amd.com
120311308Santhony.gutierrez@amd.com            switch (segment) {
120411308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
120511308Santhony.gutierrez@amd.com                o_type = Enums::OT_GLOBAL_ATOMIC;
120611308Santhony.gutierrez@amd.com                break;
120711308Santhony.gutierrez@amd.com
120811308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
120911308Santhony.gutierrez@amd.com                o_type = Enums::OT_SHARED_ATOMIC;
121011308Santhony.gutierrez@amd.com                break;
121111308Santhony.gutierrez@amd.com
121211308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
121311308Santhony.gutierrez@amd.com                o_type = Enums::OT_FLAT_ATOMIC;
121411308Santhony.gutierrez@amd.com                break;
121511308Santhony.gutierrez@amd.com
121611308Santhony.gutierrez@amd.com              default:
121711308Santhony.gutierrez@amd.com                panic("Atomic: segment %d not supported\n", segment);
121811308Santhony.gutierrez@amd.com            }
121911308Santhony.gutierrez@amd.com
122011308Santhony.gutierrez@amd.com            if (HasDst) {
122111308Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
122211308Santhony.gutierrez@amd.com                dest.init(op_offs, obj);
122311308Santhony.gutierrez@amd.com
122411308Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands, 1);
122511308Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
122611308Santhony.gutierrez@amd.com
122711308Santhony.gutierrez@amd.com                for (int i = 0; i < NumSrcOperands; ++i) {
122811308Santhony.gutierrez@amd.com                    op_offs = obj->getOperandPtr(ib->operands, i + 2);
122911308Santhony.gutierrez@amd.com                    src[i].init(op_offs, obj);
123011308Santhony.gutierrez@amd.com                }
123111308Santhony.gutierrez@amd.com            } else {
123211308Santhony.gutierrez@amd.com
123311308Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
123411308Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
123511308Santhony.gutierrez@amd.com
123611308Santhony.gutierrez@amd.com                for (int i = 0; i < NumSrcOperands; ++i) {
123711308Santhony.gutierrez@amd.com                    op_offs = obj->getOperandPtr(ib->operands, i + 1);
123811308Santhony.gutierrez@amd.com                    src[i].init(op_offs, obj);
123911308Santhony.gutierrez@amd.com                }
124011308Santhony.gutierrez@amd.com            }
124111308Santhony.gutierrez@amd.com        }
124211308Santhony.gutierrez@amd.com
124311308Santhony.gutierrez@amd.com        int numSrcRegOperands()
124411308Santhony.gutierrez@amd.com        {
124511308Santhony.gutierrez@amd.com            int operands = 0;
124611308Santhony.gutierrez@amd.com            for (int i = 0; i < NumSrcOperands; i++) {
124711325Ssteve.reinhardt@amd.com                if (src[i].isVectorRegister()) {
124811308Santhony.gutierrez@amd.com                    operands++;
124911308Santhony.gutierrez@amd.com                }
125011308Santhony.gutierrez@amd.com            }
125111308Santhony.gutierrez@amd.com            if (addr.isVectorRegister())
125211308Santhony.gutierrez@amd.com                operands++;
125311308Santhony.gutierrez@amd.com            return operands;
125411308Santhony.gutierrez@amd.com        }
125511308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
125611308Santhony.gutierrez@amd.com        int getNumOperands()
125711308Santhony.gutierrez@amd.com        {
125811308Santhony.gutierrez@amd.com            if (addr.isVectorRegister())
125911308Santhony.gutierrez@amd.com                return(NumSrcOperands + 2);
126011308Santhony.gutierrez@amd.com            return(NumSrcOperands + 1);
126111308Santhony.gutierrez@amd.com        }
126211308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex)
126311308Santhony.gutierrez@amd.com        {
126411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
126511308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
126611308Santhony.gutierrez@amd.com                return src[operandIndex].isVectorRegister();
126711308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
126811308Santhony.gutierrez@amd.com                return(addr.isVectorRegister());
126911308Santhony.gutierrez@amd.com            else
127011308Santhony.gutierrez@amd.com                return dest.isVectorRegister();
127111308Santhony.gutierrez@amd.com        }
127211308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex)
127311308Santhony.gutierrez@amd.com        {
127411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
127511308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
127611308Santhony.gutierrez@amd.com                return src[operandIndex].isCondRegister();
127711308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
127811308Santhony.gutierrez@amd.com                return(addr.isCondRegister());
127911308Santhony.gutierrez@amd.com            else
128011308Santhony.gutierrez@amd.com                return dest.isCondRegister();
128111308Santhony.gutierrez@amd.com        }
128211308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex)
128311308Santhony.gutierrez@amd.com        {
128411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
128511308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
128611308Santhony.gutierrez@amd.com                return src[operandIndex].isScalarRegister();
128711308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
128811308Santhony.gutierrez@amd.com                return(addr.isScalarRegister());
128911308Santhony.gutierrez@amd.com            else
129011308Santhony.gutierrez@amd.com                return dest.isScalarRegister();
129111308Santhony.gutierrez@amd.com        }
129211308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex)
129311308Santhony.gutierrez@amd.com        {
129411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
129511308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
129611308Santhony.gutierrez@amd.com                return true;
129711308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
129811308Santhony.gutierrez@amd.com                return(addr.isVectorRegister());
129911308Santhony.gutierrez@amd.com            else
130011308Santhony.gutierrez@amd.com                return false;
130111308Santhony.gutierrez@amd.com        }
130211308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex)
130311308Santhony.gutierrez@amd.com        {
130411308Santhony.gutierrez@amd.com            if (operandIndex <= NumSrcOperands)
130511308Santhony.gutierrez@amd.com                return false;
130611308Santhony.gutierrez@amd.com            else
130711308Santhony.gutierrez@amd.com                return true;
130811308Santhony.gutierrez@amd.com        }
130911308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex)
131011308Santhony.gutierrez@amd.com        {
131111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
131211308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
131311308Santhony.gutierrez@amd.com                return(src[operandIndex].opSize());
131411308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
131511308Santhony.gutierrez@amd.com                return(addr.opSize());
131611308Santhony.gutierrez@amd.com            else
131711308Santhony.gutierrez@amd.com                return(dest.opSize());
131811308Santhony.gutierrez@amd.com        }
131911308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex)
132011308Santhony.gutierrez@amd.com        {
132111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
132211308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
132311308Santhony.gutierrez@amd.com                return(src[operandIndex].regIndex());
132411308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
132511308Santhony.gutierrez@amd.com                return(addr.regIndex());
132611308Santhony.gutierrez@amd.com            else
132711308Santhony.gutierrez@amd.com                return(dest.regIndex());
132811308Santhony.gutierrez@amd.com            return -1;
132911308Santhony.gutierrez@amd.com        }
133011308Santhony.gutierrez@amd.com    };
133111308Santhony.gutierrez@amd.com
133211308Santhony.gutierrez@amd.com    template<typename MemDataType, typename AddrOperandType, int NumSrcOperands,
133311308Santhony.gutierrez@amd.com             bool HasDst>
133411308Santhony.gutierrez@amd.com    class AtomicInst :
133511308Santhony.gutierrez@amd.com        public AtomicInstBase<typename MemDataType::OperandType,
133611308Santhony.gutierrez@amd.com                              AddrOperandType, NumSrcOperands, HasDst>,
133711308Santhony.gutierrez@amd.com        public MemInst
133811308Santhony.gutierrez@amd.com    {
133911308Santhony.gutierrez@amd.com      public:
134011347Sandreas.hansson@arm.com        void generateDisassembly() override;
134111308Santhony.gutierrez@amd.com
134211308Santhony.gutierrez@amd.com        AtomicInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
134311308Santhony.gutierrez@amd.com                   const char *_opcode)
134411308Santhony.gutierrez@amd.com            : AtomicInstBase<typename MemDataType::OperandType, AddrOperandType,
134511308Santhony.gutierrez@amd.com                             NumSrcOperands, HasDst>
134611308Santhony.gutierrez@amd.com                (ib, obj, _opcode),
134711308Santhony.gutierrez@amd.com              MemInst(MemDataType::memType)
134811308Santhony.gutierrez@amd.com        {
134911308Santhony.gutierrez@amd.com            init_addr(&this->addr);
135011308Santhony.gutierrez@amd.com        }
135111308Santhony.gutierrez@amd.com
135211308Santhony.gutierrez@amd.com        void
135311308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst) override
135411308Santhony.gutierrez@amd.com        {
135511308Santhony.gutierrez@amd.com            // before doing the RMW, check if this atomic has
135611308Santhony.gutierrez@amd.com            // release semantics, and if so issue a release first
135711308Santhony.gutierrez@amd.com            if (!isLocalMem()) {
135811308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
135911308Santhony.gutierrez@amd.com                    && (gpuDynInst->memoryOrder ==
136011308Santhony.gutierrez@amd.com                    Enums::MEMORY_ORDER_SC_RELEASE || gpuDynInst->memoryOrder ==
136111308Santhony.gutierrez@amd.com                    Enums::MEMORY_ORDER_SC_ACQUIRE_RELEASE)) {
136211308Santhony.gutierrez@amd.com
136311308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
136411308Santhony.gutierrez@amd.com
136511308Santhony.gutierrez@amd.com                    gpuDynInst->execContinuation = &GPUStaticInst::execAtomic;
136611308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = true;
136711308Santhony.gutierrez@amd.com
136811308Santhony.gutierrez@amd.com                    // create request
136911308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
137011308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
137111435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
137211308Santhony.gutierrez@amd.com                    req->setFlags(Request::RELEASE);
137311308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
137411308Santhony.gutierrez@amd.com
137511308Santhony.gutierrez@amd.com                    return;
137611308Santhony.gutierrez@amd.com                }
137711308Santhony.gutierrez@amd.com            }
137811308Santhony.gutierrez@amd.com
137911308Santhony.gutierrez@amd.com            // if there is no release semantic, execute the RMW immediately
138011308Santhony.gutierrez@amd.com            execAtomic(gpuDynInst);
138111308Santhony.gutierrez@amd.com
138211308Santhony.gutierrez@amd.com        }
138311308Santhony.gutierrez@amd.com
138411347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
138511308Santhony.gutierrez@amd.com
138611308Santhony.gutierrez@amd.com        bool
138711308Santhony.gutierrez@amd.com        isLocalMem() const override
138811308Santhony.gutierrez@amd.com        {
138911308Santhony.gutierrez@amd.com            return this->segment == Brig::BRIG_SEGMENT_GROUP;
139011308Santhony.gutierrez@amd.com        }
139111308Santhony.gutierrez@amd.com
139211308Santhony.gutierrez@amd.com      private:
139311308Santhony.gutierrez@amd.com        // execAtomic may be called through a continuation
139411308Santhony.gutierrez@amd.com        // if the RMW had release semantics. see comment for
139511308Santhony.gutierrez@amd.com        // execContinuation in gpu_dyn_inst.hh
139611308Santhony.gutierrez@amd.com        void
139711308Santhony.gutierrez@amd.com        execAtomic(GPUDynInstPtr gpuDynInst) override
139811308Santhony.gutierrez@amd.com        {
139911308Santhony.gutierrez@amd.com            gpuDynInst->statusBitVector = gpuDynInst->exec_mask;
140011308Santhony.gutierrez@amd.com
140111308Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c0;
140211308Santhony.gutierrez@amd.com
140311308Santhony.gutierrez@amd.com            c0 *d = &((c0*) gpuDynInst->d_data)[0];
140411308Santhony.gutierrez@amd.com            c0 *e = &((c0*) gpuDynInst->a_data)[0];
140511308Santhony.gutierrez@amd.com            c0 *f = &((c0*) gpuDynInst->x_data)[0];
140611308Santhony.gutierrez@amd.com
140711534Sjohn.kalamatianos@amd.com            for (int i = 0; i < gpuDynInst->computeUnit()->wfSize(); ++i) {
140811308Santhony.gutierrez@amd.com                if (gpuDynInst->exec_mask[i]) {
140911308Santhony.gutierrez@amd.com                    Addr vaddr = gpuDynInst->addr[i];
141011308Santhony.gutierrez@amd.com
141111308Santhony.gutierrez@amd.com                    if (isLocalMem()) {
141211308Santhony.gutierrez@amd.com                        Wavefront *wavefront = gpuDynInst->wavefront();
141311308Santhony.gutierrez@amd.com                        *d = wavefront->ldsChunk->read<c0>(vaddr);
141411308Santhony.gutierrez@amd.com
141511308Santhony.gutierrez@amd.com                        switch (this->opType) {
141611308Santhony.gutierrez@amd.com                          case Enums::MO_AADD:
141711308Santhony.gutierrez@amd.com                          case Enums::MO_ANRADD:
141811308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
141911308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) + (*e));
142011308Santhony.gutierrez@amd.com                            break;
142111308Santhony.gutierrez@amd.com                          case Enums::MO_ASUB:
142211308Santhony.gutierrez@amd.com                          case Enums::MO_ANRSUB:
142311308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
142411308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) - (*e));
142511308Santhony.gutierrez@amd.com                            break;
142611308Santhony.gutierrez@amd.com                          case Enums::MO_AMAX:
142711308Santhony.gutierrez@amd.com                          case Enums::MO_ANRMAX:
142811308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
142911308Santhony.gutierrez@amd.com                            std::max(wavefront->ldsChunk->read<c0>(vaddr),
143011308Santhony.gutierrez@amd.com                            (*e)));
143111308Santhony.gutierrez@amd.com                            break;
143211308Santhony.gutierrez@amd.com                          case Enums::MO_AMIN:
143311308Santhony.gutierrez@amd.com                          case Enums::MO_ANRMIN:
143411308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
143511308Santhony.gutierrez@amd.com                            std::min(wavefront->ldsChunk->read<c0>(vaddr),
143611308Santhony.gutierrez@amd.com                            (*e)));
143711308Santhony.gutierrez@amd.com                            break;
143811308Santhony.gutierrez@amd.com                          case Enums::MO_AAND:
143911308Santhony.gutierrez@amd.com                          case Enums::MO_ANRAND:
144011308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
144111308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) & (*e));
144211308Santhony.gutierrez@amd.com                            break;
144311308Santhony.gutierrez@amd.com                          case Enums::MO_AOR:
144411308Santhony.gutierrez@amd.com                          case Enums::MO_ANROR:
144511308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
144611308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) | (*e));
144711308Santhony.gutierrez@amd.com                            break;
144811308Santhony.gutierrez@amd.com                          case Enums::MO_AXOR:
144911308Santhony.gutierrez@amd.com                          case Enums::MO_ANRXOR:
145011308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
145111308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) ^ (*e));
145211308Santhony.gutierrez@amd.com                            break;
145311308Santhony.gutierrez@amd.com                          case Enums::MO_AINC:
145411308Santhony.gutierrez@amd.com                          case Enums::MO_ANRINC:
145511308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
145611308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) + 1);
145711308Santhony.gutierrez@amd.com                            break;
145811308Santhony.gutierrez@amd.com                          case Enums::MO_ADEC:
145911308Santhony.gutierrez@amd.com                          case Enums::MO_ANRDEC:
146011308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
146111308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) - 1);
146211308Santhony.gutierrez@amd.com                            break;
146311308Santhony.gutierrez@amd.com                          case Enums::MO_AEXCH:
146411308Santhony.gutierrez@amd.com                          case Enums::MO_ANREXCH:
146511308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr, (*e));
146611308Santhony.gutierrez@amd.com                            break;
146711308Santhony.gutierrez@amd.com                          case Enums::MO_ACAS:
146811308Santhony.gutierrez@amd.com                          case Enums::MO_ANRCAS:
146911308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
147011308Santhony.gutierrez@amd.com                            (wavefront->ldsChunk->read<c0>(vaddr) == (*e)) ?
147111308Santhony.gutierrez@amd.com                            (*f) : wavefront->ldsChunk->read<c0>(vaddr));
147211308Santhony.gutierrez@amd.com                            break;
147311308Santhony.gutierrez@amd.com                          default:
147411308Santhony.gutierrez@amd.com                            fatal("Unrecognized or invalid HSAIL atomic op "
147511308Santhony.gutierrez@amd.com                                  "type.\n");
147611308Santhony.gutierrez@amd.com                            break;
147711308Santhony.gutierrez@amd.com                        }
147811308Santhony.gutierrez@amd.com                    } else {
147911308Santhony.gutierrez@amd.com                        Request *req =
148011308Santhony.gutierrez@amd.com                            new Request(0, vaddr, sizeof(c0), 0,
148111308Santhony.gutierrez@amd.com                                        gpuDynInst->computeUnit()->masterId(),
148211435Smitch.hayenga@arm.com                                        0, gpuDynInst->wfDynId,
148311308Santhony.gutierrez@amd.com                                        gpuDynInst->makeAtomicOpFunctor<c0>(e,
148411308Santhony.gutierrez@amd.com                                        f, this->opType));
148511308Santhony.gutierrez@amd.com
148611308Santhony.gutierrez@amd.com                        gpuDynInst->setRequestFlags(req);
148711308Santhony.gutierrez@amd.com                        PacketPtr pkt = new Packet(req, MemCmd::SwapReq);
148811308Santhony.gutierrez@amd.com                        pkt->dataStatic(d);
148911308Santhony.gutierrez@amd.com
149011308Santhony.gutierrez@amd.com                        if (gpuDynInst->computeUnit()->shader->
149111308Santhony.gutierrez@amd.com                            separate_acquire_release &&
149211308Santhony.gutierrez@amd.com                            (gpuDynInst->memoryOrder ==
149311308Santhony.gutierrez@amd.com                             Enums::MEMORY_ORDER_SC_ACQUIRE)) {
149411308Santhony.gutierrez@amd.com                            // if this atomic has acquire semantics,
149511308Santhony.gutierrez@amd.com                            // schedule the continuation to perform an
149611308Santhony.gutierrez@amd.com                            // acquire after the RMW completes
149711308Santhony.gutierrez@amd.com                            gpuDynInst->execContinuation =
149811308Santhony.gutierrez@amd.com                                &GPUStaticInst::execAtomicAcq;
149911308Santhony.gutierrez@amd.com
150011308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = true;
150111308Santhony.gutierrez@amd.com                        } else {
150211308Santhony.gutierrez@amd.com                            // the request will be finished when the RMW completes
150311308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = false;
150411308Santhony.gutierrez@amd.com                        }
150511308Santhony.gutierrez@amd.com                        // translation is performed in sendRequest()
150611308Santhony.gutierrez@amd.com                        gpuDynInst->computeUnit()->sendRequest(gpuDynInst, i,
150711308Santhony.gutierrez@amd.com                                                               pkt);
150811308Santhony.gutierrez@amd.com                    }
150911308Santhony.gutierrez@amd.com                }
151011308Santhony.gutierrez@amd.com
151111308Santhony.gutierrez@amd.com                ++d;
151211308Santhony.gutierrez@amd.com                ++e;
151311308Santhony.gutierrez@amd.com                ++f;
151411308Santhony.gutierrez@amd.com            }
151511308Santhony.gutierrez@amd.com
151611308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
151711308Santhony.gutierrez@amd.com        }
151811308Santhony.gutierrez@amd.com
151911308Santhony.gutierrez@amd.com        // execAtomicACq will always be called through a continuation.
152011308Santhony.gutierrez@amd.com        // see comment for execContinuation in gpu_dyn_inst.hh
152111308Santhony.gutierrez@amd.com        void
152211308Santhony.gutierrez@amd.com        execAtomicAcq(GPUDynInstPtr gpuDynInst) override
152311308Santhony.gutierrez@amd.com        {
152411308Santhony.gutierrez@amd.com            // after performing the RMW, check to see if this instruction
152511308Santhony.gutierrez@amd.com            // has acquire semantics, and if so, issue an acquire
152611308Santhony.gutierrez@amd.com            if (!isLocalMem()) {
152711308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
152811308Santhony.gutierrez@amd.com                     && gpuDynInst->memoryOrder ==
152911308Santhony.gutierrez@amd.com                     Enums::MEMORY_ORDER_SC_ACQUIRE) {
153011308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
153111308Santhony.gutierrez@amd.com
153211308Santhony.gutierrez@amd.com                    // the request will be finished when
153311308Santhony.gutierrez@amd.com                    // the acquire completes
153411308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = false;
153511308Santhony.gutierrez@amd.com                    // create request
153611308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
153711308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
153811435Smitch.hayenga@arm.com                                  0, gpuDynInst->wfDynId);
153911308Santhony.gutierrez@amd.com                    req->setFlags(Request::ACQUIRE);
154011308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
154111308Santhony.gutierrez@amd.com                }
154211308Santhony.gutierrez@amd.com            }
154311308Santhony.gutierrez@amd.com        }
154411308Santhony.gutierrez@amd.com    };
154511308Santhony.gutierrez@amd.com
154611308Santhony.gutierrez@amd.com    template<typename DataType, typename AddrOperandType, int NumSrcOperands>
154711308Santhony.gutierrez@amd.com    GPUStaticInst*
154811308Santhony.gutierrez@amd.com    constructAtomic(const Brig::BrigInstBase *ib, const BrigObject *obj)
154911308Santhony.gutierrez@amd.com    {
155011308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
155111308Santhony.gutierrez@amd.com
155211308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_LD) {
155311308Santhony.gutierrez@amd.com            return decodeLd<DataType>(ib, obj);
155411308Santhony.gutierrez@amd.com        } else if (at->atomicOperation == Brig::BRIG_ATOMIC_ST) {
155511308Santhony.gutierrez@amd.com            switch (ib->type) {
155611308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B8:
155711308Santhony.gutierrez@amd.com                return decodeSt<S8,S8>(ib, obj);
155811308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B16:
155911308Santhony.gutierrez@amd.com                return decodeSt<S8,S16>(ib, obj);
156011308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B32:
156111308Santhony.gutierrez@amd.com                return decodeSt<S8,S32>(ib, obj);
156211308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B64:
156311308Santhony.gutierrez@amd.com                return decodeSt<S8,S64>(ib, obj);
156411308Santhony.gutierrez@amd.com              default: fatal("AtomicSt: Operand type mismatch %d\n", ib->type);
156511308Santhony.gutierrez@amd.com            }
156611308Santhony.gutierrez@amd.com        } else {
156711308Santhony.gutierrez@amd.com            if ((Brig::BrigOpcode)ib->opcode == Brig::BRIG_OPCODE_ATOMICNORET)
156811308Santhony.gutierrez@amd.com                return new AtomicInst<DataType, AddrOperandType,
156911308Santhony.gutierrez@amd.com                    NumSrcOperands, false>(ib, obj, "atomicnoret");
157011308Santhony.gutierrez@amd.com            else
157111308Santhony.gutierrez@amd.com                return new AtomicInst<DataType, AddrOperandType,
157211308Santhony.gutierrez@amd.com                    NumSrcOperands, true>(ib, obj, "atomic");
157311308Santhony.gutierrez@amd.com        }
157411308Santhony.gutierrez@amd.com    }
157511308Santhony.gutierrez@amd.com
157611308Santhony.gutierrez@amd.com    template<typename DataType, int NumSrcOperands>
157711308Santhony.gutierrez@amd.com    GPUStaticInst*
157811308Santhony.gutierrez@amd.com    decodeAtomicHelper(const Brig::BrigInstBase *ib, const BrigObject *obj)
157911308Santhony.gutierrez@amd.com    {
158011308Santhony.gutierrez@amd.com        unsigned addrIndex = (Brig::BrigOpcode)ib->opcode ==
158111308Santhony.gutierrez@amd.com            Brig::BRIG_OPCODE_ATOMICNORET ? 0 : 1;
158211308Santhony.gutierrez@amd.com
158311308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,addrIndex);
158411308Santhony.gutierrez@amd.com
158511308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
158611308Santhony.gutierrez@amd.com
158711308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
158811308Santhony.gutierrez@amd.com            return constructAtomic<DataType, NoRegAddrOperand,
158911308Santhony.gutierrez@amd.com                                   NumSrcOperands>(ib, obj);
159011308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER) {
159111308Santhony.gutierrez@amd.com            // V2/V4 not allowed
159211308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
159311308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
159411308Santhony.gutierrez@amd.com                  return constructAtomic<DataType, SRegAddrOperand,
159511308Santhony.gutierrez@amd.com                                         NumSrcOperands>(ib, obj);
159611308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
159711308Santhony.gutierrez@amd.com                return constructAtomic<DataType, DRegAddrOperand,
159811308Santhony.gutierrez@amd.com                                       NumSrcOperands>(ib, obj);
159911308Santhony.gutierrez@amd.com              default:
160011308Santhony.gutierrez@amd.com                fatal("Bad atomic register operand type %d\n", tmp.type);
160111308Santhony.gutierrez@amd.com            }
160211308Santhony.gutierrez@amd.com        } else {
160311308Santhony.gutierrez@amd.com            fatal("Bad atomic register operand kind %d\n", tmp.kind);
160411308Santhony.gutierrez@amd.com        }
160511308Santhony.gutierrez@amd.com    }
160611308Santhony.gutierrez@amd.com
160711308Santhony.gutierrez@amd.com
160811308Santhony.gutierrez@amd.com    template<typename DataType>
160911308Santhony.gutierrez@amd.com    GPUStaticInst*
161011308Santhony.gutierrez@amd.com    decodeAtomic(const Brig::BrigInstBase *ib, const BrigObject *obj)
161111308Santhony.gutierrez@amd.com    {
161211308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
161311308Santhony.gutierrez@amd.com
161411308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_CAS) {
161511308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 2>(ib, obj);
161611308Santhony.gutierrez@amd.com        } else {
161711308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 1>(ib, obj);
161811308Santhony.gutierrez@amd.com        }
161911308Santhony.gutierrez@amd.com    }
162011308Santhony.gutierrez@amd.com
162111308Santhony.gutierrez@amd.com    template<typename DataType>
162211308Santhony.gutierrez@amd.com    GPUStaticInst*
162311308Santhony.gutierrez@amd.com    decodeAtomicNoRet(const Brig::BrigInstBase *ib, const BrigObject *obj)
162411308Santhony.gutierrez@amd.com    {
162511308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
162611308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_CAS) {
162711308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 2>(ib, obj);
162811308Santhony.gutierrez@amd.com        } else {
162911308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 1>(ib, obj);
163011308Santhony.gutierrez@amd.com        }
163111308Santhony.gutierrez@amd.com    }
163211308Santhony.gutierrez@amd.com} // namespace HsailISA
163311308Santhony.gutierrez@amd.com
163411308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_MEM_HH__
1635