decl.hh revision 11692
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/insts/gpu_static_inst.hh"
4211308Santhony.gutierrez@amd.com#include "arch/hsail/operand.hh"
4311308Santhony.gutierrez@amd.com#include "debug/HSAIL.hh"
4411308Santhony.gutierrez@amd.com#include "gpu-compute/gpu_dyn_inst.hh"
4511308Santhony.gutierrez@amd.com#include "gpu-compute/shader.hh"
4611308Santhony.gutierrez@amd.com
4711308Santhony.gutierrez@amd.comnamespace HsailISA
4811308Santhony.gutierrez@amd.com{
4911308Santhony.gutierrez@amd.com    template<typename _DestOperand, typename _SrcOperand>
5011308Santhony.gutierrez@amd.com    class HsailOperandType
5111308Santhony.gutierrez@amd.com    {
5211308Santhony.gutierrez@amd.com      public:
5311308Santhony.gutierrez@amd.com        typedef _DestOperand DestOperand;
5411308Santhony.gutierrez@amd.com        typedef _SrcOperand SrcOperand;
5511308Santhony.gutierrez@amd.com    };
5611308Santhony.gutierrez@amd.com
5711308Santhony.gutierrez@amd.com    typedef HsailOperandType<CRegOperand, CRegOrImmOperand> CRegOperandType;
5811308Santhony.gutierrez@amd.com    typedef HsailOperandType<SRegOperand, SRegOrImmOperand> SRegOperandType;
5911308Santhony.gutierrez@amd.com    typedef HsailOperandType<DRegOperand, DRegOrImmOperand> DRegOperandType;
6011308Santhony.gutierrez@amd.com
6111308Santhony.gutierrez@amd.com    // The IsBits parameter serves only to disambiguate tbhe B* types from
6211308Santhony.gutierrez@amd.com    // the U* types, which otherwise would be identical (and
6311308Santhony.gutierrez@amd.com    // indistinguishable).
6411308Santhony.gutierrez@amd.com    template<typename _OperandType, typename _CType, Enums::MemType _memType,
6511308Santhony.gutierrez@amd.com             vgpr_type _vgprType, int IsBits=0>
6611308Santhony.gutierrez@amd.com    class HsailDataType
6711308Santhony.gutierrez@amd.com    {
6811308Santhony.gutierrez@amd.com      public:
6911308Santhony.gutierrez@amd.com        typedef _OperandType OperandType;
7011308Santhony.gutierrez@amd.com        typedef _CType CType;
7111308Santhony.gutierrez@amd.com        static const Enums::MemType memType = _memType;
7211308Santhony.gutierrez@amd.com        static const vgpr_type vgprType = _vgprType;
7311308Santhony.gutierrez@amd.com        static const char *label;
7411308Santhony.gutierrez@amd.com    };
7511308Santhony.gutierrez@amd.com
7611308Santhony.gutierrez@amd.com    typedef HsailDataType<CRegOperandType, bool, Enums::M_U8, VT_32, 1> B1;
7711308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint8_t, Enums::M_U8, VT_32, 1> B8;
7811308Santhony.gutierrez@amd.com
7911308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint16_t,
8011308Santhony.gutierrez@amd.com                          Enums::M_U16, VT_32, 1> B16;
8111308Santhony.gutierrez@amd.com
8211308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint32_t,
8311308Santhony.gutierrez@amd.com                          Enums::M_U32, VT_32, 1> B32;
8411308Santhony.gutierrez@amd.com
8511308Santhony.gutierrez@amd.com    typedef HsailDataType<DRegOperandType, uint64_t,
8611308Santhony.gutierrez@amd.com                          Enums::M_U64, VT_64, 1> B64;
8711308Santhony.gutierrez@amd.com
8811308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, int8_t, Enums::M_S8, VT_32> S8;
8911308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, int16_t, Enums::M_S16, VT_32> S16;
9011308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, int32_t, Enums::M_S32, VT_32> S32;
9111308Santhony.gutierrez@amd.com    typedef HsailDataType<DRegOperandType, int64_t, Enums::M_S64, VT_64> S64;
9211308Santhony.gutierrez@amd.com
9311308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint8_t, Enums::M_U8, VT_32> U8;
9411308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint16_t, Enums::M_U16, VT_32> U16;
9511308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, uint32_t, Enums::M_U32, VT_32> U32;
9611308Santhony.gutierrez@amd.com    typedef HsailDataType<DRegOperandType, uint64_t, Enums::M_U64, VT_64> U64;
9711308Santhony.gutierrez@amd.com
9811308Santhony.gutierrez@amd.com    typedef HsailDataType<SRegOperandType, float, Enums::M_F32, VT_32> F32;
9911308Santhony.gutierrez@amd.com    typedef HsailDataType<DRegOperandType, double, Enums::M_F64, VT_64> F64;
10011308Santhony.gutierrez@amd.com
10111308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename SrcOperandType,
10211308Santhony.gutierrez@amd.com             int NumSrcOperands>
10311308Santhony.gutierrez@amd.com    class CommonInstBase : public HsailGPUStaticInst
10411308Santhony.gutierrez@amd.com    {
10511308Santhony.gutierrez@amd.com      protected:
10611308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
10711308Santhony.gutierrez@amd.com        typename SrcOperandType::SrcOperand src[NumSrcOperands];
10811308Santhony.gutierrez@amd.com
10911308Santhony.gutierrez@amd.com        void
11011308Santhony.gutierrez@amd.com        generateDisassembly()
11111308Santhony.gutierrez@amd.com        {
11211308Santhony.gutierrez@amd.com            disassembly = csprintf("%s%s %s", opcode, opcode_suffix(),
11311308Santhony.gutierrez@amd.com                                   dest.disassemble());
11411308Santhony.gutierrez@amd.com
11511308Santhony.gutierrez@amd.com            for (int i = 0; i < NumSrcOperands; ++i) {
11611308Santhony.gutierrez@amd.com                disassembly += ",";
11711308Santhony.gutierrez@amd.com                disassembly += src[i].disassemble();
11811308Santhony.gutierrez@amd.com            }
11911308Santhony.gutierrez@amd.com        }
12011308Santhony.gutierrez@amd.com
12111308Santhony.gutierrez@amd.com        virtual std::string opcode_suffix() = 0;
12211308Santhony.gutierrez@amd.com
12311308Santhony.gutierrez@amd.com      public:
12411308Santhony.gutierrez@amd.com        CommonInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
12511308Santhony.gutierrez@amd.com                       const char *opcode)
12611308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, opcode)
12711308Santhony.gutierrez@amd.com        {
12811692Santhony.gutierrez@amd.com            setFlag(ALU);
12911692Santhony.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        {
24311692Santhony.gutierrez@amd.com            setFlag(ALU);
24411692Santhony.gutierrez@amd.com
24511308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
24611308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
24711308Santhony.gutierrez@amd.com
24811308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
24911308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
25011308Santhony.gutierrez@amd.com
25111308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 2);
25211308Santhony.gutierrez@amd.com            src1.init(op_offs, obj);
25311308Santhony.gutierrez@amd.com
25411308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 3);
25511308Santhony.gutierrez@amd.com            src2.init(op_offs, obj);
25611308Santhony.gutierrez@amd.com        }
25711308Santhony.gutierrez@amd.com
25811308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
25911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
26011308Santhony.gutierrez@amd.com            if (!operandIndex)
26111308Santhony.gutierrez@amd.com                return src0.isVectorRegister();
26211308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
26311308Santhony.gutierrez@amd.com                return src1.isVectorRegister();
26411308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
26511308Santhony.gutierrez@amd.com                return src2.isVectorRegister();
26611308Santhony.gutierrez@amd.com            else
26711308Santhony.gutierrez@amd.com                return dest.isVectorRegister();
26811308Santhony.gutierrez@amd.com        }
26911308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
27011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
27111308Santhony.gutierrez@amd.com            if (!operandIndex)
27211308Santhony.gutierrez@amd.com                return src0.isCondRegister();
27311308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
27411308Santhony.gutierrez@amd.com                return src1.isCondRegister();
27511308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
27611308Santhony.gutierrez@amd.com                return src2.isCondRegister();
27711308Santhony.gutierrez@amd.com            else
27811308Santhony.gutierrez@amd.com                return dest.isCondRegister();
27911308Santhony.gutierrez@amd.com        }
28011308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
28111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
28211308Santhony.gutierrez@amd.com            if (!operandIndex)
28311308Santhony.gutierrez@amd.com                return src0.isScalarRegister();
28411308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
28511308Santhony.gutierrez@amd.com                return src1.isScalarRegister();
28611308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
28711308Santhony.gutierrez@amd.com                return src2.isScalarRegister();
28811308Santhony.gutierrez@amd.com            else
28911308Santhony.gutierrez@amd.com                return dest.isScalarRegister();
29011308Santhony.gutierrez@amd.com        }
29111308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) {
29211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
29311308Santhony.gutierrez@amd.com            if (operandIndex < 3)
29411308Santhony.gutierrez@amd.com                return true;
29511308Santhony.gutierrez@amd.com            else
29611308Santhony.gutierrez@amd.com                return false;
29711308Santhony.gutierrez@amd.com        }
29811308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) {
29911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
30011308Santhony.gutierrez@amd.com            if (operandIndex >= 3)
30111308Santhony.gutierrez@amd.com                return true;
30211308Santhony.gutierrez@amd.com            else
30311308Santhony.gutierrez@amd.com                return false;
30411308Santhony.gutierrez@amd.com        }
30511308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
30611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
30711308Santhony.gutierrez@amd.com            if (!operandIndex)
30811308Santhony.gutierrez@amd.com                return src0.opSize();
30911308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
31011308Santhony.gutierrez@amd.com                return src1.opSize();
31111308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
31211308Santhony.gutierrez@amd.com                return src2.opSize();
31311308Santhony.gutierrez@amd.com            else
31411308Santhony.gutierrez@amd.com                return dest.opSize();
31511308Santhony.gutierrez@amd.com        }
31611308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex) {
31711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
31811308Santhony.gutierrez@amd.com            if (!operandIndex)
31911308Santhony.gutierrez@amd.com                return src0.regIndex();
32011308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
32111308Santhony.gutierrez@amd.com                return src1.regIndex();
32211308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
32311308Santhony.gutierrez@amd.com                return src2.regIndex();
32411308Santhony.gutierrez@amd.com            else
32511308Santhony.gutierrez@amd.com                return dest.regIndex();
32611308Santhony.gutierrez@amd.com        }
32711308Santhony.gutierrez@amd.com
32811308Santhony.gutierrez@amd.com        int numSrcRegOperands() {
32911308Santhony.gutierrez@amd.com            int operands = 0;
33011325Ssteve.reinhardt@amd.com            if (src0.isVectorRegister()) {
33111308Santhony.gutierrez@amd.com                operands++;
33211308Santhony.gutierrez@amd.com            }
33311325Ssteve.reinhardt@amd.com            if (src1.isVectorRegister()) {
33411308Santhony.gutierrez@amd.com                operands++;
33511308Santhony.gutierrez@amd.com            }
33611325Ssteve.reinhardt@amd.com            if (src2.isVectorRegister()) {
33711308Santhony.gutierrez@amd.com                operands++;
33811308Santhony.gutierrez@amd.com            }
33911308Santhony.gutierrez@amd.com            return operands;
34011308Santhony.gutierrez@amd.com        }
34111308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
34211308Santhony.gutierrez@amd.com        int getNumOperands() { return 4; }
34311308Santhony.gutierrez@amd.com    };
34411308Santhony.gutierrez@amd.com
34511308Santhony.gutierrez@amd.com    template<typename DestDataType, typename Src0DataType,
34611308Santhony.gutierrez@amd.com             typename Src1DataType, typename Src2DataType>
34711308Santhony.gutierrez@amd.com    class ThreeNonUniformSourceInst :
34811308Santhony.gutierrez@amd.com        public ThreeNonUniformSourceInstBase<typename DestDataType::OperandType,
34911308Santhony.gutierrez@amd.com                                             typename Src0DataType::OperandType,
35011308Santhony.gutierrez@amd.com                                             typename Src1DataType::OperandType,
35111308Santhony.gutierrez@amd.com                                             typename Src2DataType::OperandType>
35211308Santhony.gutierrez@amd.com    {
35311308Santhony.gutierrez@amd.com      public:
35411308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
35511308Santhony.gutierrez@amd.com        typedef typename Src0DataType::CType Src0CType;
35611308Santhony.gutierrez@amd.com        typedef typename Src1DataType::CType Src1CType;
35711308Santhony.gutierrez@amd.com        typedef typename Src2DataType::CType Src2CType;
35811308Santhony.gutierrez@amd.com
35911308Santhony.gutierrez@amd.com        ThreeNonUniformSourceInst(const Brig::BrigInstBase *ib,
36011308Santhony.gutierrez@amd.com                                  const BrigObject *obj, const char *opcode)
36111308Santhony.gutierrez@amd.com            : ThreeNonUniformSourceInstBase<typename DestDataType::OperandType,
36211308Santhony.gutierrez@amd.com                                         typename Src0DataType::OperandType,
36311308Santhony.gutierrez@amd.com                                         typename Src1DataType::OperandType,
36411308Santhony.gutierrez@amd.com                                         typename Src2DataType::OperandType>(ib,
36511308Santhony.gutierrez@amd.com                                                                    obj, opcode)
36611308Santhony.gutierrez@amd.com        {
36711308Santhony.gutierrez@amd.com        }
36811308Santhony.gutierrez@amd.com    };
36911308Santhony.gutierrez@amd.com
37011308Santhony.gutierrez@amd.com    template<typename DataType>
37111308Santhony.gutierrez@amd.com    class CmovInst : public ThreeNonUniformSourceInst<DataType, B1,
37211308Santhony.gutierrez@amd.com                                                      DataType, DataType>
37311308Santhony.gutierrez@amd.com    {
37411308Santhony.gutierrez@amd.com      public:
37511308Santhony.gutierrez@amd.com        CmovInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
37611308Santhony.gutierrez@amd.com                 const char *opcode)
37711308Santhony.gutierrez@amd.com            : ThreeNonUniformSourceInst<DataType, B1, DataType,
37811308Santhony.gutierrez@amd.com                                        DataType>(ib, obj, opcode)
37911308Santhony.gutierrez@amd.com        {
38011308Santhony.gutierrez@amd.com        }
38111308Santhony.gutierrez@amd.com    };
38211308Santhony.gutierrez@amd.com
38311308Santhony.gutierrez@amd.com    template<typename DataType>
38411308Santhony.gutierrez@amd.com    class ExtractInsertInst : public ThreeNonUniformSourceInst<DataType,
38511308Santhony.gutierrez@amd.com                                                               DataType, U32,
38611308Santhony.gutierrez@amd.com                                                               U32>
38711308Santhony.gutierrez@amd.com    {
38811308Santhony.gutierrez@amd.com      public:
38911308Santhony.gutierrez@amd.com        ExtractInsertInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
39011308Santhony.gutierrez@amd.com                          const char *opcode)
39111308Santhony.gutierrez@amd.com            : ThreeNonUniformSourceInst<DataType, DataType, U32,
39211308Santhony.gutierrez@amd.com                                        U32>(ib, obj, opcode)
39311308Santhony.gutierrez@amd.com        {
39411308Santhony.gutierrez@amd.com        }
39511308Santhony.gutierrez@amd.com    };
39611308Santhony.gutierrez@amd.com
39711308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename Src0OperandType,
39811308Santhony.gutierrez@amd.com             typename Src1OperandType>
39911308Santhony.gutierrez@amd.com    class TwoNonUniformSourceInstBase : public HsailGPUStaticInst
40011308Santhony.gutierrez@amd.com    {
40111308Santhony.gutierrez@amd.com      protected:
40211308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
40311308Santhony.gutierrez@amd.com        typename Src0OperandType::SrcOperand src0;
40411308Santhony.gutierrez@amd.com        typename Src1OperandType::SrcOperand src1;
40511308Santhony.gutierrez@amd.com
40611308Santhony.gutierrez@amd.com        void
40711308Santhony.gutierrez@amd.com        generateDisassembly()
40811308Santhony.gutierrez@amd.com        {
40911308Santhony.gutierrez@amd.com            disassembly = csprintf("%s %s,%s,%s", opcode, dest.disassemble(),
41011308Santhony.gutierrez@amd.com                                   src0.disassemble(), src1.disassemble());
41111308Santhony.gutierrez@amd.com        }
41211308Santhony.gutierrez@amd.com
41311308Santhony.gutierrez@amd.com
41411308Santhony.gutierrez@amd.com      public:
41511308Santhony.gutierrez@amd.com        TwoNonUniformSourceInstBase(const Brig::BrigInstBase *ib,
41611308Santhony.gutierrez@amd.com                                    const BrigObject *obj, const char *opcode)
41711308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, opcode)
41811308Santhony.gutierrez@amd.com        {
41911692Santhony.gutierrez@amd.com            setFlag(ALU);
42011692Santhony.gutierrez@amd.com
42111308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
42211308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
42311308Santhony.gutierrez@amd.com
42411308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
42511308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
42611308Santhony.gutierrez@amd.com
42711308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 2);
42811308Santhony.gutierrez@amd.com            src1.init(op_offs, obj);
42911308Santhony.gutierrez@amd.com        }
43011308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
43111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
43211308Santhony.gutierrez@amd.com            if (!operandIndex)
43311308Santhony.gutierrez@amd.com                return src0.isVectorRegister();
43411308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
43511308Santhony.gutierrez@amd.com                return src1.isVectorRegister();
43611308Santhony.gutierrez@amd.com            else
43711308Santhony.gutierrez@amd.com                return dest.isVectorRegister();
43811308Santhony.gutierrez@amd.com        }
43911308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
44011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
44111308Santhony.gutierrez@amd.com            if (!operandIndex)
44211308Santhony.gutierrez@amd.com                return src0.isCondRegister();
44311308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
44411308Santhony.gutierrez@amd.com                return src1.isCondRegister();
44511308Santhony.gutierrez@amd.com            else
44611308Santhony.gutierrez@amd.com                return dest.isCondRegister();
44711308Santhony.gutierrez@amd.com        }
44811308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
44911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
45011308Santhony.gutierrez@amd.com            if (!operandIndex)
45111308Santhony.gutierrez@amd.com                return src0.isScalarRegister();
45211308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
45311308Santhony.gutierrez@amd.com                return src1.isScalarRegister();
45411308Santhony.gutierrez@amd.com            else
45511308Santhony.gutierrez@amd.com                return dest.isScalarRegister();
45611308Santhony.gutierrez@amd.com        }
45711308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) {
45811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
45911308Santhony.gutierrez@amd.com            if (operandIndex < 2)
46011308Santhony.gutierrez@amd.com                return true;
46111308Santhony.gutierrez@amd.com            else
46211308Santhony.gutierrez@amd.com                return false;
46311308Santhony.gutierrez@amd.com        }
46411308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) {
46511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
46611308Santhony.gutierrez@amd.com            if (operandIndex >= 2)
46711308Santhony.gutierrez@amd.com                return true;
46811308Santhony.gutierrez@amd.com            else
46911308Santhony.gutierrez@amd.com                return false;
47011308Santhony.gutierrez@amd.com        }
47111308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
47211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
47311308Santhony.gutierrez@amd.com            if (!operandIndex)
47411308Santhony.gutierrez@amd.com                return src0.opSize();
47511308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
47611308Santhony.gutierrez@amd.com                return src1.opSize();
47711308Santhony.gutierrez@amd.com            else
47811308Santhony.gutierrez@amd.com                return dest.opSize();
47911308Santhony.gutierrez@amd.com        }
48011308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex) {
48111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
48211308Santhony.gutierrez@amd.com            if (!operandIndex)
48311308Santhony.gutierrez@amd.com                return src0.regIndex();
48411308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
48511308Santhony.gutierrez@amd.com                return src1.regIndex();
48611308Santhony.gutierrez@amd.com            else
48711308Santhony.gutierrez@amd.com                return dest.regIndex();
48811308Santhony.gutierrez@amd.com        }
48911308Santhony.gutierrez@amd.com
49011308Santhony.gutierrez@amd.com        int numSrcRegOperands() {
49111308Santhony.gutierrez@amd.com            int operands = 0;
49211325Ssteve.reinhardt@amd.com            if (src0.isVectorRegister()) {
49311308Santhony.gutierrez@amd.com                operands++;
49411308Santhony.gutierrez@amd.com            }
49511325Ssteve.reinhardt@amd.com            if (src1.isVectorRegister()) {
49611308Santhony.gutierrez@amd.com                operands++;
49711308Santhony.gutierrez@amd.com            }
49811308Santhony.gutierrez@amd.com            return operands;
49911308Santhony.gutierrez@amd.com        }
50011308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
50111308Santhony.gutierrez@amd.com        int getNumOperands() { return 3; }
50211308Santhony.gutierrez@amd.com    };
50311308Santhony.gutierrez@amd.com
50411308Santhony.gutierrez@amd.com    template<typename DestDataType, typename Src0DataType,
50511308Santhony.gutierrez@amd.com             typename Src1DataType>
50611308Santhony.gutierrez@amd.com    class TwoNonUniformSourceInst :
50711308Santhony.gutierrez@amd.com        public TwoNonUniformSourceInstBase<typename DestDataType::OperandType,
50811308Santhony.gutierrez@amd.com                                           typename Src0DataType::OperandType,
50911308Santhony.gutierrez@amd.com                                           typename Src1DataType::OperandType>
51011308Santhony.gutierrez@amd.com    {
51111308Santhony.gutierrez@amd.com      public:
51211308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
51311308Santhony.gutierrez@amd.com        typedef typename Src0DataType::CType Src0CType;
51411308Santhony.gutierrez@amd.com        typedef typename Src1DataType::CType Src1CType;
51511308Santhony.gutierrez@amd.com
51611308Santhony.gutierrez@amd.com        TwoNonUniformSourceInst(const Brig::BrigInstBase *ib,
51711308Santhony.gutierrez@amd.com                                const BrigObject *obj, const char *opcode)
51811308Santhony.gutierrez@amd.com            : TwoNonUniformSourceInstBase<typename DestDataType::OperandType,
51911308Santhony.gutierrez@amd.com                                         typename Src0DataType::OperandType,
52011308Santhony.gutierrez@amd.com                                         typename Src1DataType::OperandType>(ib,
52111308Santhony.gutierrez@amd.com                                                                    obj, opcode)
52211308Santhony.gutierrez@amd.com        {
52311308Santhony.gutierrez@amd.com        }
52411308Santhony.gutierrez@amd.com    };
52511308Santhony.gutierrez@amd.com
52611308Santhony.gutierrez@amd.com    // helper function for ClassInst
52711308Santhony.gutierrez@amd.com    template<typename T>
52811308Santhony.gutierrez@amd.com    bool
52911308Santhony.gutierrez@amd.com    fpclassify(T src0, uint32_t src1)
53011308Santhony.gutierrez@amd.com    {
53111308Santhony.gutierrez@amd.com        int fpclass = std::fpclassify(src0);
53211308Santhony.gutierrez@amd.com
53311308Santhony.gutierrez@amd.com        if ((src1 & 0x3) && (fpclass == FP_NAN)) {
53411308Santhony.gutierrez@amd.com            return true;
53511308Santhony.gutierrez@amd.com        }
53611308Santhony.gutierrez@amd.com
53711308Santhony.gutierrez@amd.com        if (src0 <= -0.0) {
53811308Santhony.gutierrez@amd.com            if ((src1 & 0x4) && fpclass == FP_INFINITE)
53911308Santhony.gutierrez@amd.com                return true;
54011308Santhony.gutierrez@amd.com            if ((src1 & 0x8) && fpclass == FP_NORMAL)
54111308Santhony.gutierrez@amd.com                return true;
54211308Santhony.gutierrez@amd.com            if ((src1 & 0x10) && fpclass == FP_SUBNORMAL)
54311308Santhony.gutierrez@amd.com                return true;
54411308Santhony.gutierrez@amd.com            if ((src1 & 0x20) && fpclass == FP_ZERO)
54511308Santhony.gutierrez@amd.com                return true;
54611308Santhony.gutierrez@amd.com        } else {
54711308Santhony.gutierrez@amd.com            if ((src1 & 0x40) && fpclass == FP_ZERO)
54811308Santhony.gutierrez@amd.com                return true;
54911308Santhony.gutierrez@amd.com            if ((src1 & 0x80) && fpclass == FP_SUBNORMAL)
55011308Santhony.gutierrez@amd.com                return true;
55111308Santhony.gutierrez@amd.com            if ((src1 & 0x100) && fpclass == FP_NORMAL)
55211308Santhony.gutierrez@amd.com                return true;
55311308Santhony.gutierrez@amd.com            if ((src1 & 0x200) && fpclass == FP_INFINITE)
55411308Santhony.gutierrez@amd.com                return true;
55511308Santhony.gutierrez@amd.com        }
55611308Santhony.gutierrez@amd.com        return false;
55711308Santhony.gutierrez@amd.com    }
55811308Santhony.gutierrez@amd.com
55911308Santhony.gutierrez@amd.com    template<typename DataType>
56011308Santhony.gutierrez@amd.com    class ClassInst : public TwoNonUniformSourceInst<B1, DataType, U32>
56111308Santhony.gutierrez@amd.com    {
56211308Santhony.gutierrez@amd.com      public:
56311308Santhony.gutierrez@amd.com        ClassInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
56411308Santhony.gutierrez@amd.com                  const char *opcode)
56511308Santhony.gutierrez@amd.com            : TwoNonUniformSourceInst<B1, DataType, U32>(ib, obj, opcode)
56611308Santhony.gutierrez@amd.com        {
56711308Santhony.gutierrez@amd.com        }
56811308Santhony.gutierrez@amd.com    };
56911308Santhony.gutierrez@amd.com
57011308Santhony.gutierrez@amd.com    template<typename DataType>
57111308Santhony.gutierrez@amd.com    class ShiftInst : public TwoNonUniformSourceInst<DataType, DataType, U32>
57211308Santhony.gutierrez@amd.com    {
57311308Santhony.gutierrez@amd.com      public:
57411308Santhony.gutierrez@amd.com        ShiftInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
57511308Santhony.gutierrez@amd.com                  const char *opcode)
57611308Santhony.gutierrez@amd.com            : TwoNonUniformSourceInst<DataType, DataType, U32>(ib, obj, opcode)
57711308Santhony.gutierrez@amd.com        {
57811308Santhony.gutierrez@amd.com        }
57911308Santhony.gutierrez@amd.com    };
58011308Santhony.gutierrez@amd.com
58111308Santhony.gutierrez@amd.com    // helper function for CmpInst
58211308Santhony.gutierrez@amd.com    template<typename T>
58311308Santhony.gutierrez@amd.com    bool
58411308Santhony.gutierrez@amd.com    compare(T src0, T src1, Brig::BrigCompareOperation cmpOp)
58511308Santhony.gutierrez@amd.com    {
58611308Santhony.gutierrez@amd.com        using namespace Brig;
58711308Santhony.gutierrez@amd.com
58811308Santhony.gutierrez@amd.com        switch (cmpOp) {
58911308Santhony.gutierrez@amd.com          case BRIG_COMPARE_EQ:
59011308Santhony.gutierrez@amd.com          case BRIG_COMPARE_EQU:
59111308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SEQ:
59211308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SEQU:
59311308Santhony.gutierrez@amd.com            return (src0 == src1);
59411308Santhony.gutierrez@amd.com
59511308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NE:
59611308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NEU:
59711308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNE:
59811308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNEU:
59911308Santhony.gutierrez@amd.com            return (src0 != src1);
60011308Santhony.gutierrez@amd.com
60111308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LT:
60211308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LTU:
60311308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLT:
60411308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLTU:
60511308Santhony.gutierrez@amd.com            return (src0 < src1);
60611308Santhony.gutierrez@amd.com
60711308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LE:
60811308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LEU:
60911308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLE:
61011308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLEU:
61111308Santhony.gutierrez@amd.com            return (src0 <= src1);
61211308Santhony.gutierrez@amd.com
61311308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GT:
61411308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GTU:
61511308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGT:
61611308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGTU:
61711308Santhony.gutierrez@amd.com            return (src0 > src1);
61811308Santhony.gutierrez@amd.com
61911308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GE:
62011308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GEU:
62111308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGE:
62211308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGEU:
62311308Santhony.gutierrez@amd.com            return (src0 >= src1);
62411308Santhony.gutierrez@amd.com
62511308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NUM:
62611308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNUM:
62711308Santhony.gutierrez@amd.com            return (src0 == src0) || (src1 == src1);
62811308Santhony.gutierrez@amd.com
62911308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NAN:
63011308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNAN:
63111308Santhony.gutierrez@amd.com            return (src0 != src0) || (src1 != src1);
63211308Santhony.gutierrez@amd.com
63311308Santhony.gutierrez@amd.com          default:
63411308Santhony.gutierrez@amd.com            fatal("Bad cmpOp value %d\n", (int)cmpOp);
63511308Santhony.gutierrez@amd.com        }
63611308Santhony.gutierrez@amd.com    }
63711308Santhony.gutierrez@amd.com
63811308Santhony.gutierrez@amd.com    template<typename T>
63911308Santhony.gutierrez@amd.com    int32_t
64011308Santhony.gutierrez@amd.com    firstbit(T src0)
64111308Santhony.gutierrez@amd.com    {
64211308Santhony.gutierrez@amd.com        if (!src0)
64311308Santhony.gutierrez@amd.com            return -1;
64411308Santhony.gutierrez@amd.com
64511308Santhony.gutierrez@amd.com        //handle positive and negative numbers
64611308Santhony.gutierrez@amd.com        T tmp = (src0 < 0) ? (~src0) : (src0);
64711308Santhony.gutierrez@amd.com
64811308Santhony.gutierrez@amd.com        //the starting pos is MSB
64911308Santhony.gutierrez@amd.com        int pos = 8 * sizeof(T) - 1;
65011308Santhony.gutierrez@amd.com        int cnt = 0;
65111308Santhony.gutierrez@amd.com
65211308Santhony.gutierrez@amd.com        //search the first bit set to 1
65311308Santhony.gutierrez@amd.com        while (!(tmp & (1 << pos))) {
65411308Santhony.gutierrez@amd.com            ++cnt;
65511308Santhony.gutierrez@amd.com            --pos;
65611308Santhony.gutierrez@amd.com        }
65711308Santhony.gutierrez@amd.com        return cnt;
65811308Santhony.gutierrez@amd.com    }
65911308Santhony.gutierrez@amd.com
66011308Santhony.gutierrez@amd.com    const char* cmpOpToString(Brig::BrigCompareOperation cmpOp);
66111308Santhony.gutierrez@amd.com
66211308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename SrcOperandType>
66311308Santhony.gutierrez@amd.com    class CmpInstBase : public CommonInstBase<DestOperandType, SrcOperandType,
66411308Santhony.gutierrez@amd.com                                              2>
66511308Santhony.gutierrez@amd.com    {
66611308Santhony.gutierrez@amd.com      protected:
66711308Santhony.gutierrez@amd.com        Brig::BrigCompareOperation cmpOp;
66811308Santhony.gutierrez@amd.com
66911308Santhony.gutierrez@amd.com      public:
67011308Santhony.gutierrez@amd.com        CmpInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
67111308Santhony.gutierrez@amd.com                    const char *_opcode)
67211308Santhony.gutierrez@amd.com            : CommonInstBase<DestOperandType, SrcOperandType, 2>(ib, obj,
67311308Santhony.gutierrez@amd.com                                                                 _opcode)
67411308Santhony.gutierrez@amd.com        {
67511308Santhony.gutierrez@amd.com            assert(ib->base.kind == Brig::BRIG_KIND_INST_CMP);
67611308Santhony.gutierrez@amd.com            Brig::BrigInstCmp *i = (Brig::BrigInstCmp*)ib;
67711308Santhony.gutierrez@amd.com            cmpOp = (Brig::BrigCompareOperation)i->compare;
67811308Santhony.gutierrez@amd.com        }
67911308Santhony.gutierrez@amd.com    };
68011308Santhony.gutierrez@amd.com
68111308Santhony.gutierrez@amd.com    template<typename DestDataType, typename SrcDataType>
68211308Santhony.gutierrez@amd.com    class CmpInst : public CmpInstBase<typename DestDataType::OperandType,
68311308Santhony.gutierrez@amd.com                                       typename SrcDataType::OperandType>
68411308Santhony.gutierrez@amd.com    {
68511308Santhony.gutierrez@amd.com      public:
68611308Santhony.gutierrez@amd.com        std::string
68711308Santhony.gutierrez@amd.com        opcode_suffix()
68811308Santhony.gutierrez@amd.com        {
68911308Santhony.gutierrez@amd.com            return csprintf("_%s_%s_%s", cmpOpToString(this->cmpOp),
69011308Santhony.gutierrez@amd.com                            DestDataType::label, SrcDataType::label);
69111308Santhony.gutierrez@amd.com        }
69211308Santhony.gutierrez@amd.com
69311308Santhony.gutierrez@amd.com        CmpInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
69411308Santhony.gutierrez@amd.com                const char *_opcode)
69511308Santhony.gutierrez@amd.com            : CmpInstBase<typename DestDataType::OperandType,
69611308Santhony.gutierrez@amd.com                          typename SrcDataType::OperandType>(ib, obj, _opcode)
69711308Santhony.gutierrez@amd.com        {
69811308Santhony.gutierrez@amd.com        }
69911308Santhony.gutierrez@amd.com    };
70011308Santhony.gutierrez@amd.com
70111308Santhony.gutierrez@amd.com    template<typename DestDataType, typename SrcDataType>
70211308Santhony.gutierrez@amd.com    class CvtInst : public CommonInstBase<typename DestDataType::OperandType,
70311308Santhony.gutierrez@amd.com                                          typename SrcDataType::OperandType, 1>
70411308Santhony.gutierrez@amd.com    {
70511308Santhony.gutierrez@amd.com      public:
70611308Santhony.gutierrez@amd.com        std::string opcode_suffix()
70711308Santhony.gutierrez@amd.com        {
70811308Santhony.gutierrez@amd.com            return csprintf("_%s_%s", DestDataType::label, SrcDataType::label);
70911308Santhony.gutierrez@amd.com        }
71011308Santhony.gutierrez@amd.com
71111308Santhony.gutierrez@amd.com        CvtInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
71211308Santhony.gutierrez@amd.com                const char *_opcode)
71311308Santhony.gutierrez@amd.com            : CommonInstBase<typename DestDataType::OperandType,
71411308Santhony.gutierrez@amd.com                             typename SrcDataType::OperandType,
71511308Santhony.gutierrez@amd.com                             1>(ib, obj, _opcode)
71611308Santhony.gutierrez@amd.com        {
71711308Santhony.gutierrez@amd.com        }
71811308Santhony.gutierrez@amd.com    };
71911308Santhony.gutierrez@amd.com
72011308Santhony.gutierrez@amd.com    class SpecialInstNoSrcNoDest : public HsailGPUStaticInst
72111308Santhony.gutierrez@amd.com    {
72211308Santhony.gutierrez@amd.com      public:
72311308Santhony.gutierrez@amd.com        SpecialInstNoSrcNoDest(const Brig::BrigInstBase *ib,
72411308Santhony.gutierrez@amd.com                               const BrigObject *obj, const char *_opcode)
72511308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, _opcode)
72611308Santhony.gutierrez@amd.com        {
72711308Santhony.gutierrez@amd.com        }
72811308Santhony.gutierrez@amd.com
72911308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) { return false; }
73011308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) { return false; }
73111308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) { return false; }
73211308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
73311308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return false; }
73411308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) { return 0; }
73511308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex) { return -1; }
73611308Santhony.gutierrez@amd.com
73711308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
73811308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
73911308Santhony.gutierrez@amd.com        int getNumOperands() { return 0; }
74011308Santhony.gutierrez@amd.com    };
74111308Santhony.gutierrez@amd.com
74211308Santhony.gutierrez@amd.com    template<typename DestOperandType>
74311308Santhony.gutierrez@amd.com    class SpecialInstNoSrcBase : public HsailGPUStaticInst
74411308Santhony.gutierrez@amd.com    {
74511308Santhony.gutierrez@amd.com      protected:
74611308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
74711308Santhony.gutierrez@amd.com
74811308Santhony.gutierrez@amd.com        void generateDisassembly()
74911308Santhony.gutierrez@amd.com        {
75011308Santhony.gutierrez@amd.com            disassembly = csprintf("%s %s", opcode, dest.disassemble());
75111308Santhony.gutierrez@amd.com        }
75211308Santhony.gutierrez@amd.com
75311308Santhony.gutierrez@amd.com      public:
75411308Santhony.gutierrez@amd.com        SpecialInstNoSrcBase(const Brig::BrigInstBase *ib,
75511308Santhony.gutierrez@amd.com                             const BrigObject *obj, const char *_opcode)
75611308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, _opcode)
75711308Santhony.gutierrez@amd.com        {
75811308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
75911308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
76011308Santhony.gutierrez@amd.com        }
76111308Santhony.gutierrez@amd.com
76211308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
76311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
76411308Santhony.gutierrez@amd.com            return dest.isVectorRegister();
76511308Santhony.gutierrez@amd.com        }
76611308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
76711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
76811308Santhony.gutierrez@amd.com            return dest.isCondRegister();
76911308Santhony.gutierrez@amd.com        }
77011308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
77111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
77211308Santhony.gutierrez@amd.com            return dest.isScalarRegister();
77311308Santhony.gutierrez@amd.com        }
77411308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
77511308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return true; }
77611308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
77711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
77811308Santhony.gutierrez@amd.com            return dest.opSize();
77911308Santhony.gutierrez@amd.com        }
78011308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex) {
78111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
78211308Santhony.gutierrez@amd.com            return dest.regIndex();
78311308Santhony.gutierrez@amd.com        }
78411308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
78511308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
78611308Santhony.gutierrez@amd.com        int getNumOperands() { return 1; }
78711308Santhony.gutierrez@amd.com    };
78811308Santhony.gutierrez@amd.com
78911308Santhony.gutierrez@amd.com    template<typename DestDataType>
79011308Santhony.gutierrez@amd.com    class SpecialInstNoSrc :
79111308Santhony.gutierrez@amd.com        public SpecialInstNoSrcBase<typename DestDataType::OperandType>
79211308Santhony.gutierrez@amd.com    {
79311308Santhony.gutierrez@amd.com      public:
79411308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
79511308Santhony.gutierrez@amd.com
79611308Santhony.gutierrez@amd.com        SpecialInstNoSrc(const Brig::BrigInstBase *ib, const BrigObject *obj,
79711308Santhony.gutierrez@amd.com                         const char *_opcode)
79811308Santhony.gutierrez@amd.com            : SpecialInstNoSrcBase<typename DestDataType::OperandType>(ib, obj,
79911308Santhony.gutierrez@amd.com                                                                       _opcode)
80011308Santhony.gutierrez@amd.com        {
80111308Santhony.gutierrez@amd.com        }
80211308Santhony.gutierrez@amd.com    };
80311308Santhony.gutierrez@amd.com
80411308Santhony.gutierrez@amd.com    template<typename DestOperandType>
80511308Santhony.gutierrez@amd.com    class SpecialInst1SrcBase : public HsailGPUStaticInst
80611308Santhony.gutierrez@amd.com    {
80711308Santhony.gutierrez@amd.com      protected:
80811308Santhony.gutierrez@amd.com        typedef int SrcCType;  // used in execute() template
80911308Santhony.gutierrez@amd.com
81011308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
81111308Santhony.gutierrez@amd.com        ImmOperand<SrcCType> src0;
81211308Santhony.gutierrez@amd.com
81311308Santhony.gutierrez@amd.com        void
81411308Santhony.gutierrez@amd.com        generateDisassembly()
81511308Santhony.gutierrez@amd.com        {
81611308Santhony.gutierrez@amd.com            disassembly = csprintf("%s %s,%s", opcode, dest.disassemble(),
81711308Santhony.gutierrez@amd.com                                   src0.disassemble());
81811308Santhony.gutierrez@amd.com        }
81911308Santhony.gutierrez@amd.com
82011308Santhony.gutierrez@amd.com      public:
82111308Santhony.gutierrez@amd.com        SpecialInst1SrcBase(const Brig::BrigInstBase *ib,
82211308Santhony.gutierrez@amd.com                            const BrigObject *obj, const char *_opcode)
82311308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, _opcode)
82411308Santhony.gutierrez@amd.com        {
82511692Santhony.gutierrez@amd.com            setFlag(ALU);
82611692Santhony.gutierrez@amd.com
82711308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
82811308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
82911308Santhony.gutierrez@amd.com
83011308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
83111308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
83211308Santhony.gutierrez@amd.com        }
83311308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
83411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
83511308Santhony.gutierrez@amd.com            return dest.isVectorRegister();
83611308Santhony.gutierrez@amd.com        }
83711308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
83811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
83911308Santhony.gutierrez@amd.com            return dest.isCondRegister();
84011308Santhony.gutierrez@amd.com        }
84111308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
84211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
84311308Santhony.gutierrez@amd.com            return dest.isScalarRegister();
84411308Santhony.gutierrez@amd.com        }
84511308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
84611308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return true; }
84711308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
84811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
84911308Santhony.gutierrez@amd.com            return dest.opSize();
85011308Santhony.gutierrez@amd.com        }
85111308Santhony.gutierrez@amd.com        int getRegisterIndex(int operandIndex) {
85211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
85311308Santhony.gutierrez@amd.com            return dest.regIndex();
85411308Santhony.gutierrez@amd.com        }
85511308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
85611308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
85711308Santhony.gutierrez@amd.com        int getNumOperands() { return 1; }
85811308Santhony.gutierrez@amd.com    };
85911308Santhony.gutierrez@amd.com
86011308Santhony.gutierrez@amd.com    template<typename DestDataType>
86111308Santhony.gutierrez@amd.com    class SpecialInst1Src :
86211308Santhony.gutierrez@amd.com        public SpecialInst1SrcBase<typename DestDataType::OperandType>
86311308Santhony.gutierrez@amd.com    {
86411308Santhony.gutierrez@amd.com      public:
86511308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
86611308Santhony.gutierrez@amd.com
86711308Santhony.gutierrez@amd.com        SpecialInst1Src(const Brig::BrigInstBase *ib, const BrigObject *obj,
86811308Santhony.gutierrez@amd.com                        const char *_opcode)
86911308Santhony.gutierrez@amd.com            : SpecialInst1SrcBase<typename DestDataType::OperandType>(ib, obj,
87011308Santhony.gutierrez@amd.com                                                                      _opcode)
87111308Santhony.gutierrez@amd.com        {
87211308Santhony.gutierrez@amd.com        }
87311308Santhony.gutierrez@amd.com    };
87411308Santhony.gutierrez@amd.com
87511308Santhony.gutierrez@amd.com    class Ret : public SpecialInstNoSrcNoDest
87611308Santhony.gutierrez@amd.com    {
87711308Santhony.gutierrez@amd.com      public:
87811308Santhony.gutierrez@amd.com        typedef SpecialInstNoSrcNoDest Base;
87911308Santhony.gutierrez@amd.com
88011308Santhony.gutierrez@amd.com        Ret(const Brig::BrigInstBase *ib, const BrigObject *obj)
88111308Santhony.gutierrez@amd.com           : Base(ib, obj, "ret")
88211308Santhony.gutierrez@amd.com        {
88311692Santhony.gutierrez@amd.com            setFlag(GPUStaticInst::Return);
88411308Santhony.gutierrez@amd.com        }
88511308Santhony.gutierrez@amd.com
88611308Santhony.gutierrez@amd.com        void execute(GPUDynInstPtr gpuDynInst);
88711308Santhony.gutierrez@amd.com    };
88811308Santhony.gutierrez@amd.com
88911308Santhony.gutierrez@amd.com    class Barrier : public SpecialInstNoSrcNoDest
89011308Santhony.gutierrez@amd.com    {
89111308Santhony.gutierrez@amd.com      public:
89211308Santhony.gutierrez@amd.com        typedef SpecialInstNoSrcNoDest Base;
89311308Santhony.gutierrez@amd.com        uint8_t width;
89411308Santhony.gutierrez@amd.com
89511308Santhony.gutierrez@amd.com        Barrier(const Brig::BrigInstBase *ib, const BrigObject *obj)
89611308Santhony.gutierrez@amd.com            : Base(ib, obj, "barrier")
89711308Santhony.gutierrez@amd.com        {
89811692Santhony.gutierrez@amd.com            setFlag(GPUStaticInst::MemBarrier);
89911308Santhony.gutierrez@amd.com            assert(ib->base.kind == Brig::BRIG_KIND_INST_BR);
90011308Santhony.gutierrez@amd.com            width = (uint8_t)((Brig::BrigInstBr*)ib)->width;
90111308Santhony.gutierrez@amd.com        }
90211308Santhony.gutierrez@amd.com
90311308Santhony.gutierrez@amd.com        void execute(GPUDynInstPtr gpuDynInst);
90411308Santhony.gutierrez@amd.com    };
90511308Santhony.gutierrez@amd.com
90611308Santhony.gutierrez@amd.com    class MemFence : public SpecialInstNoSrcNoDest
90711308Santhony.gutierrez@amd.com    {
90811308Santhony.gutierrez@amd.com      public:
90911308Santhony.gutierrez@amd.com        typedef SpecialInstNoSrcNoDest Base;
91011308Santhony.gutierrez@amd.com
91111308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memFenceMemOrder;
91211308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memFenceScopeSegGroup;
91311308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memFenceScopeSegGlobal;
91411308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memFenceScopeSegImage;
91511308Santhony.gutierrez@amd.com
91611308Santhony.gutierrez@amd.com        MemFence(const Brig::BrigInstBase *ib, const BrigObject *obj)
91711308Santhony.gutierrez@amd.com            : Base(ib, obj, "memfence")
91811308Santhony.gutierrez@amd.com        {
91911308Santhony.gutierrez@amd.com            assert(ib->base.kind == Brig::BRIG_KIND_INST_MEM_FENCE);
92011308Santhony.gutierrez@amd.com
92111308Santhony.gutierrez@amd.com            memFenceScopeSegGlobal = (Brig::BrigMemoryScope)
92211308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->globalSegmentMemoryScope;
92311308Santhony.gutierrez@amd.com
92411308Santhony.gutierrez@amd.com            memFenceScopeSegGroup = (Brig::BrigMemoryScope)
92511308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->groupSegmentMemoryScope;
92611308Santhony.gutierrez@amd.com
92711308Santhony.gutierrez@amd.com            memFenceScopeSegImage = (Brig::BrigMemoryScope)
92811308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->imageSegmentMemoryScope;
92911308Santhony.gutierrez@amd.com
93011308Santhony.gutierrez@amd.com            memFenceMemOrder = (Brig::BrigMemoryOrder)
93111308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->memoryOrder;
93211308Santhony.gutierrez@amd.com
93311692Santhony.gutierrez@amd.com            setFlag(MemoryRef);
93411692Santhony.gutierrez@amd.com            setFlag(GPUStaticInst::MemFence);
93511692Santhony.gutierrez@amd.com
93611692Santhony.gutierrez@amd.com            switch (memFenceMemOrder) {
93711692Santhony.gutierrez@amd.com              case Brig::BRIG_MEMORY_ORDER_NONE:
93811692Santhony.gutierrez@amd.com                setFlag(NoOrder);
93911692Santhony.gutierrez@amd.com                break;
94011692Santhony.gutierrez@amd.com              case Brig::BRIG_MEMORY_ORDER_RELAXED:
94111692Santhony.gutierrez@amd.com                setFlag(RelaxedOrder);
94211692Santhony.gutierrez@amd.com                break;
94311692Santhony.gutierrez@amd.com              case Brig::BRIG_MEMORY_ORDER_SC_ACQUIRE:
94411692Santhony.gutierrez@amd.com                setFlag(Acquire);
94511692Santhony.gutierrez@amd.com                break;
94611692Santhony.gutierrez@amd.com              case Brig::BRIG_MEMORY_ORDER_SC_RELEASE:
94711692Santhony.gutierrez@amd.com                setFlag(Release);
94811692Santhony.gutierrez@amd.com                break;
94911692Santhony.gutierrez@amd.com              case Brig::BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE:
95011692Santhony.gutierrez@amd.com                setFlag(AcquireRelease);
95111692Santhony.gutierrez@amd.com                break;
95211692Santhony.gutierrez@amd.com              default:
95311692Santhony.gutierrez@amd.com                fatal("MemInst has bad BrigMemoryOrder\n");
95411692Santhony.gutierrez@amd.com            }
95511692Santhony.gutierrez@amd.com
95611692Santhony.gutierrez@amd.com            // set inst flags based on scopes
95711308Santhony.gutierrez@amd.com            if (memFenceScopeSegGlobal != Brig::BRIG_MEMORY_SCOPE_NONE &&
95811308Santhony.gutierrez@amd.com                memFenceScopeSegGroup != Brig::BRIG_MEMORY_SCOPE_NONE) {
95911692Santhony.gutierrez@amd.com                setFlag(GPUStaticInst::GlobalSegment);
96011692Santhony.gutierrez@amd.com
96111692Santhony.gutierrez@amd.com                /**
96211692Santhony.gutierrez@amd.com                 * A memory fence that has scope for
96311692Santhony.gutierrez@amd.com                 * both segments will use the global
96411692Santhony.gutierrez@amd.com                 * segment, and be executed in the
96511692Santhony.gutierrez@amd.com                 * global memory pipeline, therefore,
96611692Santhony.gutierrez@amd.com                 * we set the segment to match the
96711692Santhony.gutierrez@amd.com                 * global scope only
96811692Santhony.gutierrez@amd.com                 */
96911692Santhony.gutierrez@amd.com                switch (memFenceScopeSegGlobal) {
97011692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_NONE:
97111692Santhony.gutierrez@amd.com                    setFlag(NoScope);
97211692Santhony.gutierrez@amd.com                    break;
97311692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKITEM:
97411692Santhony.gutierrez@amd.com                    setFlag(WorkitemScope);
97511692Santhony.gutierrez@amd.com                    break;
97611692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKGROUP:
97711692Santhony.gutierrez@amd.com                    setFlag(WorkgroupScope);
97811692Santhony.gutierrez@amd.com                    break;
97911692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_AGENT:
98011692Santhony.gutierrez@amd.com                    setFlag(DeviceScope);
98111692Santhony.gutierrez@amd.com                    break;
98211692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_SYSTEM:
98311692Santhony.gutierrez@amd.com                    setFlag(SystemScope);
98411692Santhony.gutierrez@amd.com                    break;
98511692Santhony.gutierrez@amd.com                  default:
98611692Santhony.gutierrez@amd.com                    fatal("MemFence has bad global scope type\n");
98711692Santhony.gutierrez@amd.com                }
98811308Santhony.gutierrez@amd.com            } else if (memFenceScopeSegGlobal != Brig::BRIG_MEMORY_SCOPE_NONE) {
98911692Santhony.gutierrez@amd.com                setFlag(GPUStaticInst::GlobalSegment);
99011692Santhony.gutierrez@amd.com
99111692Santhony.gutierrez@amd.com                switch (memFenceScopeSegGlobal) {
99211692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_NONE:
99311692Santhony.gutierrez@amd.com                    setFlag(NoScope);
99411692Santhony.gutierrez@amd.com                    break;
99511692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKITEM:
99611692Santhony.gutierrez@amd.com                    setFlag(WorkitemScope);
99711692Santhony.gutierrez@amd.com                    break;
99811692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKGROUP:
99911692Santhony.gutierrez@amd.com                    setFlag(WorkgroupScope);
100011692Santhony.gutierrez@amd.com                    break;
100111692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_AGENT:
100211692Santhony.gutierrez@amd.com                    setFlag(DeviceScope);
100311692Santhony.gutierrez@amd.com                    break;
100411692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_SYSTEM:
100511692Santhony.gutierrez@amd.com                    setFlag(SystemScope);
100611692Santhony.gutierrez@amd.com                    break;
100711692Santhony.gutierrez@amd.com                  default:
100811692Santhony.gutierrez@amd.com                    fatal("MemFence has bad global scope type\n");
100911692Santhony.gutierrez@amd.com                }
101011308Santhony.gutierrez@amd.com            } else if (memFenceScopeSegGroup != Brig::BRIG_MEMORY_SCOPE_NONE) {
101111692Santhony.gutierrez@amd.com                setFlag(GPUStaticInst::GroupSegment);
101211692Santhony.gutierrez@amd.com
101311692Santhony.gutierrez@amd.com                switch (memFenceScopeSegGroup) {
101411692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_NONE:
101511692Santhony.gutierrez@amd.com                    setFlag(NoScope);
101611692Santhony.gutierrez@amd.com                    break;
101711692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKITEM:
101811692Santhony.gutierrez@amd.com                    setFlag(WorkitemScope);
101911692Santhony.gutierrez@amd.com                    break;
102011692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKGROUP:
102111692Santhony.gutierrez@amd.com                    setFlag(WorkgroupScope);
102211692Santhony.gutierrez@amd.com                    break;
102311692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_AGENT:
102411692Santhony.gutierrez@amd.com                    setFlag(DeviceScope);
102511692Santhony.gutierrez@amd.com                    break;
102611692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_SYSTEM:
102711692Santhony.gutierrez@amd.com                    setFlag(SystemScope);
102811692Santhony.gutierrez@amd.com                    break;
102911692Santhony.gutierrez@amd.com                  default:
103011692Santhony.gutierrez@amd.com                    fatal("MemFence has bad group scope type\n");
103111692Santhony.gutierrez@amd.com                }
103211308Santhony.gutierrez@amd.com            } else {
103311308Santhony.gutierrez@amd.com                fatal("MemFence constructor: bad scope specifiers\n");
103411308Santhony.gutierrez@amd.com            }
103511308Santhony.gutierrez@amd.com        }
103611308Santhony.gutierrez@amd.com
103711308Santhony.gutierrez@amd.com        void
103811308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst)
103911308Santhony.gutierrez@amd.com        {
104011308Santhony.gutierrez@amd.com            Wavefront *wave = gpuDynInst->wavefront();
104111308Santhony.gutierrez@amd.com            wave->computeUnit->injectGlobalMemFence(gpuDynInst);
104211308Santhony.gutierrez@amd.com        }
104311308Santhony.gutierrez@amd.com
104411308Santhony.gutierrez@amd.com        void
104511308Santhony.gutierrez@amd.com        execute(GPUDynInstPtr gpuDynInst)
104611308Santhony.gutierrez@amd.com        {
104711308Santhony.gutierrez@amd.com            Wavefront *w = gpuDynInst->wavefront();
104811308Santhony.gutierrez@amd.com            // 2 cases:
104911308Santhony.gutierrez@amd.com            //   * memfence to a sequentially consistent memory (e.g., LDS).
105011308Santhony.gutierrez@amd.com            //     These can be handled as no-ops.
105111308Santhony.gutierrez@amd.com            //   * memfence to a relaxed consistency cache (e.g., Hermes, Viper,
105211308Santhony.gutierrez@amd.com            //     etc.). We send a packet, tagged with the memory order and
105311308Santhony.gutierrez@amd.com            //     scope, and let the GPU coalescer handle it.
105411308Santhony.gutierrez@amd.com
105511692Santhony.gutierrez@amd.com            if (isGlobalSeg()) {
105611308Santhony.gutierrez@amd.com                gpuDynInst->simdId = w->simdId;
105711308Santhony.gutierrez@amd.com                gpuDynInst->wfSlotId = w->wfSlotId;
105811308Santhony.gutierrez@amd.com                gpuDynInst->wfDynId = w->wfDynId;
105911639Salexandru.dutu@amd.com                gpuDynInst->kern_id = w->kernId;
106011308Santhony.gutierrez@amd.com                gpuDynInst->cu_id = w->computeUnit->cu_id;
106111308Santhony.gutierrez@amd.com
106211308Santhony.gutierrez@amd.com                gpuDynInst->useContinuation = false;
106311308Santhony.gutierrez@amd.com                GlobalMemPipeline* gmp = &(w->computeUnit->globalMemoryPipe);
106411308Santhony.gutierrez@amd.com                gmp->getGMReqFIFO().push(gpuDynInst);
106511308Santhony.gutierrez@amd.com
106611639Salexandru.dutu@amd.com                w->wrGmReqsInPipe--;
106711639Salexandru.dutu@amd.com                w->rdGmReqsInPipe--;
106811639Salexandru.dutu@amd.com                w->memReqsInPipe--;
106911639Salexandru.dutu@amd.com                w->outstandingReqs++;
107011692Santhony.gutierrez@amd.com            } else if (isGroupSeg()) {
107111308Santhony.gutierrez@amd.com                // no-op
107211308Santhony.gutierrez@amd.com            } else {
107311692Santhony.gutierrez@amd.com                fatal("MemFence execute: bad op type\n");
107411308Santhony.gutierrez@amd.com            }
107511308Santhony.gutierrez@amd.com        }
107611308Santhony.gutierrez@amd.com    };
107711308Santhony.gutierrez@amd.com
107811308Santhony.gutierrez@amd.com    class Call : public HsailGPUStaticInst
107911308Santhony.gutierrez@amd.com    {
108011308Santhony.gutierrez@amd.com      public:
108111308Santhony.gutierrez@amd.com        // private helper functions
108211308Santhony.gutierrez@amd.com        void calcAddr(Wavefront* w, GPUDynInstPtr m);
108311308Santhony.gutierrez@amd.com
108411308Santhony.gutierrez@amd.com        void
108511308Santhony.gutierrez@amd.com        generateDisassembly()
108611308Santhony.gutierrez@amd.com        {
108711308Santhony.gutierrez@amd.com            if (dest.disassemble() == "") {
108811308Santhony.gutierrez@amd.com                disassembly = csprintf("%s %s (%s)", opcode, src0.disassemble(),
108911308Santhony.gutierrez@amd.com                                       src1.disassemble());
109011308Santhony.gutierrez@amd.com            } else {
109111308Santhony.gutierrez@amd.com                disassembly = csprintf("%s %s (%s) (%s)", opcode,
109211308Santhony.gutierrez@amd.com                                       src0.disassemble(), dest.disassemble(),
109311308Santhony.gutierrez@amd.com                                       src1.disassemble());
109411308Santhony.gutierrez@amd.com            }
109511308Santhony.gutierrez@amd.com        }
109611308Santhony.gutierrez@amd.com
109711308Santhony.gutierrez@amd.com        bool
109811308Santhony.gutierrez@amd.com        isPseudoOp()
109911308Santhony.gutierrez@amd.com        {
110011308Santhony.gutierrez@amd.com            std::string func_name = src0.disassemble();
110111308Santhony.gutierrez@amd.com            if (func_name.find("__gem5_hsail_op") != std::string::npos) {
110211308Santhony.gutierrez@amd.com                return true;
110311308Santhony.gutierrez@amd.com            }
110411308Santhony.gutierrez@amd.com            return false;
110511308Santhony.gutierrez@amd.com        }
110611308Santhony.gutierrez@amd.com
110711308Santhony.gutierrez@amd.com        // member variables
110811308Santhony.gutierrez@amd.com        ListOperand dest;
110911308Santhony.gutierrez@amd.com        FunctionRefOperand src0;
111011308Santhony.gutierrez@amd.com        ListOperand src1;
111111308Santhony.gutierrez@amd.com        HsailCode *func_ptr;
111211308Santhony.gutierrez@amd.com
111311308Santhony.gutierrez@amd.com        // exec function for pseudo instructions mapped on top of call opcode
111411308Santhony.gutierrez@amd.com        void execPseudoInst(Wavefront *w, GPUDynInstPtr gpuDynInst);
111511308Santhony.gutierrez@amd.com
111611308Santhony.gutierrez@amd.com        // user-defined pseudo instructions
111711308Santhony.gutierrez@amd.com        void MagicPrintLane(Wavefront *w);
111811308Santhony.gutierrez@amd.com        void MagicPrintLane64(Wavefront *w);
111911308Santhony.gutierrez@amd.com        void MagicPrintWF32(Wavefront *w);
112011308Santhony.gutierrez@amd.com        void MagicPrintWF64(Wavefront *w);
112111308Santhony.gutierrez@amd.com        void MagicPrintWFFloat(Wavefront *w);
112211308Santhony.gutierrez@amd.com        void MagicSimBreak(Wavefront *w);
112311308Santhony.gutierrez@amd.com        void MagicPrefixSum(Wavefront *w);
112411308Santhony.gutierrez@amd.com        void MagicReduction(Wavefront *w);
112511308Santhony.gutierrez@amd.com        void MagicMaskLower(Wavefront *w);
112611308Santhony.gutierrez@amd.com        void MagicMaskUpper(Wavefront *w);
112711308Santhony.gutierrez@amd.com        void MagicJoinWFBar(Wavefront *w);
112811308Santhony.gutierrez@amd.com        void MagicWaitWFBar(Wavefront *w);
112911308Santhony.gutierrez@amd.com        void MagicPanic(Wavefront *w);
113011308Santhony.gutierrez@amd.com
113111308Santhony.gutierrez@amd.com        void MagicAtomicNRAddGlobalU32Reg(Wavefront *w,
113211308Santhony.gutierrez@amd.com                                          GPUDynInstPtr gpuDynInst);
113311308Santhony.gutierrez@amd.com
113411308Santhony.gutierrez@amd.com        void MagicAtomicNRAddGroupU32Reg(Wavefront *w,
113511308Santhony.gutierrez@amd.com                                         GPUDynInstPtr gpuDynInst);
113611308Santhony.gutierrez@amd.com
113711308Santhony.gutierrez@amd.com        void MagicLoadGlobalU32Reg(Wavefront *w, GPUDynInstPtr gpuDynInst);
113811308Santhony.gutierrez@amd.com
113911308Santhony.gutierrez@amd.com        void MagicXactCasLd(Wavefront *w);
114011308Santhony.gutierrez@amd.com        void MagicMostSigThread(Wavefront *w);
114111308Santhony.gutierrez@amd.com        void MagicMostSigBroadcast(Wavefront *w);
114211308Santhony.gutierrez@amd.com
114311308Santhony.gutierrez@amd.com        void MagicPrintWF32ID(Wavefront *w);
114411308Santhony.gutierrez@amd.com        void MagicPrintWFID64(Wavefront *w);
114511308Santhony.gutierrez@amd.com
114611308Santhony.gutierrez@amd.com        Call(const Brig::BrigInstBase *ib, const BrigObject *obj)
114711308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, "call")
114811308Santhony.gutierrez@amd.com        {
114911692Santhony.gutierrez@amd.com            setFlag(ALU);
115011308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
115111308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
115211308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
115311308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
115411308Santhony.gutierrez@amd.com
115511308Santhony.gutierrez@amd.com            func_ptr = nullptr;
115611308Santhony.gutierrez@amd.com            std::string func_name = src0.disassemble();
115711308Santhony.gutierrez@amd.com            if (!isPseudoOp()) {
115811308Santhony.gutierrez@amd.com                func_ptr = dynamic_cast<HsailCode*>(obj->
115911308Santhony.gutierrez@amd.com                                                    getFunction(func_name));
116011308Santhony.gutierrez@amd.com
116111308Santhony.gutierrez@amd.com                if (!func_ptr)
116211308Santhony.gutierrez@amd.com                    fatal("call::exec cannot find function: %s\n", func_name);
116311308Santhony.gutierrez@amd.com            }
116411308Santhony.gutierrez@amd.com
116511308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 2);
116611308Santhony.gutierrez@amd.com            src1.init(op_offs, obj);
116711308Santhony.gutierrez@amd.com        }
116811308Santhony.gutierrez@amd.com
116911308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) { return false; }
117011308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) { return false; }
117111308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) { return false; }
117211308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
117311308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return false; }
117411308Santhony.gutierrez@amd.com        int  getOperandSize(int operandIndex) { return 0; }
117511308Santhony.gutierrez@amd.com        int  getRegisterIndex(int operandIndex) { return -1; }
117611308Santhony.gutierrez@amd.com
117711308Santhony.gutierrez@amd.com        void
117811308Santhony.gutierrez@amd.com        execute(GPUDynInstPtr gpuDynInst)
117911308Santhony.gutierrez@amd.com        {
118011308Santhony.gutierrez@amd.com            Wavefront *w = gpuDynInst->wavefront();
118111308Santhony.gutierrez@amd.com
118211308Santhony.gutierrez@amd.com            std::string func_name = src0.disassemble();
118311308Santhony.gutierrez@amd.com            if (isPseudoOp()) {
118411308Santhony.gutierrez@amd.com                execPseudoInst(w, gpuDynInst);
118511308Santhony.gutierrez@amd.com            } else {
118611308Santhony.gutierrez@amd.com                fatal("Native HSAIL functions are not yet implemented: %s\n",
118711308Santhony.gutierrez@amd.com                      func_name);
118811308Santhony.gutierrez@amd.com            }
118911308Santhony.gutierrez@amd.com        }
119011308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
119111308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
119211308Santhony.gutierrez@amd.com        int getNumOperands() { return 2; }
119311308Santhony.gutierrez@amd.com    };
119411308Santhony.gutierrez@amd.com
119511308Santhony.gutierrez@amd.com    template<typename T> T heynot(T arg) { return ~arg; }
119611308Santhony.gutierrez@amd.com    template<> inline bool heynot<bool>(bool arg) { return !arg; }
119711308Santhony.gutierrez@amd.com} // namespace HsailISA
119811308Santhony.gutierrez@amd.com
119911308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_DECL_HH__
1200