/*
 * Copyright (c) 2016-2021 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __ARCH_GCN3_INSTS_OP_ENCODINGS_HH__
#define __ARCH_GCN3_INSTS_OP_ENCODINGS_HH__

#include "arch/amdgpu/gcn3/gpu_decoder.hh"
#include "arch/amdgpu/gcn3/gpu_mem_helpers.hh"
#include "arch/amdgpu/gcn3/insts/gpu_static_inst.hh"
#include "arch/amdgpu/gcn3/operand.hh"
#include "debug/GCN3.hh"
#include "debug/GPUExec.hh"
#include "mem/ruby/system/RubySystem.hh"

namespace gem5
{

namespace Gcn3ISA
{
    struct BufferRsrcDescriptor
    {
        uint64_t baseAddr : 48;
        uint32_t stride : 14;
        uint32_t cacheSwizzle : 1;
        uint32_t swizzleEn : 1;
        uint32_t numRecords : 32;
        uint32_t dstSelX : 3;
        uint32_t dstSelY : 3;
        uint32_t dstSelZ : 3;
        uint32_t dstSelW : 3;
        uint32_t numFmt : 3;
        uint32_t dataFmt : 4;
        uint32_t elemSize : 2;
        uint32_t idxStride : 2;
        uint32_t addTidEn : 1;
        uint32_t atc : 1;
        uint32_t hashEn : 1;
        uint32_t heap : 1;
        uint32_t mType : 3;
        uint32_t type : 2;
    };

    // --- purely virtual instruction classes ---

    class Inst_SOP2 : public GCN3GPUStaticInst
    {
      public:
        Inst_SOP2(InFmt_SOP2*, const std::string &opcode);

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_SOP2 instData;
        // possible second DWORD
        InstFormat extData;
        uint32_t varSize;

      private:
        bool hasSecondDword(InFmt_SOP2 *);
    }; // Inst_SOP2

    class Inst_SOPK : public GCN3GPUStaticInst
    {
      public:
        Inst_SOPK(InFmt_SOPK*, const std::string &opcode);
        ~Inst_SOPK();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_SOPK instData;
        // possible second DWORD
        InstFormat extData;
        uint32_t varSize;

      private:
        bool hasSecondDword(InFmt_SOPK *);
    }; // Inst_SOPK

    class Inst_SOP1 : public GCN3GPUStaticInst
    {
      public:
        Inst_SOP1(InFmt_SOP1*, const std::string &opcode);
        ~Inst_SOP1();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_SOP1 instData;
        // possible second DWORD
        InstFormat extData;
        uint32_t varSize;

      private:
        bool hasSecondDword(InFmt_SOP1 *);
    }; // Inst_SOP1

    class Inst_SOPC : public GCN3GPUStaticInst
    {
      public:
        Inst_SOPC(InFmt_SOPC*, const std::string &opcode);
        ~Inst_SOPC();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_SOPC instData;
        // possible second DWORD
        InstFormat extData;
        uint32_t varSize;

      private:
        bool hasSecondDword(InFmt_SOPC *);
    }; // Inst_SOPC

    class Inst_SOPP : public GCN3GPUStaticInst
    {
      public:
        Inst_SOPP(InFmt_SOPP*, const std::string &opcode);
        ~Inst_SOPP();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_SOPP instData;
    }; // Inst_SOPP

    class Inst_SMEM : public GCN3GPUStaticInst
    {
      public:
        Inst_SMEM(InFmt_SMEM*, const std::string &opcode);
        ~Inst_SMEM();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        /**
         * initiate a memory read access for N dwords
         */
        template<int N>
        void
        initMemRead(GPUDynInstPtr gpuDynInst)
        {
            initMemReqScalarHelper<ScalarRegU32, N>(gpuDynInst,
                                                    MemCmd::ReadReq);
        }

        /**
         * initiate a memory write access for N dwords
         */
        template<int N>
        void
        initMemWrite(GPUDynInstPtr gpuDynInst)
        {
            initMemReqScalarHelper<ScalarRegU32, N>(gpuDynInst,
                                                    MemCmd::WriteReq);
        }

        /**
         * For normal s_load_dword/s_store_dword instruction addresses.
         */
        void
        calcAddr(GPUDynInstPtr gpu_dyn_inst, ConstScalarOperandU64 &addr,
                 ScalarRegU32 offset)
        {
            Addr vaddr = ((addr.rawData() + offset) & ~0x3);
            gpu_dyn_inst->scalarAddr = vaddr;
        }

        /**
         * For s_buffer_load_dword/s_buffer_store_dword instruction addresses.
         * The s_buffer instructions use the same buffer resource descriptor
         * as the MUBUF instructions.
         */
        void
        calcAddr(GPUDynInstPtr gpu_dyn_inst,
                 ConstScalarOperandU128 &s_rsrc_desc, ScalarRegU32 offset)
        {
            BufferRsrcDescriptor rsrc_desc;
            ScalarRegU32 clamped_offset(offset);
            std::memcpy((void*)&rsrc_desc, s_rsrc_desc.rawDataPtr(),
                        sizeof(BufferRsrcDescriptor));

            /**
             * The address is clamped if:
             *     Stride is zero: clamp if offset >= num_records
             *     Stride is non-zero: clamp if offset > (stride * num_records)
             */
            if (!rsrc_desc.stride && offset >= rsrc_desc.numRecords) {
                clamped_offset = rsrc_desc.numRecords;
            } else if (rsrc_desc.stride && offset
                       > (rsrc_desc.stride * rsrc_desc.numRecords)) {
                clamped_offset = (rsrc_desc.stride * rsrc_desc.numRecords);
            }

            Addr vaddr = ((rsrc_desc.baseAddr + clamped_offset) & ~0x3);
            gpu_dyn_inst->scalarAddr = vaddr;
        }

        // first instruction DWORD
        InFmt_SMEM instData;
        // second instruction DWORD
        InFmt_SMEM_1 extData;
    }; // Inst_SMEM

    class Inst_VOP2 : public GCN3GPUStaticInst
    {
      public:
        Inst_VOP2(InFmt_VOP2*, const std::string &opcode);
        ~Inst_VOP2();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_VOP2 instData;
        // possible second DWORD
        InstFormat extData;
        uint32_t varSize;

      private:
        bool hasSecondDword(InFmt_VOP2 *);
    }; // Inst_VOP2

    class Inst_VOP1 : public GCN3GPUStaticInst
    {
      public:
        Inst_VOP1(InFmt_VOP1*, const std::string &opcode);
        ~Inst_VOP1();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_VOP1 instData;
        // possible second DWORD
        InstFormat extData;
        uint32_t varSize;

      private:
        bool hasSecondDword(InFmt_VOP1 *);
    }; // Inst_VOP1

    class Inst_VOPC : public GCN3GPUStaticInst
    {
      public:
        Inst_VOPC(InFmt_VOPC*, const std::string &opcode);
        ~Inst_VOPC();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_VOPC instData;
        // possible second DWORD
        InstFormat extData;
        uint32_t varSize;

      private:
        bool hasSecondDword(InFmt_VOPC *);
    }; // Inst_VOPC

    class Inst_VINTRP : public GCN3GPUStaticInst
    {
      public:
        Inst_VINTRP(InFmt_VINTRP*, const std::string &opcode);
        ~Inst_VINTRP();

        int instSize() const override;

      protected:
        // first instruction DWORD
        InFmt_VINTRP instData;
    }; // Inst_VINTRP

    class Inst_VOP3 : public GCN3GPUStaticInst
    {
      public:
        Inst_VOP3(InFmt_VOP3*, const std::string &opcode, bool sgpr_dst);
        ~Inst_VOP3();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_VOP3 instData;
        // second instruction DWORD
        InFmt_VOP3_1 extData;

      private:
        bool hasSecondDword(InFmt_VOP3 *);
        /**
         * the v_cmp and readlane instructions in the VOP3
         * encoding are unique because they are the only
         * instructions that use the VDST field to specify
         * a scalar register destination. for VOP3::V_CMP insts
         * VDST specifies the arbitrary SGPR pair used to write
         * VCC. for V_READLANE VDST specifies the SGPR to return
         * the value of the selected lane in the source VGPR
         * from which we are reading.
         */
        const bool sgprDst;
    }; // Inst_VOP3

    class Inst_VOP3_SDST_ENC : public GCN3GPUStaticInst
    {
      public:
        Inst_VOP3_SDST_ENC(InFmt_VOP3_SDST_ENC*, const std::string &opcode);
        ~Inst_VOP3_SDST_ENC();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_VOP3_SDST_ENC instData;
        // second instruction DWORD
        InFmt_VOP3_1 extData;

      private:
        bool hasSecondDword(InFmt_VOP3_SDST_ENC *);
    }; // Inst_VOP3_SDST_ENC

    class Inst_DS : public GCN3GPUStaticInst
    {
      public:
        Inst_DS(InFmt_DS*, const std::string &opcode);
        ~Inst_DS();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        template<typename T>
        void
        initMemRead(GPUDynInstPtr gpuDynInst, Addr offset)
        {
            Wavefront *wf = gpuDynInst->wavefront();

            for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                if (gpuDynInst->exec_mask[lane]) {
                    Addr vaddr = gpuDynInst->addr[lane] + offset;

                    (reinterpret_cast<T*>(gpuDynInst->d_data))[lane]
                        = wf->ldsChunk->read<T>(vaddr);
                }
            }
        }

        template<int N>
        void
        initMemRead(GPUDynInstPtr gpuDynInst, Addr offset)
        {
            Wavefront *wf = gpuDynInst->wavefront();

            for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                if (gpuDynInst->exec_mask[lane]) {
                    Addr vaddr = gpuDynInst->addr[lane] + offset;
                    for (int i = 0; i < N; ++i) {
                        (reinterpret_cast<VecElemU32*>(
                            gpuDynInst->d_data))[lane * N + i]
                            = wf->ldsChunk->read<VecElemU32>(
                                vaddr + i*sizeof(VecElemU32));
                    }
                }
            }
        }

        template<typename T>
        void
        initDualMemRead(GPUDynInstPtr gpuDynInst, Addr offset0, Addr offset1)
        {
            Wavefront *wf = gpuDynInst->wavefront();

            for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                if (gpuDynInst->exec_mask[lane]) {
                    Addr vaddr0 = gpuDynInst->addr[lane] + offset0;
                    Addr vaddr1 = gpuDynInst->addr[lane] + offset1;

                    (reinterpret_cast<T*>(gpuDynInst->d_data))[lane * 2]
                        = wf->ldsChunk->read<T>(vaddr0);
                    (reinterpret_cast<T*>(gpuDynInst->d_data))[lane * 2 + 1]
                        = wf->ldsChunk->read<T>(vaddr1);
                }
            }
        }

        template<typename T>
        void
        initMemWrite(GPUDynInstPtr gpuDynInst, Addr offset)
        {
            Wavefront *wf = gpuDynInst->wavefront();

            for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                if (gpuDynInst->exec_mask[lane]) {
                    Addr vaddr = gpuDynInst->addr[lane] + offset;
                    wf->ldsChunk->write<T>(vaddr,
                        (reinterpret_cast<T*>(gpuDynInst->d_data))[lane]);
                }
            }
        }

        template<int N>
        void
        initMemWrite(GPUDynInstPtr gpuDynInst, Addr offset)
        {
            Wavefront *wf = gpuDynInst->wavefront();

            for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                if (gpuDynInst->exec_mask[lane]) {
                    Addr vaddr = gpuDynInst->addr[lane] + offset;
                    for (int i = 0; i < N; ++i) {
                        wf->ldsChunk->write<VecElemU32>(
                            vaddr + i*sizeof(VecElemU32),
                            (reinterpret_cast<VecElemU32*>(
                                gpuDynInst->d_data))[lane * N + i]);
                    }
                }
            }
        }

        template<typename T>
        void
        initDualMemWrite(GPUDynInstPtr gpuDynInst, Addr offset0, Addr offset1)
        {
            Wavefront *wf = gpuDynInst->wavefront();

            for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                if (gpuDynInst->exec_mask[lane]) {
                    Addr vaddr0 = gpuDynInst->addr[lane] + offset0;
                    Addr vaddr1 = gpuDynInst->addr[lane] + offset1;
                    wf->ldsChunk->write<T>(vaddr0, (reinterpret_cast<T*>(
                        gpuDynInst->d_data))[lane * 2]);
                    wf->ldsChunk->write<T>(vaddr1, (reinterpret_cast<T*>(
                        gpuDynInst->d_data))[lane * 2 + 1]);
                }
            }
        }

        void
        calcAddr(GPUDynInstPtr gpuDynInst, ConstVecOperandU32 &addr)
        {
            Wavefront *wf = gpuDynInst->wavefront();

            for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                if (wf->execMask(lane)) {
                    gpuDynInst->addr.at(lane) = (Addr)addr[lane];
                }
            }
        }

        // first instruction DWORD
        InFmt_DS instData;
        // second instruction DWORD
        InFmt_DS_1 extData;
    }; // Inst_DS

    class Inst_MUBUF : public GCN3GPUStaticInst
    {
      public:
        Inst_MUBUF(InFmt_MUBUF*, const std::string &opcode);
        ~Inst_MUBUF();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        template<typename T>
        void
        initMemRead(GPUDynInstPtr gpuDynInst)
        {
            // temporarily modify exec_mask to supress memory accesses to oob
            // regions.  Only issue memory requests for lanes that have their
            // exec_mask set and are not out of bounds.
            VectorMask old_exec_mask = gpuDynInst->exec_mask;
            gpuDynInst->exec_mask &= ~oobMask;
            initMemReqHelper<T, 1>(gpuDynInst, MemCmd::ReadReq);
            gpuDynInst->exec_mask = old_exec_mask;
        }


        template<int N>
        void
        initMemRead(GPUDynInstPtr gpuDynInst)
        {
            // temporarily modify exec_mask to supress memory accesses to oob
            // regions.  Only issue memory requests for lanes that have their
            // exec_mask set and are not out of bounds.
            VectorMask old_exec_mask = gpuDynInst->exec_mask;
            gpuDynInst->exec_mask &= ~oobMask;
            initMemReqHelper<VecElemU32, N>(gpuDynInst, MemCmd::ReadReq);
            gpuDynInst->exec_mask = old_exec_mask;
        }

        template<typename T>
        void
        initMemWrite(GPUDynInstPtr gpuDynInst)
        {
            // temporarily modify exec_mask to supress memory accesses to oob
            // regions.  Only issue memory requests for lanes that have their
            // exec_mask set and are not out of bounds.
            VectorMask old_exec_mask = gpuDynInst->exec_mask;
            gpuDynInst->exec_mask &= ~oobMask;
            initMemReqHelper<T, 1>(gpuDynInst, MemCmd::WriteReq);
            gpuDynInst->exec_mask = old_exec_mask;
        }

        template<int N>
        void
        initMemWrite(GPUDynInstPtr gpuDynInst)
        {
            // temporarily modify exec_mask to supress memory accesses to oob
            // regions.  Only issue memory requests for lanes that have their
            // exec_mask set and are not out of bounds.
            VectorMask old_exec_mask = gpuDynInst->exec_mask;
            gpuDynInst->exec_mask &= ~oobMask;
            initMemReqHelper<VecElemU32, N>(gpuDynInst, MemCmd::WriteReq);
            gpuDynInst->exec_mask = old_exec_mask;
        }

        void
        injectGlobalMemFence(GPUDynInstPtr gpuDynInst)
        {
            // create request and set flags
            gpuDynInst->resetEntireStatusVector();
            gpuDynInst->setStatusVector(0, 1);
            RequestPtr req = std::make_shared<Request>(0, 0, 0,
                                       gpuDynInst->computeUnit()->
                                       requestorId(), 0,
                                       gpuDynInst->wfDynId);
            gpuDynInst->setRequestFlags(req);
            gpuDynInst->computeUnit()->
                injectGlobalMemFence(gpuDynInst, false, req);
        }

        /**
         * MUBUF insructions calculate their addresses as follows:
         *
         * index  = (IDXEN ? vgpr_idx : 0) + (const_add_tid_en ? TID : 0)
         * offset = (OFFEN ? vgpr_off : 0) + inst_off
         *
         * / ====================== LINEAR ADDRESSING ====================== /
         * VADDR = base + sgpr_off + offset + stride * index
         *
         * / ===================== SWIZZLED ADDRESSING ===================== /
         * index_msb  = index / const_index_stride
         * index_lsb  = index % const_index_stride
         * offset_msb = offset / const_element_size
         * offset_lsb = offset % const_element_size
         * buffer_offset = ((index_msb * stride + offset_msb *
         *                  const_element_size) * const_index_stride +
         *                  index_lsb * const_element_size + offset_lsb)
         *
         * VADDR = base + sgpr_off + buffer_offset
         */
        template<typename VOFF, typename VIDX, typename SRSRC, typename SOFF>
        void
        calcAddr(GPUDynInstPtr gpuDynInst, VOFF v_off, VIDX v_idx,
            SRSRC s_rsrc_desc, SOFF s_offset, int inst_offset)
        {
            Addr vaddr = 0;
            Addr base_addr = 0;
            Addr stride = 0;
            Addr buf_idx = 0;
            Addr buf_off = 0;
            Addr buffer_offset = 0;
            BufferRsrcDescriptor rsrc_desc;

            std::memcpy((void*)&rsrc_desc, s_rsrc_desc.rawDataPtr(),
                sizeof(BufferRsrcDescriptor));

            base_addr = rsrc_desc.baseAddr;

            stride = rsrc_desc.addTidEn ? ((rsrc_desc.dataFmt << 14)
                + rsrc_desc.stride) : rsrc_desc.stride;

            for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                if (gpuDynInst->exec_mask[lane]) {
                    vaddr = base_addr + s_offset.rawData();
                    /**
                     * first we calculate the buffer's index and offset.
                     * these will be used for either linear or swizzled
                     * buffers.
                     */
                    buf_idx = v_idx[lane] + (rsrc_desc.addTidEn ? lane : 0);

                    buf_off = v_off[lane] + inst_offset;

                    if (rsrc_desc.swizzleEn) {
                        Addr idx_stride = 8 << rsrc_desc.idxStride;
                        Addr elem_size = 2 << rsrc_desc.elemSize;
                        Addr idx_msb = buf_idx / idx_stride;
                        Addr idx_lsb = buf_idx % idx_stride;
                        Addr off_msb = buf_off / elem_size;
                        Addr off_lsb = buf_off % elem_size;
                        DPRINTF(GCN3, "mubuf swizzled lane %d: "
                                "idx_stride = %llx, elem_size = %llx, "
                                "idx_msb = %llx, idx_lsb = %llx, "
                                "off_msb = %llx, off_lsb = %llx\n",
                                lane, idx_stride, elem_size, idx_msb, idx_lsb,
                                off_msb, off_lsb);

                        buffer_offset =(idx_msb * stride + off_msb * elem_size)
                            * idx_stride + idx_lsb * elem_size + off_lsb;
                    } else {
                        buffer_offset = buf_off + stride * buf_idx;
                    }


                    /**
                     * Range check behavior causes out of range accesses to
                     * to be treated differently. Out of range accesses return
                     * 0 for loads and are ignored for stores. For
                     * non-formatted accesses, this is done on a per-lane
                     * basis.
                     */
                    if (rsrc_desc.stride == 0 || !rsrc_desc.swizzleEn) {
                        if (buffer_offset >=
                            rsrc_desc.numRecords - s_offset.rawData()) {
                            DPRINTF(GCN3, "mubuf out-of-bounds condition 1: "
                                    "lane = %d, buffer_offset = %llx, "
                                    "const_stride = %llx, "
                                    "const_num_records = %llx\n",
                                    lane, buf_off + stride * buf_idx,
                                    rsrc_desc.stride, rsrc_desc.numRecords);
                            oobMask.set(lane);
                            continue;
                        }
                    }

                    if (rsrc_desc.stride != 0 && rsrc_desc.swizzleEn) {
                        if (buf_idx >= rsrc_desc.numRecords ||
                            buf_off >= stride) {
                            DPRINTF(GCN3, "mubuf out-of-bounds condition 2: "
                                    "lane = %d, offset = %llx, "
                                    "index = %llx, "
                                    "const_num_records = %llx\n",
                                    lane, buf_off, buf_idx,
                                    rsrc_desc.numRecords);
                            oobMask.set(lane);
                            continue;
                        }
                    }

                    vaddr += buffer_offset;

                    DPRINTF(GCN3, "Calculating mubuf address for lane %d: "
                            "vaddr = %llx, base_addr = %llx, "
                            "stride = %llx, buf_idx = %llx, buf_off = %llx\n",
                            lane, vaddr, base_addr, stride,
                            buf_idx, buf_off);
                    gpuDynInst->addr.at(lane) = vaddr;
                }
            }
        }

        // first instruction DWORD
        InFmt_MUBUF instData;
        // second instruction DWORD
        InFmt_MUBUF_1 extData;
        // Mask of lanes with out-of-bounds accesses.  Needs to be tracked
        // seperately from the exec_mask so that we remember to write zero
        // to the registers associated with out of bounds lanes.
        VectorMask oobMask;
    }; // Inst_MUBUF

    class Inst_MTBUF : public GCN3GPUStaticInst
    {
      public:
        Inst_MTBUF(InFmt_MTBUF*, const std::string &opcode);
        ~Inst_MTBUF();

        int instSize() const override;
        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_MTBUF instData;
        // second instruction DWORD
        InFmt_MTBUF_1 extData;

      private:
        bool hasSecondDword(InFmt_MTBUF *);
    }; // Inst_MTBUF

    class Inst_MIMG : public GCN3GPUStaticInst
    {
      public:
        Inst_MIMG(InFmt_MIMG*, const std::string &opcode);
        ~Inst_MIMG();

        int instSize() const override;
        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_MIMG instData;
        // second instruction DWORD
        InFmt_MIMG_1 extData;
    }; // Inst_MIMG

    class Inst_EXP : public GCN3GPUStaticInst
    {
      public:
        Inst_EXP(InFmt_EXP*, const std::string &opcode);
        ~Inst_EXP();

        int instSize() const override;
        void initOperandInfo() override;

      protected:
        // first instruction DWORD
        InFmt_EXP instData;
        // second instruction DWORD
        InFmt_EXP_1 extData;
    }; // Inst_EXP

    class Inst_FLAT : public GCN3GPUStaticInst
    {
      public:
        Inst_FLAT(InFmt_FLAT*, const std::string &opcode);
        ~Inst_FLAT();

        int instSize() const override;
        void generateDisassembly() override;

        void initOperandInfo() override;

      protected:
        template<typename T>
        void
        initMemRead(GPUDynInstPtr gpuDynInst)
        {
            if (gpuDynInst->executedAs() == enums::SC_GLOBAL) {
                initMemReqHelper<T, 1>(gpuDynInst, MemCmd::ReadReq);
            } else if (gpuDynInst->executedAs() == enums::SC_GROUP) {
                Wavefront *wf = gpuDynInst->wavefront();
                for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                    if (gpuDynInst->exec_mask[lane]) {
                        Addr vaddr = gpuDynInst->addr[lane];
                        (reinterpret_cast<T*>(gpuDynInst->d_data))[lane]
                            = wf->ldsChunk->read<T>(vaddr);
                    }
                }
            }
        }

        template<int N>
        void
        initMemRead(GPUDynInstPtr gpuDynInst)
        {
            if (gpuDynInst->executedAs() == enums::SC_GLOBAL) {
                initMemReqHelper<VecElemU32, N>(gpuDynInst, MemCmd::ReadReq);
            } else if (gpuDynInst->executedAs() == enums::SC_GROUP) {
                Wavefront *wf = gpuDynInst->wavefront();
                for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                    if (gpuDynInst->exec_mask[lane]) {
                        Addr vaddr = gpuDynInst->addr[lane];
                        for (int i = 0; i < N; ++i) {
                            (reinterpret_cast<VecElemU32*>(
                                gpuDynInst->d_data))[lane * N + i]
                                = wf->ldsChunk->read<VecElemU32>(
                                        vaddr + i*sizeof(VecElemU32));
                        }
                    }
                }
            }
        }

        template<typename T>
        void
        initMemWrite(GPUDynInstPtr gpuDynInst)
        {
            if (gpuDynInst->executedAs() == enums::SC_GLOBAL) {
                initMemReqHelper<T, 1>(gpuDynInst, MemCmd::WriteReq);
            } else if (gpuDynInst->executedAs() == enums::SC_GROUP) {
                Wavefront *wf = gpuDynInst->wavefront();
                for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                    if (gpuDynInst->exec_mask[lane]) {
                        Addr vaddr = gpuDynInst->addr[lane];
                        wf->ldsChunk->write<T>(vaddr,
                            (reinterpret_cast<T*>(gpuDynInst->d_data))[lane]);
                    }
                }
            }
        }

        template<int N>
        void
        initMemWrite(GPUDynInstPtr gpuDynInst)
        {
            if (gpuDynInst->executedAs() == enums::SC_GLOBAL) {
                initMemReqHelper<VecElemU32, N>(gpuDynInst, MemCmd::WriteReq);
            } else if (gpuDynInst->executedAs() == enums::SC_GROUP) {
                Wavefront *wf = gpuDynInst->wavefront();
                for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                    if (gpuDynInst->exec_mask[lane]) {
                        Addr vaddr = gpuDynInst->addr[lane];
                        for (int i = 0; i < N; ++i) {
                            wf->ldsChunk->write<VecElemU32>(
                                vaddr + i*sizeof(VecElemU32),
                                (reinterpret_cast<VecElemU32*>(
                                    gpuDynInst->d_data))[lane * N + i]);
                        }
                    }
                }
            }
        }

        template<typename T>
        void
        initAtomicAccess(GPUDynInstPtr gpuDynInst)
        {
            if (gpuDynInst->executedAs() == enums::SC_GLOBAL) {
                initMemReqHelper<T, 1>(gpuDynInst, MemCmd::SwapReq, true);
            } else if (gpuDynInst->executedAs() == enums::SC_GROUP) {
                Wavefront *wf = gpuDynInst->wavefront();
                for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                    if (gpuDynInst->exec_mask[lane]) {
                        Addr vaddr = gpuDynInst->addr[lane];
                        auto amo_op =
                            gpuDynInst->makeAtomicOpFunctor<T>(
                                &(reinterpret_cast<T*>(
                                    gpuDynInst->a_data))[lane],
                                &(reinterpret_cast<T*>(
                                    gpuDynInst->x_data))[lane]);

                        T tmp = wf->ldsChunk->read<T>(vaddr);
                        (*amo_op)(reinterpret_cast<uint8_t *>(&tmp));
                        wf->ldsChunk->write<T>(vaddr, tmp);
                        (reinterpret_cast<T*>(gpuDynInst->d_data))[lane] = tmp;
                    }
                }
            }
        }

        void
        calcAddr(GPUDynInstPtr gpuDynInst, ConstVecOperandU64 &addr)
        {
            for (int lane = 0; lane < NumVecElemPerVecReg; ++lane) {
                if (gpuDynInst->exec_mask[lane]) {
                    gpuDynInst->addr.at(lane) = addr[lane];
                }
            }
            gpuDynInst->resolveFlatSegment(gpuDynInst->exec_mask);
        }

        // first instruction DWORD
        InFmt_FLAT instData;
        // second instruction DWORD
        InFmt_FLAT_1 extData;
    }; // Inst_FLAT
} // namespace Gcn3ISA
} // namespace gem5

#endif // __ARCH_GCN3_INSTS_OP_ENCODINGS_HH__
