decl.hh revision 11700
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        }
18111699Santhony.gutierrez@amd.com        int
18211699Santhony.gutierrez@amd.com        getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst)
18311699Santhony.gutierrez@amd.com        {
18411308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
18511308Santhony.gutierrez@amd.com
18611308Santhony.gutierrez@amd.com            if (operandIndex < NumSrcOperands)
18711308Santhony.gutierrez@amd.com                return src[operandIndex].regIndex();
18811308Santhony.gutierrez@amd.com            else
18911308Santhony.gutierrez@amd.com                return dest.regIndex();
19011308Santhony.gutierrez@amd.com        }
19111308Santhony.gutierrez@amd.com        int numSrcRegOperands() {
19211308Santhony.gutierrez@amd.com            int operands = 0;
19311308Santhony.gutierrez@amd.com            for (int i = 0; i < NumSrcOperands; i++) {
19411325Ssteve.reinhardt@amd.com                if (src[i].isVectorRegister()) {
19511308Santhony.gutierrez@amd.com                    operands++;
19611308Santhony.gutierrez@amd.com                }
19711308Santhony.gutierrez@amd.com            }
19811308Santhony.gutierrez@amd.com            return operands;
19911308Santhony.gutierrez@amd.com        }
20011308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
20111308Santhony.gutierrez@amd.com        int getNumOperands() { return NumSrcOperands + 1; }
20211308Santhony.gutierrez@amd.com    };
20311308Santhony.gutierrez@amd.com
20411308Santhony.gutierrez@amd.com    template<typename DataType, int NumSrcOperands>
20511308Santhony.gutierrez@amd.com    class ArithInst : public CommonInstBase<typename DataType::OperandType,
20611308Santhony.gutierrez@amd.com                                            typename DataType::OperandType,
20711308Santhony.gutierrez@amd.com                                            NumSrcOperands>
20811308Santhony.gutierrez@amd.com    {
20911308Santhony.gutierrez@amd.com      public:
21011308Santhony.gutierrez@amd.com        std::string opcode_suffix() { return csprintf("_%s", DataType::label); }
21111308Santhony.gutierrez@amd.com
21211308Santhony.gutierrez@amd.com        ArithInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
21311308Santhony.gutierrez@amd.com                  const char *opcode)
21411308Santhony.gutierrez@amd.com            : CommonInstBase<typename DataType::OperandType,
21511308Santhony.gutierrez@amd.com                             typename DataType::OperandType,
21611308Santhony.gutierrez@amd.com                             NumSrcOperands>(ib, obj, opcode)
21711308Santhony.gutierrez@amd.com        {
21811308Santhony.gutierrez@amd.com        }
21911308Santhony.gutierrez@amd.com    };
22011308Santhony.gutierrez@amd.com
22111308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename Src0OperandType,
22211308Santhony.gutierrez@amd.com             typename Src1OperandType, typename Src2OperandType>
22311308Santhony.gutierrez@amd.com    class ThreeNonUniformSourceInstBase : public HsailGPUStaticInst
22411308Santhony.gutierrez@amd.com    {
22511308Santhony.gutierrez@amd.com      protected:
22611308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
22711308Santhony.gutierrez@amd.com        typename Src0OperandType::SrcOperand  src0;
22811308Santhony.gutierrez@amd.com        typename Src1OperandType::SrcOperand  src1;
22911308Santhony.gutierrez@amd.com        typename Src2OperandType::SrcOperand  src2;
23011308Santhony.gutierrez@amd.com
23111308Santhony.gutierrez@amd.com        void
23211308Santhony.gutierrez@amd.com        generateDisassembly()
23311308Santhony.gutierrez@amd.com        {
23411308Santhony.gutierrez@amd.com            disassembly = csprintf("%s %s,%s,%s,%s", opcode, dest.disassemble(),
23511308Santhony.gutierrez@amd.com                                   src0.disassemble(), src1.disassemble(),
23611308Santhony.gutierrez@amd.com                                   src2.disassemble());
23711308Santhony.gutierrez@amd.com        }
23811308Santhony.gutierrez@amd.com
23911308Santhony.gutierrez@amd.com      public:
24011308Santhony.gutierrez@amd.com        ThreeNonUniformSourceInstBase(const Brig::BrigInstBase *ib,
24111308Santhony.gutierrez@amd.com                                      const BrigObject *obj,
24211308Santhony.gutierrez@amd.com                                      const char *opcode)
24311308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, opcode)
24411308Santhony.gutierrez@amd.com        {
24511692Santhony.gutierrez@amd.com            setFlag(ALU);
24611692Santhony.gutierrez@amd.com
24711308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
24811308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
24911308Santhony.gutierrez@amd.com
25011308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
25111308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
25211308Santhony.gutierrez@amd.com
25311308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 2);
25411308Santhony.gutierrez@amd.com            src1.init(op_offs, obj);
25511308Santhony.gutierrez@amd.com
25611308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 3);
25711308Santhony.gutierrez@amd.com            src2.init(op_offs, obj);
25811308Santhony.gutierrez@amd.com        }
25911308Santhony.gutierrez@amd.com
26011308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
26111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
26211308Santhony.gutierrez@amd.com            if (!operandIndex)
26311308Santhony.gutierrez@amd.com                return src0.isVectorRegister();
26411308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
26511308Santhony.gutierrez@amd.com                return src1.isVectorRegister();
26611308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
26711308Santhony.gutierrez@amd.com                return src2.isVectorRegister();
26811308Santhony.gutierrez@amd.com            else
26911308Santhony.gutierrez@amd.com                return dest.isVectorRegister();
27011308Santhony.gutierrez@amd.com        }
27111308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
27211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
27311308Santhony.gutierrez@amd.com            if (!operandIndex)
27411308Santhony.gutierrez@amd.com                return src0.isCondRegister();
27511308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
27611308Santhony.gutierrez@amd.com                return src1.isCondRegister();
27711308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
27811308Santhony.gutierrez@amd.com                return src2.isCondRegister();
27911308Santhony.gutierrez@amd.com            else
28011308Santhony.gutierrez@amd.com                return dest.isCondRegister();
28111308Santhony.gutierrez@amd.com        }
28211308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
28311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
28411308Santhony.gutierrez@amd.com            if (!operandIndex)
28511308Santhony.gutierrez@amd.com                return src0.isScalarRegister();
28611308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
28711308Santhony.gutierrez@amd.com                return src1.isScalarRegister();
28811308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
28911308Santhony.gutierrez@amd.com                return src2.isScalarRegister();
29011308Santhony.gutierrez@amd.com            else
29111308Santhony.gutierrez@amd.com                return dest.isScalarRegister();
29211308Santhony.gutierrez@amd.com        }
29311308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) {
29411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
29511308Santhony.gutierrez@amd.com            if (operandIndex < 3)
29611308Santhony.gutierrez@amd.com                return true;
29711308Santhony.gutierrez@amd.com            else
29811308Santhony.gutierrez@amd.com                return false;
29911308Santhony.gutierrez@amd.com        }
30011308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) {
30111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
30211308Santhony.gutierrez@amd.com            if (operandIndex >= 3)
30311308Santhony.gutierrez@amd.com                return true;
30411308Santhony.gutierrez@amd.com            else
30511308Santhony.gutierrez@amd.com                return false;
30611308Santhony.gutierrez@amd.com        }
30711308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
30811308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
30911308Santhony.gutierrez@amd.com            if (!operandIndex)
31011308Santhony.gutierrez@amd.com                return src0.opSize();
31111308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
31211308Santhony.gutierrez@amd.com                return src1.opSize();
31311308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
31411308Santhony.gutierrez@amd.com                return src2.opSize();
31511308Santhony.gutierrez@amd.com            else
31611308Santhony.gutierrez@amd.com                return dest.opSize();
31711308Santhony.gutierrez@amd.com        }
31811699Santhony.gutierrez@amd.com
31911699Santhony.gutierrez@amd.com        int
32011699Santhony.gutierrez@amd.com        getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst)
32111699Santhony.gutierrez@amd.com        {
32211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
32311308Santhony.gutierrez@amd.com            if (!operandIndex)
32411308Santhony.gutierrez@amd.com                return src0.regIndex();
32511308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
32611308Santhony.gutierrez@amd.com                return src1.regIndex();
32711308Santhony.gutierrez@amd.com            else if (operandIndex == 2)
32811308Santhony.gutierrez@amd.com                return src2.regIndex();
32911308Santhony.gutierrez@amd.com            else
33011308Santhony.gutierrez@amd.com                return dest.regIndex();
33111308Santhony.gutierrez@amd.com        }
33211308Santhony.gutierrez@amd.com
33311308Santhony.gutierrez@amd.com        int numSrcRegOperands() {
33411308Santhony.gutierrez@amd.com            int operands = 0;
33511325Ssteve.reinhardt@amd.com            if (src0.isVectorRegister()) {
33611308Santhony.gutierrez@amd.com                operands++;
33711308Santhony.gutierrez@amd.com            }
33811325Ssteve.reinhardt@amd.com            if (src1.isVectorRegister()) {
33911308Santhony.gutierrez@amd.com                operands++;
34011308Santhony.gutierrez@amd.com            }
34111325Ssteve.reinhardt@amd.com            if (src2.isVectorRegister()) {
34211308Santhony.gutierrez@amd.com                operands++;
34311308Santhony.gutierrez@amd.com            }
34411308Santhony.gutierrez@amd.com            return operands;
34511308Santhony.gutierrez@amd.com        }
34611308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
34711308Santhony.gutierrez@amd.com        int getNumOperands() { return 4; }
34811308Santhony.gutierrez@amd.com    };
34911308Santhony.gutierrez@amd.com
35011308Santhony.gutierrez@amd.com    template<typename DestDataType, typename Src0DataType,
35111308Santhony.gutierrez@amd.com             typename Src1DataType, typename Src2DataType>
35211308Santhony.gutierrez@amd.com    class ThreeNonUniformSourceInst :
35311308Santhony.gutierrez@amd.com        public ThreeNonUniformSourceInstBase<typename DestDataType::OperandType,
35411308Santhony.gutierrez@amd.com                                             typename Src0DataType::OperandType,
35511308Santhony.gutierrez@amd.com                                             typename Src1DataType::OperandType,
35611308Santhony.gutierrez@amd.com                                             typename Src2DataType::OperandType>
35711308Santhony.gutierrez@amd.com    {
35811308Santhony.gutierrez@amd.com      public:
35911308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
36011308Santhony.gutierrez@amd.com        typedef typename Src0DataType::CType Src0CType;
36111308Santhony.gutierrez@amd.com        typedef typename Src1DataType::CType Src1CType;
36211308Santhony.gutierrez@amd.com        typedef typename Src2DataType::CType Src2CType;
36311308Santhony.gutierrez@amd.com
36411308Santhony.gutierrez@amd.com        ThreeNonUniformSourceInst(const Brig::BrigInstBase *ib,
36511308Santhony.gutierrez@amd.com                                  const BrigObject *obj, const char *opcode)
36611308Santhony.gutierrez@amd.com            : ThreeNonUniformSourceInstBase<typename DestDataType::OperandType,
36711308Santhony.gutierrez@amd.com                                         typename Src0DataType::OperandType,
36811308Santhony.gutierrez@amd.com                                         typename Src1DataType::OperandType,
36911308Santhony.gutierrez@amd.com                                         typename Src2DataType::OperandType>(ib,
37011308Santhony.gutierrez@amd.com                                                                    obj, opcode)
37111308Santhony.gutierrez@amd.com        {
37211308Santhony.gutierrez@amd.com        }
37311308Santhony.gutierrez@amd.com    };
37411308Santhony.gutierrez@amd.com
37511308Santhony.gutierrez@amd.com    template<typename DataType>
37611308Santhony.gutierrez@amd.com    class CmovInst : public ThreeNonUniformSourceInst<DataType, B1,
37711308Santhony.gutierrez@amd.com                                                      DataType, DataType>
37811308Santhony.gutierrez@amd.com    {
37911308Santhony.gutierrez@amd.com      public:
38011308Santhony.gutierrez@amd.com        CmovInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
38111308Santhony.gutierrez@amd.com                 const char *opcode)
38211308Santhony.gutierrez@amd.com            : ThreeNonUniformSourceInst<DataType, B1, DataType,
38311308Santhony.gutierrez@amd.com                                        DataType>(ib, obj, opcode)
38411308Santhony.gutierrez@amd.com        {
38511308Santhony.gutierrez@amd.com        }
38611308Santhony.gutierrez@amd.com    };
38711308Santhony.gutierrez@amd.com
38811308Santhony.gutierrez@amd.com    template<typename DataType>
38911308Santhony.gutierrez@amd.com    class ExtractInsertInst : public ThreeNonUniformSourceInst<DataType,
39011308Santhony.gutierrez@amd.com                                                               DataType, U32,
39111308Santhony.gutierrez@amd.com                                                               U32>
39211308Santhony.gutierrez@amd.com    {
39311308Santhony.gutierrez@amd.com      public:
39411308Santhony.gutierrez@amd.com        ExtractInsertInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
39511308Santhony.gutierrez@amd.com                          const char *opcode)
39611308Santhony.gutierrez@amd.com            : ThreeNonUniformSourceInst<DataType, DataType, U32,
39711308Santhony.gutierrez@amd.com                                        U32>(ib, obj, opcode)
39811308Santhony.gutierrez@amd.com        {
39911308Santhony.gutierrez@amd.com        }
40011308Santhony.gutierrez@amd.com    };
40111308Santhony.gutierrez@amd.com
40211308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename Src0OperandType,
40311308Santhony.gutierrez@amd.com             typename Src1OperandType>
40411308Santhony.gutierrez@amd.com    class TwoNonUniformSourceInstBase : public HsailGPUStaticInst
40511308Santhony.gutierrez@amd.com    {
40611308Santhony.gutierrez@amd.com      protected:
40711308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
40811308Santhony.gutierrez@amd.com        typename Src0OperandType::SrcOperand src0;
40911308Santhony.gutierrez@amd.com        typename Src1OperandType::SrcOperand src1;
41011308Santhony.gutierrez@amd.com
41111308Santhony.gutierrez@amd.com        void
41211308Santhony.gutierrez@amd.com        generateDisassembly()
41311308Santhony.gutierrez@amd.com        {
41411308Santhony.gutierrez@amd.com            disassembly = csprintf("%s %s,%s,%s", opcode, dest.disassemble(),
41511308Santhony.gutierrez@amd.com                                   src0.disassemble(), src1.disassemble());
41611308Santhony.gutierrez@amd.com        }
41711308Santhony.gutierrez@amd.com
41811308Santhony.gutierrez@amd.com
41911308Santhony.gutierrez@amd.com      public:
42011308Santhony.gutierrez@amd.com        TwoNonUniformSourceInstBase(const Brig::BrigInstBase *ib,
42111308Santhony.gutierrez@amd.com                                    const BrigObject *obj, const char *opcode)
42211308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, opcode)
42311308Santhony.gutierrez@amd.com        {
42411692Santhony.gutierrez@amd.com            setFlag(ALU);
42511692Santhony.gutierrez@amd.com
42611308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
42711308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
42811308Santhony.gutierrez@amd.com
42911308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
43011308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
43111308Santhony.gutierrez@amd.com
43211308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 2);
43311308Santhony.gutierrez@amd.com            src1.init(op_offs, obj);
43411308Santhony.gutierrez@amd.com        }
43511308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
43611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
43711308Santhony.gutierrez@amd.com            if (!operandIndex)
43811308Santhony.gutierrez@amd.com                return src0.isVectorRegister();
43911308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
44011308Santhony.gutierrez@amd.com                return src1.isVectorRegister();
44111308Santhony.gutierrez@amd.com            else
44211308Santhony.gutierrez@amd.com                return dest.isVectorRegister();
44311308Santhony.gutierrez@amd.com        }
44411308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
44511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
44611308Santhony.gutierrez@amd.com            if (!operandIndex)
44711308Santhony.gutierrez@amd.com                return src0.isCondRegister();
44811308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
44911308Santhony.gutierrez@amd.com                return src1.isCondRegister();
45011308Santhony.gutierrez@amd.com            else
45111308Santhony.gutierrez@amd.com                return dest.isCondRegister();
45211308Santhony.gutierrez@amd.com        }
45311308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
45411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
45511308Santhony.gutierrez@amd.com            if (!operandIndex)
45611308Santhony.gutierrez@amd.com                return src0.isScalarRegister();
45711308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
45811308Santhony.gutierrez@amd.com                return src1.isScalarRegister();
45911308Santhony.gutierrez@amd.com            else
46011308Santhony.gutierrez@amd.com                return dest.isScalarRegister();
46111308Santhony.gutierrez@amd.com        }
46211308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) {
46311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
46411308Santhony.gutierrez@amd.com            if (operandIndex < 2)
46511308Santhony.gutierrez@amd.com                return true;
46611308Santhony.gutierrez@amd.com            else
46711308Santhony.gutierrez@amd.com                return false;
46811308Santhony.gutierrez@amd.com        }
46911308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) {
47011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
47111308Santhony.gutierrez@amd.com            if (operandIndex >= 2)
47211308Santhony.gutierrez@amd.com                return true;
47311308Santhony.gutierrez@amd.com            else
47411308Santhony.gutierrez@amd.com                return false;
47511308Santhony.gutierrez@amd.com        }
47611308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
47711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
47811308Santhony.gutierrez@amd.com            if (!operandIndex)
47911308Santhony.gutierrez@amd.com                return src0.opSize();
48011308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
48111308Santhony.gutierrez@amd.com                return src1.opSize();
48211308Santhony.gutierrez@amd.com            else
48311308Santhony.gutierrez@amd.com                return dest.opSize();
48411308Santhony.gutierrez@amd.com        }
48511699Santhony.gutierrez@amd.com
48611699Santhony.gutierrez@amd.com        int
48711699Santhony.gutierrez@amd.com        getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst)
48811699Santhony.gutierrez@amd.com        {
48911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
49011308Santhony.gutierrez@amd.com            if (!operandIndex)
49111308Santhony.gutierrez@amd.com                return src0.regIndex();
49211308Santhony.gutierrez@amd.com            else if (operandIndex == 1)
49311308Santhony.gutierrez@amd.com                return src1.regIndex();
49411308Santhony.gutierrez@amd.com            else
49511308Santhony.gutierrez@amd.com                return dest.regIndex();
49611308Santhony.gutierrez@amd.com        }
49711308Santhony.gutierrez@amd.com
49811308Santhony.gutierrez@amd.com        int numSrcRegOperands() {
49911308Santhony.gutierrez@amd.com            int operands = 0;
50011325Ssteve.reinhardt@amd.com            if (src0.isVectorRegister()) {
50111308Santhony.gutierrez@amd.com                operands++;
50211308Santhony.gutierrez@amd.com            }
50311325Ssteve.reinhardt@amd.com            if (src1.isVectorRegister()) {
50411308Santhony.gutierrez@amd.com                operands++;
50511308Santhony.gutierrez@amd.com            }
50611308Santhony.gutierrez@amd.com            return operands;
50711308Santhony.gutierrez@amd.com        }
50811308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
50911308Santhony.gutierrez@amd.com        int getNumOperands() { return 3; }
51011308Santhony.gutierrez@amd.com    };
51111308Santhony.gutierrez@amd.com
51211308Santhony.gutierrez@amd.com    template<typename DestDataType, typename Src0DataType,
51311308Santhony.gutierrez@amd.com             typename Src1DataType>
51411308Santhony.gutierrez@amd.com    class TwoNonUniformSourceInst :
51511308Santhony.gutierrez@amd.com        public TwoNonUniformSourceInstBase<typename DestDataType::OperandType,
51611308Santhony.gutierrez@amd.com                                           typename Src0DataType::OperandType,
51711308Santhony.gutierrez@amd.com                                           typename Src1DataType::OperandType>
51811308Santhony.gutierrez@amd.com    {
51911308Santhony.gutierrez@amd.com      public:
52011308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
52111308Santhony.gutierrez@amd.com        typedef typename Src0DataType::CType Src0CType;
52211308Santhony.gutierrez@amd.com        typedef typename Src1DataType::CType Src1CType;
52311308Santhony.gutierrez@amd.com
52411308Santhony.gutierrez@amd.com        TwoNonUniformSourceInst(const Brig::BrigInstBase *ib,
52511308Santhony.gutierrez@amd.com                                const BrigObject *obj, const char *opcode)
52611308Santhony.gutierrez@amd.com            : TwoNonUniformSourceInstBase<typename DestDataType::OperandType,
52711308Santhony.gutierrez@amd.com                                         typename Src0DataType::OperandType,
52811308Santhony.gutierrez@amd.com                                         typename Src1DataType::OperandType>(ib,
52911308Santhony.gutierrez@amd.com                                                                    obj, opcode)
53011308Santhony.gutierrez@amd.com        {
53111308Santhony.gutierrez@amd.com        }
53211308Santhony.gutierrez@amd.com    };
53311308Santhony.gutierrez@amd.com
53411308Santhony.gutierrez@amd.com    // helper function for ClassInst
53511308Santhony.gutierrez@amd.com    template<typename T>
53611308Santhony.gutierrez@amd.com    bool
53711308Santhony.gutierrez@amd.com    fpclassify(T src0, uint32_t src1)
53811308Santhony.gutierrez@amd.com    {
53911308Santhony.gutierrez@amd.com        int fpclass = std::fpclassify(src0);
54011308Santhony.gutierrez@amd.com
54111308Santhony.gutierrez@amd.com        if ((src1 & 0x3) && (fpclass == FP_NAN)) {
54211308Santhony.gutierrez@amd.com            return true;
54311308Santhony.gutierrez@amd.com        }
54411308Santhony.gutierrez@amd.com
54511308Santhony.gutierrez@amd.com        if (src0 <= -0.0) {
54611308Santhony.gutierrez@amd.com            if ((src1 & 0x4) && fpclass == FP_INFINITE)
54711308Santhony.gutierrez@amd.com                return true;
54811308Santhony.gutierrez@amd.com            if ((src1 & 0x8) && fpclass == FP_NORMAL)
54911308Santhony.gutierrez@amd.com                return true;
55011308Santhony.gutierrez@amd.com            if ((src1 & 0x10) && fpclass == FP_SUBNORMAL)
55111308Santhony.gutierrez@amd.com                return true;
55211308Santhony.gutierrez@amd.com            if ((src1 & 0x20) && fpclass == FP_ZERO)
55311308Santhony.gutierrez@amd.com                return true;
55411308Santhony.gutierrez@amd.com        } else {
55511308Santhony.gutierrez@amd.com            if ((src1 & 0x40) && fpclass == FP_ZERO)
55611308Santhony.gutierrez@amd.com                return true;
55711308Santhony.gutierrez@amd.com            if ((src1 & 0x80) && fpclass == FP_SUBNORMAL)
55811308Santhony.gutierrez@amd.com                return true;
55911308Santhony.gutierrez@amd.com            if ((src1 & 0x100) && fpclass == FP_NORMAL)
56011308Santhony.gutierrez@amd.com                return true;
56111308Santhony.gutierrez@amd.com            if ((src1 & 0x200) && fpclass == FP_INFINITE)
56211308Santhony.gutierrez@amd.com                return true;
56311308Santhony.gutierrez@amd.com        }
56411308Santhony.gutierrez@amd.com        return false;
56511308Santhony.gutierrez@amd.com    }
56611308Santhony.gutierrez@amd.com
56711308Santhony.gutierrez@amd.com    template<typename DataType>
56811308Santhony.gutierrez@amd.com    class ClassInst : public TwoNonUniformSourceInst<B1, DataType, U32>
56911308Santhony.gutierrez@amd.com    {
57011308Santhony.gutierrez@amd.com      public:
57111308Santhony.gutierrez@amd.com        ClassInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
57211308Santhony.gutierrez@amd.com                  const char *opcode)
57311308Santhony.gutierrez@amd.com            : TwoNonUniformSourceInst<B1, DataType, U32>(ib, obj, opcode)
57411308Santhony.gutierrez@amd.com        {
57511308Santhony.gutierrez@amd.com        }
57611308Santhony.gutierrez@amd.com    };
57711308Santhony.gutierrez@amd.com
57811308Santhony.gutierrez@amd.com    template<typename DataType>
57911308Santhony.gutierrez@amd.com    class ShiftInst : public TwoNonUniformSourceInst<DataType, DataType, U32>
58011308Santhony.gutierrez@amd.com    {
58111308Santhony.gutierrez@amd.com      public:
58211308Santhony.gutierrez@amd.com        ShiftInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
58311308Santhony.gutierrez@amd.com                  const char *opcode)
58411308Santhony.gutierrez@amd.com            : TwoNonUniformSourceInst<DataType, DataType, U32>(ib, obj, opcode)
58511308Santhony.gutierrez@amd.com        {
58611308Santhony.gutierrez@amd.com        }
58711308Santhony.gutierrez@amd.com    };
58811308Santhony.gutierrez@amd.com
58911308Santhony.gutierrez@amd.com    // helper function for CmpInst
59011308Santhony.gutierrez@amd.com    template<typename T>
59111308Santhony.gutierrez@amd.com    bool
59211308Santhony.gutierrez@amd.com    compare(T src0, T src1, Brig::BrigCompareOperation cmpOp)
59311308Santhony.gutierrez@amd.com    {
59411308Santhony.gutierrez@amd.com        using namespace Brig;
59511308Santhony.gutierrez@amd.com
59611308Santhony.gutierrez@amd.com        switch (cmpOp) {
59711308Santhony.gutierrez@amd.com          case BRIG_COMPARE_EQ:
59811308Santhony.gutierrez@amd.com          case BRIG_COMPARE_EQU:
59911308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SEQ:
60011308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SEQU:
60111308Santhony.gutierrez@amd.com            return (src0 == src1);
60211308Santhony.gutierrez@amd.com
60311308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NE:
60411308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NEU:
60511308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNE:
60611308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNEU:
60711308Santhony.gutierrez@amd.com            return (src0 != src1);
60811308Santhony.gutierrez@amd.com
60911308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LT:
61011308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LTU:
61111308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLT:
61211308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLTU:
61311308Santhony.gutierrez@amd.com            return (src0 < src1);
61411308Santhony.gutierrez@amd.com
61511308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LE:
61611308Santhony.gutierrez@amd.com          case BRIG_COMPARE_LEU:
61711308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLE:
61811308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SLEU:
61911308Santhony.gutierrez@amd.com            return (src0 <= src1);
62011308Santhony.gutierrez@amd.com
62111308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GT:
62211308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GTU:
62311308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGT:
62411308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGTU:
62511308Santhony.gutierrez@amd.com            return (src0 > src1);
62611308Santhony.gutierrez@amd.com
62711308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GE:
62811308Santhony.gutierrez@amd.com          case BRIG_COMPARE_GEU:
62911308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGE:
63011308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SGEU:
63111308Santhony.gutierrez@amd.com            return (src0 >= src1);
63211308Santhony.gutierrez@amd.com
63311308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NUM:
63411308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNUM:
63511308Santhony.gutierrez@amd.com            return (src0 == src0) || (src1 == src1);
63611308Santhony.gutierrez@amd.com
63711308Santhony.gutierrez@amd.com          case BRIG_COMPARE_NAN:
63811308Santhony.gutierrez@amd.com          case BRIG_COMPARE_SNAN:
63911308Santhony.gutierrez@amd.com            return (src0 != src0) || (src1 != src1);
64011308Santhony.gutierrez@amd.com
64111308Santhony.gutierrez@amd.com          default:
64211308Santhony.gutierrez@amd.com            fatal("Bad cmpOp value %d\n", (int)cmpOp);
64311308Santhony.gutierrez@amd.com        }
64411308Santhony.gutierrez@amd.com    }
64511308Santhony.gutierrez@amd.com
64611308Santhony.gutierrez@amd.com    template<typename T>
64711308Santhony.gutierrez@amd.com    int32_t
64811308Santhony.gutierrez@amd.com    firstbit(T src0)
64911308Santhony.gutierrez@amd.com    {
65011308Santhony.gutierrez@amd.com        if (!src0)
65111308Santhony.gutierrez@amd.com            return -1;
65211308Santhony.gutierrez@amd.com
65311308Santhony.gutierrez@amd.com        //handle positive and negative numbers
65411699Santhony.gutierrez@amd.com        T tmp = ((int64_t)src0 < 0) ? (~src0) : (src0);
65511308Santhony.gutierrez@amd.com
65611308Santhony.gutierrez@amd.com        //the starting pos is MSB
65711308Santhony.gutierrez@amd.com        int pos = 8 * sizeof(T) - 1;
65811308Santhony.gutierrez@amd.com        int cnt = 0;
65911308Santhony.gutierrez@amd.com
66011308Santhony.gutierrez@amd.com        //search the first bit set to 1
66111308Santhony.gutierrez@amd.com        while (!(tmp & (1 << pos))) {
66211308Santhony.gutierrez@amd.com            ++cnt;
66311308Santhony.gutierrez@amd.com            --pos;
66411308Santhony.gutierrez@amd.com        }
66511308Santhony.gutierrez@amd.com        return cnt;
66611308Santhony.gutierrez@amd.com    }
66711308Santhony.gutierrez@amd.com
66811308Santhony.gutierrez@amd.com    const char* cmpOpToString(Brig::BrigCompareOperation cmpOp);
66911308Santhony.gutierrez@amd.com
67011308Santhony.gutierrez@amd.com    template<typename DestOperandType, typename SrcOperandType>
67111308Santhony.gutierrez@amd.com    class CmpInstBase : public CommonInstBase<DestOperandType, SrcOperandType,
67211308Santhony.gutierrez@amd.com                                              2>
67311308Santhony.gutierrez@amd.com    {
67411308Santhony.gutierrez@amd.com      protected:
67511308Santhony.gutierrez@amd.com        Brig::BrigCompareOperation cmpOp;
67611308Santhony.gutierrez@amd.com
67711308Santhony.gutierrez@amd.com      public:
67811308Santhony.gutierrez@amd.com        CmpInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj,
67911308Santhony.gutierrez@amd.com                    const char *_opcode)
68011308Santhony.gutierrez@amd.com            : CommonInstBase<DestOperandType, SrcOperandType, 2>(ib, obj,
68111308Santhony.gutierrez@amd.com                                                                 _opcode)
68211308Santhony.gutierrez@amd.com        {
68311308Santhony.gutierrez@amd.com            assert(ib->base.kind == Brig::BRIG_KIND_INST_CMP);
68411308Santhony.gutierrez@amd.com            Brig::BrigInstCmp *i = (Brig::BrigInstCmp*)ib;
68511308Santhony.gutierrez@amd.com            cmpOp = (Brig::BrigCompareOperation)i->compare;
68611308Santhony.gutierrez@amd.com        }
68711308Santhony.gutierrez@amd.com    };
68811308Santhony.gutierrez@amd.com
68911308Santhony.gutierrez@amd.com    template<typename DestDataType, typename SrcDataType>
69011308Santhony.gutierrez@amd.com    class CmpInst : public CmpInstBase<typename DestDataType::OperandType,
69111308Santhony.gutierrez@amd.com                                       typename SrcDataType::OperandType>
69211308Santhony.gutierrez@amd.com    {
69311308Santhony.gutierrez@amd.com      public:
69411308Santhony.gutierrez@amd.com        std::string
69511308Santhony.gutierrez@amd.com        opcode_suffix()
69611308Santhony.gutierrez@amd.com        {
69711308Santhony.gutierrez@amd.com            return csprintf("_%s_%s_%s", cmpOpToString(this->cmpOp),
69811308Santhony.gutierrez@amd.com                            DestDataType::label, SrcDataType::label);
69911308Santhony.gutierrez@amd.com        }
70011308Santhony.gutierrez@amd.com
70111308Santhony.gutierrez@amd.com        CmpInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
70211308Santhony.gutierrez@amd.com                const char *_opcode)
70311308Santhony.gutierrez@amd.com            : CmpInstBase<typename DestDataType::OperandType,
70411308Santhony.gutierrez@amd.com                          typename SrcDataType::OperandType>(ib, obj, _opcode)
70511308Santhony.gutierrez@amd.com        {
70611308Santhony.gutierrez@amd.com        }
70711308Santhony.gutierrez@amd.com    };
70811308Santhony.gutierrez@amd.com
70911308Santhony.gutierrez@amd.com    template<typename DestDataType, typename SrcDataType>
71011308Santhony.gutierrez@amd.com    class CvtInst : public CommonInstBase<typename DestDataType::OperandType,
71111308Santhony.gutierrez@amd.com                                          typename SrcDataType::OperandType, 1>
71211308Santhony.gutierrez@amd.com    {
71311308Santhony.gutierrez@amd.com      public:
71411308Santhony.gutierrez@amd.com        std::string opcode_suffix()
71511308Santhony.gutierrez@amd.com        {
71611308Santhony.gutierrez@amd.com            return csprintf("_%s_%s", DestDataType::label, SrcDataType::label);
71711308Santhony.gutierrez@amd.com        }
71811308Santhony.gutierrez@amd.com
71911308Santhony.gutierrez@amd.com        CvtInst(const Brig::BrigInstBase *ib, const BrigObject *obj,
72011308Santhony.gutierrez@amd.com                const char *_opcode)
72111308Santhony.gutierrez@amd.com            : CommonInstBase<typename DestDataType::OperandType,
72211308Santhony.gutierrez@amd.com                             typename SrcDataType::OperandType,
72311308Santhony.gutierrez@amd.com                             1>(ib, obj, _opcode)
72411308Santhony.gutierrez@amd.com        {
72511308Santhony.gutierrez@amd.com        }
72611308Santhony.gutierrez@amd.com    };
72711308Santhony.gutierrez@amd.com
72811308Santhony.gutierrez@amd.com    class SpecialInstNoSrcNoDest : public HsailGPUStaticInst
72911308Santhony.gutierrez@amd.com    {
73011308Santhony.gutierrez@amd.com      public:
73111308Santhony.gutierrez@amd.com        SpecialInstNoSrcNoDest(const Brig::BrigInstBase *ib,
73211308Santhony.gutierrez@amd.com                               const BrigObject *obj, const char *_opcode)
73311308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, _opcode)
73411308Santhony.gutierrez@amd.com        {
73511308Santhony.gutierrez@amd.com        }
73611308Santhony.gutierrez@amd.com
73711308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) { return false; }
73811308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) { return false; }
73911308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) { return false; }
74011308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
74111308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return false; }
74211308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) { return 0; }
74311699Santhony.gutierrez@amd.com
74411699Santhony.gutierrez@amd.com        int
74511699Santhony.gutierrez@amd.com        getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst)
74611699Santhony.gutierrez@amd.com        {
74711699Santhony.gutierrez@amd.com            return -1;
74811699Santhony.gutierrez@amd.com        }
74911308Santhony.gutierrez@amd.com
75011308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
75111308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
75211308Santhony.gutierrez@amd.com        int getNumOperands() { return 0; }
75311308Santhony.gutierrez@amd.com    };
75411308Santhony.gutierrez@amd.com
75511308Santhony.gutierrez@amd.com    template<typename DestOperandType>
75611308Santhony.gutierrez@amd.com    class SpecialInstNoSrcBase : public HsailGPUStaticInst
75711308Santhony.gutierrez@amd.com    {
75811308Santhony.gutierrez@amd.com      protected:
75911308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
76011308Santhony.gutierrez@amd.com
76111308Santhony.gutierrez@amd.com        void generateDisassembly()
76211308Santhony.gutierrez@amd.com        {
76311308Santhony.gutierrez@amd.com            disassembly = csprintf("%s %s", opcode, dest.disassemble());
76411308Santhony.gutierrez@amd.com        }
76511308Santhony.gutierrez@amd.com
76611308Santhony.gutierrez@amd.com      public:
76711308Santhony.gutierrez@amd.com        SpecialInstNoSrcBase(const Brig::BrigInstBase *ib,
76811308Santhony.gutierrez@amd.com                             const BrigObject *obj, const char *_opcode)
76911308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, _opcode)
77011308Santhony.gutierrez@amd.com        {
77111308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
77211308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
77311308Santhony.gutierrez@amd.com        }
77411308Santhony.gutierrez@amd.com
77511308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
77611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
77711308Santhony.gutierrez@amd.com            return dest.isVectorRegister();
77811308Santhony.gutierrez@amd.com        }
77911308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
78011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
78111308Santhony.gutierrez@amd.com            return dest.isCondRegister();
78211308Santhony.gutierrez@amd.com        }
78311308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
78411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
78511308Santhony.gutierrez@amd.com            return dest.isScalarRegister();
78611308Santhony.gutierrez@amd.com        }
78711308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
78811308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return true; }
78911308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
79011308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
79111308Santhony.gutierrez@amd.com            return dest.opSize();
79211308Santhony.gutierrez@amd.com        }
79311699Santhony.gutierrez@amd.com
79411699Santhony.gutierrez@amd.com        int
79511699Santhony.gutierrez@amd.com        getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst)
79611699Santhony.gutierrez@amd.com        {
79711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
79811308Santhony.gutierrez@amd.com            return dest.regIndex();
79911308Santhony.gutierrez@amd.com        }
80011699Santhony.gutierrez@amd.com
80111308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
80211308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
80311308Santhony.gutierrez@amd.com        int getNumOperands() { return 1; }
80411308Santhony.gutierrez@amd.com    };
80511308Santhony.gutierrez@amd.com
80611308Santhony.gutierrez@amd.com    template<typename DestDataType>
80711308Santhony.gutierrez@amd.com    class SpecialInstNoSrc :
80811308Santhony.gutierrez@amd.com        public SpecialInstNoSrcBase<typename DestDataType::OperandType>
80911308Santhony.gutierrez@amd.com    {
81011308Santhony.gutierrez@amd.com      public:
81111308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
81211308Santhony.gutierrez@amd.com
81311308Santhony.gutierrez@amd.com        SpecialInstNoSrc(const Brig::BrigInstBase *ib, const BrigObject *obj,
81411308Santhony.gutierrez@amd.com                         const char *_opcode)
81511308Santhony.gutierrez@amd.com            : SpecialInstNoSrcBase<typename DestDataType::OperandType>(ib, obj,
81611308Santhony.gutierrez@amd.com                                                                       _opcode)
81711308Santhony.gutierrez@amd.com        {
81811308Santhony.gutierrez@amd.com        }
81911308Santhony.gutierrez@amd.com    };
82011308Santhony.gutierrez@amd.com
82111308Santhony.gutierrez@amd.com    template<typename DestOperandType>
82211308Santhony.gutierrez@amd.com    class SpecialInst1SrcBase : public HsailGPUStaticInst
82311308Santhony.gutierrez@amd.com    {
82411308Santhony.gutierrez@amd.com      protected:
82511308Santhony.gutierrez@amd.com        typedef int SrcCType;  // used in execute() template
82611308Santhony.gutierrez@amd.com
82711308Santhony.gutierrez@amd.com        typename DestOperandType::DestOperand dest;
82811308Santhony.gutierrez@amd.com        ImmOperand<SrcCType> src0;
82911308Santhony.gutierrez@amd.com
83011308Santhony.gutierrez@amd.com        void
83111308Santhony.gutierrez@amd.com        generateDisassembly()
83211308Santhony.gutierrez@amd.com        {
83311308Santhony.gutierrez@amd.com            disassembly = csprintf("%s %s,%s", opcode, dest.disassemble(),
83411308Santhony.gutierrez@amd.com                                   src0.disassemble());
83511308Santhony.gutierrez@amd.com        }
83611308Santhony.gutierrez@amd.com
83711308Santhony.gutierrez@amd.com      public:
83811308Santhony.gutierrez@amd.com        SpecialInst1SrcBase(const Brig::BrigInstBase *ib,
83911308Santhony.gutierrez@amd.com                            const BrigObject *obj, const char *_opcode)
84011308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, _opcode)
84111308Santhony.gutierrez@amd.com        {
84211692Santhony.gutierrez@amd.com            setFlag(ALU);
84311692Santhony.gutierrez@amd.com
84411308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
84511308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
84611308Santhony.gutierrez@amd.com
84711308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
84811308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
84911308Santhony.gutierrez@amd.com        }
85011308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) {
85111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
85211308Santhony.gutierrez@amd.com            return dest.isVectorRegister();
85311308Santhony.gutierrez@amd.com        }
85411308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) {
85511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
85611308Santhony.gutierrez@amd.com            return dest.isCondRegister();
85711308Santhony.gutierrez@amd.com        }
85811308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) {
85911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
86011308Santhony.gutierrez@amd.com            return dest.isScalarRegister();
86111308Santhony.gutierrez@amd.com        }
86211308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
86311308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return true; }
86411308Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) {
86511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
86611308Santhony.gutierrez@amd.com            return dest.opSize();
86711308Santhony.gutierrez@amd.com        }
86811699Santhony.gutierrez@amd.com
86911699Santhony.gutierrez@amd.com        int
87011699Santhony.gutierrez@amd.com        getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst)
87111699Santhony.gutierrez@amd.com        {
87211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
87311308Santhony.gutierrez@amd.com            return dest.regIndex();
87411308Santhony.gutierrez@amd.com        }
87511699Santhony.gutierrez@amd.com
87611308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
87711308Santhony.gutierrez@amd.com        int numDstRegOperands() { return dest.isVectorRegister(); }
87811308Santhony.gutierrez@amd.com        int getNumOperands() { return 1; }
87911308Santhony.gutierrez@amd.com    };
88011308Santhony.gutierrez@amd.com
88111308Santhony.gutierrez@amd.com    template<typename DestDataType>
88211308Santhony.gutierrez@amd.com    class SpecialInst1Src :
88311308Santhony.gutierrez@amd.com        public SpecialInst1SrcBase<typename DestDataType::OperandType>
88411308Santhony.gutierrez@amd.com    {
88511308Santhony.gutierrez@amd.com      public:
88611308Santhony.gutierrez@amd.com        typedef typename DestDataType::CType DestCType;
88711308Santhony.gutierrez@amd.com
88811308Santhony.gutierrez@amd.com        SpecialInst1Src(const Brig::BrigInstBase *ib, const BrigObject *obj,
88911308Santhony.gutierrez@amd.com                        const char *_opcode)
89011308Santhony.gutierrez@amd.com            : SpecialInst1SrcBase<typename DestDataType::OperandType>(ib, obj,
89111308Santhony.gutierrez@amd.com                                                                      _opcode)
89211308Santhony.gutierrez@amd.com        {
89311308Santhony.gutierrez@amd.com        }
89411308Santhony.gutierrez@amd.com    };
89511308Santhony.gutierrez@amd.com
89611308Santhony.gutierrez@amd.com    class Ret : public SpecialInstNoSrcNoDest
89711308Santhony.gutierrez@amd.com    {
89811308Santhony.gutierrez@amd.com      public:
89911308Santhony.gutierrez@amd.com        typedef SpecialInstNoSrcNoDest Base;
90011308Santhony.gutierrez@amd.com
90111308Santhony.gutierrez@amd.com        Ret(const Brig::BrigInstBase *ib, const BrigObject *obj)
90211308Santhony.gutierrez@amd.com           : Base(ib, obj, "ret")
90311308Santhony.gutierrez@amd.com        {
90411692Santhony.gutierrez@amd.com            setFlag(GPUStaticInst::Return);
90511308Santhony.gutierrez@amd.com        }
90611308Santhony.gutierrez@amd.com
90711308Santhony.gutierrez@amd.com        void execute(GPUDynInstPtr gpuDynInst);
90811308Santhony.gutierrez@amd.com    };
90911308Santhony.gutierrez@amd.com
91011308Santhony.gutierrez@amd.com    class Barrier : public SpecialInstNoSrcNoDest
91111308Santhony.gutierrez@amd.com    {
91211308Santhony.gutierrez@amd.com      public:
91311308Santhony.gutierrez@amd.com        typedef SpecialInstNoSrcNoDest Base;
91411308Santhony.gutierrez@amd.com        uint8_t width;
91511308Santhony.gutierrez@amd.com
91611308Santhony.gutierrez@amd.com        Barrier(const Brig::BrigInstBase *ib, const BrigObject *obj)
91711308Santhony.gutierrez@amd.com            : Base(ib, obj, "barrier")
91811308Santhony.gutierrez@amd.com        {
91911692Santhony.gutierrez@amd.com            setFlag(GPUStaticInst::MemBarrier);
92011308Santhony.gutierrez@amd.com            assert(ib->base.kind == Brig::BRIG_KIND_INST_BR);
92111308Santhony.gutierrez@amd.com            width = (uint8_t)((Brig::BrigInstBr*)ib)->width;
92211308Santhony.gutierrez@amd.com        }
92311308Santhony.gutierrez@amd.com
92411308Santhony.gutierrez@amd.com        void execute(GPUDynInstPtr gpuDynInst);
92511308Santhony.gutierrez@amd.com    };
92611308Santhony.gutierrez@amd.com
92711308Santhony.gutierrez@amd.com    class MemFence : public SpecialInstNoSrcNoDest
92811308Santhony.gutierrez@amd.com    {
92911308Santhony.gutierrez@amd.com      public:
93011308Santhony.gutierrez@amd.com        typedef SpecialInstNoSrcNoDest Base;
93111308Santhony.gutierrez@amd.com
93211308Santhony.gutierrez@amd.com        Brig::BrigMemoryOrder memFenceMemOrder;
93311308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memFenceScopeSegGroup;
93411308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memFenceScopeSegGlobal;
93511308Santhony.gutierrez@amd.com        Brig::BrigMemoryScope memFenceScopeSegImage;
93611308Santhony.gutierrez@amd.com
93711308Santhony.gutierrez@amd.com        MemFence(const Brig::BrigInstBase *ib, const BrigObject *obj)
93811308Santhony.gutierrez@amd.com            : Base(ib, obj, "memfence")
93911308Santhony.gutierrez@amd.com        {
94011308Santhony.gutierrez@amd.com            assert(ib->base.kind == Brig::BRIG_KIND_INST_MEM_FENCE);
94111308Santhony.gutierrez@amd.com
94211308Santhony.gutierrez@amd.com            memFenceScopeSegGlobal = (Brig::BrigMemoryScope)
94311308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->globalSegmentMemoryScope;
94411308Santhony.gutierrez@amd.com
94511308Santhony.gutierrez@amd.com            memFenceScopeSegGroup = (Brig::BrigMemoryScope)
94611308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->groupSegmentMemoryScope;
94711308Santhony.gutierrez@amd.com
94811308Santhony.gutierrez@amd.com            memFenceScopeSegImage = (Brig::BrigMemoryScope)
94911308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->imageSegmentMemoryScope;
95011308Santhony.gutierrez@amd.com
95111308Santhony.gutierrez@amd.com            memFenceMemOrder = (Brig::BrigMemoryOrder)
95211308Santhony.gutierrez@amd.com                ((Brig::BrigInstMemFence*)ib)->memoryOrder;
95311308Santhony.gutierrez@amd.com
95411692Santhony.gutierrez@amd.com            setFlag(MemoryRef);
95511692Santhony.gutierrez@amd.com            setFlag(GPUStaticInst::MemFence);
95611692Santhony.gutierrez@amd.com
95711692Santhony.gutierrez@amd.com            switch (memFenceMemOrder) {
95811692Santhony.gutierrez@amd.com              case Brig::BRIG_MEMORY_ORDER_NONE:
95911692Santhony.gutierrez@amd.com                setFlag(NoOrder);
96011692Santhony.gutierrez@amd.com                break;
96111692Santhony.gutierrez@amd.com              case Brig::BRIG_MEMORY_ORDER_RELAXED:
96211692Santhony.gutierrez@amd.com                setFlag(RelaxedOrder);
96311692Santhony.gutierrez@amd.com                break;
96411692Santhony.gutierrez@amd.com              case Brig::BRIG_MEMORY_ORDER_SC_ACQUIRE:
96511692Santhony.gutierrez@amd.com                setFlag(Acquire);
96611692Santhony.gutierrez@amd.com                break;
96711692Santhony.gutierrez@amd.com              case Brig::BRIG_MEMORY_ORDER_SC_RELEASE:
96811692Santhony.gutierrez@amd.com                setFlag(Release);
96911692Santhony.gutierrez@amd.com                break;
97011692Santhony.gutierrez@amd.com              case Brig::BRIG_MEMORY_ORDER_SC_ACQUIRE_RELEASE:
97111692Santhony.gutierrez@amd.com                setFlag(AcquireRelease);
97211692Santhony.gutierrez@amd.com                break;
97311692Santhony.gutierrez@amd.com              default:
97411692Santhony.gutierrez@amd.com                fatal("MemInst has bad BrigMemoryOrder\n");
97511692Santhony.gutierrez@amd.com            }
97611692Santhony.gutierrez@amd.com
97711692Santhony.gutierrez@amd.com            // set inst flags based on scopes
97811308Santhony.gutierrez@amd.com            if (memFenceScopeSegGlobal != Brig::BRIG_MEMORY_SCOPE_NONE &&
97911308Santhony.gutierrez@amd.com                memFenceScopeSegGroup != Brig::BRIG_MEMORY_SCOPE_NONE) {
98011692Santhony.gutierrez@amd.com                setFlag(GPUStaticInst::GlobalSegment);
98111692Santhony.gutierrez@amd.com
98211692Santhony.gutierrez@amd.com                /**
98311692Santhony.gutierrez@amd.com                 * A memory fence that has scope for
98411692Santhony.gutierrez@amd.com                 * both segments will use the global
98511692Santhony.gutierrez@amd.com                 * segment, and be executed in the
98611692Santhony.gutierrez@amd.com                 * global memory pipeline, therefore,
98711692Santhony.gutierrez@amd.com                 * we set the segment to match the
98811692Santhony.gutierrez@amd.com                 * global scope only
98911692Santhony.gutierrez@amd.com                 */
99011692Santhony.gutierrez@amd.com                switch (memFenceScopeSegGlobal) {
99111692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_NONE:
99211692Santhony.gutierrez@amd.com                    setFlag(NoScope);
99311692Santhony.gutierrez@amd.com                    break;
99411692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKITEM:
99511692Santhony.gutierrez@amd.com                    setFlag(WorkitemScope);
99611692Santhony.gutierrez@amd.com                    break;
99711692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKGROUP:
99811692Santhony.gutierrez@amd.com                    setFlag(WorkgroupScope);
99911692Santhony.gutierrez@amd.com                    break;
100011692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_AGENT:
100111692Santhony.gutierrez@amd.com                    setFlag(DeviceScope);
100211692Santhony.gutierrez@amd.com                    break;
100311692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_SYSTEM:
100411692Santhony.gutierrez@amd.com                    setFlag(SystemScope);
100511692Santhony.gutierrez@amd.com                    break;
100611692Santhony.gutierrez@amd.com                  default:
100711692Santhony.gutierrez@amd.com                    fatal("MemFence has bad global scope type\n");
100811692Santhony.gutierrez@amd.com                }
100911308Santhony.gutierrez@amd.com            } else if (memFenceScopeSegGlobal != Brig::BRIG_MEMORY_SCOPE_NONE) {
101011692Santhony.gutierrez@amd.com                setFlag(GPUStaticInst::GlobalSegment);
101111692Santhony.gutierrez@amd.com
101211692Santhony.gutierrez@amd.com                switch (memFenceScopeSegGlobal) {
101311692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_NONE:
101411692Santhony.gutierrez@amd.com                    setFlag(NoScope);
101511692Santhony.gutierrez@amd.com                    break;
101611692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKITEM:
101711692Santhony.gutierrez@amd.com                    setFlag(WorkitemScope);
101811692Santhony.gutierrez@amd.com                    break;
101911692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKGROUP:
102011692Santhony.gutierrez@amd.com                    setFlag(WorkgroupScope);
102111692Santhony.gutierrez@amd.com                    break;
102211692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_AGENT:
102311692Santhony.gutierrez@amd.com                    setFlag(DeviceScope);
102411692Santhony.gutierrez@amd.com                    break;
102511692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_SYSTEM:
102611692Santhony.gutierrez@amd.com                    setFlag(SystemScope);
102711692Santhony.gutierrez@amd.com                    break;
102811692Santhony.gutierrez@amd.com                  default:
102911692Santhony.gutierrez@amd.com                    fatal("MemFence has bad global scope type\n");
103011692Santhony.gutierrez@amd.com                }
103111308Santhony.gutierrez@amd.com            } else if (memFenceScopeSegGroup != Brig::BRIG_MEMORY_SCOPE_NONE) {
103211692Santhony.gutierrez@amd.com                setFlag(GPUStaticInst::GroupSegment);
103311692Santhony.gutierrez@amd.com
103411692Santhony.gutierrez@amd.com                switch (memFenceScopeSegGroup) {
103511692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_NONE:
103611692Santhony.gutierrez@amd.com                    setFlag(NoScope);
103711692Santhony.gutierrez@amd.com                    break;
103811692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKITEM:
103911692Santhony.gutierrez@amd.com                    setFlag(WorkitemScope);
104011692Santhony.gutierrez@amd.com                    break;
104111692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_WORKGROUP:
104211692Santhony.gutierrez@amd.com                    setFlag(WorkgroupScope);
104311692Santhony.gutierrez@amd.com                    break;
104411692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_AGENT:
104511692Santhony.gutierrez@amd.com                    setFlag(DeviceScope);
104611692Santhony.gutierrez@amd.com                    break;
104711692Santhony.gutierrez@amd.com                  case Brig::BRIG_MEMORY_SCOPE_SYSTEM:
104811692Santhony.gutierrez@amd.com                    setFlag(SystemScope);
104911692Santhony.gutierrez@amd.com                    break;
105011692Santhony.gutierrez@amd.com                  default:
105111692Santhony.gutierrez@amd.com                    fatal("MemFence has bad group scope type\n");
105211692Santhony.gutierrez@amd.com                }
105311308Santhony.gutierrez@amd.com            } else {
105411308Santhony.gutierrez@amd.com                fatal("MemFence constructor: bad scope specifiers\n");
105511308Santhony.gutierrez@amd.com            }
105611308Santhony.gutierrez@amd.com        }
105711308Santhony.gutierrez@amd.com
105811308Santhony.gutierrez@amd.com        void
105911308Santhony.gutierrez@amd.com        initiateAcc(GPUDynInstPtr gpuDynInst)
106011308Santhony.gutierrez@amd.com        {
106111308Santhony.gutierrez@amd.com            Wavefront *wave = gpuDynInst->wavefront();
106211308Santhony.gutierrez@amd.com            wave->computeUnit->injectGlobalMemFence(gpuDynInst);
106311308Santhony.gutierrez@amd.com        }
106411308Santhony.gutierrez@amd.com
106511308Santhony.gutierrez@amd.com        void
106611308Santhony.gutierrez@amd.com        execute(GPUDynInstPtr gpuDynInst)
106711308Santhony.gutierrez@amd.com        {
106811308Santhony.gutierrez@amd.com            Wavefront *w = gpuDynInst->wavefront();
106911308Santhony.gutierrez@amd.com            // 2 cases:
107011308Santhony.gutierrez@amd.com            //   * memfence to a sequentially consistent memory (e.g., LDS).
107111308Santhony.gutierrez@amd.com            //     These can be handled as no-ops.
107211308Santhony.gutierrez@amd.com            //   * memfence to a relaxed consistency cache (e.g., Hermes, Viper,
107311308Santhony.gutierrez@amd.com            //     etc.). We send a packet, tagged with the memory order and
107411308Santhony.gutierrez@amd.com            //     scope, and let the GPU coalescer handle it.
107511308Santhony.gutierrez@amd.com
107611692Santhony.gutierrez@amd.com            if (isGlobalSeg()) {
107711308Santhony.gutierrez@amd.com                gpuDynInst->simdId = w->simdId;
107811308Santhony.gutierrez@amd.com                gpuDynInst->wfSlotId = w->wfSlotId;
107911308Santhony.gutierrez@amd.com                gpuDynInst->wfDynId = w->wfDynId;
108011639Salexandru.dutu@amd.com                gpuDynInst->kern_id = w->kernId;
108111308Santhony.gutierrez@amd.com                gpuDynInst->cu_id = w->computeUnit->cu_id;
108211308Santhony.gutierrez@amd.com
108311308Santhony.gutierrez@amd.com                gpuDynInst->useContinuation = false;
108411308Santhony.gutierrez@amd.com                GlobalMemPipeline* gmp = &(w->computeUnit->globalMemoryPipe);
108511700Santhony.gutierrez@amd.com                gmp->issueRequest(gpuDynInst);
108611308Santhony.gutierrez@amd.com
108711639Salexandru.dutu@amd.com                w->wrGmReqsInPipe--;
108811639Salexandru.dutu@amd.com                w->rdGmReqsInPipe--;
108911639Salexandru.dutu@amd.com                w->memReqsInPipe--;
109011639Salexandru.dutu@amd.com                w->outstandingReqs++;
109111692Santhony.gutierrez@amd.com            } else if (isGroupSeg()) {
109211308Santhony.gutierrez@amd.com                // no-op
109311308Santhony.gutierrez@amd.com            } else {
109411692Santhony.gutierrez@amd.com                fatal("MemFence execute: bad op type\n");
109511308Santhony.gutierrez@amd.com            }
109611308Santhony.gutierrez@amd.com        }
109711308Santhony.gutierrez@amd.com    };
109811308Santhony.gutierrez@amd.com
109911308Santhony.gutierrez@amd.com    class Call : public HsailGPUStaticInst
110011308Santhony.gutierrez@amd.com    {
110111308Santhony.gutierrez@amd.com      public:
110211308Santhony.gutierrez@amd.com        // private helper functions
110311308Santhony.gutierrez@amd.com        void calcAddr(Wavefront* w, GPUDynInstPtr m);
110411308Santhony.gutierrez@amd.com
110511308Santhony.gutierrez@amd.com        void
110611308Santhony.gutierrez@amd.com        generateDisassembly()
110711308Santhony.gutierrez@amd.com        {
110811308Santhony.gutierrez@amd.com            if (dest.disassemble() == "") {
110911308Santhony.gutierrez@amd.com                disassembly = csprintf("%s %s (%s)", opcode, src0.disassemble(),
111011308Santhony.gutierrez@amd.com                                       src1.disassemble());
111111308Santhony.gutierrez@amd.com            } else {
111211308Santhony.gutierrez@amd.com                disassembly = csprintf("%s %s (%s) (%s)", opcode,
111311308Santhony.gutierrez@amd.com                                       src0.disassemble(), dest.disassemble(),
111411308Santhony.gutierrez@amd.com                                       src1.disassemble());
111511308Santhony.gutierrez@amd.com            }
111611308Santhony.gutierrez@amd.com        }
111711308Santhony.gutierrez@amd.com
111811308Santhony.gutierrez@amd.com        bool
111911308Santhony.gutierrez@amd.com        isPseudoOp()
112011308Santhony.gutierrez@amd.com        {
112111308Santhony.gutierrez@amd.com            std::string func_name = src0.disassemble();
112211308Santhony.gutierrez@amd.com            if (func_name.find("__gem5_hsail_op") != std::string::npos) {
112311308Santhony.gutierrez@amd.com                return true;
112411308Santhony.gutierrez@amd.com            }
112511308Santhony.gutierrez@amd.com            return false;
112611308Santhony.gutierrez@amd.com        }
112711308Santhony.gutierrez@amd.com
112811308Santhony.gutierrez@amd.com        // member variables
112911308Santhony.gutierrez@amd.com        ListOperand dest;
113011308Santhony.gutierrez@amd.com        FunctionRefOperand src0;
113111308Santhony.gutierrez@amd.com        ListOperand src1;
113211308Santhony.gutierrez@amd.com        HsailCode *func_ptr;
113311308Santhony.gutierrez@amd.com
113411308Santhony.gutierrez@amd.com        // exec function for pseudo instructions mapped on top of call opcode
113511308Santhony.gutierrez@amd.com        void execPseudoInst(Wavefront *w, GPUDynInstPtr gpuDynInst);
113611308Santhony.gutierrez@amd.com
113711308Santhony.gutierrez@amd.com        // user-defined pseudo instructions
113811308Santhony.gutierrez@amd.com        void MagicPrintLane(Wavefront *w);
113911308Santhony.gutierrez@amd.com        void MagicPrintLane64(Wavefront *w);
114011308Santhony.gutierrez@amd.com        void MagicPrintWF32(Wavefront *w);
114111308Santhony.gutierrez@amd.com        void MagicPrintWF64(Wavefront *w);
114211308Santhony.gutierrez@amd.com        void MagicPrintWFFloat(Wavefront *w);
114311308Santhony.gutierrez@amd.com        void MagicSimBreak(Wavefront *w);
114411308Santhony.gutierrez@amd.com        void MagicPrefixSum(Wavefront *w);
114511308Santhony.gutierrez@amd.com        void MagicReduction(Wavefront *w);
114611308Santhony.gutierrez@amd.com        void MagicMaskLower(Wavefront *w);
114711308Santhony.gutierrez@amd.com        void MagicMaskUpper(Wavefront *w);
114811308Santhony.gutierrez@amd.com        void MagicJoinWFBar(Wavefront *w);
114911308Santhony.gutierrez@amd.com        void MagicWaitWFBar(Wavefront *w);
115011308Santhony.gutierrez@amd.com        void MagicPanic(Wavefront *w);
115111308Santhony.gutierrez@amd.com
115211308Santhony.gutierrez@amd.com        void MagicAtomicNRAddGlobalU32Reg(Wavefront *w,
115311308Santhony.gutierrez@amd.com                                          GPUDynInstPtr gpuDynInst);
115411308Santhony.gutierrez@amd.com
115511308Santhony.gutierrez@amd.com        void MagicAtomicNRAddGroupU32Reg(Wavefront *w,
115611308Santhony.gutierrez@amd.com                                         GPUDynInstPtr gpuDynInst);
115711308Santhony.gutierrez@amd.com
115811308Santhony.gutierrez@amd.com        void MagicLoadGlobalU32Reg(Wavefront *w, GPUDynInstPtr gpuDynInst);
115911308Santhony.gutierrez@amd.com
116011308Santhony.gutierrez@amd.com        void MagicXactCasLd(Wavefront *w);
116111308Santhony.gutierrez@amd.com        void MagicMostSigThread(Wavefront *w);
116211308Santhony.gutierrez@amd.com        void MagicMostSigBroadcast(Wavefront *w);
116311308Santhony.gutierrez@amd.com
116411308Santhony.gutierrez@amd.com        void MagicPrintWF32ID(Wavefront *w);
116511308Santhony.gutierrez@amd.com        void MagicPrintWFID64(Wavefront *w);
116611308Santhony.gutierrez@amd.com
116711308Santhony.gutierrez@amd.com        Call(const Brig::BrigInstBase *ib, const BrigObject *obj)
116811308Santhony.gutierrez@amd.com            : HsailGPUStaticInst(obj, "call")
116911308Santhony.gutierrez@amd.com        {
117011692Santhony.gutierrez@amd.com            setFlag(ALU);
117111308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
117211308Santhony.gutierrez@amd.com            dest.init(op_offs, obj);
117311308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
117411308Santhony.gutierrez@amd.com            src0.init(op_offs, obj);
117511308Santhony.gutierrez@amd.com
117611308Santhony.gutierrez@amd.com            func_ptr = nullptr;
117711308Santhony.gutierrez@amd.com            std::string func_name = src0.disassemble();
117811308Santhony.gutierrez@amd.com            if (!isPseudoOp()) {
117911308Santhony.gutierrez@amd.com                func_ptr = dynamic_cast<HsailCode*>(obj->
118011308Santhony.gutierrez@amd.com                                                    getFunction(func_name));
118111308Santhony.gutierrez@amd.com
118211308Santhony.gutierrez@amd.com                if (!func_ptr)
118311308Santhony.gutierrez@amd.com                    fatal("call::exec cannot find function: %s\n", func_name);
118411308Santhony.gutierrez@amd.com            }
118511308Santhony.gutierrez@amd.com
118611308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 2);
118711308Santhony.gutierrez@amd.com            src1.init(op_offs, obj);
118811308Santhony.gutierrez@amd.com        }
118911308Santhony.gutierrez@amd.com
119011308Santhony.gutierrez@amd.com        bool isVectorRegister(int operandIndex) { return false; }
119111308Santhony.gutierrez@amd.com        bool isCondRegister(int operandIndex) { return false; }
119211308Santhony.gutierrez@amd.com        bool isScalarRegister(int operandIndex) { return false; }
119311308Santhony.gutierrez@amd.com        bool isSrcOperand(int operandIndex) { return false; }
119411308Santhony.gutierrez@amd.com        bool isDstOperand(int operandIndex) { return false; }
119511699Santhony.gutierrez@amd.com        int getOperandSize(int operandIndex) { return 0; }
119611699Santhony.gutierrez@amd.com
119711699Santhony.gutierrez@amd.com        int
119811699Santhony.gutierrez@amd.com        getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst)
119911699Santhony.gutierrez@amd.com        {
120011699Santhony.gutierrez@amd.com            return -1;
120111699Santhony.gutierrez@amd.com        }
120211308Santhony.gutierrez@amd.com
120311308Santhony.gutierrez@amd.com        void
120411308Santhony.gutierrez@amd.com        execute(GPUDynInstPtr gpuDynInst)
120511308Santhony.gutierrez@amd.com        {
120611308Santhony.gutierrez@amd.com            Wavefront *w = gpuDynInst->wavefront();
120711308Santhony.gutierrez@amd.com
120811308Santhony.gutierrez@amd.com            std::string func_name = src0.disassemble();
120911308Santhony.gutierrez@amd.com            if (isPseudoOp()) {
121011308Santhony.gutierrez@amd.com                execPseudoInst(w, gpuDynInst);
121111308Santhony.gutierrez@amd.com            } else {
121211308Santhony.gutierrez@amd.com                fatal("Native HSAIL functions are not yet implemented: %s\n",
121311308Santhony.gutierrez@amd.com                      func_name);
121411308Santhony.gutierrez@amd.com            }
121511308Santhony.gutierrez@amd.com        }
121611308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
121711308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
121811308Santhony.gutierrez@amd.com        int getNumOperands() { return 2; }
121911308Santhony.gutierrez@amd.com    };
122011308Santhony.gutierrez@amd.com
122111308Santhony.gutierrez@amd.com    template<typename T> T heynot(T arg) { return ~arg; }
122211308Santhony.gutierrez@amd.com    template<> inline bool heynot<bool>(bool arg) { return !arg; }
122311308Santhony.gutierrez@amd.com} // namespace HsailISA
122411308Santhony.gutierrez@amd.com
122511308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_DECL_HH__
1226