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_BRANCH_HH__
3711308Santhony.gutierrez@amd.com#define __ARCH_HSAIL_INSTS_BRANCH_HH__
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.com#include "arch/hsail/insts/gpu_static_inst.hh"
4011308Santhony.gutierrez@amd.com#include "arch/hsail/operand.hh"
4111308Santhony.gutierrez@amd.com#include "gpu-compute/gpu_dyn_inst.hh"
4211308Santhony.gutierrez@amd.com#include "gpu-compute/wavefront.hh"
4311308Santhony.gutierrez@amd.com
4411308Santhony.gutierrez@amd.comnamespace HsailISA
4511308Santhony.gutierrez@amd.com{
4611308Santhony.gutierrez@amd.com
4711308Santhony.gutierrez@amd.com    // The main difference between a direct branch and an indirect branch
4811308Santhony.gutierrez@amd.com    // is whether the target is a register or a label, so we can share a
4911308Santhony.gutierrez@amd.com    // lot of code if we template the base implementation on that type.
5011308Santhony.gutierrez@amd.com    template<typename TargetType>
5111308Santhony.gutierrez@amd.com    class BrnInstBase : public HsailGPUStaticInst
5211308Santhony.gutierrez@amd.com    {
5311308Santhony.gutierrez@amd.com    public:
5411347Sandreas.hansson@arm.com        void generateDisassembly() override;
5511308Santhony.gutierrez@amd.com
5611308Santhony.gutierrez@amd.com        Brig::BrigWidth8_t width;
5711308Santhony.gutierrez@amd.com        TargetType target;
5811308Santhony.gutierrez@amd.com
5911308Santhony.gutierrez@amd.com        BrnInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj)
6011308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, "brn")
6111308Santhony.gutierrez@amd.com        {
6211692Santhony.gutierrez@amd.com            setFlag(Branch);
6311692Santhony.gutierrez@amd.com            setFlag(UnconditionalJump);
6411308Santhony.gutierrez@amd.com            width = ((Brig::BrigInstBr*)ib)->width;
6511308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
6611308Santhony.gutierrez@amd.com            target.init(op_offs, obj);
6711308Santhony.gutierrez@amd.com        }
6811308Santhony.gutierrez@amd.com
6911308Santhony.gutierrez@amd.com        uint32_t getTargetPc()  override { return target.getTarget(0, 0); }
7011308Santhony.gutierrez@amd.com
7111347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override {
7211308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
7311308Santhony.gutierrez@amd.com            return target.isVectorRegister();
7411308Santhony.gutierrez@amd.com        }
7511347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override {
7611308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
7711308Santhony.gutierrez@amd.com            return target.isCondRegister();
7811308Santhony.gutierrez@amd.com        }
7911347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override {
8011308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
8111308Santhony.gutierrez@amd.com            return target.isScalarRegister();
8211308Santhony.gutierrez@amd.com        }
8311308Santhony.gutierrez@amd.com
8411347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override {
8511308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
8611308Santhony.gutierrez@amd.com            return true;
8711308Santhony.gutierrez@amd.com        }
8811308Santhony.gutierrez@amd.com
8911347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override {
9011308Santhony.gutierrez@amd.com            return false;
9111308Santhony.gutierrez@amd.com        }
9211308Santhony.gutierrez@amd.com
9311347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override {
9411308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
9511308Santhony.gutierrez@amd.com            return target.opSize();
9611308Santhony.gutierrez@amd.com        }
9711308Santhony.gutierrez@amd.com
9811699Santhony.gutierrez@amd.com        int
9911699Santhony.gutierrez@amd.com        getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override
10011699Santhony.gutierrez@amd.com        {
10111308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
10211308Santhony.gutierrez@amd.com            return target.regIndex();
10311308Santhony.gutierrez@amd.com        }
10411308Santhony.gutierrez@amd.com
10511347Sandreas.hansson@arm.com        int getNumOperands() override {
10611308Santhony.gutierrez@amd.com            return 1;
10711308Santhony.gutierrez@amd.com        }
10811308Santhony.gutierrez@amd.com
10911347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
11011308Santhony.gutierrez@amd.com    };
11111308Santhony.gutierrez@amd.com
11211308Santhony.gutierrez@amd.com    template<typename TargetType>
11311308Santhony.gutierrez@amd.com    void
11411308Santhony.gutierrez@amd.com    BrnInstBase<TargetType>::generateDisassembly()
11511308Santhony.gutierrez@amd.com    {
11611308Santhony.gutierrez@amd.com        std::string widthClause;
11711308Santhony.gutierrez@amd.com
11811308Santhony.gutierrez@amd.com        if (width != 1) {
11911308Santhony.gutierrez@amd.com            widthClause = csprintf("_width(%d)", width);
12011308Santhony.gutierrez@amd.com        }
12111308Santhony.gutierrez@amd.com
12211308Santhony.gutierrez@amd.com        disassembly = csprintf("%s%s %s", opcode, widthClause,
12311308Santhony.gutierrez@amd.com                               target.disassemble());
12411308Santhony.gutierrez@amd.com    }
12511308Santhony.gutierrez@amd.com
12611308Santhony.gutierrez@amd.com    template<typename TargetType>
12711308Santhony.gutierrez@amd.com    void
12811308Santhony.gutierrez@amd.com    BrnInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst)
12911308Santhony.gutierrez@amd.com    {
13011308Santhony.gutierrez@amd.com        Wavefront *w = gpuDynInst->wavefront();
13111308Santhony.gutierrez@amd.com
13211308Santhony.gutierrez@amd.com        if (getTargetPc() == w->rpc()) {
13311308Santhony.gutierrez@amd.com            w->popFromReconvergenceStack();
13411308Santhony.gutierrez@amd.com        } else {
13511308Santhony.gutierrez@amd.com            // Rpc and execution mask remain the same
13611308Santhony.gutierrez@amd.com            w->pc(getTargetPc());
13711308Santhony.gutierrez@amd.com        }
13811308Santhony.gutierrez@amd.com    }
13911308Santhony.gutierrez@amd.com
14011308Santhony.gutierrez@amd.com    class BrnDirectInst : public BrnInstBase<LabelOperand>
14111308Santhony.gutierrez@amd.com    {
14211308Santhony.gutierrez@amd.com      public:
14311308Santhony.gutierrez@amd.com        BrnDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
14411308Santhony.gutierrez@amd.com            : BrnInstBase<LabelOperand>(ib, obj)
14511308Santhony.gutierrez@amd.com        {
14611308Santhony.gutierrez@amd.com        }
14711308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
14811308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
14911308Santhony.gutierrez@amd.com    };
15011308Santhony.gutierrez@amd.com
15111308Santhony.gutierrez@amd.com    class BrnIndirectInst : public BrnInstBase<SRegOperand>
15211308Santhony.gutierrez@amd.com    {
15311308Santhony.gutierrez@amd.com      public:
15411308Santhony.gutierrez@amd.com        BrnIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
15511308Santhony.gutierrez@amd.com            : BrnInstBase<SRegOperand>(ib, obj)
15611308Santhony.gutierrez@amd.com        {
15711308Santhony.gutierrez@amd.com        }
15811308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return target.isVectorRegister(); }
15911308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
16011308Santhony.gutierrez@amd.com    };
16111308Santhony.gutierrez@amd.com
16211308Santhony.gutierrez@amd.com    GPUStaticInst* decodeBrn(const Brig::BrigInstBase *ib,
16311308Santhony.gutierrez@amd.com                             const BrigObject *obj);
16411308Santhony.gutierrez@amd.com
16511308Santhony.gutierrez@amd.com    template<typename TargetType>
16611308Santhony.gutierrez@amd.com    class CbrInstBase : public HsailGPUStaticInst
16711308Santhony.gutierrez@amd.com    {
16811308Santhony.gutierrez@amd.com      public:
16911347Sandreas.hansson@arm.com        void generateDisassembly() override;
17011308Santhony.gutierrez@amd.com
17111308Santhony.gutierrez@amd.com        Brig::BrigWidth8_t width;
17211308Santhony.gutierrez@amd.com        CRegOperand cond;
17311308Santhony.gutierrez@amd.com        TargetType target;
17411308Santhony.gutierrez@amd.com
17511308Santhony.gutierrez@amd.com        CbrInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj)
17611308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, "cbr")
17711308Santhony.gutierrez@amd.com        {
17811692Santhony.gutierrez@amd.com            setFlag(Branch);
17911308Santhony.gutierrez@amd.com            width = ((Brig::BrigInstBr *)ib)->width;
18011308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
18111308Santhony.gutierrez@amd.com            cond.init(op_offs, obj);
18211308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
18311308Santhony.gutierrez@amd.com            target.init(op_offs, obj);
18411308Santhony.gutierrez@amd.com        }
18511308Santhony.gutierrez@amd.com
18611308Santhony.gutierrez@amd.com        uint32_t getTargetPc() override { return target.getTarget(0, 0); }
18711308Santhony.gutierrez@amd.com
18811347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
18911308Santhony.gutierrez@amd.com        // Assumption: Target is operand 0, Condition Register is operand 1
19011347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override {
19111308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
19211308Santhony.gutierrez@amd.com            if (!operandIndex)
19311308Santhony.gutierrez@amd.com                return target.isVectorRegister();
19411308Santhony.gutierrez@amd.com            else
19511308Santhony.gutierrez@amd.com                return false;
19611308Santhony.gutierrez@amd.com        }
19711347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override {
19811308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
19911308Santhony.gutierrez@amd.com            if (!operandIndex)
20011308Santhony.gutierrez@amd.com                return target.isCondRegister();
20111308Santhony.gutierrez@amd.com            else
20211308Santhony.gutierrez@amd.com                return true;
20311308Santhony.gutierrez@amd.com        }
20411347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override {
20511308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
20611308Santhony.gutierrez@amd.com            if (!operandIndex)
20711308Santhony.gutierrez@amd.com                return target.isScalarRegister();
20811308Santhony.gutierrez@amd.com            else
20911308Santhony.gutierrez@amd.com                return false;
21011308Santhony.gutierrez@amd.com        }
21111347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override {
21211308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
21311308Santhony.gutierrez@amd.com            if (operandIndex == 0)
21411308Santhony.gutierrez@amd.com                return true;
21511308Santhony.gutierrez@amd.com            return false;
21611308Santhony.gutierrez@amd.com        }
21711308Santhony.gutierrez@amd.com        // both Condition Register and Target are source operands
21811347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override {
21911308Santhony.gutierrez@amd.com            return false;
22011308Santhony.gutierrez@amd.com        }
22111347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override {
22211308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
22311308Santhony.gutierrez@amd.com            if (!operandIndex)
22411308Santhony.gutierrez@amd.com                return target.opSize();
22511308Santhony.gutierrez@amd.com            else
22611308Santhony.gutierrez@amd.com                return 1;
22711308Santhony.gutierrez@amd.com        }
22811699Santhony.gutierrez@amd.com        int
22911699Santhony.gutierrez@amd.com        getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override
23011699Santhony.gutierrez@amd.com        {
23111308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
23211308Santhony.gutierrez@amd.com            if (!operandIndex)
23311308Santhony.gutierrez@amd.com                return target.regIndex();
23411308Santhony.gutierrez@amd.com            else
23511308Santhony.gutierrez@amd.com                return -1;
23611308Santhony.gutierrez@amd.com         }
23711308Santhony.gutierrez@amd.com
23811308Santhony.gutierrez@amd.com        // Operands = Target, Condition Register
23911347Sandreas.hansson@arm.com        int getNumOperands() override {
24011308Santhony.gutierrez@amd.com            return 2;
24111308Santhony.gutierrez@amd.com        }
24211308Santhony.gutierrez@amd.com    };
24311308Santhony.gutierrez@amd.com
24411308Santhony.gutierrez@amd.com    template<typename TargetType>
24511308Santhony.gutierrez@amd.com    void
24611308Santhony.gutierrez@amd.com    CbrInstBase<TargetType>::generateDisassembly()
24711308Santhony.gutierrez@amd.com    {
24811308Santhony.gutierrez@amd.com        std::string widthClause;
24911308Santhony.gutierrez@amd.com
25011308Santhony.gutierrez@amd.com        if (width != 1) {
25111308Santhony.gutierrez@amd.com            widthClause = csprintf("_width(%d)", width);
25211308Santhony.gutierrez@amd.com        }
25311308Santhony.gutierrez@amd.com
25411308Santhony.gutierrez@amd.com        disassembly = csprintf("%s%s %s,%s", opcode, widthClause,
25511308Santhony.gutierrez@amd.com                               cond.disassemble(), target.disassemble());
25611308Santhony.gutierrez@amd.com    }
25711308Santhony.gutierrez@amd.com
25811308Santhony.gutierrez@amd.com    template<typename TargetType>
25911308Santhony.gutierrez@amd.com    void
26011308Santhony.gutierrez@amd.com    CbrInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst)
26111308Santhony.gutierrez@amd.com    {
26211308Santhony.gutierrez@amd.com        Wavefront *w = gpuDynInst->wavefront();
26311308Santhony.gutierrez@amd.com
26411697Santhony.gutierrez@amd.com        const uint32_t curr_pc M5_VAR_USED = w->pc();
26511308Santhony.gutierrez@amd.com        const uint32_t curr_rpc = w->rpc();
26611308Santhony.gutierrez@amd.com        const VectorMask curr_mask = w->execMask();
26711308Santhony.gutierrez@amd.com
26811308Santhony.gutierrez@amd.com        /**
26911308Santhony.gutierrez@amd.com         * TODO: can we move this pop outside the instruction, and
27011308Santhony.gutierrez@amd.com         * into the wavefront?
27111308Santhony.gutierrez@amd.com         */
27211308Santhony.gutierrez@amd.com        w->popFromReconvergenceStack();
27311308Santhony.gutierrez@amd.com
27411308Santhony.gutierrez@amd.com        // immediate post-dominator instruction
27511308Santhony.gutierrez@amd.com        const uint32_t rpc = static_cast<uint32_t>(ipdInstNum());
27611308Santhony.gutierrez@amd.com        if (curr_rpc != rpc) {
27711308Santhony.gutierrez@amd.com            w->pushToReconvergenceStack(rpc, curr_rpc, curr_mask);
27811308Santhony.gutierrez@amd.com        }
27911308Santhony.gutierrez@amd.com
28011308Santhony.gutierrez@amd.com        // taken branch
28111308Santhony.gutierrez@amd.com        const uint32_t true_pc = getTargetPc();
28211308Santhony.gutierrez@amd.com        VectorMask true_mask;
28311534Sjohn.kalamatianos@amd.com        for (unsigned int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
28411308Santhony.gutierrez@amd.com            true_mask[lane] = cond.get<bool>(w, lane) & curr_mask[lane];
28511308Santhony.gutierrez@amd.com        }
28611308Santhony.gutierrez@amd.com
28711308Santhony.gutierrez@amd.com        // not taken branch
28811697Santhony.gutierrez@amd.com        const uint32_t false_pc = nextInstAddr();
28911308Santhony.gutierrez@amd.com        assert(true_pc != false_pc);
29011308Santhony.gutierrez@amd.com        if (false_pc != rpc && true_mask.count() < curr_mask.count()) {
29111308Santhony.gutierrez@amd.com            VectorMask false_mask = curr_mask & ~true_mask;
29211308Santhony.gutierrez@amd.com            w->pushToReconvergenceStack(false_pc, rpc, false_mask);
29311308Santhony.gutierrez@amd.com        }
29411308Santhony.gutierrez@amd.com
29511308Santhony.gutierrez@amd.com        if (true_pc != rpc && true_mask.count()) {
29611308Santhony.gutierrez@amd.com            w->pushToReconvergenceStack(true_pc, rpc, true_mask);
29711308Santhony.gutierrez@amd.com        }
29811308Santhony.gutierrez@amd.com        assert(w->pc() != curr_pc);
29911308Santhony.gutierrez@amd.com    }
30011308Santhony.gutierrez@amd.com
30111308Santhony.gutierrez@amd.com
30211308Santhony.gutierrez@amd.com    class CbrDirectInst : public CbrInstBase<LabelOperand>
30311308Santhony.gutierrez@amd.com    {
30411308Santhony.gutierrez@amd.com      public:
30511308Santhony.gutierrez@amd.com        CbrDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
30611308Santhony.gutierrez@amd.com            : CbrInstBase<LabelOperand>(ib, obj)
30711308Santhony.gutierrez@amd.com        {
30811308Santhony.gutierrez@amd.com        }
30911308Santhony.gutierrez@amd.com        // the source operand of a conditional branch is a Condition
31011308Santhony.gutierrez@amd.com        // Register which is not stored in the VRF
31111308Santhony.gutierrez@amd.com        // so we do not count it as a source-register operand
31211308Santhony.gutierrez@amd.com        // even though, formally, it is one.
31311308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
31411308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
31511308Santhony.gutierrez@amd.com    };
31611308Santhony.gutierrez@amd.com
31711308Santhony.gutierrez@amd.com    class CbrIndirectInst : public CbrInstBase<SRegOperand>
31811308Santhony.gutierrez@amd.com    {
31911308Santhony.gutierrez@amd.com      public:
32011308Santhony.gutierrez@amd.com        CbrIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
32111308Santhony.gutierrez@amd.com            : CbrInstBase<SRegOperand>(ib, obj)
32211308Santhony.gutierrez@amd.com        {
32311308Santhony.gutierrez@amd.com        }
32411308Santhony.gutierrez@amd.com        // one source operand of the conditional indirect branch is a Condition
32511308Santhony.gutierrez@amd.com        // register which is not stored in the VRF so we do not count it
32611308Santhony.gutierrez@amd.com        // as a source-register operand even though, formally, it is one.
32711308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return target.isVectorRegister(); }
32811308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
32911308Santhony.gutierrez@amd.com    };
33011308Santhony.gutierrez@amd.com
33111308Santhony.gutierrez@amd.com    GPUStaticInst* decodeCbr(const Brig::BrigInstBase *ib,
33211308Santhony.gutierrez@amd.com                             const BrigObject *obj);
33311308Santhony.gutierrez@amd.com
33411308Santhony.gutierrez@amd.com    template<typename TargetType>
33511308Santhony.gutierrez@amd.com    class BrInstBase : public HsailGPUStaticInst
33611308Santhony.gutierrez@amd.com    {
33711308Santhony.gutierrez@amd.com      public:
33811347Sandreas.hansson@arm.com        void generateDisassembly() override;
33911308Santhony.gutierrez@amd.com
34011308Santhony.gutierrez@amd.com        ImmOperand<uint32_t> width;
34111308Santhony.gutierrez@amd.com        TargetType target;
34211308Santhony.gutierrez@amd.com
34311308Santhony.gutierrez@amd.com        BrInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj)
34411308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, "br")
34511308Santhony.gutierrez@amd.com        {
34611692Santhony.gutierrez@amd.com            setFlag(Branch);
34711692Santhony.gutierrez@amd.com            setFlag(UnconditionalJump);
34811308Santhony.gutierrez@amd.com            width.init(((Brig::BrigInstBr *)ib)->width, obj);
34911308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
35011308Santhony.gutierrez@amd.com            target.init(op_offs, obj);
35111308Santhony.gutierrez@amd.com        }
35211308Santhony.gutierrez@amd.com
35311308Santhony.gutierrez@amd.com        uint32_t getTargetPc() override { return target.getTarget(0, 0); }
35411308Santhony.gutierrez@amd.com
35511347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
35611347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override {
35711308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
35811308Santhony.gutierrez@amd.com            return target.isVectorRegister();
35911308Santhony.gutierrez@amd.com        }
36011347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override {
36111308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
36211308Santhony.gutierrez@amd.com            return target.isCondRegister();
36311308Santhony.gutierrez@amd.com        }
36411347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override {
36511308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
36611308Santhony.gutierrez@amd.com            return target.isScalarRegister();
36711308Santhony.gutierrez@amd.com        }
36811347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override {
36911308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
37011308Santhony.gutierrez@amd.com            return true;
37111308Santhony.gutierrez@amd.com        }
37211347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override { return false; }
37311347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override {
37411308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
37511308Santhony.gutierrez@amd.com            return target.opSize();
37611308Santhony.gutierrez@amd.com        }
37711699Santhony.gutierrez@amd.com        int
37811699Santhony.gutierrez@amd.com        getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override
37911699Santhony.gutierrez@amd.com        {
38011308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
38111308Santhony.gutierrez@amd.com            return target.regIndex();
38211308Santhony.gutierrez@amd.com        }
38311347Sandreas.hansson@arm.com        int getNumOperands() override { return 1; }
38411308Santhony.gutierrez@amd.com    };
38511308Santhony.gutierrez@amd.com
38611308Santhony.gutierrez@amd.com    template<typename TargetType>
38711308Santhony.gutierrez@amd.com    void
38811308Santhony.gutierrez@amd.com    BrInstBase<TargetType>::generateDisassembly()
38911308Santhony.gutierrez@amd.com    {
39011308Santhony.gutierrez@amd.com        std::string widthClause;
39111308Santhony.gutierrez@amd.com
39211308Santhony.gutierrez@amd.com        if (width.bits != 1) {
39311308Santhony.gutierrez@amd.com            widthClause = csprintf("_width(%d)", width.bits);
39411308Santhony.gutierrez@amd.com        }
39511308Santhony.gutierrez@amd.com
39611308Santhony.gutierrez@amd.com        disassembly = csprintf("%s%s %s", opcode, widthClause,
39711308Santhony.gutierrez@amd.com                               target.disassemble());
39811308Santhony.gutierrez@amd.com    }
39911308Santhony.gutierrez@amd.com
40011308Santhony.gutierrez@amd.com    template<typename TargetType>
40111308Santhony.gutierrez@amd.com    void
40211308Santhony.gutierrez@amd.com    BrInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst)
40311308Santhony.gutierrez@amd.com    {
40411308Santhony.gutierrez@amd.com        Wavefront *w = gpuDynInst->wavefront();
40511308Santhony.gutierrez@amd.com
40611308Santhony.gutierrez@amd.com        if (getTargetPc() == w->rpc()) {
40711308Santhony.gutierrez@amd.com            w->popFromReconvergenceStack();
40811308Santhony.gutierrez@amd.com        } else {
40911308Santhony.gutierrez@amd.com            // Rpc and execution mask remain the same
41011308Santhony.gutierrez@amd.com            w->pc(getTargetPc());
41111308Santhony.gutierrez@amd.com        }
41211308Santhony.gutierrez@amd.com    }
41311308Santhony.gutierrez@amd.com
41411308Santhony.gutierrez@amd.com    class BrDirectInst : public BrInstBase<LabelOperand>
41511308Santhony.gutierrez@amd.com    {
41611308Santhony.gutierrez@amd.com      public:
41711308Santhony.gutierrez@amd.com        BrDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
41811308Santhony.gutierrez@amd.com            : BrInstBase<LabelOperand>(ib, obj)
41911308Santhony.gutierrez@amd.com        {
42011308Santhony.gutierrez@amd.com        }
42111308Santhony.gutierrez@amd.com
42211308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
42311308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
42411308Santhony.gutierrez@amd.com    };
42511308Santhony.gutierrez@amd.com
42611308Santhony.gutierrez@amd.com    class BrIndirectInst : public BrInstBase<SRegOperand>
42711308Santhony.gutierrez@amd.com    {
42811308Santhony.gutierrez@amd.com      public:
42911308Santhony.gutierrez@amd.com        BrIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
43011308Santhony.gutierrez@amd.com            : BrInstBase<SRegOperand>(ib, obj)
43111308Santhony.gutierrez@amd.com        {
43211308Santhony.gutierrez@amd.com        }
43311308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return target.isVectorRegister(); }
43411308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
43511308Santhony.gutierrez@amd.com    };
43611308Santhony.gutierrez@amd.com
43711308Santhony.gutierrez@amd.com    GPUStaticInst* decodeBr(const Brig::BrigInstBase *ib,
43811308Santhony.gutierrez@amd.com                            const BrigObject *obj);
43911308Santhony.gutierrez@amd.com} // namespace HsailISA
44011308Santhony.gutierrez@amd.com
44111308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_BRANCH_HH__
442