decl.hh revision 11639
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_DECL_HH__
3711308Santhony.gutierrez@amd.com#define __ARCH_HSAIL_INSTS_DECL_HH__
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.com#include <cmath>
4011308Santhony.gutierrez@amd.com
4111308Santhony.gutierrez@amd.com#include "arch/hsail/generic_types.hh"
4211308Santhony.gutierrez@amd.com#include "arch/hsail/insts/gpu_static_inst.hh"
4311308Santhony.gutierrez@amd.com#include "arch/hsail/operand.hh"
4411308Santhony.gutierrez@amd.com#include "debug/HSAIL.hh"
4511308Santhony.gutierrez@amd.com#include "enums/OpType.hh"
4611308Santhony.gutierrez@amd.com#include "gpu-compute/gpu_dyn_inst.hh"
4711308Santhony.gutierrez@amd.com#include "gpu-compute/shader.hh"
4811308Santhony.gutierrez@amd.com
4911308Santhony.gutierrez@amd.comnamespace HsailISA
5011308Santhony.gutierrez@amd.com{
5111308Santhony.gutierrez@amd.com    template<typename _DestOperand, typename _SrcOperand>
5211308Santhony.gutierrez@amd.com    class HsailOperandType
5311308Santhony.gutierrez@amd.com    {
5411308Santhony.gutierrez@amd.com      public:
5511308Santhony.gutierrez@amd.com        typedef _DestOperand DestOperand;
5611308Santhony.gutierrez@amd.com        typedef _SrcOperand SrcOperand;
5711308Santhony.gutierrez@amd.com    };
5811308Santhony.gutierrez@amd.com
5911308Santhony.gutierrez@amd.com    typedef HsailOperandType<CRegOperand, CRegOrImmOperand> CRegOperandType;
6011308Santhony.gutierrez@amd.com    typedef HsailOperandType<SRegOperand, SRegOrImmOperand> SRegOperandType;
6111308Santhony.gutierrez@amd.com    typedef HsailOperandType<DRegOperand, DRegOrImmOperand> DRegOperandType;
6211308Santhony.gutierrez@amd.com
6311308Santhony.gutierrez@amd.com    // The IsBits parameter serves only to disambiguate tbhe B* types from
6411308Santhony.gutierrez@amd.com    // the U* types, which otherwise would be identical (and
6511308Santhony.gutierrez@amd.com    // indistinguishable).
6611308Santhony.gutierrez@amd.com    template<typename _OperandType, typename _CType, Enums::MemType _memType,
6711308Santhony.gutierrez@amd.com             vgpr_type _vgprType, int IsBits=0>
6811308Santhony.gutierrez@amd.com    class HsailDataType
6911308Santhony.gutierrez@amd.com    {
7011308Santhony.gutierrez@amd.com      public:
7111308Santhony.gutierrez@amd.com        typedef _OperandType OperandType;
7211308Santhony.gutierrez@amd.com        typedef _CType CType;
7311308Santhony.gutierrez@amd.com        static const Enums::MemType memType = _memType;
7411308Santhony.gutierrez@amd.com        static const vgpr_type vgprType = _vgprType;
7511308Santhony.gutierrez@amd.com        static const char *label;
7611308Santhony.gutierrez@amd.com    };
7711308Santhony.gutierrez@amd.com
7811308Santhony.gutierrez@amd.com    typedef HsailDataType<CRegOperandType, bool, Enums::M_U8, VT_32, 1> B1;
7911308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint8_t, Enums::M_U8, VT_32, 1> B8;
8011308Santhony.gutierrez@amd.com
8111308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint16_t,
8211308Santhony.gutierrez@amd.com                          Enums::M_U16, VT_32, 1> B16;
8311308Santhony.gutierrez@amd.com
8411308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint32_t,
8511308Santhony.gutierrez@amd.com                          Enums::M_U32, VT_32, 1> B32;
8611308Santhony.gutierrez@amd.com
8711308Santhony.gutierrez@amd.com    typedef HsailDataType<DRegOperandType, uint64_t,
8811308Santhony.gutierrez@amd.com                          Enums::M_U64, VT_64, 1> B64;
8911308Santhony.gutierrez@amd.com
9011308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, int8_t, Enums::M_S8, VT_32> S8;
9111308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, int16_t, Enums::M_S16, VT_32> S16;
9211308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, int32_t, Enums::M_S32, VT_32> S32;
9311308Santhony.gutierrez@amd.com    typedef HsailDataType<DRegOperandType, int64_t, Enums::M_S64, VT_64> S64;
9411308Santhony.gutierrez@amd.com
9511308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint8_t, Enums::M_U8, VT_32> U8;
9611308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint16_t, Enums::M_U16, VT_32> U16;
9711308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint32_t, Enums::M_U32, VT_32> U32;
9811308Santhony.gutierrez@amd.com    typedef HsailDataType<DRegOperandType, uint64_t, Enums::M_U64, VT_64> U64;
9911308Santhony.gutierrez@amd.com
10011308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, float, Enums::M_F32, VT_32> F32;
10111308Santhony.gutierrez@amd.com    typedef HsailDataType<DRegOperandType, double, Enums::M_F64, VT_64> F64;
10211308Santhony.gutierrez@amd.com
10311308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename SrcOperandType,
10411308Santhony.gutierrez@amd.com             int NumSrcOperands>
10511308Santhony.gutierrez@amd.com    class CommonInstBase : public HsailGPUStaticInst
10611308Santhony.gutierrez@amd.com    {
10711308Santhony.gutierrez@amd.com      protected:
10811308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
10911308Santhony.gutierrez@amd.com        typename SrcOperandType::SrcOperand src[NumSrcOperands];
11011308Santhony.gutierrez@amd.com
11111308Santhony.gutierrez@amd.com        void
11211308Santhony.gutierrez@amd.com        generateDisassembly()
11311308Santhony.gutierrez@amd.com        {
11411308Santhony.gutierrez@amd.com            disassembly = csprintf("%s%s %s", opcode, opcode_suffix(),
11511308Santhony.gutierrez@amd.com                                   dest.disassemble());
11611308Santhony.gutierrez@amd.com
11711308Santhony.gutierrez@amd.com            for (int i = 0; i < NumSrcOperands; ++i) {
11811308Santhony.gutierrez@amd.com                disassembly += ",";
11911308Santhony.gutierrez@amd.com                disassembly += src[i].disassemble();
12011308Santhony.gutierrez@amd.com            }
12111308Santhony.gutierrez@amd.com        }
12211308Santhony.gutierrez@amd.com
12311308Santhony.gutierrez@amd.com        virtual std::string opcode_suffix() = 0;
12411308Santhony.gutierrez@amd.com
12511308Santhony.gutierrez@amd.com      public:
12611308Santhony.gutierrez@amd.com        CommonInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
12711308Santhony.gutierrez@amd.com                       const char *opcode)
12811308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, opcode)
12911308Santhony.gutierrez@amd.com        {
13011308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
13111308Santhony.gutierrez@amd.com
13211308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
13311308Santhony.gutierrez@amd.com
13411308Santhony.gutierrez@amd.com            for (int i = 0; i < NumSrcOperands; ++i) {
13511308Santhony.gutierrez@amd.com                op_offs = obj->getOperandPtr(ib->operands, i + 1);
13611308Santhony.gutierrez@amd.com                src[i].init(op_offs, obj);
13711308Santhony.gutierrez@amd.com            }
13811308Santhony.gutierrez@amd.com        }
13911308Santhony.gutierrez@amd.com
14011308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
14111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
14211308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
14311308Santhony.gutierrez@amd.com                return src[operandIndex].isVectorRegister();
14411308Santhony.gutierrez@amd.com            else
14511308Santhony.gutierrez@amd.com                return dest.isVectorRegister();
14611308Santhony.gutierrez@amd.com        }
14711308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
14811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
14911308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
15011308Santhony.gutierrez@amd.com                return src[operandIndex].isCondRegister();
15111308Santhony.gutierrez@amd.com            else
15211308Santhony.gutierrez@amd.com                return dest.isCondRegister();
15311308Santhony.gutierrez@amd.com        }
15411308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
15511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
15611308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
15711308Santhony.gutierrez@amd.com                return src[operandIndex].isScalarRegister();
15811308Santhony.gutierrez@amd.com            else
15911308Santhony.gutierrez@amd.com                return dest.isScalarRegister();
16011308Santhony.gutierrez@amd.com        }
16111308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) {
16211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
16311308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
16411308Santhony.gutierrez@amd.com                return true;
16511308Santhony.gutierrez@amd.com            return false;
16611308Santhony.gutierrez@amd.com        }
16711308Santhony.gutierrez@amd.com
16811308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) {
16911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
17011308Santhony.gutierrez@amd.com            if (operandIndex >= NumSrcOperands)
17111308Santhony.gutierrez@amd.com                return true;
17211308Santhony.gutierrez@amd.com            return false;
17311308Santhony.gutierrez@amd.com        }
17411308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
17511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
17611308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
17711308Santhony.gutierrez@amd.com                return src[operandIndex].opSize();
17811308Santhony.gutierrez@amd.com            else
17911308Santhony.gutierrez@amd.com                return dest.opSize();
18011308Santhony.gutierrez@amd.com        }
18111308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex) {
18211308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
18311308Santhony.gutierrez@amd.com
18411308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
18511308Santhony.gutierrez@amd.com                return src[operandIndex].regIndex();
18611308Santhony.gutierrez@amd.com            else
18711308Santhony.gutierrez@amd.com                return dest.regIndex();
18811308Santhony.gutierrez@amd.com        }
18911308Santhony.gutierrez@amd.com        int numSrcRegOperands() {
19011308Santhony.gutierrez@amd.com            int operands = 0;
19111308Santhony.gutierrez@amd.com            for (int i = 0; i < NumSrcOperands; i++) {
19211325Ssteve.reinhardt@amd.com                if (src[i].isVectorRegister()) {
19311308Santhony.gutierrez@amd.com                    operands++;
19411308Santhony.gutierrez@amd.com                }
19511308Santhony.gutierrez@amd.com            }
19611308Santhony.gutierrez@amd.com            return operands;
19711308Santhony.gutierrez@amd.com        }
19811308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
19911308Santhony.gutierrez@amd.com        int getNumOperands() { return NumSrcOperands + 1; }
20011308Santhony.gutierrez@amd.com    };
20111308Santhony.gutierrez@amd.com
20211308Santhony.gutierrez@amd.com    template<typename DataType, int NumSrcOperands>
20311308Santhony.gutierrez@amd.com    class ArithInst : public CommonInstBase<typename DataType::OperandType,
20411308Santhony.gutierrez@amd.com                                            typename DataType::OperandType,
20511308Santhony.gutierrez@amd.com                                            NumSrcOperands>
20611308Santhony.gutierrez@amd.com    {
20711308Santhony.gutierrez@amd.com      public:
20811308Santhony.gutierrez@amd.com        std::string opcode_suffix() { return csprintf("_%s", DataType::label); }
20911308Santhony.gutierrez@amd.com
21011308Santhony.gutierrez@amd.com        ArithInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
21111308Santhony.gutierrez@amd.com                  const char *opcode)
21211308Santhony.gutierrez@amd.com            : CommonInstBase<typename DataType::OperandType,
21311308Santhony.gutierrez@amd.com                             typename DataType::OperandType,
21411308Santhony.gutierrez@amd.com                             NumSrcOperands>(ib, obj, opcode)
21511308Santhony.gutierrez@amd.com        {
21611308Santhony.gutierrez@amd.com        }
21711308Santhony.gutierrez@amd.com    };
21811308Santhony.gutierrez@amd.com
21911308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename Src0OperandType,
22011308Santhony.gutierrez@amd.com             typename Src1OperandType, typename Src2OperandType>
22111308Santhony.gutierrez@amd.com    class ThreeNonUniformSourceInstBase : public HsailGPUStaticInst
22211308Santhony.gutierrez@amd.com    {
22311308Santhony.gutierrez@amd.com      protected:
22411308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
22511308Santhony.gutierrez@amd.com        typename Src0OperandType::SrcOperand  src0;
22611308Santhony.gutierrez@amd.com        typename Src1OperandType::SrcOperand  src1;
22711308Santhony.gutierrez@amd.com        typename Src2OperandType::SrcOperand  src2;
22811308Santhony.gutierrez@amd.com
22911308Santhony.gutierrez@amd.com        void
23011308Santhony.gutierrez@amd.com        generateDisassembly()
23111308Santhony.gutierrez@amd.com        {
23211308Santhony.gutierrez@amd.com            disassembly = csprintf("%s %s,%s,%s,%s", opcode, dest.disassemble(),
23311308Santhony.gutierrez@amd.com                                   src0.disassemble(), src1.disassemble(),
23411308Santhony.gutierrez@amd.com                                   src2.disassemble());
23511308Santhony.gutierrez@amd.com        }
23611308Santhony.gutierrez@amd.com
23711308Santhony.gutierrez@amd.com      public:
23811308Santhony.gutierrez@amd.com        ThreeNonUniformSourceInstBase(const Brig::BrigInstBase *ib,
23911308Santhony.gutierrez@amd.com                                      const BrigObject *obj,
24011308Santhony.gutierrez@amd.com                                      const char *opcode)
24111308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, opcode)
24211308Santhony.gutierrez@amd.com        {
24311308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
24411308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
24511308Santhony.gutierrez@amd.com
24611308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
24711308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
24811308Santhony.gutierrez@amd.com
24911308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 2);
25011308Santhony.gutierrez@amd.com            src1.init(op_offs, obj);
25111308Santhony.gutierrez@amd.com
25211308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 3);
25311308Santhony.gutierrez@amd.com            src2.init(op_offs, obj);
25411308Santhony.gutierrez@amd.com        }
25511308Santhony.gutierrez@amd.com
25611308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
25711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
25811308Santhony.gutierrez@amd.com            if (!operandIndex)
25911308Santhony.gutierrez@amd.com                return src0.isVectorRegister();
26011308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
26111308Santhony.gutierrez@amd.com                return src1.isVectorRegister();
26211308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
26311308Santhony.gutierrez@amd.com                return src2.isVectorRegister();
26411308Santhony.gutierrez@amd.com            else
26511308Santhony.gutierrez@amd.com                return dest.isVectorRegister();
26611308Santhony.gutierrez@amd.com        }
26711308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
26811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
26911308Santhony.gutierrez@amd.com            if (!operandIndex)
27011308Santhony.gutierrez@amd.com                return src0.isCondRegister();
27111308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
27211308Santhony.gutierrez@amd.com                return src1.isCondRegister();
27311308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
27411308Santhony.gutierrez@amd.com                return src2.isCondRegister();
27511308Santhony.gutierrez@amd.com            else
27611308Santhony.gutierrez@amd.com                return dest.isCondRegister();
27711308Santhony.gutierrez@amd.com        }
27811308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
27911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
28011308Santhony.gutierrez@amd.com            if (!operandIndex)
28111308Santhony.gutierrez@amd.com                return src0.isScalarRegister();
28211308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
28311308Santhony.gutierrez@amd.com                return src1.isScalarRegister();
28411308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
28511308Santhony.gutierrez@amd.com                return src2.isScalarRegister();
28611308Santhony.gutierrez@amd.com            else
28711308Santhony.gutierrez@amd.com                return dest.isScalarRegister();
28811308Santhony.gutierrez@amd.com        }
28911308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) {
29011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
29111308Santhony.gutierrez@amd.com            if (operandIndex < 3)
29211308Santhony.gutierrez@amd.com                return true;
29311308Santhony.gutierrez@amd.com            else
29411308Santhony.gutierrez@amd.com                return false;
29511308Santhony.gutierrez@amd.com        }
29611308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) {
29711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
29811308Santhony.gutierrez@amd.com            if (operandIndex >= 3)
29911308Santhony.gutierrez@amd.com                return true;
30011308Santhony.gutierrez@amd.com            else
30111308Santhony.gutierrez@amd.com                return false;
30211308Santhony.gutierrez@amd.com        }
30311308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
30411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
30511308Santhony.gutierrez@amd.com            if (!operandIndex)
30611308Santhony.gutierrez@amd.com                return src0.opSize();
30711308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
30811308Santhony.gutierrez@amd.com                return src1.opSize();
30911308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
31011308Santhony.gutierrez@amd.com                return src2.opSize();
31111308Santhony.gutierrez@amd.com            else
31211308Santhony.gutierrez@amd.com                return dest.opSize();
31311308Santhony.gutierrez@amd.com        }
31411308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex) {
31511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
31611308Santhony.gutierrez@amd.com            if (!operandIndex)
31711308Santhony.gutierrez@amd.com                return src0.regIndex();
31811308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
31911308Santhony.gutierrez@amd.com                return src1.regIndex();
32011308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
32111308Santhony.gutierrez@amd.com                return src2.regIndex();
32211308Santhony.gutierrez@amd.com            else
32311308Santhony.gutierrez@amd.com                return dest.regIndex();
32411308Santhony.gutierrez@amd.com        }
32511308Santhony.gutierrez@amd.com
32611308Santhony.gutierrez@amd.com        int numSrcRegOperands() {
32711308Santhony.gutierrez@amd.com            int operands = 0;
32811325Ssteve.reinhardt@amd.com            if (src0.isVectorRegister()) {
32911308Santhony.gutierrez@amd.com                operands++;
33011308Santhony.gutierrez@amd.com            }
33111325Ssteve.reinhardt@amd.com            if (src1.isVectorRegister()) {
33211308Santhony.gutierrez@amd.com                operands++;
33311308Santhony.gutierrez@amd.com            }
33411325Ssteve.reinhardt@amd.com            if (src2.isVectorRegister()) {
33511308Santhony.gutierrez@amd.com                operands++;
33611308Santhony.gutierrez@amd.com            }
33711308Santhony.gutierrez@amd.com            return operands;
33811308Santhony.gutierrez@amd.com        }
33911308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
34011308Santhony.gutierrez@amd.com        int getNumOperands() { return 4; }
34111308Santhony.gutierrez@amd.com    };
34211308Santhony.gutierrez@amd.com
34311308Santhony.gutierrez@amd.com    template<typename DestDataType, typename Src0DataType,
34411308Santhony.gutierrez@amd.com             typename Src1DataType, typename Src2DataType>
34511308Santhony.gutierrez@amd.com    class ThreeNonUniformSourceInst :
34611308Santhony.gutierrez@amd.com        public ThreeNonUniformSourceInstBase<typename DestDataType::OperandType,
34711308Santhony.gutierrez@amd.com                                             typename Src0DataType::OperandType,
34811308Santhony.gutierrez@amd.com                                             typename Src1DataType::OperandType,
34911308Santhony.gutierrez@amd.com                                             typename Src2DataType::OperandType>
35011308Santhony.gutierrez@amd.com    {
35111308Santhony.gutierrez@amd.com      public:
35211308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
35311308Santhony.gutierrez@amd.com        typedef typename Src0DataType::CType Src0CType;
35411308Santhony.gutierrez@amd.com        typedef typename Src1DataType::CType Src1CType;
35511308Santhony.gutierrez@amd.com        typedef typename Src2DataType::CType Src2CType;
35611308Santhony.gutierrez@amd.com
35711308Santhony.gutierrez@amd.com        ThreeNonUniformSourceInst(const Brig::BrigInstBase *ib,
35811308Santhony.gutierrez@amd.com                                  const BrigObject *obj, const char *opcode)
35911308Santhony.gutierrez@amd.com            : ThreeNonUniformSourceInstBase<typename DestDataType::OperandType,
36011308Santhony.gutierrez@amd.com                                         typename Src0DataType::OperandType,
36111308Santhony.gutierrez@amd.com                                         typename Src1DataType::OperandType,
36211308Santhony.gutierrez@amd.com                                         typename Src2DataType::OperandType>(ib,
36311308Santhony.gutierrez@amd.com                                                                    obj, opcode)
36411308Santhony.gutierrez@amd.com        {
36511308Santhony.gutierrez@amd.com        }
36611308Santhony.gutierrez@amd.com    };
36711308Santhony.gutierrez@amd.com
36811308Santhony.gutierrez@amd.com    template<typename DataType>
36911308Santhony.gutierrez@amd.com    class CmovInst : public ThreeNonUniformSourceInst<DataType, B1,
37011308Santhony.gutierrez@amd.com                                                      DataType, DataType>
37111308Santhony.gutierrez@amd.com    {
37211308Santhony.gutierrez@amd.com      public:
37311308Santhony.gutierrez@amd.com        CmovInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
37411308Santhony.gutierrez@amd.com                 const char *opcode)
37511308Santhony.gutierrez@amd.com            : ThreeNonUniformSourceInst<DataType, B1, DataType,
37611308Santhony.gutierrez@amd.com                                        DataType>(ib, obj, opcode)
37711308Santhony.gutierrez@amd.com        {
37811308Santhony.gutierrez@amd.com        }
37911308Santhony.gutierrez@amd.com    };
38011308Santhony.gutierrez@amd.com
38111308Santhony.gutierrez@amd.com    template<typename DataType>
38211308Santhony.gutierrez@amd.com    class ExtractInsertInst : public ThreeNonUniformSourceInst<DataType,
38311308Santhony.gutierrez@amd.com                                                               DataType, U32,
38411308Santhony.gutierrez@amd.com                                                               U32>
38511308Santhony.gutierrez@amd.com    {
38611308Santhony.gutierrez@amd.com      public:
38711308Santhony.gutierrez@amd.com        ExtractInsertInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
38811308Santhony.gutierrez@amd.com                          const char *opcode)
38911308Santhony.gutierrez@amd.com            : ThreeNonUniformSourceInst<DataType, DataType, U32,
39011308Santhony.gutierrez@amd.com                                        U32>(ib, obj, opcode)
39111308Santhony.gutierrez@amd.com        {
39211308Santhony.gutierrez@amd.com        }
39311308Santhony.gutierrez@amd.com    };
39411308Santhony.gutierrez@amd.com
39511308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename Src0OperandType,
39611308Santhony.gutierrez@amd.com             typename Src1OperandType>
39711308Santhony.gutierrez@amd.com    class TwoNonUniformSourceInstBase : public HsailGPUStaticInst
39811308Santhony.gutierrez@amd.com    {
39911308Santhony.gutierrez@amd.com      protected:
40011308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
40111308Santhony.gutierrez@amd.com        typename Src0OperandType::SrcOperand src0;
40211308Santhony.gutierrez@amd.com        typename Src1OperandType::SrcOperand src1;
40311308Santhony.gutierrez@amd.com
40411308Santhony.gutierrez@amd.com        void
40511308Santhony.gutierrez@amd.com        generateDisassembly()
40611308Santhony.gutierrez@amd.com        {
40711308Santhony.gutierrez@amd.com            disassembly = csprintf("%s %s,%s,%s", opcode, dest.disassemble(),
40811308Santhony.gutierrez@amd.com                                   src0.disassemble(), src1.disassemble());
40911308Santhony.gutierrez@amd.com        }
41011308Santhony.gutierrez@amd.com
41111308Santhony.gutierrez@amd.com
41211308Santhony.gutierrez@amd.com      public:
41311308Santhony.gutierrez@amd.com        TwoNonUniformSourceInstBase(const Brig::BrigInstBase *ib,
41411308Santhony.gutierrez@amd.com                                    const BrigObject *obj, const char *opcode)
41511308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, opcode)
41611308Santhony.gutierrez@amd.com        {
41711308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
41811308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
41911308Santhony.gutierrez@amd.com
42011308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
42111308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
42211308Santhony.gutierrez@amd.com
42311308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 2);
42411308Santhony.gutierrez@amd.com            src1.init(op_offs, obj);
42511308Santhony.gutierrez@amd.com        }
42611308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
42711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
42811308Santhony.gutierrez@amd.com            if (!operandIndex)
42911308Santhony.gutierrez@amd.com                return src0.isVectorRegister();
43011308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
43111308Santhony.gutierrez@amd.com                return src1.isVectorRegister();
43211308Santhony.gutierrez@amd.com            else
43311308Santhony.gutierrez@amd.com                return dest.isVectorRegister();
43411308Santhony.gutierrez@amd.com        }
43511308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
43611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
43711308Santhony.gutierrez@amd.com            if (!operandIndex)
43811308Santhony.gutierrez@amd.com                return src0.isCondRegister();
43911308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
44011308Santhony.gutierrez@amd.com                return src1.isCondRegister();
44111308Santhony.gutierrez@amd.com            else
44211308Santhony.gutierrez@amd.com                return dest.isCondRegister();
44311308Santhony.gutierrez@amd.com        }
44411308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
44511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
44611308Santhony.gutierrez@amd.com            if (!operandIndex)
44711308Santhony.gutierrez@amd.com                return src0.isScalarRegister();
44811308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
44911308Santhony.gutierrez@amd.com                return src1.isScalarRegister();
45011308Santhony.gutierrez@amd.com            else
45111308Santhony.gutierrez@amd.com                return dest.isScalarRegister();
45211308Santhony.gutierrez@amd.com        }
45311308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) {
45411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
45511308Santhony.gutierrez@amd.com            if (operandIndex < 2)
45611308Santhony.gutierrez@amd.com                return true;
45711308Santhony.gutierrez@amd.com            else
45811308Santhony.gutierrez@amd.com                return false;
45911308Santhony.gutierrez@amd.com        }
46011308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) {
46111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
46211308Santhony.gutierrez@amd.com            if (operandIndex >= 2)
46311308Santhony.gutierrez@amd.com                return true;
46411308Santhony.gutierrez@amd.com            else
46511308Santhony.gutierrez@amd.com                return false;
46611308Santhony.gutierrez@amd.com        }
46711308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
46811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
46911308Santhony.gutierrez@amd.com            if (!operandIndex)
47011308Santhony.gutierrez@amd.com                return src0.opSize();
47111308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
47211308Santhony.gutierrez@amd.com                return src1.opSize();
47311308Santhony.gutierrez@amd.com            else
47411308Santhony.gutierrez@amd.com                return dest.opSize();
47511308Santhony.gutierrez@amd.com        }
47611308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex) {
47711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
47811308Santhony.gutierrez@amd.com            if (!operandIndex)
47911308Santhony.gutierrez@amd.com                return src0.regIndex();
48011308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
48111308Santhony.gutierrez@amd.com                return src1.regIndex();
48211308Santhony.gutierrez@amd.com            else
48311308Santhony.gutierrez@amd.com                return dest.regIndex();
48411308Santhony.gutierrez@amd.com        }
48511308Santhony.gutierrez@amd.com
48611308Santhony.gutierrez@amd.com        int numSrcRegOperands() {
48711308Santhony.gutierrez@amd.com            int operands = 0;
48811325Ssteve.reinhardt@amd.com            if (src0.isVectorRegister()) {
48911308Santhony.gutierrez@amd.com                operands++;
49011308Santhony.gutierrez@amd.com            }
49111325Ssteve.reinhardt@amd.com            if (src1.isVectorRegister()) {
49211308Santhony.gutierrez@amd.com                operands++;
49311308Santhony.gutierrez@amd.com            }
49411308Santhony.gutierrez@amd.com            return operands;
49511308Santhony.gutierrez@amd.com        }
49611308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
49711308Santhony.gutierrez@amd.com        int getNumOperands() { return 3; }
49811308Santhony.gutierrez@amd.com    };
49911308Santhony.gutierrez@amd.com
50011308Santhony.gutierrez@amd.com    template<typename DestDataType, typename Src0DataType,
50111308Santhony.gutierrez@amd.com             typename Src1DataType>
50211308Santhony.gutierrez@amd.com    class TwoNonUniformSourceInst :
50311308Santhony.gutierrez@amd.com        public TwoNonUniformSourceInstBase<typename DestDataType::OperandType,
50411308Santhony.gutierrez@amd.com                                           typename Src0DataType::OperandType,
50511308Santhony.gutierrez@amd.com                                           typename Src1DataType::OperandType>
50611308Santhony.gutierrez@amd.com    {
50711308Santhony.gutierrez@amd.com      public:
50811308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
50911308Santhony.gutierrez@amd.com        typedef typename Src0DataType::CType Src0CType;
51011308Santhony.gutierrez@amd.com        typedef typename Src1DataType::CType Src1CType;
51111308Santhony.gutierrez@amd.com
51211308Santhony.gutierrez@amd.com        TwoNonUniformSourceInst(const Brig::BrigInstBase *ib,
51311308Santhony.gutierrez@amd.com                                const BrigObject *obj, const char *opcode)
51411308Santhony.gutierrez@amd.com            : TwoNonUniformSourceInstBase<typename DestDataType::OperandType,
51511308Santhony.gutierrez@amd.com                                         typename Src0DataType::OperandType,
51611308Santhony.gutierrez@amd.com                                         typename Src1DataType::OperandType>(ib,
51711308Santhony.gutierrez@amd.com                                                                    obj, opcode)
51811308Santhony.gutierrez@amd.com        {
51911308Santhony.gutierrez@amd.com        }
52011308Santhony.gutierrez@amd.com    };
52111308Santhony.gutierrez@amd.com
52211308Santhony.gutierrez@amd.com    // helper function for ClassInst
52311308Santhony.gutierrez@amd.com    template<typename T>
52411308Santhony.gutierrez@amd.com    bool
52511308Santhony.gutierrez@amd.com    fpclassify(T src0, uint32_t src1)
52611308Santhony.gutierrez@amd.com    {
52711308Santhony.gutierrez@amd.com        int fpclass = std::fpclassify(src0);
52811308Santhony.gutierrez@amd.com
52911308Santhony.gutierrez@amd.com        if ((src1 & 0x3) && (fpclass == FP_NAN)) {
53011308Santhony.gutierrez@amd.com            return true;
53111308Santhony.gutierrez@amd.com        }
53211308Santhony.gutierrez@amd.com
53311308Santhony.gutierrez@amd.com        if (src0 <= -0.0) {
53411308Santhony.gutierrez@amd.com            if ((src1 & 0x4) && fpclass == FP_INFINITE)
53511308Santhony.gutierrez@amd.com                return true;
53611308Santhony.gutierrez@amd.com            if ((src1 & 0x8) && fpclass == FP_NORMAL)
53711308Santhony.gutierrez@amd.com                return true;
53811308Santhony.gutierrez@amd.com            if ((src1 & 0x10) && fpclass == FP_SUBNORMAL)
53911308Santhony.gutierrez@amd.com                return true;
54011308Santhony.gutierrez@amd.com            if ((src1 & 0x20) && fpclass == FP_ZERO)
54111308Santhony.gutierrez@amd.com                return true;
54211308Santhony.gutierrez@amd.com        } else {
54311308Santhony.gutierrez@amd.com            if ((src1 & 0x40) && fpclass == FP_ZERO)
54411308Santhony.gutierrez@amd.com                return true;
54511308Santhony.gutierrez@amd.com            if ((src1 & 0x80) && fpclass == FP_SUBNORMAL)
54611308Santhony.gutierrez@amd.com                return true;
54711308Santhony.gutierrez@amd.com            if ((src1 & 0x100) && fpclass == FP_NORMAL)
54811308Santhony.gutierrez@amd.com                return true;
54911308Santhony.gutierrez@amd.com            if ((src1 & 0x200) && fpclass == FP_INFINITE)
55011308Santhony.gutierrez@amd.com                return true;
55111308Santhony.gutierrez@amd.com        }
55211308Santhony.gutierrez@amd.com        return false;
55311308Santhony.gutierrez@amd.com    }
55411308Santhony.gutierrez@amd.com
55511308Santhony.gutierrez@amd.com    template<typename DataType>
55611308Santhony.gutierrez@amd.com    class ClassInst : public TwoNonUniformSourceInst<B1, DataType, U32>
55711308Santhony.gutierrez@amd.com    {
55811308Santhony.gutierrez@amd.com      public:
55911308Santhony.gutierrez@amd.com        ClassInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
56011308Santhony.gutierrez@amd.com                  const char *opcode)
56111308Santhony.gutierrez@amd.com            : TwoNonUniformSourceInst<B1, DataType, U32>(ib, obj, opcode)
56211308Santhony.gutierrez@amd.com        {
56311308Santhony.gutierrez@amd.com        }
56411308Santhony.gutierrez@amd.com    };
56511308Santhony.gutierrez@amd.com
56611308Santhony.gutierrez@amd.com    template<typename DataType>
56711308Santhony.gutierrez@amd.com    class ShiftInst : public TwoNonUniformSourceInst<DataType, DataType, U32>
56811308Santhony.gutierrez@amd.com    {
56911308Santhony.gutierrez@amd.com      public:
57011308Santhony.gutierrez@amd.com        ShiftInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
57111308Santhony.gutierrez@amd.com                  const char *opcode)
57211308Santhony.gutierrez@amd.com            : TwoNonUniformSourceInst<DataType, DataType, U32>(ib, obj, opcode)
57311308Santhony.gutierrez@amd.com        {
57411308Santhony.gutierrez@amd.com        }
57511308Santhony.gutierrez@amd.com    };
57611308Santhony.gutierrez@amd.com
57711308Santhony.gutierrez@amd.com    // helper function for CmpInst
57811308Santhony.gutierrez@amd.com    template<typename T>
57911308Santhony.gutierrez@amd.com    bool
58011308Santhony.gutierrez@amd.com    compare(T src0, T src1, Brig::BrigCompareOperation cmpOp)
58111308Santhony.gutierrez@amd.com    {
58211308Santhony.gutierrez@amd.com        using namespace Brig;
58311308Santhony.gutierrez@amd.com
58411308Santhony.gutierrez@amd.com        switch (cmpOp) {
58511308Santhony.gutierrez@amd.com          case BRIG_COMPARE_EQ:
58611308Santhony.gutierrez@amd.com          case BRIG_COMPARE_EQU:
58711308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SEQ:
58811308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SEQU:
58911308Santhony.gutierrez@amd.com            return (src0 == src1);
59011308Santhony.gutierrez@amd.com
59111308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NE:
59211308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NEU:
59311308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNE:
59411308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNEU:
59511308Santhony.gutierrez@amd.com            return (src0 != src1);
59611308Santhony.gutierrez@amd.com
59711308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LT:
59811308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LTU:
59911308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLT:
60011308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLTU:
60111308Santhony.gutierrez@amd.com            return (src0 < src1);
60211308Santhony.gutierrez@amd.com
60311308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LE:
60411308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LEU:
60511308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLE:
60611308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLEU:
60711308Santhony.gutierrez@amd.com            return (src0 <= src1);
60811308Santhony.gutierrez@amd.com
60911308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GT:
61011308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GTU:
61111308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGT:
61211308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGTU:
61311308Santhony.gutierrez@amd.com            return (src0 > src1);
61411308Santhony.gutierrez@amd.com
61511308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GE:
61611308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GEU:
61711308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGE:
61811308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGEU:
61911308Santhony.gutierrez@amd.com            return (src0 >= src1);
62011308Santhony.gutierrez@amd.com
62111308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NUM:
62211308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNUM:
62311308Santhony.gutierrez@amd.com            return (src0 == src0) || (src1 == src1);
62411308Santhony.gutierrez@amd.com
62511308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NAN:
62611308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNAN:
62711308Santhony.gutierrez@amd.com            return (src0 != src0) || (src1 != src1);
62811308Santhony.gutierrez@amd.com
62911308Santhony.gutierrez@amd.com          default:
63011308Santhony.gutierrez@amd.com            fatal("Bad cmpOp value %d\n", (int)cmpOp);
63111308Santhony.gutierrez@amd.com        }
63211308Santhony.gutierrez@amd.com    }
63311308Santhony.gutierrez@amd.com
63411308Santhony.gutierrez@amd.com    template<typename T>
63511308Santhony.gutierrez@amd.com    int32_t
63611308Santhony.gutierrez@amd.com    firstbit(T src0)
63711308Santhony.gutierrez@amd.com    {
63811308Santhony.gutierrez@amd.com        if (!src0)
63911308Santhony.gutierrez@amd.com            return -1;
64011308Santhony.gutierrez@amd.com
64111308Santhony.gutierrez@amd.com        //handle positive and negative numbers
64211308Santhony.gutierrez@amd.com        T tmp = (src0 < 0) ? (~src0) : (src0);
64311308Santhony.gutierrez@amd.com
64411308Santhony.gutierrez@amd.com        //the starting pos is MSB
64511308Santhony.gutierrez@amd.com        int pos = 8 * sizeof(T) - 1;
64611308Santhony.gutierrez@amd.com        int cnt = 0;
64711308Santhony.gutierrez@amd.com
64811308Santhony.gutierrez@amd.com        //search the first bit set to 1
64911308Santhony.gutierrez@amd.com        while (!(tmp & (1 << pos))) {
65011308Santhony.gutierrez@amd.com            ++cnt;
65111308Santhony.gutierrez@amd.com            --pos;
65211308Santhony.gutierrez@amd.com        }
65311308Santhony.gutierrez@amd.com        return cnt;
65411308Santhony.gutierrez@amd.com    }
65511308Santhony.gutierrez@amd.com
65611308Santhony.gutierrez@amd.com    const char* cmpOpToString(Brig::BrigCompareOperation cmpOp);
65711308Santhony.gutierrez@amd.com
65811308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename SrcOperandType>
65911308Santhony.gutierrez@amd.com    class CmpInstBase : public CommonInstBase<DestOperandType, SrcOperandType,
66011308Santhony.gutierrez@amd.com                                              2>
66111308Santhony.gutierrez@amd.com    {
66211308Santhony.gutierrez@amd.com      protected:
66311308Santhony.gutierrez@amd.com        Brig::BrigCompareOperation cmpOp;
66411308Santhony.gutierrez@amd.com
66511308Santhony.gutierrez@amd.com      public:
66611308Santhony.gutierrez@amd.com        CmpInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
66711308Santhony.gutierrez@amd.com                    const char *_opcode)
66811308Santhony.gutierrez@amd.com            : CommonInstBase<DestOperandType, SrcOperandType, 2>(ib, obj,
66911308Santhony.gutierrez@amd.com                                                                 _opcode)
67011308Santhony.gutierrez@amd.com        {
67111308Santhony.gutierrez@amd.com            assert(ib->base.kind == Brig::BRIG_KIND_INST_CMP);
67211308Santhony.gutierrez@amd.com            Brig::BrigInstCmp *i = (Brig::BrigInstCmp*)ib;
67311308Santhony.gutierrez@amd.com            cmpOp = (Brig::BrigCompareOperation)i->compare;
67411308Santhony.gutierrez@amd.com        }
67511308Santhony.gutierrez@amd.com    };
67611308Santhony.gutierrez@amd.com
67711308Santhony.gutierrez@amd.com    template<typename DestDataType, typename SrcDataType>
67811308Santhony.gutierrez@amd.com    class CmpInst : public CmpInstBase<typename DestDataType::OperandType,
67911308Santhony.gutierrez@amd.com                                       typename SrcDataType::OperandType>
68011308Santhony.gutierrez@amd.com    {
68111308Santhony.gutierrez@amd.com      public:
68211308Santhony.gutierrez@amd.com        std::string
68311308Santhony.gutierrez@amd.com        opcode_suffix()
68411308Santhony.gutierrez@amd.com        {
68511308Santhony.gutierrez@amd.com            return csprintf("_%s_%s_%s", cmpOpToString(this->cmpOp),
68611308Santhony.gutierrez@amd.com                            DestDataType::label, SrcDataType::label);
68711308Santhony.gutierrez@amd.com        }
68811308Santhony.gutierrez@amd.com
68911308Santhony.gutierrez@amd.com        CmpInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
69011308Santhony.gutierrez@amd.com                const char *_opcode)
69111308Santhony.gutierrez@amd.com            : CmpInstBase<typename DestDataType::OperandType,
69211308Santhony.gutierrez@amd.com                          typename SrcDataType::OperandType>(ib, obj, _opcode)
69311308Santhony.gutierrez@amd.com        {
69411308Santhony.gutierrez@amd.com        }
69511308Santhony.gutierrez@amd.com    };
69611308Santhony.gutierrez@amd.com
69711308Santhony.gutierrez@amd.com    template<typename DestDataType, typename SrcDataType>
69811308Santhony.gutierrez@amd.com    class CvtInst : public CommonInstBase<typename DestDataType::OperandType,
69911308Santhony.gutierrez@amd.com                                          typename SrcDataType::OperandType, 1>
70011308Santhony.gutierrez@amd.com    {
70111308Santhony.gutierrez@amd.com      public:
70211308Santhony.gutierrez@amd.com        std::string opcode_suffix()
70311308Santhony.gutierrez@amd.com        {
70411308Santhony.gutierrez@amd.com            return csprintf("_%s_%s", DestDataType::label, SrcDataType::label);
70511308Santhony.gutierrez@amd.com        }
70611308Santhony.gutierrez@amd.com
70711308Santhony.gutierrez@amd.com        CvtInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
70811308Santhony.gutierrez@amd.com                const char *_opcode)
70911308Santhony.gutierrez@amd.com            : CommonInstBase<typename DestDataType::OperandType,
71011308Santhony.gutierrez@amd.com                             typename SrcDataType::OperandType,
71111308Santhony.gutierrez@amd.com                             1>(ib, obj, _opcode)
71211308Santhony.gutierrez@amd.com        {
71311308Santhony.gutierrez@amd.com        }
71411308Santhony.gutierrez@amd.com    };
71511308Santhony.gutierrez@amd.com
71611308Santhony.gutierrez@amd.com    class SpecialInstNoSrcNoDest : public HsailGPUStaticInst
71711308Santhony.gutierrez@amd.com    {
71811308Santhony.gutierrez@amd.com      public:
71911308Santhony.gutierrez@amd.com        SpecialInstNoSrcNoDest(const Brig::BrigInstBase *ib,
72011308Santhony.gutierrez@amd.com                               const BrigObject *obj, const char *_opcode)
72111308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, _opcode)
72211308Santhony.gutierrez@amd.com        {
72311308Santhony.gutierrez@amd.com        }
72411308Santhony.gutierrez@amd.com
72511308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) { return false; }
72611308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) { return false; }
72711308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) { return false; }
72811308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
72911308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return false; }
73011308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) { return 0; }
73111308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex) { return -1; }
73211308Santhony.gutierrez@amd.com
73311308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
73411308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
73511308Santhony.gutierrez@amd.com        int getNumOperands() { return 0; }
73611308Santhony.gutierrez@amd.com    };
73711308Santhony.gutierrez@amd.com
73811308Santhony.gutierrez@amd.com    template<typename DestOperandType>
73911308Santhony.gutierrez@amd.com    class SpecialInstNoSrcBase : public HsailGPUStaticInst
74011308Santhony.gutierrez@amd.com    {
74111308Santhony.gutierrez@amd.com      protected:
74211308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
74311308Santhony.gutierrez@amd.com
74411308Santhony.gutierrez@amd.com        void generateDisassembly()
74511308Santhony.gutierrez@amd.com        {
74611308Santhony.gutierrez@amd.com            disassembly = csprintf("%s %s", opcode, dest.disassemble());
74711308Santhony.gutierrez@amd.com        }
74811308Santhony.gutierrez@amd.com
74911308Santhony.gutierrez@amd.com      public:
75011308Santhony.gutierrez@amd.com        SpecialInstNoSrcBase(const Brig::BrigInstBase *ib,
75111308Santhony.gutierrez@amd.com                             const BrigObject *obj, const char *_opcode)
75211308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, _opcode)
75311308Santhony.gutierrez@amd.com        {
75411308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
75511308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
75611308Santhony.gutierrez@amd.com        }
75711308Santhony.gutierrez@amd.com
75811308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
75911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
76011308Santhony.gutierrez@amd.com            return dest.isVectorRegister();
76111308Santhony.gutierrez@amd.com        }
76211308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
76311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
76411308Santhony.gutierrez@amd.com            return dest.isCondRegister();
76511308Santhony.gutierrez@amd.com        }
76611308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
76711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
76811308Santhony.gutierrez@amd.com            return dest.isScalarRegister();
76911308Santhony.gutierrez@amd.com        }
77011308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
77111308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return true; }
77211308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
77311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
77411308Santhony.gutierrez@amd.com            return dest.opSize();
77511308Santhony.gutierrez@amd.com        }
77611308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex) {
77711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
77811308Santhony.gutierrez@amd.com            return dest.regIndex();
77911308Santhony.gutierrez@amd.com        }
78011308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
78111308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
78211308Santhony.gutierrez@amd.com        int getNumOperands() { return 1; }
78311308Santhony.gutierrez@amd.com    };
78411308Santhony.gutierrez@amd.com
78511308Santhony.gutierrez@amd.com    template<typename DestDataType>
78611308Santhony.gutierrez@amd.com    class SpecialInstNoSrc :
78711308Santhony.gutierrez@amd.com        public SpecialInstNoSrcBase<typename DestDataType::OperandType>
78811308Santhony.gutierrez@amd.com    {
78911308Santhony.gutierrez@amd.com      public:
79011308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
79111308Santhony.gutierrez@amd.com
79211308Santhony.gutierrez@amd.com        SpecialInstNoSrc(const Brig::BrigInstBase *ib, const BrigObject *obj,
79311308Santhony.gutierrez@amd.com                         const char *_opcode)
79411308Santhony.gutierrez@amd.com            : SpecialInstNoSrcBase<typename DestDataType::OperandType>(ib, obj,
79511308Santhony.gutierrez@amd.com                                                                       _opcode)
79611308Santhony.gutierrez@amd.com        {
79711308Santhony.gutierrez@amd.com        }
79811308Santhony.gutierrez@amd.com    };
79911308Santhony.gutierrez@amd.com
80011308Santhony.gutierrez@amd.com    template<typename DestOperandType>
80111308Santhony.gutierrez@amd.com    class SpecialInst1SrcBase : public HsailGPUStaticInst
80211308Santhony.gutierrez@amd.com    {
80311308Santhony.gutierrez@amd.com      protected:
80411308Santhony.gutierrez@amd.com        typedef int SrcCType;  // used in execute() template
80511308Santhony.gutierrez@amd.com
80611308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
80711308Santhony.gutierrez@amd.com        ImmOperand<SrcCType> src0;
80811308Santhony.gutierrez@amd.com
80911308Santhony.gutierrez@amd.com        void
81011308Santhony.gutierrez@amd.com        generateDisassembly()
81111308Santhony.gutierrez@amd.com        {
81211308Santhony.gutierrez@amd.com            disassembly = csprintf("%s %s,%s", opcode, dest.disassemble(),
81311308Santhony.gutierrez@amd.com                                   src0.disassemble());
81411308Santhony.gutierrez@amd.com        }
81511308Santhony.gutierrez@amd.com
81611308Santhony.gutierrez@amd.com      public:
81711308Santhony.gutierrez@amd.com        SpecialInst1SrcBase(const Brig::BrigInstBase *ib,
81811308Santhony.gutierrez@amd.com                            const BrigObject *obj, const char *_opcode)
81911308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, _opcode)
82011308Santhony.gutierrez@amd.com        {
82111308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
82211308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
82311308Santhony.gutierrez@amd.com
82411308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
82511308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
82611308Santhony.gutierrez@amd.com        }
82711308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
82811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
82911308Santhony.gutierrez@amd.com            return dest.isVectorRegister();
83011308Santhony.gutierrez@amd.com        }
83111308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
83211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
83311308Santhony.gutierrez@amd.com            return dest.isCondRegister();
83411308Santhony.gutierrez@amd.com        }
83511308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
83611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
83711308Santhony.gutierrez@amd.com            return dest.isScalarRegister();
83811308Santhony.gutierrez@amd.com        }
83911308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
84011308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return true; }
84111308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
84211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
84311308Santhony.gutierrez@amd.com            return dest.opSize();
84411308Santhony.gutierrez@amd.com        }
84511308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex) {
84611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
84711308Santhony.gutierrez@amd.com            return dest.regIndex();
84811308Santhony.gutierrez@amd.com        }
84911308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
85011308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
85111308Santhony.gutierrez@amd.com        int getNumOperands() { return 1; }
85211308Santhony.gutierrez@amd.com    };
85311308Santhony.gutierrez@amd.com
85411308Santhony.gutierrez@amd.com    template<typename DestDataType>
85511308Santhony.gutierrez@amd.com    class SpecialInst1Src :
85611308Santhony.gutierrez@amd.com        public SpecialInst1SrcBase<typename DestDataType::OperandType>
85711308Santhony.gutierrez@amd.com    {
85811308Santhony.gutierrez@amd.com      public:
85911308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
86011308Santhony.gutierrez@amd.com
86111308Santhony.gutierrez@amd.com        SpecialInst1Src(const Brig::BrigInstBase *ib, const BrigObject *obj,
86211308Santhony.gutierrez@amd.com                        const char *_opcode)
86311308Santhony.gutierrez@amd.com            : SpecialInst1SrcBase<typename DestDataType::OperandType>(ib, obj,
86411308Santhony.gutierrez@amd.com                                                                      _opcode)
86511308Santhony.gutierrez@amd.com        {
86611308Santhony.gutierrez@amd.com        }
86711308Santhony.gutierrez@amd.com    };
86811308Santhony.gutierrez@amd.com
86911308Santhony.gutierrez@amd.com    class Ret : public SpecialInstNoSrcNoDest
87011308Santhony.gutierrez@amd.com    {
87111308Santhony.gutierrez@amd.com      public:
87211308Santhony.gutierrez@amd.com        typedef SpecialInstNoSrcNoDest Base;
87311308Santhony.gutierrez@amd.com
87411308Santhony.gutierrez@amd.com        Ret(const Brig::BrigInstBase *ib, const BrigObject *obj)
87511308Santhony.gutierrez@amd.com           : Base(ib, obj, "ret")
87611308Santhony.gutierrez@amd.com        {
87711308Santhony.gutierrez@amd.com            o_type = Enums::OT_RET;
87811308Santhony.gutierrez@amd.com        }
87911308Santhony.gutierrez@amd.com
88011308Santhony.gutierrez@amd.com        void execute(GPUDynInstPtr gpuDynInst);
88111308Santhony.gutierrez@amd.com    };
88211308Santhony.gutierrez@amd.com
88311308Santhony.gutierrez@amd.com    class Barrier : public SpecialInstNoSrcNoDest
88411308Santhony.gutierrez@amd.com    {
88511308Santhony.gutierrez@amd.com      public:
88611308Santhony.gutierrez@amd.com        typedef SpecialInstNoSrcNoDest Base;
88711308Santhony.gutierrez@amd.com        uint8_t width;
88811308Santhony.gutierrez@amd.com
88911308Santhony.gutierrez@amd.com        Barrier(const Brig::BrigInstBase *ib, const BrigObject *obj)
89011308Santhony.gutierrez@amd.com            : Base(ib, obj, "barrier")
89111308Santhony.gutierrez@amd.com        {
89211308Santhony.gutierrez@amd.com            o_type = Enums::OT_BARRIER;
89311308Santhony.gutierrez@amd.com            assert(ib->base.kind == Brig::BRIG_KIND_INST_BR);
89411308Santhony.gutierrez@amd.com            width = (uint8_t)((Brig::BrigInstBr*)ib)->width;
89511308Santhony.gutierrez@amd.com        }
89611308Santhony.gutierrez@amd.com
89711308Santhony.gutierrez@amd.com        void execute(GPUDynInstPtr gpuDynInst);
89811308Santhony.gutierrez@amd.com    };
89911308Santhony.gutierrez@amd.com
90011308Santhony.gutierrez@amd.com    class MemFence : public SpecialInstNoSrcNoDest
90111308Santhony.gutierrez@amd.com    {
90211308Santhony.gutierrez@amd.com      public:
90311308Santhony.gutierrez@amd.com        typedef SpecialInstNoSrcNoDest Base;
90411308Santhony.gutierrez@amd.com
90511308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memFenceMemOrder;
90611308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memFenceScopeSegGroup;
90711308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memFenceScopeSegGlobal;
90811308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memFenceScopeSegImage;
90911308Santhony.gutierrez@amd.com
91011308Santhony.gutierrez@amd.com        MemFence(const Brig::BrigInstBase *ib, const BrigObject *obj)
91111308Santhony.gutierrez@amd.com            : Base(ib, obj, "memfence")
91211308Santhony.gutierrez@amd.com        {
91311308Santhony.gutierrez@amd.com            assert(ib->base.kind == Brig::BRIG_KIND_INST_MEM_FENCE);
91411308Santhony.gutierrez@amd.com
91511308Santhony.gutierrez@amd.com            memFenceScopeSegGlobal = (Brig::BrigMemoryScope)
91611308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->globalSegmentMemoryScope;
91711308Santhony.gutierrez@amd.com
91811308Santhony.gutierrez@amd.com            memFenceScopeSegGroup = (Brig::BrigMemoryScope)
91911308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->groupSegmentMemoryScope;
92011308Santhony.gutierrez@amd.com
92111308Santhony.gutierrez@amd.com            memFenceScopeSegImage = (Brig::BrigMemoryScope)
92211308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->imageSegmentMemoryScope;
92311308Santhony.gutierrez@amd.com
92411308Santhony.gutierrez@amd.com            memFenceMemOrder = (Brig::BrigMemoryOrder)
92511308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->memoryOrder;
92611308Santhony.gutierrez@amd.com
92711308Santhony.gutierrez@amd.com            // set o_type based on scopes
92811308Santhony.gutierrez@amd.com            if (memFenceScopeSegGlobal != Brig::BRIG_MEMORY_SCOPE_NONE &&
92911308Santhony.gutierrez@amd.com                memFenceScopeSegGroup != Brig::BRIG_MEMORY_SCOPE_NONE) {
93011308Santhony.gutierrez@amd.com                o_type = Enums::OT_BOTH_MEMFENCE;
93111308Santhony.gutierrez@amd.com            } else if (memFenceScopeSegGlobal != Brig::BRIG_MEMORY_SCOPE_NONE) {
93211308Santhony.gutierrez@amd.com                o_type = Enums::OT_GLOBAL_MEMFENCE;
93311308Santhony.gutierrez@amd.com            } else if (memFenceScopeSegGroup != Brig::BRIG_MEMORY_SCOPE_NONE) {
93411308Santhony.gutierrez@amd.com                o_type = Enums::OT_SHARED_MEMFENCE;
93511308Santhony.gutierrez@amd.com            } else {
93611308Santhony.gutierrez@amd.com                fatal("MemFence constructor: bad scope specifiers\n");
93711308Santhony.gutierrez@amd.com            }
93811308Santhony.gutierrez@amd.com        }
93911308Santhony.gutierrez@amd.com
94011308Santhony.gutierrez@amd.com        void
94111308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst)
94211308Santhony.gutierrez@amd.com        {
94311308Santhony.gutierrez@amd.com            Wavefront *wave = gpuDynInst->wavefront();
94411308Santhony.gutierrez@amd.com            wave->computeUnit->injectGlobalMemFence(gpuDynInst);
94511308Santhony.gutierrez@amd.com        }
94611308Santhony.gutierrez@amd.com
94711308Santhony.gutierrez@amd.com        void
94811308Santhony.gutierrez@amd.com        execute(GPUDynInstPtr gpuDynInst)
94911308Santhony.gutierrez@amd.com        {
95011308Santhony.gutierrez@amd.com            Wavefront *w = gpuDynInst->wavefront();
95111308Santhony.gutierrez@amd.com            // 2 cases:
95211308Santhony.gutierrez@amd.com            //   * memfence to a sequentially consistent memory (e.g., LDS).
95311308Santhony.gutierrez@amd.com            //     These can be handled as no-ops.
95411308Santhony.gutierrez@amd.com            //   * memfence to a relaxed consistency cache (e.g., Hermes, Viper,
95511308Santhony.gutierrez@amd.com            //     etc.). We send a packet, tagged with the memory order and
95611308Santhony.gutierrez@amd.com            //     scope, and let the GPU coalescer handle it.
95711308Santhony.gutierrez@amd.com
95811308Santhony.gutierrez@amd.com            if (o_type == Enums::OT_GLOBAL_MEMFENCE ||
95911308Santhony.gutierrez@amd.com                o_type == Enums::OT_BOTH_MEMFENCE) {
96011308Santhony.gutierrez@amd.com                gpuDynInst->simdId = w->simdId;
96111308Santhony.gutierrez@amd.com                gpuDynInst->wfSlotId = w->wfSlotId;
96211308Santhony.gutierrez@amd.com                gpuDynInst->wfDynId = w->wfDynId;
96311639Salexandru.dutu@amd.com                gpuDynInst->kern_id = w->kernId;
96411308Santhony.gutierrez@amd.com                gpuDynInst->cu_id = w->computeUnit->cu_id;
96511308Santhony.gutierrez@amd.com
96611308Santhony.gutierrez@amd.com                gpuDynInst->memoryOrder =
96711308Santhony.gutierrez@amd.com                    getGenericMemoryOrder(memFenceMemOrder);
96811308Santhony.gutierrez@amd.com                gpuDynInst->scope =
96911308Santhony.gutierrez@amd.com                    getGenericMemoryScope(memFenceScopeSegGlobal);
97011308Santhony.gutierrez@amd.com                gpuDynInst->useContinuation = false;
97111308Santhony.gutierrez@amd.com                GlobalMemPipeline* gmp = &(w->computeUnit->globalMemoryPipe);
97211308Santhony.gutierrez@amd.com                gmp->getGMReqFIFO().push(gpuDynInst);
97311308Santhony.gutierrez@amd.com
97411639Salexandru.dutu@amd.com                w->wrGmReqsInPipe--;
97511639Salexandru.dutu@amd.com                w->rdGmReqsInPipe--;
97611639Salexandru.dutu@amd.com                w->memReqsInPipe--;
97711639Salexandru.dutu@amd.com                w->outstandingReqs++;
97811308Santhony.gutierrez@amd.com            } else if (o_type == Enums::OT_SHARED_MEMFENCE) {
97911308Santhony.gutierrez@amd.com                // no-op
98011308Santhony.gutierrez@amd.com            } else {
98111308Santhony.gutierrez@amd.com                fatal("MemFence execute: bad o_type\n");
98211308Santhony.gutierrez@amd.com            }
98311308Santhony.gutierrez@amd.com        }
98411308Santhony.gutierrez@amd.com    };
98511308Santhony.gutierrez@amd.com
98611308Santhony.gutierrez@amd.com    class Call : public HsailGPUStaticInst
98711308Santhony.gutierrez@amd.com    {
98811308Santhony.gutierrez@amd.com      public:
98911308Santhony.gutierrez@amd.com        // private helper functions
99011308Santhony.gutierrez@amd.com        void calcAddr(Wavefront* w, GPUDynInstPtr m);
99111308Santhony.gutierrez@amd.com
99211308Santhony.gutierrez@amd.com        void
99311308Santhony.gutierrez@amd.com        generateDisassembly()
99411308Santhony.gutierrez@amd.com        {
99511308Santhony.gutierrez@amd.com            if (dest.disassemble() == "") {
99611308Santhony.gutierrez@amd.com                disassembly = csprintf("%s %s (%s)", opcode, src0.disassemble(),
99711308Santhony.gutierrez@amd.com                                       src1.disassemble());
99811308Santhony.gutierrez@amd.com            } else {
99911308Santhony.gutierrez@amd.com                disassembly = csprintf("%s %s (%s) (%s)", opcode,
100011308Santhony.gutierrez@amd.com                                       src0.disassemble(), dest.disassemble(),
100111308Santhony.gutierrez@amd.com                                       src1.disassemble());
100211308Santhony.gutierrez@amd.com            }
100311308Santhony.gutierrez@amd.com        }
100411308Santhony.gutierrez@amd.com
100511308Santhony.gutierrez@amd.com        bool
100611308Santhony.gutierrez@amd.com        isPseudoOp()
100711308Santhony.gutierrez@amd.com        {
100811308Santhony.gutierrez@amd.com            std::string func_name = src0.disassemble();
100911308Santhony.gutierrez@amd.com            if (func_name.find("__gem5_hsail_op") != std::string::npos) {
101011308Santhony.gutierrez@amd.com                return true;
101111308Santhony.gutierrez@amd.com            }
101211308Santhony.gutierrez@amd.com            return false;
101311308Santhony.gutierrez@amd.com        }
101411308Santhony.gutierrez@amd.com
101511308Santhony.gutierrez@amd.com        // member variables
101611308Santhony.gutierrez@amd.com        ListOperand dest;
101711308Santhony.gutierrez@amd.com        FunctionRefOperand src0;
101811308Santhony.gutierrez@amd.com        ListOperand src1;
101911308Santhony.gutierrez@amd.com        HsailCode *func_ptr;
102011308Santhony.gutierrez@amd.com
102111308Santhony.gutierrez@amd.com        // exec function for pseudo instructions mapped on top of call opcode
102211308Santhony.gutierrez@amd.com        void execPseudoInst(Wavefront *w, GPUDynInstPtr gpuDynInst);
102311308Santhony.gutierrez@amd.com
102411308Santhony.gutierrez@amd.com        // user-defined pseudo instructions
102511308Santhony.gutierrez@amd.com        void MagicPrintLane(Wavefront *w);
102611308Santhony.gutierrez@amd.com        void MagicPrintLane64(Wavefront *w);
102711308Santhony.gutierrez@amd.com        void MagicPrintWF32(Wavefront *w);
102811308Santhony.gutierrez@amd.com        void MagicPrintWF64(Wavefront *w);
102911308Santhony.gutierrez@amd.com        void MagicPrintWFFloat(Wavefront *w);
103011308Santhony.gutierrez@amd.com        void MagicSimBreak(Wavefront *w);
103111308Santhony.gutierrez@amd.com        void MagicPrefixSum(Wavefront *w);
103211308Santhony.gutierrez@amd.com        void MagicReduction(Wavefront *w);
103311308Santhony.gutierrez@amd.com        void MagicMaskLower(Wavefront *w);
103411308Santhony.gutierrez@amd.com        void MagicMaskUpper(Wavefront *w);
103511308Santhony.gutierrez@amd.com        void MagicJoinWFBar(Wavefront *w);
103611308Santhony.gutierrez@amd.com        void MagicWaitWFBar(Wavefront *w);
103711308Santhony.gutierrez@amd.com        void MagicPanic(Wavefront *w);
103811308Santhony.gutierrez@amd.com
103911308Santhony.gutierrez@amd.com        void MagicAtomicNRAddGlobalU32Reg(Wavefront *w,
104011308Santhony.gutierrez@amd.com                                          GPUDynInstPtr gpuDynInst);
104111308Santhony.gutierrez@amd.com
104211308Santhony.gutierrez@amd.com        void MagicAtomicNRAddGroupU32Reg(Wavefront *w,
104311308Santhony.gutierrez@amd.com                                         GPUDynInstPtr gpuDynInst);
104411308Santhony.gutierrez@amd.com
104511308Santhony.gutierrez@amd.com        void MagicLoadGlobalU32Reg(Wavefront *w, GPUDynInstPtr gpuDynInst);
104611308Santhony.gutierrez@amd.com
104711308Santhony.gutierrez@amd.com        void MagicXactCasLd(Wavefront *w);
104811308Santhony.gutierrez@amd.com        void MagicMostSigThread(Wavefront *w);
104911308Santhony.gutierrez@amd.com        void MagicMostSigBroadcast(Wavefront *w);
105011308Santhony.gutierrez@amd.com
105111308Santhony.gutierrez@amd.com        void MagicPrintWF32ID(Wavefront *w);
105211308Santhony.gutierrez@amd.com        void MagicPrintWFID64(Wavefront *w);
105311308Santhony.gutierrez@amd.com
105411308Santhony.gutierrez@amd.com        Call(const Brig::BrigInstBase *ib, const BrigObject *obj)
105511308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, "call")
105611308Santhony.gutierrez@amd.com        {
105711308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
105811308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
105911308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
106011308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
106111308Santhony.gutierrez@amd.com
106211308Santhony.gutierrez@amd.com            func_ptr = nullptr;
106311308Santhony.gutierrez@amd.com            std::string func_name = src0.disassemble();
106411308Santhony.gutierrez@amd.com            if (!isPseudoOp()) {
106511308Santhony.gutierrez@amd.com                func_ptr = dynamic_cast<HsailCode*>(obj->
106611308Santhony.gutierrez@amd.com                                                    getFunction(func_name));
106711308Santhony.gutierrez@amd.com
106811308Santhony.gutierrez@amd.com                if (!func_ptr)
106911308Santhony.gutierrez@amd.com                    fatal("call::exec cannot find function: %s\n", func_name);
107011308Santhony.gutierrez@amd.com            }
107111308Santhony.gutierrez@amd.com
107211308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 2);
107311308Santhony.gutierrez@amd.com            src1.init(op_offs, obj);
107411308Santhony.gutierrez@amd.com        }
107511308Santhony.gutierrez@amd.com
107611308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) { return false; }
107711308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) { return false; }
107811308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) { return false; }
107911308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
108011308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return false; }
108111308Santhony.gutierrez@amd.com        int  getOperandSize(int operandIndex) { return 0; }
108211308Santhony.gutierrez@amd.com        int  getRegisterIndex(int operandIndex) { return -1; }
108311308Santhony.gutierrez@amd.com
108411308Santhony.gutierrez@amd.com        void
108511308Santhony.gutierrez@amd.com        execute(GPUDynInstPtr gpuDynInst)
108611308Santhony.gutierrez@amd.com        {
108711308Santhony.gutierrez@amd.com            Wavefront *w = gpuDynInst->wavefront();
108811308Santhony.gutierrez@amd.com
108911308Santhony.gutierrez@amd.com            std::string func_name = src0.disassemble();
109011308Santhony.gutierrez@amd.com            if (isPseudoOp()) {
109111308Santhony.gutierrez@amd.com                execPseudoInst(w, gpuDynInst);
109211308Santhony.gutierrez@amd.com            } else {
109311308Santhony.gutierrez@amd.com                fatal("Native HSAIL functions are not yet implemented: %s\n",
109411308Santhony.gutierrez@amd.com                      func_name);
109511308Santhony.gutierrez@amd.com            }
109611308Santhony.gutierrez@amd.com        }
109711308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
109811308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
109911308Santhony.gutierrez@amd.com        int getNumOperands() { return 2; }
110011308Santhony.gutierrez@amd.com    };
110111308Santhony.gutierrez@amd.com
110211308Santhony.gutierrez@amd.com    template<typename T> T heynot(T arg) { return ~arg; }
110311308Santhony.gutierrez@amd.com    template<> inline bool heynot<bool>(bool arg) { return !arg; }
110411308Santhony.gutierrez@amd.com} // namespace HsailISA
110511308Santhony.gutierrez@amd.com
110611308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_DECL_HH__
1107