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