mem.hh revision 11347
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) {
46011308Santhony.gutierrez@amd.com                for (int i = 0; i < VSZ; ++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
46911308Santhony.gutierrez@amd.com                c0 *d = &((c0*)gpuDynInst->d_data)[k * VSZ];
47011308Santhony.gutierrez@amd.com
47111308Santhony.gutierrez@amd.com                for (int i = 0; i < VSZ; ++i) {
47211308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i]) {
47311308Santhony.gutierrez@amd.com                        Addr vaddr = gpuDynInst->addr[i] + k * sizeof(c0);
47411308Santhony.gutierrez@amd.com
47511308Santhony.gutierrez@amd.com                        if (isLocalMem()) {
47611308Santhony.gutierrez@amd.com                            // load from shared memory
47711308Santhony.gutierrez@amd.com                            *d = gpuDynInst->wavefront()->ldsChunk->
47811308Santhony.gutierrez@amd.com                                read<c0>(vaddr);
47911308Santhony.gutierrez@amd.com                        } else {
48011308Santhony.gutierrez@amd.com                            Request *req = new Request(0, vaddr, sizeof(c0), 0,
48111308Santhony.gutierrez@amd.com                                          gpuDynInst->computeUnit()->masterId(),
48211308Santhony.gutierrez@amd.com                                          0, gpuDynInst->wfDynId, i);
48311308Santhony.gutierrez@amd.com
48411308Santhony.gutierrez@amd.com                            gpuDynInst->setRequestFlags(req);
48511308Santhony.gutierrez@amd.com                            PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
48611308Santhony.gutierrez@amd.com                            pkt->dataStatic(d);
48711308Santhony.gutierrez@amd.com
48811308Santhony.gutierrez@amd.com                            if (gpuDynInst->computeUnit()->shader->
48911308Santhony.gutierrez@amd.com                                separate_acquire_release &&
49011308Santhony.gutierrez@amd.com                                gpuDynInst->memoryOrder ==
49111308Santhony.gutierrez@amd.com                                Enums::MEMORY_ORDER_SC_ACQUIRE) {
49211308Santhony.gutierrez@amd.com                                // if this load has acquire semantics,
49311308Santhony.gutierrez@amd.com                                // set the response continuation function
49411308Santhony.gutierrez@amd.com                                // to perform an Acquire request
49511308Santhony.gutierrez@amd.com                                gpuDynInst->execContinuation =
49611308Santhony.gutierrez@amd.com                                    &GPUStaticInst::execLdAcq;
49711308Santhony.gutierrez@amd.com
49811308Santhony.gutierrez@amd.com                                gpuDynInst->useContinuation = true;
49911308Santhony.gutierrez@amd.com                            } else {
50011308Santhony.gutierrez@amd.com                                // the request will be finished when
50111308Santhony.gutierrez@amd.com                                // the load completes
50211308Santhony.gutierrez@amd.com                                gpuDynInst->useContinuation = false;
50311308Santhony.gutierrez@amd.com                            }
50411308Santhony.gutierrez@amd.com                            // translation is performed in sendRequest()
50511308Santhony.gutierrez@amd.com                            gpuDynInst->computeUnit()->sendRequest(gpuDynInst,
50611308Santhony.gutierrez@amd.com                                                                   i, pkt);
50711308Santhony.gutierrez@amd.com                        }
50811308Santhony.gutierrez@amd.com                    }
50911308Santhony.gutierrez@amd.com                    ++d;
51011308Santhony.gutierrez@amd.com                }
51111308Santhony.gutierrez@amd.com            }
51211308Santhony.gutierrez@amd.com
51311308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
51411308Santhony.gutierrez@amd.com        }
51511308Santhony.gutierrez@amd.com
51611308Santhony.gutierrez@amd.com      private:
51711308Santhony.gutierrez@amd.com        void
51811308Santhony.gutierrez@amd.com        execLdAcq(GPUDynInstPtr gpuDynInst) override
51911308Santhony.gutierrez@amd.com        {
52011308Santhony.gutierrez@amd.com            // after the load has complete and if the load has acquire
52111308Santhony.gutierrez@amd.com            // semantics, issue an acquire request.
52211308Santhony.gutierrez@amd.com            if (!isLocalMem()) {
52311308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
52411308Santhony.gutierrez@amd.com                    && gpuDynInst->memoryOrder ==
52511308Santhony.gutierrez@amd.com                    Enums::MEMORY_ORDER_SC_ACQUIRE) {
52611308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
52711308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = false;
52811308Santhony.gutierrez@amd.com                    // create request
52911308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
53011308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
53111308Santhony.gutierrez@amd.com                                  0, gpuDynInst->wfDynId, -1);
53211308Santhony.gutierrez@amd.com                    req->setFlags(Request::ACQUIRE);
53311308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
53411308Santhony.gutierrez@amd.com                }
53511308Santhony.gutierrez@amd.com            }
53611308Santhony.gutierrez@amd.com        }
53711308Santhony.gutierrez@amd.com
53811308Santhony.gutierrez@amd.com      public:
53911308Santhony.gutierrez@amd.com        bool
54011308Santhony.gutierrez@amd.com        isLocalMem() const override
54111308Santhony.gutierrez@amd.com        {
54211308Santhony.gutierrez@amd.com            return this->segment == Brig::BRIG_SEGMENT_GROUP;
54311308Santhony.gutierrez@amd.com        }
54411308Santhony.gutierrez@amd.com
54511347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
54611308Santhony.gutierrez@amd.com        {
54711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
54811308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
54911308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
55011308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
55111308Santhony.gutierrez@amd.com            if (num_dest_operands > 1) {
55211308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isVectorRegister();
55311308Santhony.gutierrez@amd.com            }
55411308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1) {
55511308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
55611308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
55711308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isVectorRegister();
55811308Santhony.gutierrez@amd.com            }
55911308Santhony.gutierrez@amd.com            return false;
56011308Santhony.gutierrez@amd.com        }
56111347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
56211308Santhony.gutierrez@amd.com        {
56311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
56411308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
56511308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
56611308Santhony.gutierrez@amd.com                return(this->addr.isCondRegister());
56711308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
56811308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isCondRegister();
56911308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
57011308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
57111308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
57211308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isCondRegister();
57311308Santhony.gutierrez@amd.com            return false;
57411308Santhony.gutierrez@amd.com        }
57511347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
57611308Santhony.gutierrez@amd.com        {
57711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
57811308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
57911308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
58011308Santhony.gutierrez@amd.com                return(this->addr.isScalarRegister());
58111308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
58211308Santhony.gutierrez@amd.com                return dest_vect[operandIndex].isScalarRegister();
58311308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
58411308Santhony.gutierrez@amd.com                return LdInstBase<typename MemDataType::CType,
58511308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
58611308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.isScalarRegister();
58711308Santhony.gutierrez@amd.com            return false;
58811308Santhony.gutierrez@amd.com        }
58911347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
59011308Santhony.gutierrez@amd.com        {
59111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
59211308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
59311308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
59411308Santhony.gutierrez@amd.com                return(this->addr.isVectorRegister());
59511308Santhony.gutierrez@amd.com            return false;
59611308Santhony.gutierrez@amd.com        }
59711347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override
59811308Santhony.gutierrez@amd.com        {
59911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
60011308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
60111308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
60211308Santhony.gutierrez@amd.com                return false;
60311308Santhony.gutierrez@amd.com            return true;
60411308Santhony.gutierrez@amd.com        }
60511347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
60611308Santhony.gutierrez@amd.com        {
60711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
60811308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
60911308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
61011308Santhony.gutierrez@amd.com                return(this->addr.opSize());
61111308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
61211308Santhony.gutierrez@amd.com                return(dest_vect[operandIndex].opSize());
61311308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
61411308Santhony.gutierrez@amd.com                return(LdInstBase<typename MemDataType::CType,
61511308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
61611308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.opSize());
61711308Santhony.gutierrez@amd.com            return 0;
61811308Santhony.gutierrez@amd.com        }
61911347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
62011308Santhony.gutierrez@amd.com        {
62111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
62211308Santhony.gutierrez@amd.com            if ((num_dest_operands != getNumOperands()) &&
62311308Santhony.gutierrez@amd.com                (operandIndex == (getNumOperands()-1)))
62411308Santhony.gutierrez@amd.com                return(this->addr.regIndex());
62511308Santhony.gutierrez@amd.com            if (num_dest_operands > 1)
62611308Santhony.gutierrez@amd.com                return(dest_vect[operandIndex].regIndex());
62711308Santhony.gutierrez@amd.com            else if (num_dest_operands == 1)
62811308Santhony.gutierrez@amd.com                return(LdInstBase<typename MemDataType::CType,
62911308Santhony.gutierrez@amd.com                       typename DestDataType::OperandType,
63011308Santhony.gutierrez@amd.com                       AddrOperandType>::dest.regIndex());
63111308Santhony.gutierrez@amd.com            return -1;
63211308Santhony.gutierrez@amd.com        }
63311347Sandreas.hansson@arm.com        int getNumOperands() override
63411308Santhony.gutierrez@amd.com        {
63511308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
63611308Santhony.gutierrez@amd.com                return(num_dest_operands+1);
63711308Santhony.gutierrez@amd.com            else
63811308Santhony.gutierrez@amd.com                return(num_dest_operands);
63911308Santhony.gutierrez@amd.com        }
64011347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
64111308Santhony.gutierrez@amd.com    };
64211308Santhony.gutierrez@amd.com
64311308Santhony.gutierrez@amd.com    template<typename MemDT, typename DestDT>
64411308Santhony.gutierrez@amd.com    GPUStaticInst*
64511308Santhony.gutierrez@amd.com    decodeLd2(const Brig::BrigInstBase *ib, const BrigObject *obj)
64611308Santhony.gutierrez@amd.com    {
64711308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,1);
64811308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
64911308Santhony.gutierrez@amd.com
65011308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
65111308Santhony.gutierrez@amd.com            return new LdInst<MemDT, DestDT, NoRegAddrOperand>(ib, obj, "ld");
65211308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER ||
65311308Santhony.gutierrez@amd.com                   tmp.kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
65411308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
65511308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
65611308Santhony.gutierrez@amd.com                return new LdInst<MemDT, DestDT,
65711308Santhony.gutierrez@amd.com                                  SRegAddrOperand>(ib, obj, "ld");
65811308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
65911308Santhony.gutierrez@amd.com                return new LdInst<MemDT, DestDT,
66011308Santhony.gutierrez@amd.com                                  DRegAddrOperand>(ib, obj, "ld");
66111308Santhony.gutierrez@amd.com              default:
66211308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d\n", tmp.regKind);
66311308Santhony.gutierrez@amd.com            }
66411308Santhony.gutierrez@amd.com        } else {
66511308Santhony.gutierrez@amd.com            fatal("Bad ld register operand kind %d\n", tmp.kind);
66611308Santhony.gutierrez@amd.com        }
66711308Santhony.gutierrez@amd.com    }
66811308Santhony.gutierrez@amd.com
66911308Santhony.gutierrez@amd.com    template<typename MemDT>
67011308Santhony.gutierrez@amd.com    GPUStaticInst*
67111308Santhony.gutierrez@amd.com    decodeLd(const Brig::BrigInstBase *ib, const BrigObject *obj)
67211308Santhony.gutierrez@amd.com    {
67311308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,0);
67411308Santhony.gutierrez@amd.com        BrigRegOperandInfo dest = findRegDataType(op_offs, obj);
67511308Santhony.gutierrez@amd.com
67611308Santhony.gutierrez@amd.com        assert(dest.kind == Brig::BRIG_KIND_OPERAND_REGISTER ||
67711308Santhony.gutierrez@amd.com               dest.kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST);
67811308Santhony.gutierrez@amd.com        switch(dest.regKind) {
67911308Santhony.gutierrez@amd.com          case Brig::BRIG_REGISTER_KIND_SINGLE:
68011308Santhony.gutierrez@amd.com            switch (ib->type) {
68111308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B8:
68211308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B16:
68311308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B32:
68411308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, B32>(ib, obj);
68511308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U8:
68611308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U16:
68711308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U32:
68811308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U32>(ib, obj);
68911308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S8:
69011308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S16:
69111308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S32:
69211308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, S32>(ib, obj);
69311308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F16:
69411308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F32:
69511308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U32>(ib, obj);
69611308Santhony.gutierrez@amd.com              default:
69711308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d, %d\n",
69811308Santhony.gutierrez@amd.com                      dest.regKind, ib->type);
69911308Santhony.gutierrez@amd.com            };
70011308Santhony.gutierrez@amd.com          case Brig::BRIG_REGISTER_KIND_DOUBLE:
70111308Santhony.gutierrez@amd.com            switch (ib->type) {
70211308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B64:
70311308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, B64>(ib, obj);
70411308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_U64:
70511308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U64>(ib, obj);
70611308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_S64:
70711308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, S64>(ib, obj);
70811308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_F64:
70911308Santhony.gutierrez@amd.com                return decodeLd2<MemDT, U64>(ib, obj);
71011308Santhony.gutierrez@amd.com              default:
71111308Santhony.gutierrez@amd.com                fatal("Bad ld register operand type %d, %d\n",
71211308Santhony.gutierrez@amd.com                      dest.regKind, ib->type);
71311308Santhony.gutierrez@amd.com            };
71411308Santhony.gutierrez@amd.com          default:
71511308Santhony.gutierrez@amd.com            fatal("Bad ld register operand type %d, %d\n", dest.regKind,
71611308Santhony.gutierrez@amd.com                  ib->type);
71711308Santhony.gutierrez@amd.com        }
71811308Santhony.gutierrez@amd.com    }
71911308Santhony.gutierrez@amd.com
72011308Santhony.gutierrez@amd.com    template<typename MemDataType, typename SrcOperandType,
72111308Santhony.gutierrez@amd.com             typename AddrOperandType>
72211308Santhony.gutierrez@amd.com    class StInstBase : public HsailGPUStaticInst
72311308Santhony.gutierrez@amd.com    {
72411308Santhony.gutierrez@amd.com      public:
72511308Santhony.gutierrez@amd.com        typename SrcOperandType::SrcOperand src;
72611308Santhony.gutierrez@amd.com        AddrOperandType addr;
72711308Santhony.gutierrez@amd.com
72811308Santhony.gutierrez@amd.com        Brig::BrigSegment segment;
72911308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memoryScope;
73011308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memoryOrder;
73111308Santhony.gutierrez@amd.com        unsigned int equivClass;
73211308Santhony.gutierrez@amd.com
73311308Santhony.gutierrez@amd.com        void
73411308Santhony.gutierrez@amd.com        initSt(const Brig::BrigInstBase *ib, const BrigObject *obj,
73511308Santhony.gutierrez@amd.com               const char *_opcode)
73611308Santhony.gutierrez@amd.com        {
73711308Santhony.gutierrez@amd.com            using namespace Brig;
73811308Santhony.gutierrez@amd.com
73911308Santhony.gutierrez@amd.com            const BrigInstMem *ldst = (const BrigInstMem*)ib;
74011308Santhony.gutierrez@amd.com
74111308Santhony.gutierrez@amd.com            segment = (BrigSegment)ldst->segment;
74211308Santhony.gutierrez@amd.com            memoryOrder = BRIG_MEMORY_ORDER_NONE;
74311308Santhony.gutierrez@amd.com            memoryScope = BRIG_MEMORY_SCOPE_NONE;
74411308Santhony.gutierrez@amd.com            equivClass = ldst->equivClass;
74511308Santhony.gutierrez@amd.com
74611308Santhony.gutierrez@amd.com            switch (segment) {
74711308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
74811308Santhony.gutierrez@amd.com                o_type = Enums::OT_GLOBAL_WRITE;
74911308Santhony.gutierrez@amd.com                break;
75011308Santhony.gutierrez@amd.com
75111308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
75211308Santhony.gutierrez@amd.com                o_type = Enums::OT_SHARED_WRITE;
75311308Santhony.gutierrez@amd.com                break;
75411308Santhony.gutierrez@amd.com
75511308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_PRIVATE:
75611308Santhony.gutierrez@amd.com                o_type = Enums::OT_PRIVATE_WRITE;
75711308Santhony.gutierrez@amd.com                break;
75811308Santhony.gutierrez@amd.com
75911308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_READONLY:
76011308Santhony.gutierrez@amd.com                o_type = Enums::OT_READONLY_WRITE;
76111308Santhony.gutierrez@amd.com                break;
76211308Santhony.gutierrez@amd.com
76311308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_SPILL:
76411308Santhony.gutierrez@amd.com                o_type = Enums::OT_SPILL_WRITE;
76511308Santhony.gutierrez@amd.com                break;
76611308Santhony.gutierrez@amd.com
76711308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
76811308Santhony.gutierrez@amd.com                o_type = Enums::OT_FLAT_WRITE;
76911308Santhony.gutierrez@amd.com                break;
77011308Santhony.gutierrez@amd.com
77111308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_ARG:
77211308Santhony.gutierrez@amd.com                o_type = Enums::OT_ARG;
77311308Santhony.gutierrez@amd.com                break;
77411308Santhony.gutierrez@amd.com
77511308Santhony.gutierrez@amd.com              default:
77611308Santhony.gutierrez@amd.com                panic("St: segment %d not supported\n", segment);
77711308Santhony.gutierrez@amd.com            }
77811308Santhony.gutierrez@amd.com
77911308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
78011308Santhony.gutierrez@amd.com            const BrigOperand *baseOp = obj->getOperand(op_offs);
78111308Santhony.gutierrez@amd.com
78211308Santhony.gutierrez@amd.com            if ((baseOp->kind == BRIG_KIND_OPERAND_CONSTANT_BYTES) ||
78311308Santhony.gutierrez@amd.com                (baseOp->kind == BRIG_KIND_OPERAND_REGISTER)) {
78411308Santhony.gutierrez@amd.com                src.init(op_offs, obj);
78511308Santhony.gutierrez@amd.com            }
78611308Santhony.gutierrez@amd.com
78711308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
78811308Santhony.gutierrez@amd.com            addr.init(op_offs, obj);
78911308Santhony.gutierrez@amd.com        }
79011308Santhony.gutierrez@amd.com
79111308Santhony.gutierrez@amd.com        void
79211308Santhony.gutierrez@amd.com        initAtomicSt(const Brig::BrigInstBase *ib, const BrigObject *obj,
79311308Santhony.gutierrez@amd.com                     const char *_opcode)
79411308Santhony.gutierrez@amd.com        {
79511308Santhony.gutierrez@amd.com            using namespace Brig;
79611308Santhony.gutierrez@amd.com
79711308Santhony.gutierrez@amd.com            const BrigInstAtomic *at = (const BrigInstAtomic*)ib;
79811308Santhony.gutierrez@amd.com
79911308Santhony.gutierrez@amd.com            segment = (BrigSegment)at->segment;
80011308Santhony.gutierrez@amd.com            memoryScope = (BrigMemoryScope)at->memoryScope;
80111308Santhony.gutierrez@amd.com            memoryOrder = (BrigMemoryOrder)at->memoryOrder;
80211308Santhony.gutierrez@amd.com            equivClass = 0;
80311308Santhony.gutierrez@amd.com
80411308Santhony.gutierrez@amd.com            switch (segment) {
80511308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
80611308Santhony.gutierrez@amd.com                o_type = Enums::OT_GLOBAL_WRITE;
80711308Santhony.gutierrez@amd.com                break;
80811308Santhony.gutierrez@amd.com
80911308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
81011308Santhony.gutierrez@amd.com                o_type = Enums::OT_SHARED_WRITE;
81111308Santhony.gutierrez@amd.com                break;
81211308Santhony.gutierrez@amd.com
81311308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_PRIVATE:
81411308Santhony.gutierrez@amd.com                o_type = Enums::OT_PRIVATE_WRITE;
81511308Santhony.gutierrez@amd.com                break;
81611308Santhony.gutierrez@amd.com
81711308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_READONLY:
81811308Santhony.gutierrez@amd.com                o_type = Enums::OT_READONLY_WRITE;
81911308Santhony.gutierrez@amd.com                break;
82011308Santhony.gutierrez@amd.com
82111308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_SPILL:
82211308Santhony.gutierrez@amd.com                o_type = Enums::OT_SPILL_WRITE;
82311308Santhony.gutierrez@amd.com                break;
82411308Santhony.gutierrez@amd.com
82511308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
82611308Santhony.gutierrez@amd.com                o_type = Enums::OT_FLAT_WRITE;
82711308Santhony.gutierrez@amd.com                break;
82811308Santhony.gutierrez@amd.com
82911308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_ARG:
83011308Santhony.gutierrez@amd.com                o_type = Enums::OT_ARG;
83111308Santhony.gutierrez@amd.com                break;
83211308Santhony.gutierrez@amd.com
83311308Santhony.gutierrez@amd.com              default:
83411308Santhony.gutierrez@amd.com                panic("St: segment %d not supported\n", segment);
83511308Santhony.gutierrez@amd.com            }
83611308Santhony.gutierrez@amd.com
83711308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
83811308Santhony.gutierrez@amd.com            addr.init(op_offs, obj);
83911308Santhony.gutierrez@amd.com
84011308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
84111308Santhony.gutierrez@amd.com            src.init(op_offs, obj);
84211308Santhony.gutierrez@amd.com        }
84311308Santhony.gutierrez@amd.com
84411308Santhony.gutierrez@amd.com        StInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
84511308Santhony.gutierrez@amd.com                   const char *_opcode)
84611308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
84711308Santhony.gutierrez@amd.com        {
84811308Santhony.gutierrez@amd.com            using namespace Brig;
84911308Santhony.gutierrez@amd.com
85011308Santhony.gutierrez@amd.com            if (ib->opcode == BRIG_OPCODE_ST) {
85111308Santhony.gutierrez@amd.com                initSt(ib, obj, _opcode);
85211308Santhony.gutierrez@amd.com            } else {
85311308Santhony.gutierrez@amd.com                initAtomicSt(ib, obj, _opcode);
85411308Santhony.gutierrez@amd.com            }
85511308Santhony.gutierrez@amd.com        }
85611308Santhony.gutierrez@amd.com
85711347Sandreas.hansson@arm.com        int numDstRegOperands() override { return 0; }
85811347Sandreas.hansson@arm.com        int numSrcRegOperands() override
85911308Santhony.gutierrez@amd.com        {
86011308Santhony.gutierrez@amd.com            return src.isVectorRegister() + this->addr.isVectorRegister();
86111308Santhony.gutierrez@amd.com        }
86211347Sandreas.hansson@arm.com        int getNumOperands() override
86311308Santhony.gutierrez@amd.com        {
86411308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
86511308Santhony.gutierrez@amd.com                return 2;
86611308Santhony.gutierrez@amd.com            else
86711308Santhony.gutierrez@amd.com                return 1;
86811308Santhony.gutierrez@amd.com        }
86911347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
87011308Santhony.gutierrez@amd.com        {
87111308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
87211308Santhony.gutierrez@amd.com            return !operandIndex ? src.isVectorRegister() :
87311308Santhony.gutierrez@amd.com                   this->addr.isVectorRegister();
87411308Santhony.gutierrez@amd.com        }
87511347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
87611308Santhony.gutierrez@amd.com        {
87711308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
87811308Santhony.gutierrez@amd.com            return !operandIndex ? src.isCondRegister() :
87911308Santhony.gutierrez@amd.com                   this->addr.isCondRegister();
88011308Santhony.gutierrez@amd.com        }
88111347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
88211308Santhony.gutierrez@amd.com        {
88311308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
88411308Santhony.gutierrez@amd.com            return !operandIndex ? src.isScalarRegister() :
88511308Santhony.gutierrez@amd.com                   this->addr.isScalarRegister();
88611308Santhony.gutierrez@amd.com        }
88711347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
88811308Santhony.gutierrez@amd.com        {
88911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
89011308Santhony.gutierrez@amd.com            return true;
89111308Santhony.gutierrez@amd.com        }
89211347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override { return false; }
89311347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
89411308Santhony.gutierrez@amd.com        {
89511308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
89611308Santhony.gutierrez@amd.com            return !operandIndex ? src.opSize() : this->addr.opSize();
89711308Santhony.gutierrez@amd.com        }
89811347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
89911308Santhony.gutierrez@amd.com        {
90011308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
90111308Santhony.gutierrez@amd.com            return !operandIndex ? src.regIndex() : this->addr.regIndex();
90211308Santhony.gutierrez@amd.com        }
90311308Santhony.gutierrez@amd.com    };
90411308Santhony.gutierrez@amd.com
90511308Santhony.gutierrez@amd.com
90611308Santhony.gutierrez@amd.com    template<typename MemDataType, typename SrcDataType,
90711308Santhony.gutierrez@amd.com             typename AddrOperandType>
90811308Santhony.gutierrez@amd.com    class StInst :
90911308Santhony.gutierrez@amd.com        public StInstBase<MemDataType, typename SrcDataType::OperandType,
91011308Santhony.gutierrez@amd.com                          AddrOperandType>,
91111308Santhony.gutierrez@amd.com        public MemInst
91211308Santhony.gutierrez@amd.com    {
91311308Santhony.gutierrez@amd.com      public:
91411308Santhony.gutierrez@amd.com        typename SrcDataType::OperandType::SrcOperand src_vect[4];
91511308Santhony.gutierrez@amd.com        uint16_t num_src_operands;
91611347Sandreas.hansson@arm.com        void generateDisassembly() override;
91711308Santhony.gutierrez@amd.com
91811308Santhony.gutierrez@amd.com        StInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
91911308Santhony.gutierrez@amd.com                        const char *_opcode, int srcIdx)
92011308Santhony.gutierrez@amd.com            : StInstBase<MemDataType, typename SrcDataType::OperandType,
92111308Santhony.gutierrez@amd.com                         AddrOperandType>(ib, obj, _opcode),
92211308Santhony.gutierrez@amd.com              MemInst(SrcDataType::memType)
92311308Santhony.gutierrez@amd.com        {
92411308Santhony.gutierrez@amd.com            init_addr(&this->addr);
92511308Santhony.gutierrez@amd.com
92611308Santhony.gutierrez@amd.com            BrigRegOperandInfo rinfo;
92711308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands,srcIdx);
92811308Santhony.gutierrez@amd.com            const Brig::BrigOperand *baseOp = obj->getOperand(op_offs);
92911308Santhony.gutierrez@amd.com
93011308Santhony.gutierrez@amd.com            if (baseOp->kind == Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES) {
93111308Santhony.gutierrez@amd.com                const Brig::BrigOperandConstantBytes *op =
93211308Santhony.gutierrez@amd.com                    (Brig::BrigOperandConstantBytes*)baseOp;
93311308Santhony.gutierrez@amd.com
93411308Santhony.gutierrez@amd.com                rinfo = BrigRegOperandInfo((Brig::BrigKind16_t)op->base.kind,
93511308Santhony.gutierrez@amd.com                                           Brig::BRIG_TYPE_NONE);
93611308Santhony.gutierrez@amd.com            } else {
93711308Santhony.gutierrez@amd.com                rinfo = findRegDataType(op_offs, obj);
93811308Santhony.gutierrez@amd.com            }
93911308Santhony.gutierrez@amd.com
94011308Santhony.gutierrez@amd.com            if (baseOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
94111308Santhony.gutierrez@amd.com                const Brig::BrigOperandOperandList *brigRegVecOp =
94211308Santhony.gutierrez@amd.com                    (const Brig::BrigOperandOperandList*)baseOp;
94311308Santhony.gutierrez@amd.com
94411308Santhony.gutierrez@amd.com                num_src_operands =
94511308Santhony.gutierrez@amd.com                    *((unsigned*)obj->getData(brigRegVecOp->elements)) / 4;
94611308Santhony.gutierrez@amd.com
94711308Santhony.gutierrez@amd.com                assert(num_src_operands <= 4);
94811308Santhony.gutierrez@amd.com            } else {
94911308Santhony.gutierrez@amd.com                num_src_operands = 1;
95011308Santhony.gutierrez@amd.com            }
95111308Santhony.gutierrez@amd.com
95211308Santhony.gutierrez@amd.com            if (num_src_operands > 1) {
95311308Santhony.gutierrez@amd.com                assert(baseOp->kind == Brig::BRIG_KIND_OPERAND_OPERAND_LIST);
95411308Santhony.gutierrez@amd.com
95511308Santhony.gutierrez@amd.com                for (int i = 0; i < num_src_operands; ++i) {
95611308Santhony.gutierrez@amd.com                    src_vect[i].init_from_vect(op_offs, obj, i);
95711308Santhony.gutierrez@amd.com                }
95811308Santhony.gutierrez@amd.com            }
95911308Santhony.gutierrez@amd.com        }
96011308Santhony.gutierrez@amd.com
96111308Santhony.gutierrez@amd.com        void
96211308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst) override
96311308Santhony.gutierrez@amd.com        {
96411308Santhony.gutierrez@amd.com            // before performing a store, check if this store has
96511308Santhony.gutierrez@amd.com            // release semantics, and if so issue a release first
96611308Santhony.gutierrez@amd.com            if (!isLocalMem()) {
96711308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
96811308Santhony.gutierrez@amd.com                    && gpuDynInst->memoryOrder ==
96911308Santhony.gutierrez@amd.com                    Enums::MEMORY_ORDER_SC_RELEASE) {
97011308Santhony.gutierrez@amd.com
97111308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
97211308Santhony.gutierrez@amd.com                    gpuDynInst->execContinuation = &GPUStaticInst::execSt;
97311308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = true;
97411308Santhony.gutierrez@amd.com                    // create request
97511308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
97611308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
97711308Santhony.gutierrez@amd.com                                  0, gpuDynInst->wfDynId, -1);
97811308Santhony.gutierrez@amd.com                    req->setFlags(Request::RELEASE);
97911308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
98011308Santhony.gutierrez@amd.com
98111308Santhony.gutierrez@amd.com                    return;
98211308Santhony.gutierrez@amd.com                }
98311308Santhony.gutierrez@amd.com            }
98411308Santhony.gutierrez@amd.com
98511308Santhony.gutierrez@amd.com            // if there is no release semantic, perform stores immediately
98611308Santhony.gutierrez@amd.com            execSt(gpuDynInst);
98711308Santhony.gutierrez@amd.com        }
98811308Santhony.gutierrez@amd.com
98911308Santhony.gutierrez@amd.com        bool
99011308Santhony.gutierrez@amd.com        isLocalMem() const override
99111308Santhony.gutierrez@amd.com        {
99211308Santhony.gutierrez@amd.com            return this->segment == Brig::BRIG_SEGMENT_GROUP;
99311308Santhony.gutierrez@amd.com        }
99411308Santhony.gutierrez@amd.com
99511308Santhony.gutierrez@amd.com      private:
99611308Santhony.gutierrez@amd.com        // execSt may be called through a continuation
99711308Santhony.gutierrez@amd.com        // if the store had release semantics. see comment for
99811308Santhony.gutierrez@amd.com        // execSt in gpu_static_inst.hh
99911308Santhony.gutierrez@amd.com        void
100011308Santhony.gutierrez@amd.com        execSt(GPUDynInstPtr gpuDynInst) override
100111308Santhony.gutierrez@amd.com        {
100211308Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c0;
100311308Santhony.gutierrez@amd.com
100411308Santhony.gutierrez@amd.com            gpuDynInst->statusBitVector = gpuDynInst->exec_mask;
100511308Santhony.gutierrez@amd.com
100611308Santhony.gutierrez@amd.com            if (num_src_operands > 1) {
100711308Santhony.gutierrez@amd.com                for (int i = 0; i < VSZ; ++i)
100811308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i])
100911308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(num_src_operands);
101011308Santhony.gutierrez@amd.com                    else
101111308Santhony.gutierrez@amd.com                        gpuDynInst->statusVector.push_back(0);
101211308Santhony.gutierrez@amd.com            }
101311308Santhony.gutierrez@amd.com
101411308Santhony.gutierrez@amd.com            for (int k = 0; k < num_src_operands; ++k) {
101511308Santhony.gutierrez@amd.com                c0 *d = &((c0*)gpuDynInst->d_data)[k * VSZ];
101611308Santhony.gutierrez@amd.com
101711308Santhony.gutierrez@amd.com                for (int i = 0; i < VSZ; ++i) {
101811308Santhony.gutierrez@amd.com                    if (gpuDynInst->exec_mask[i]) {
101911308Santhony.gutierrez@amd.com                        Addr vaddr = gpuDynInst->addr[i] + k * sizeof(c0);
102011308Santhony.gutierrez@amd.com
102111308Santhony.gutierrez@amd.com                        if (isLocalMem()) {
102211308Santhony.gutierrez@amd.com                            //store to shared memory
102311308Santhony.gutierrez@amd.com                            gpuDynInst->wavefront()->ldsChunk->write<c0>(vaddr,
102411308Santhony.gutierrez@amd.com                                                                         *d);
102511308Santhony.gutierrez@amd.com                        } else {
102611308Santhony.gutierrez@amd.com                            Request *req =
102711308Santhony.gutierrez@amd.com                              new Request(0, vaddr, sizeof(c0), 0,
102811308Santhony.gutierrez@amd.com                                          gpuDynInst->computeUnit()->masterId(),
102911308Santhony.gutierrez@amd.com                                          0, gpuDynInst->wfDynId, i);
103011308Santhony.gutierrez@amd.com
103111308Santhony.gutierrez@amd.com                            gpuDynInst->setRequestFlags(req);
103211308Santhony.gutierrez@amd.com                            PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
103311308Santhony.gutierrez@amd.com                            pkt->dataStatic<c0>(d);
103411308Santhony.gutierrez@amd.com
103511308Santhony.gutierrez@amd.com                            // translation is performed in sendRequest()
103611308Santhony.gutierrez@amd.com                            // the request will be finished when the store completes
103711308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = false;
103811308Santhony.gutierrez@amd.com                            gpuDynInst->computeUnit()->sendRequest(gpuDynInst,
103911308Santhony.gutierrez@amd.com                                                                   i, pkt);
104011308Santhony.gutierrez@amd.com
104111308Santhony.gutierrez@amd.com                        }
104211308Santhony.gutierrez@amd.com                    }
104311308Santhony.gutierrez@amd.com                    ++d;
104411308Santhony.gutierrez@amd.com                }
104511308Santhony.gutierrez@amd.com            }
104611308Santhony.gutierrez@amd.com
104711308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
104811308Santhony.gutierrez@amd.com        }
104911308Santhony.gutierrez@amd.com
105011308Santhony.gutierrez@amd.com      public:
105111347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override
105211308Santhony.gutierrez@amd.com        {
105311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
105411308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
105511308Santhony.gutierrez@amd.com                return this->addr.isVectorRegister();
105611308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
105711308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isVectorRegister();
105811308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
105911308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
106011308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
106111308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isVectorRegister();
106211308Santhony.gutierrez@amd.com            return false;
106311308Santhony.gutierrez@amd.com        }
106411347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override
106511308Santhony.gutierrez@amd.com        {
106611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
106711308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
106811308Santhony.gutierrez@amd.com                return this->addr.isCondRegister();
106911308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
107011308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isCondRegister();
107111308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
107211308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
107311308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
107411308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isCondRegister();
107511308Santhony.gutierrez@amd.com            return false;
107611308Santhony.gutierrez@amd.com        }
107711347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override
107811308Santhony.gutierrez@amd.com        {
107911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
108011308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
108111308Santhony.gutierrez@amd.com                return this->addr.isScalarRegister();
108211308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
108311308Santhony.gutierrez@amd.com                return src_vect[operandIndex].isScalarRegister();
108411308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
108511308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
108611308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
108711308Santhony.gutierrez@amd.com                       AddrOperandType>::src.isScalarRegister();
108811308Santhony.gutierrez@amd.com            return false;
108911308Santhony.gutierrez@amd.com        }
109011347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override
109111308Santhony.gutierrez@amd.com        {
109211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
109311308Santhony.gutierrez@amd.com            return true;
109411308Santhony.gutierrez@amd.com        }
109511347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override { return false; }
109611347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override
109711308Santhony.gutierrez@amd.com        {
109811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
109911308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
110011308Santhony.gutierrez@amd.com                return this->addr.opSize();
110111308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
110211308Santhony.gutierrez@amd.com                return src_vect[operandIndex].opSize();
110311308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
110411308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
110511308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
110611308Santhony.gutierrez@amd.com                       AddrOperandType>::src.opSize();
110711308Santhony.gutierrez@amd.com            return 0;
110811308Santhony.gutierrez@amd.com        }
110911347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override
111011308Santhony.gutierrez@amd.com        {
111111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
111211308Santhony.gutierrez@amd.com            if (operandIndex == num_src_operands)
111311308Santhony.gutierrez@amd.com                return this->addr.regIndex();
111411308Santhony.gutierrez@amd.com            if (num_src_operands > 1)
111511308Santhony.gutierrez@amd.com                return src_vect[operandIndex].regIndex();
111611308Santhony.gutierrez@amd.com            else if (num_src_operands == 1)
111711308Santhony.gutierrez@amd.com                return StInstBase<MemDataType,
111811308Santhony.gutierrez@amd.com                       typename SrcDataType::OperandType,
111911308Santhony.gutierrez@amd.com                       AddrOperandType>::src.regIndex();
112011308Santhony.gutierrez@amd.com            return -1;
112111308Santhony.gutierrez@amd.com        }
112211347Sandreas.hansson@arm.com        int getNumOperands() override
112311308Santhony.gutierrez@amd.com        {
112411308Santhony.gutierrez@amd.com            if (this->addr.isVectorRegister() || this->addr.isScalarRegister())
112511308Santhony.gutierrez@amd.com                return num_src_operands + 1;
112611308Santhony.gutierrez@amd.com            else
112711308Santhony.gutierrez@amd.com                return num_src_operands;
112811308Santhony.gutierrez@amd.com        }
112911347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
113011308Santhony.gutierrez@amd.com    };
113111308Santhony.gutierrez@amd.com
113211308Santhony.gutierrez@amd.com    template<typename DataType, typename SrcDataType>
113311308Santhony.gutierrez@amd.com    GPUStaticInst*
113411308Santhony.gutierrez@amd.com    decodeSt(const Brig::BrigInstBase *ib, const BrigObject *obj)
113511308Santhony.gutierrez@amd.com    {
113611308Santhony.gutierrez@amd.com        int srcIdx = 0;
113711308Santhony.gutierrez@amd.com        int destIdx = 1;
113811308Santhony.gutierrez@amd.com        if (ib->opcode == Brig::BRIG_OPCODE_ATOMIC ||
113911308Santhony.gutierrez@amd.com            ib->opcode == Brig::BRIG_OPCODE_ATOMICNORET) {
114011308Santhony.gutierrez@amd.com            srcIdx = 1;
114111308Santhony.gutierrez@amd.com            destIdx = 0;
114211308Santhony.gutierrez@amd.com        }
114311308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,destIdx);
114411308Santhony.gutierrez@amd.com
114511308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
114611308Santhony.gutierrez@amd.com
114711308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
114811308Santhony.gutierrez@amd.com            return new StInst<DataType, SrcDataType,
114911308Santhony.gutierrez@amd.com                              NoRegAddrOperand>(ib, obj, "st", srcIdx);
115011308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER) {
115111308Santhony.gutierrez@amd.com            // V2/V4 not allowed
115211308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
115311308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
115411308Santhony.gutierrez@amd.com                return new StInst<DataType, SrcDataType,
115511308Santhony.gutierrez@amd.com                                  SRegAddrOperand>(ib, obj, "st", srcIdx);
115611308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
115711308Santhony.gutierrez@amd.com                return new StInst<DataType, SrcDataType,
115811308Santhony.gutierrez@amd.com                                  DRegAddrOperand>(ib, obj, "st", srcIdx);
115911308Santhony.gutierrez@amd.com              default:
116011308Santhony.gutierrez@amd.com                fatal("Bad st register operand type %d\n", tmp.type);
116111308Santhony.gutierrez@amd.com            }
116211308Santhony.gutierrez@amd.com        } else {
116311308Santhony.gutierrez@amd.com            fatal("Bad st register operand kind %d\n", tmp.kind);
116411308Santhony.gutierrez@amd.com        }
116511308Santhony.gutierrez@amd.com    }
116611308Santhony.gutierrez@amd.com
116711308Santhony.gutierrez@amd.com    Enums::MemOpType brigAtomicToMemOpType(Brig::BrigOpcode brigOpCode,
116811308Santhony.gutierrez@amd.com                                           Brig::BrigAtomicOperation brigOp);
116911308Santhony.gutierrez@amd.com
117011308Santhony.gutierrez@amd.com    template<typename OperandType, typename AddrOperandType, int NumSrcOperands,
117111308Santhony.gutierrez@amd.com             bool HasDst>
117211308Santhony.gutierrez@amd.com    class AtomicInstBase : public HsailGPUStaticInst
117311308Santhony.gutierrez@amd.com    {
117411308Santhony.gutierrez@amd.com      public:
117511308Santhony.gutierrez@amd.com        typename OperandType::DestOperand dest;
117611308Santhony.gutierrez@amd.com        typename OperandType::SrcOperand src[NumSrcOperands];
117711308Santhony.gutierrez@amd.com        AddrOperandType addr;
117811308Santhony.gutierrez@amd.com
117911308Santhony.gutierrez@amd.com        Brig::BrigSegment segment;
118011308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memoryOrder;
118111308Santhony.gutierrez@amd.com        Brig::BrigAtomicOperation atomicOperation;
118211308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memoryScope;
118311308Santhony.gutierrez@amd.com        Brig::BrigOpcode opcode;
118411308Santhony.gutierrez@amd.com        Enums::MemOpType opType;
118511308Santhony.gutierrez@amd.com
118611308Santhony.gutierrez@amd.com        AtomicInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
118711308Santhony.gutierrez@amd.com                       const char *_opcode)
118811308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, _opcode)
118911308Santhony.gutierrez@amd.com        {
119011308Santhony.gutierrez@amd.com            using namespace Brig;
119111308Santhony.gutierrez@amd.com
119211308Santhony.gutierrez@amd.com            const BrigInstAtomic *at = (const BrigInstAtomic*)ib;
119311308Santhony.gutierrez@amd.com
119411308Santhony.gutierrez@amd.com            segment = (BrigSegment)at->segment;
119511308Santhony.gutierrez@amd.com            memoryScope = (BrigMemoryScope)at->memoryScope;
119611308Santhony.gutierrez@amd.com            memoryOrder = (BrigMemoryOrder)at->memoryOrder;
119711308Santhony.gutierrez@amd.com            atomicOperation = (BrigAtomicOperation)at->atomicOperation;
119811308Santhony.gutierrez@amd.com            opcode = (BrigOpcode)ib->opcode;
119911308Santhony.gutierrez@amd.com            opType = brigAtomicToMemOpType(opcode, atomicOperation);
120011308Santhony.gutierrez@amd.com
120111308Santhony.gutierrez@amd.com            switch (segment) {
120211308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GLOBAL:
120311308Santhony.gutierrez@amd.com                o_type = Enums::OT_GLOBAL_ATOMIC;
120411308Santhony.gutierrez@amd.com                break;
120511308Santhony.gutierrez@amd.com
120611308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_GROUP:
120711308Santhony.gutierrez@amd.com                o_type = Enums::OT_SHARED_ATOMIC;
120811308Santhony.gutierrez@amd.com                break;
120911308Santhony.gutierrez@amd.com
121011308Santhony.gutierrez@amd.com              case BRIG_SEGMENT_FLAT:
121111308Santhony.gutierrez@amd.com                o_type = Enums::OT_FLAT_ATOMIC;
121211308Santhony.gutierrez@amd.com                break;
121311308Santhony.gutierrez@amd.com
121411308Santhony.gutierrez@amd.com              default:
121511308Santhony.gutierrez@amd.com                panic("Atomic: segment %d not supported\n", segment);
121611308Santhony.gutierrez@amd.com            }
121711308Santhony.gutierrez@amd.com
121811308Santhony.gutierrez@amd.com            if (HasDst) {
121911308Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
122011308Santhony.gutierrez@amd.com                dest.init(op_offs, obj);
122111308Santhony.gutierrez@amd.com
122211308Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands, 1);
122311308Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
122411308Santhony.gutierrez@amd.com
122511308Santhony.gutierrez@amd.com                for (int i = 0; i < NumSrcOperands; ++i) {
122611308Santhony.gutierrez@amd.com                    op_offs = obj->getOperandPtr(ib->operands, i + 2);
122711308Santhony.gutierrez@amd.com                    src[i].init(op_offs, obj);
122811308Santhony.gutierrez@amd.com                }
122911308Santhony.gutierrez@amd.com            } else {
123011308Santhony.gutierrez@amd.com
123111308Santhony.gutierrez@amd.com                unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
123211308Santhony.gutierrez@amd.com                addr.init(op_offs, obj);
123311308Santhony.gutierrez@amd.com
123411308Santhony.gutierrez@amd.com                for (int i = 0; i < NumSrcOperands; ++i) {
123511308Santhony.gutierrez@amd.com                    op_offs = obj->getOperandPtr(ib->operands, i + 1);
123611308Santhony.gutierrez@amd.com                    src[i].init(op_offs, obj);
123711308Santhony.gutierrez@amd.com                }
123811308Santhony.gutierrez@amd.com            }
123911308Santhony.gutierrez@amd.com        }
124011308Santhony.gutierrez@amd.com
124111308Santhony.gutierrez@amd.com        int numSrcRegOperands()
124211308Santhony.gutierrez@amd.com        {
124311308Santhony.gutierrez@amd.com            int operands = 0;
124411308Santhony.gutierrez@amd.com            for (int i = 0; i < NumSrcOperands; i++) {
124511325Ssteve.reinhardt@amd.com                if (src[i].isVectorRegister()) {
124611308Santhony.gutierrez@amd.com                    operands++;
124711308Santhony.gutierrez@amd.com                }
124811308Santhony.gutierrez@amd.com            }
124911308Santhony.gutierrez@amd.com            if (addr.isVectorRegister())
125011308Santhony.gutierrez@amd.com                operands++;
125111308Santhony.gutierrez@amd.com            return operands;
125211308Santhony.gutierrez@amd.com        }
125311308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
125411308Santhony.gutierrez@amd.com        int getNumOperands()
125511308Santhony.gutierrez@amd.com        {
125611308Santhony.gutierrez@amd.com            if (addr.isVectorRegister())
125711308Santhony.gutierrez@amd.com                return(NumSrcOperands + 2);
125811308Santhony.gutierrez@amd.com            return(NumSrcOperands + 1);
125911308Santhony.gutierrez@amd.com        }
126011308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex)
126111308Santhony.gutierrez@amd.com        {
126211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
126311308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
126411308Santhony.gutierrez@amd.com                return src[operandIndex].isVectorRegister();
126511308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
126611308Santhony.gutierrez@amd.com                return(addr.isVectorRegister());
126711308Santhony.gutierrez@amd.com            else
126811308Santhony.gutierrez@amd.com                return dest.isVectorRegister();
126911308Santhony.gutierrez@amd.com        }
127011308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex)
127111308Santhony.gutierrez@amd.com        {
127211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
127311308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
127411308Santhony.gutierrez@amd.com                return src[operandIndex].isCondRegister();
127511308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
127611308Santhony.gutierrez@amd.com                return(addr.isCondRegister());
127711308Santhony.gutierrez@amd.com            else
127811308Santhony.gutierrez@amd.com                return dest.isCondRegister();
127911308Santhony.gutierrez@amd.com        }
128011308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex)
128111308Santhony.gutierrez@amd.com        {
128211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
128311308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
128411308Santhony.gutierrez@amd.com                return src[operandIndex].isScalarRegister();
128511308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
128611308Santhony.gutierrez@amd.com                return(addr.isScalarRegister());
128711308Santhony.gutierrez@amd.com            else
128811308Santhony.gutierrez@amd.com                return dest.isScalarRegister();
128911308Santhony.gutierrez@amd.com        }
129011308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex)
129111308Santhony.gutierrez@amd.com        {
129211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
129311308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
129411308Santhony.gutierrez@amd.com                return true;
129511308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
129611308Santhony.gutierrez@amd.com                return(addr.isVectorRegister());
129711308Santhony.gutierrez@amd.com            else
129811308Santhony.gutierrez@amd.com                return false;
129911308Santhony.gutierrez@amd.com        }
130011308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex)
130111308Santhony.gutierrez@amd.com        {
130211308Santhony.gutierrez@amd.com            if (operandIndex <= NumSrcOperands)
130311308Santhony.gutierrez@amd.com                return false;
130411308Santhony.gutierrez@amd.com            else
130511308Santhony.gutierrez@amd.com                return true;
130611308Santhony.gutierrez@amd.com        }
130711308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex)
130811308Santhony.gutierrez@amd.com        {
130911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
131011308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
131111308Santhony.gutierrez@amd.com                return(src[operandIndex].opSize());
131211308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
131311308Santhony.gutierrez@amd.com                return(addr.opSize());
131411308Santhony.gutierrez@amd.com            else
131511308Santhony.gutierrez@amd.com                return(dest.opSize());
131611308Santhony.gutierrez@amd.com        }
131711308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex)
131811308Santhony.gutierrez@amd.com        {
131911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
132011308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
132111308Santhony.gutierrez@amd.com                return(src[operandIndex].regIndex());
132211308Santhony.gutierrez@amd.com            else if (operandIndex == NumSrcOperands)
132311308Santhony.gutierrez@amd.com                return(addr.regIndex());
132411308Santhony.gutierrez@amd.com            else
132511308Santhony.gutierrez@amd.com                return(dest.regIndex());
132611308Santhony.gutierrez@amd.com            return -1;
132711308Santhony.gutierrez@amd.com        }
132811308Santhony.gutierrez@amd.com    };
132911308Santhony.gutierrez@amd.com
133011308Santhony.gutierrez@amd.com    template<typename MemDataType, typename AddrOperandType, int NumSrcOperands,
133111308Santhony.gutierrez@amd.com             bool HasDst>
133211308Santhony.gutierrez@amd.com    class AtomicInst :
133311308Santhony.gutierrez@amd.com        public AtomicInstBase<typename MemDataType::OperandType,
133411308Santhony.gutierrez@amd.com                              AddrOperandType, NumSrcOperands, HasDst>,
133511308Santhony.gutierrez@amd.com        public MemInst
133611308Santhony.gutierrez@amd.com    {
133711308Santhony.gutierrez@amd.com      public:
133811347Sandreas.hansson@arm.com        void generateDisassembly() override;
133911308Santhony.gutierrez@amd.com
134011308Santhony.gutierrez@amd.com        AtomicInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
134111308Santhony.gutierrez@amd.com                   const char *_opcode)
134211308Santhony.gutierrez@amd.com            : AtomicInstBase<typename MemDataType::OperandType, AddrOperandType,
134311308Santhony.gutierrez@amd.com                             NumSrcOperands, HasDst>
134411308Santhony.gutierrez@amd.com                (ib, obj, _opcode),
134511308Santhony.gutierrez@amd.com              MemInst(MemDataType::memType)
134611308Santhony.gutierrez@amd.com        {
134711308Santhony.gutierrez@amd.com            init_addr(&this->addr);
134811308Santhony.gutierrez@amd.com        }
134911308Santhony.gutierrez@amd.com
135011308Santhony.gutierrez@amd.com        void
135111308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst) override
135211308Santhony.gutierrez@amd.com        {
135311308Santhony.gutierrez@amd.com            // before doing the RMW, check if this atomic has
135411308Santhony.gutierrez@amd.com            // release semantics, and if so issue a release first
135511308Santhony.gutierrez@amd.com            if (!isLocalMem()) {
135611308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
135711308Santhony.gutierrez@amd.com                    && (gpuDynInst->memoryOrder ==
135811308Santhony.gutierrez@amd.com                    Enums::MEMORY_ORDER_SC_RELEASE || gpuDynInst->memoryOrder ==
135911308Santhony.gutierrez@amd.com                    Enums::MEMORY_ORDER_SC_ACQUIRE_RELEASE)) {
136011308Santhony.gutierrez@amd.com
136111308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
136211308Santhony.gutierrez@amd.com
136311308Santhony.gutierrez@amd.com                    gpuDynInst->execContinuation = &GPUStaticInst::execAtomic;
136411308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = true;
136511308Santhony.gutierrez@amd.com
136611308Santhony.gutierrez@amd.com                    // create request
136711308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
136811308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
136911308Santhony.gutierrez@amd.com                                  0, gpuDynInst->wfDynId, -1);
137011308Santhony.gutierrez@amd.com                    req->setFlags(Request::RELEASE);
137111308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
137211308Santhony.gutierrez@amd.com
137311308Santhony.gutierrez@amd.com                    return;
137411308Santhony.gutierrez@amd.com                }
137511308Santhony.gutierrez@amd.com            }
137611308Santhony.gutierrez@amd.com
137711308Santhony.gutierrez@amd.com            // if there is no release semantic, execute the RMW immediately
137811308Santhony.gutierrez@amd.com            execAtomic(gpuDynInst);
137911308Santhony.gutierrez@amd.com
138011308Santhony.gutierrez@amd.com        }
138111308Santhony.gutierrez@amd.com
138211347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
138311308Santhony.gutierrez@amd.com
138411308Santhony.gutierrez@amd.com        bool
138511308Santhony.gutierrez@amd.com        isLocalMem() const override
138611308Santhony.gutierrez@amd.com        {
138711308Santhony.gutierrez@amd.com            return this->segment == Brig::BRIG_SEGMENT_GROUP;
138811308Santhony.gutierrez@amd.com        }
138911308Santhony.gutierrez@amd.com
139011308Santhony.gutierrez@amd.com      private:
139111308Santhony.gutierrez@amd.com        // execAtomic may be called through a continuation
139211308Santhony.gutierrez@amd.com        // if the RMW had release semantics. see comment for
139311308Santhony.gutierrez@amd.com        // execContinuation in gpu_dyn_inst.hh
139411308Santhony.gutierrez@amd.com        void
139511308Santhony.gutierrez@amd.com        execAtomic(GPUDynInstPtr gpuDynInst) override
139611308Santhony.gutierrez@amd.com        {
139711308Santhony.gutierrez@amd.com            gpuDynInst->statusBitVector = gpuDynInst->exec_mask;
139811308Santhony.gutierrez@amd.com
139911308Santhony.gutierrez@amd.com            typedef typename MemDataType::CType c0;
140011308Santhony.gutierrez@amd.com
140111308Santhony.gutierrez@amd.com            c0 *d = &((c0*) gpuDynInst->d_data)[0];
140211308Santhony.gutierrez@amd.com            c0 *e = &((c0*) gpuDynInst->a_data)[0];
140311308Santhony.gutierrez@amd.com            c0 *f = &((c0*) gpuDynInst->x_data)[0];
140411308Santhony.gutierrez@amd.com
140511308Santhony.gutierrez@amd.com            for (int i = 0; i < VSZ; ++i) {
140611308Santhony.gutierrez@amd.com                if (gpuDynInst->exec_mask[i]) {
140711308Santhony.gutierrez@amd.com                    Addr vaddr = gpuDynInst->addr[i];
140811308Santhony.gutierrez@amd.com
140911308Santhony.gutierrez@amd.com                    if (isLocalMem()) {
141011308Santhony.gutierrez@amd.com                        Wavefront *wavefront = gpuDynInst->wavefront();
141111308Santhony.gutierrez@amd.com                        *d = wavefront->ldsChunk->read<c0>(vaddr);
141211308Santhony.gutierrez@amd.com
141311308Santhony.gutierrez@amd.com                        switch (this->opType) {
141411308Santhony.gutierrez@amd.com                          case Enums::MO_AADD:
141511308Santhony.gutierrez@amd.com                          case Enums::MO_ANRADD:
141611308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
141711308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) + (*e));
141811308Santhony.gutierrez@amd.com                            break;
141911308Santhony.gutierrez@amd.com                          case Enums::MO_ASUB:
142011308Santhony.gutierrez@amd.com                          case Enums::MO_ANRSUB:
142111308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
142211308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) - (*e));
142311308Santhony.gutierrez@amd.com                            break;
142411308Santhony.gutierrez@amd.com                          case Enums::MO_AMAX:
142511308Santhony.gutierrez@amd.com                          case Enums::MO_ANRMAX:
142611308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
142711308Santhony.gutierrez@amd.com                            std::max(wavefront->ldsChunk->read<c0>(vaddr),
142811308Santhony.gutierrez@amd.com                            (*e)));
142911308Santhony.gutierrez@amd.com                            break;
143011308Santhony.gutierrez@amd.com                          case Enums::MO_AMIN:
143111308Santhony.gutierrez@amd.com                          case Enums::MO_ANRMIN:
143211308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
143311308Santhony.gutierrez@amd.com                            std::min(wavefront->ldsChunk->read<c0>(vaddr),
143411308Santhony.gutierrez@amd.com                            (*e)));
143511308Santhony.gutierrez@amd.com                            break;
143611308Santhony.gutierrez@amd.com                          case Enums::MO_AAND:
143711308Santhony.gutierrez@amd.com                          case Enums::MO_ANRAND:
143811308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
143911308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) & (*e));
144011308Santhony.gutierrez@amd.com                            break;
144111308Santhony.gutierrez@amd.com                          case Enums::MO_AOR:
144211308Santhony.gutierrez@amd.com                          case Enums::MO_ANROR:
144311308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
144411308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) | (*e));
144511308Santhony.gutierrez@amd.com                            break;
144611308Santhony.gutierrez@amd.com                          case Enums::MO_AXOR:
144711308Santhony.gutierrez@amd.com                          case Enums::MO_ANRXOR:
144811308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
144911308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) ^ (*e));
145011308Santhony.gutierrez@amd.com                            break;
145111308Santhony.gutierrez@amd.com                          case Enums::MO_AINC:
145211308Santhony.gutierrez@amd.com                          case Enums::MO_ANRINC:
145311308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
145411308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) + 1);
145511308Santhony.gutierrez@amd.com                            break;
145611308Santhony.gutierrez@amd.com                          case Enums::MO_ADEC:
145711308Santhony.gutierrez@amd.com                          case Enums::MO_ANRDEC:
145811308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
145911308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->read<c0>(vaddr) - 1);
146011308Santhony.gutierrez@amd.com                            break;
146111308Santhony.gutierrez@amd.com                          case Enums::MO_AEXCH:
146211308Santhony.gutierrez@amd.com                          case Enums::MO_ANREXCH:
146311308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr, (*e));
146411308Santhony.gutierrez@amd.com                            break;
146511308Santhony.gutierrez@amd.com                          case Enums::MO_ACAS:
146611308Santhony.gutierrez@amd.com                          case Enums::MO_ANRCAS:
146711308Santhony.gutierrez@amd.com                            wavefront->ldsChunk->write<c0>(vaddr,
146811308Santhony.gutierrez@amd.com                            (wavefront->ldsChunk->read<c0>(vaddr) == (*e)) ?
146911308Santhony.gutierrez@amd.com                            (*f) : wavefront->ldsChunk->read<c0>(vaddr));
147011308Santhony.gutierrez@amd.com                            break;
147111308Santhony.gutierrez@amd.com                          default:
147211308Santhony.gutierrez@amd.com                            fatal("Unrecognized or invalid HSAIL atomic op "
147311308Santhony.gutierrez@amd.com                                  "type.\n");
147411308Santhony.gutierrez@amd.com                            break;
147511308Santhony.gutierrez@amd.com                        }
147611308Santhony.gutierrez@amd.com                    } else {
147711308Santhony.gutierrez@amd.com                        Request *req =
147811308Santhony.gutierrez@amd.com                            new Request(0, vaddr, sizeof(c0), 0,
147911308Santhony.gutierrez@amd.com                                        gpuDynInst->computeUnit()->masterId(),
148011308Santhony.gutierrez@amd.com                                        0, gpuDynInst->wfDynId, i,
148111308Santhony.gutierrez@amd.com                                        gpuDynInst->makeAtomicOpFunctor<c0>(e,
148211308Santhony.gutierrez@amd.com                                        f, this->opType));
148311308Santhony.gutierrez@amd.com
148411308Santhony.gutierrez@amd.com                        gpuDynInst->setRequestFlags(req);
148511308Santhony.gutierrez@amd.com                        PacketPtr pkt = new Packet(req, MemCmd::SwapReq);
148611308Santhony.gutierrez@amd.com                        pkt->dataStatic(d);
148711308Santhony.gutierrez@amd.com
148811308Santhony.gutierrez@amd.com                        if (gpuDynInst->computeUnit()->shader->
148911308Santhony.gutierrez@amd.com                            separate_acquire_release &&
149011308Santhony.gutierrez@amd.com                            (gpuDynInst->memoryOrder ==
149111308Santhony.gutierrez@amd.com                             Enums::MEMORY_ORDER_SC_ACQUIRE)) {
149211308Santhony.gutierrez@amd.com                            // if this atomic has acquire semantics,
149311308Santhony.gutierrez@amd.com                            // schedule the continuation to perform an
149411308Santhony.gutierrez@amd.com                            // acquire after the RMW completes
149511308Santhony.gutierrez@amd.com                            gpuDynInst->execContinuation =
149611308Santhony.gutierrez@amd.com                                &GPUStaticInst::execAtomicAcq;
149711308Santhony.gutierrez@amd.com
149811308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = true;
149911308Santhony.gutierrez@amd.com                        } else {
150011308Santhony.gutierrez@amd.com                            // the request will be finished when the RMW completes
150111308Santhony.gutierrez@amd.com                            gpuDynInst->useContinuation = false;
150211308Santhony.gutierrez@amd.com                        }
150311308Santhony.gutierrez@amd.com                        // translation is performed in sendRequest()
150411308Santhony.gutierrez@amd.com                        gpuDynInst->computeUnit()->sendRequest(gpuDynInst, i,
150511308Santhony.gutierrez@amd.com                                                               pkt);
150611308Santhony.gutierrez@amd.com                    }
150711308Santhony.gutierrez@amd.com                }
150811308Santhony.gutierrez@amd.com
150911308Santhony.gutierrez@amd.com                ++d;
151011308Santhony.gutierrez@amd.com                ++e;
151111308Santhony.gutierrez@amd.com                ++f;
151211308Santhony.gutierrez@amd.com            }
151311308Santhony.gutierrez@amd.com
151411308Santhony.gutierrez@amd.com            gpuDynInst->updateStats();
151511308Santhony.gutierrez@amd.com        }
151611308Santhony.gutierrez@amd.com
151711308Santhony.gutierrez@amd.com        // execAtomicACq will always be called through a continuation.
151811308Santhony.gutierrez@amd.com        // see comment for execContinuation in gpu_dyn_inst.hh
151911308Santhony.gutierrez@amd.com        void
152011308Santhony.gutierrez@amd.com        execAtomicAcq(GPUDynInstPtr gpuDynInst) override
152111308Santhony.gutierrez@amd.com        {
152211308Santhony.gutierrez@amd.com            // after performing the RMW, check to see if this instruction
152311308Santhony.gutierrez@amd.com            // has acquire semantics, and if so, issue an acquire
152411308Santhony.gutierrez@amd.com            if (!isLocalMem()) {
152511308Santhony.gutierrez@amd.com                if (gpuDynInst->computeUnit()->shader->separate_acquire_release
152611308Santhony.gutierrez@amd.com                     && gpuDynInst->memoryOrder ==
152711308Santhony.gutierrez@amd.com                     Enums::MEMORY_ORDER_SC_ACQUIRE) {
152811308Santhony.gutierrez@amd.com                    gpuDynInst->statusBitVector = VectorMask(1);
152911308Santhony.gutierrez@amd.com
153011308Santhony.gutierrez@amd.com                    // the request will be finished when
153111308Santhony.gutierrez@amd.com                    // the acquire completes
153211308Santhony.gutierrez@amd.com                    gpuDynInst->useContinuation = false;
153311308Santhony.gutierrez@amd.com                    // create request
153411308Santhony.gutierrez@amd.com                    Request *req = new Request(0, 0, 0, 0,
153511308Santhony.gutierrez@amd.com                                  gpuDynInst->computeUnit()->masterId(),
153611308Santhony.gutierrez@amd.com                                  0, gpuDynInst->wfDynId, -1);
153711308Santhony.gutierrez@amd.com                    req->setFlags(Request::ACQUIRE);
153811308Santhony.gutierrez@amd.com                    gpuDynInst->computeUnit()->injectGlobalMemFence(gpuDynInst, false, req);
153911308Santhony.gutierrez@amd.com                }
154011308Santhony.gutierrez@amd.com            }
154111308Santhony.gutierrez@amd.com        }
154211308Santhony.gutierrez@amd.com    };
154311308Santhony.gutierrez@amd.com
154411308Santhony.gutierrez@amd.com    template<typename DataType, typename AddrOperandType, int NumSrcOperands>
154511308Santhony.gutierrez@amd.com    GPUStaticInst*
154611308Santhony.gutierrez@amd.com    constructAtomic(const Brig::BrigInstBase *ib, const BrigObject *obj)
154711308Santhony.gutierrez@amd.com    {
154811308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
154911308Santhony.gutierrez@amd.com
155011308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_LD) {
155111308Santhony.gutierrez@amd.com            return decodeLd<DataType>(ib, obj);
155211308Santhony.gutierrez@amd.com        } else if (at->atomicOperation == Brig::BRIG_ATOMIC_ST) {
155311308Santhony.gutierrez@amd.com            switch (ib->type) {
155411308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B8:
155511308Santhony.gutierrez@amd.com                return decodeSt<S8,S8>(ib, obj);
155611308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B16:
155711308Santhony.gutierrez@amd.com                return decodeSt<S8,S16>(ib, obj);
155811308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B32:
155911308Santhony.gutierrez@amd.com                return decodeSt<S8,S32>(ib, obj);
156011308Santhony.gutierrez@amd.com              case Brig::BRIG_TYPE_B64:
156111308Santhony.gutierrez@amd.com                return decodeSt<S8,S64>(ib, obj);
156211308Santhony.gutierrez@amd.com              default: fatal("AtomicSt: Operand type mismatch %d\n", ib->type);
156311308Santhony.gutierrez@amd.com            }
156411308Santhony.gutierrez@amd.com        } else {
156511308Santhony.gutierrez@amd.com            if ((Brig::BrigOpcode)ib->opcode == Brig::BRIG_OPCODE_ATOMICNORET)
156611308Santhony.gutierrez@amd.com                return new AtomicInst<DataType, AddrOperandType,
156711308Santhony.gutierrez@amd.com                    NumSrcOperands, false>(ib, obj, "atomicnoret");
156811308Santhony.gutierrez@amd.com            else
156911308Santhony.gutierrez@amd.com                return new AtomicInst<DataType, AddrOperandType,
157011308Santhony.gutierrez@amd.com                    NumSrcOperands, true>(ib, obj, "atomic");
157111308Santhony.gutierrez@amd.com        }
157211308Santhony.gutierrez@amd.com    }
157311308Santhony.gutierrez@amd.com
157411308Santhony.gutierrez@amd.com    template<typename DataType, int NumSrcOperands>
157511308Santhony.gutierrez@amd.com    GPUStaticInst*
157611308Santhony.gutierrez@amd.com    decodeAtomicHelper(const Brig::BrigInstBase *ib, const BrigObject *obj)
157711308Santhony.gutierrez@amd.com    {
157811308Santhony.gutierrez@amd.com        unsigned addrIndex = (Brig::BrigOpcode)ib->opcode ==
157911308Santhony.gutierrez@amd.com            Brig::BRIG_OPCODE_ATOMICNORET ? 0 : 1;
158011308Santhony.gutierrez@amd.com
158111308Santhony.gutierrez@amd.com        unsigned op_offs = obj->getOperandPtr(ib->operands,addrIndex);
158211308Santhony.gutierrez@amd.com
158311308Santhony.gutierrez@amd.com        BrigRegOperandInfo tmp = findRegDataType(op_offs, obj);
158411308Santhony.gutierrez@amd.com
158511308Santhony.gutierrez@amd.com        if (tmp.kind == Brig::BRIG_KIND_OPERAND_ADDRESS) {
158611308Santhony.gutierrez@amd.com            return constructAtomic<DataType, NoRegAddrOperand,
158711308Santhony.gutierrez@amd.com                                   NumSrcOperands>(ib, obj);
158811308Santhony.gutierrez@amd.com        } else if (tmp.kind == Brig::BRIG_KIND_OPERAND_REGISTER) {
158911308Santhony.gutierrez@amd.com            // V2/V4 not allowed
159011308Santhony.gutierrez@amd.com            switch (tmp.regKind) {
159111308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_SINGLE:
159211308Santhony.gutierrez@amd.com                  return constructAtomic<DataType, SRegAddrOperand,
159311308Santhony.gutierrez@amd.com                                         NumSrcOperands>(ib, obj);
159411308Santhony.gutierrez@amd.com              case Brig::BRIG_REGISTER_KIND_DOUBLE:
159511308Santhony.gutierrez@amd.com                return constructAtomic<DataType, DRegAddrOperand,
159611308Santhony.gutierrez@amd.com                                       NumSrcOperands>(ib, obj);
159711308Santhony.gutierrez@amd.com              default:
159811308Santhony.gutierrez@amd.com                fatal("Bad atomic register operand type %d\n", tmp.type);
159911308Santhony.gutierrez@amd.com            }
160011308Santhony.gutierrez@amd.com        } else {
160111308Santhony.gutierrez@amd.com            fatal("Bad atomic register operand kind %d\n", tmp.kind);
160211308Santhony.gutierrez@amd.com        }
160311308Santhony.gutierrez@amd.com    }
160411308Santhony.gutierrez@amd.com
160511308Santhony.gutierrez@amd.com
160611308Santhony.gutierrez@amd.com    template<typename DataType>
160711308Santhony.gutierrez@amd.com    GPUStaticInst*
160811308Santhony.gutierrez@amd.com    decodeAtomic(const Brig::BrigInstBase *ib, const BrigObject *obj)
160911308Santhony.gutierrez@amd.com    {
161011308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
161111308Santhony.gutierrez@amd.com
161211308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_CAS) {
161311308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 2>(ib, obj);
161411308Santhony.gutierrez@amd.com        } else {
161511308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 1>(ib, obj);
161611308Santhony.gutierrez@amd.com        }
161711308Santhony.gutierrez@amd.com    }
161811308Santhony.gutierrez@amd.com
161911308Santhony.gutierrez@amd.com    template<typename DataType>
162011308Santhony.gutierrez@amd.com    GPUStaticInst*
162111308Santhony.gutierrez@amd.com    decodeAtomicNoRet(const Brig::BrigInstBase *ib, const BrigObject *obj)
162211308Santhony.gutierrez@amd.com    {
162311308Santhony.gutierrez@amd.com        const Brig::BrigInstAtomic *at = (const Brig::BrigInstAtomic*)ib;
162411308Santhony.gutierrez@amd.com        if (at->atomicOperation == Brig::BRIG_ATOMIC_CAS) {
162511308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 2>(ib, obj);
162611308Santhony.gutierrez@amd.com        } else {
162711308Santhony.gutierrez@amd.com            return decodeAtomicHelper<DataType, 1>(ib, obj);
162811308Santhony.gutierrez@amd.com        }
162911308Santhony.gutierrez@amd.com    }
163011308Santhony.gutierrez@amd.com} // namespace HsailISA
163111308Santhony.gutierrez@amd.com
163211308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_MEM_HH__
1633