branch.hh revision 11534
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        {
6211308Santhony.gutierrez@amd.com            o_type = Enums::OT_BRANCH;
6311308Santhony.gutierrez@amd.com            width = ((Brig::BrigInstBr*)ib)->width;
6411308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
6511308Santhony.gutierrez@amd.com            target.init(op_offs, obj);
6611308Santhony.gutierrez@amd.com            o_type = Enums::OT_BRANCH;
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
7111308Santhony.gutierrez@amd.com        bool unconditionalJumpInstruction() override { return true; }
7211347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override {
7311308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
7411308Santhony.gutierrez@amd.com            return target.isVectorRegister();
7511308Santhony.gutierrez@amd.com        }
7611347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override {
7711308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
7811308Santhony.gutierrez@amd.com            return target.isCondRegister();
7911308Santhony.gutierrez@amd.com        }
8011347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override {
8111308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
8211308Santhony.gutierrez@amd.com            return target.isScalarRegister();
8311308Santhony.gutierrez@amd.com        }
8411308Santhony.gutierrez@amd.com
8511347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override {
8611308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
8711308Santhony.gutierrez@amd.com            return true;
8811308Santhony.gutierrez@amd.com        }
8911308Santhony.gutierrez@amd.com
9011347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override {
9111308Santhony.gutierrez@amd.com            return false;
9211308Santhony.gutierrez@amd.com        }
9311308Santhony.gutierrez@amd.com
9411347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override {
9511308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
9611308Santhony.gutierrez@amd.com            return target.opSize();
9711308Santhony.gutierrez@amd.com        }
9811308Santhony.gutierrez@amd.com
9911347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override {
10011308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
10111308Santhony.gutierrez@amd.com            return target.regIndex();
10211308Santhony.gutierrez@amd.com        }
10311308Santhony.gutierrez@amd.com
10411347Sandreas.hansson@arm.com        int getNumOperands() override {
10511308Santhony.gutierrez@amd.com            return 1;
10611308Santhony.gutierrez@amd.com        }
10711308Santhony.gutierrez@amd.com
10811347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
10911308Santhony.gutierrez@amd.com    };
11011308Santhony.gutierrez@amd.com
11111308Santhony.gutierrez@amd.com    template<typename TargetType>
11211308Santhony.gutierrez@amd.com    void
11311308Santhony.gutierrez@amd.com    BrnInstBase<TargetType>::generateDisassembly()
11411308Santhony.gutierrez@amd.com    {
11511308Santhony.gutierrez@amd.com        std::string widthClause;
11611308Santhony.gutierrez@amd.com
11711308Santhony.gutierrez@amd.com        if (width != 1) {
11811308Santhony.gutierrez@amd.com            widthClause = csprintf("_width(%d)", width);
11911308Santhony.gutierrez@amd.com        }
12011308Santhony.gutierrez@amd.com
12111308Santhony.gutierrez@amd.com        disassembly = csprintf("%s%s %s", opcode, widthClause,
12211308Santhony.gutierrez@amd.com                               target.disassemble());
12311308Santhony.gutierrez@amd.com    }
12411308Santhony.gutierrez@amd.com
12511308Santhony.gutierrez@amd.com    template<typename TargetType>
12611308Santhony.gutierrez@amd.com    void
12711308Santhony.gutierrez@amd.com    BrnInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst)
12811308Santhony.gutierrez@amd.com    {
12911308Santhony.gutierrez@amd.com        Wavefront *w = gpuDynInst->wavefront();
13011308Santhony.gutierrez@amd.com
13111308Santhony.gutierrez@amd.com        if (getTargetPc() == w->rpc()) {
13211308Santhony.gutierrez@amd.com            w->popFromReconvergenceStack();
13311308Santhony.gutierrez@amd.com        } else {
13411308Santhony.gutierrez@amd.com            // Rpc and execution mask remain the same
13511308Santhony.gutierrez@amd.com            w->pc(getTargetPc());
13611308Santhony.gutierrez@amd.com        }
13711308Santhony.gutierrez@amd.com        w->discardFetch();
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        {
17811308Santhony.gutierrez@amd.com            o_type = Enums::OT_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            o_type = Enums::OT_BRANCH;
18511308Santhony.gutierrez@amd.com        }
18611308Santhony.gutierrez@amd.com
18711308Santhony.gutierrez@amd.com        uint32_t getTargetPc() override { return target.getTarget(0, 0); }
18811308Santhony.gutierrez@amd.com
18911347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
19011308Santhony.gutierrez@amd.com        // Assumption: Target is operand 0, Condition Register is operand 1
19111347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override {
19211308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
19311308Santhony.gutierrez@amd.com            if (!operandIndex)
19411308Santhony.gutierrez@amd.com                return target.isVectorRegister();
19511308Santhony.gutierrez@amd.com            else
19611308Santhony.gutierrez@amd.com                return false;
19711308Santhony.gutierrez@amd.com        }
19811347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override {
19911308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
20011308Santhony.gutierrez@amd.com            if (!operandIndex)
20111308Santhony.gutierrez@amd.com                return target.isCondRegister();
20211308Santhony.gutierrez@amd.com            else
20311308Santhony.gutierrez@amd.com                return true;
20411308Santhony.gutierrez@amd.com        }
20511347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override {
20611308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
20711308Santhony.gutierrez@amd.com            if (!operandIndex)
20811308Santhony.gutierrez@amd.com                return target.isScalarRegister();
20911308Santhony.gutierrez@amd.com            else
21011308Santhony.gutierrez@amd.com                return false;
21111308Santhony.gutierrez@amd.com        }
21211347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override {
21311308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
21411308Santhony.gutierrez@amd.com            if (operandIndex == 0)
21511308Santhony.gutierrez@amd.com                return true;
21611308Santhony.gutierrez@amd.com            return false;
21711308Santhony.gutierrez@amd.com        }
21811308Santhony.gutierrez@amd.com        // both Condition Register and Target are source operands
21911347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override {
22011308Santhony.gutierrez@amd.com            return false;
22111308Santhony.gutierrez@amd.com        }
22211347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override {
22311308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
22411308Santhony.gutierrez@amd.com            if (!operandIndex)
22511308Santhony.gutierrez@amd.com                return target.opSize();
22611308Santhony.gutierrez@amd.com            else
22711308Santhony.gutierrez@amd.com                return 1;
22811308Santhony.gutierrez@amd.com        }
22911347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override {
23011308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
23111308Santhony.gutierrez@amd.com            if (!operandIndex)
23211308Santhony.gutierrez@amd.com                return target.regIndex();
23311308Santhony.gutierrez@amd.com            else
23411308Santhony.gutierrez@amd.com                return -1;
23511308Santhony.gutierrez@amd.com         }
23611308Santhony.gutierrez@amd.com
23711308Santhony.gutierrez@amd.com        // Operands = Target, Condition Register
23811347Sandreas.hansson@arm.com        int getNumOperands() override {
23911308Santhony.gutierrez@amd.com            return 2;
24011308Santhony.gutierrez@amd.com        }
24111308Santhony.gutierrez@amd.com    };
24211308Santhony.gutierrez@amd.com
24311308Santhony.gutierrez@amd.com    template<typename TargetType>
24411308Santhony.gutierrez@amd.com    void
24511308Santhony.gutierrez@amd.com    CbrInstBase<TargetType>::generateDisassembly()
24611308Santhony.gutierrez@amd.com    {
24711308Santhony.gutierrez@amd.com        std::string widthClause;
24811308Santhony.gutierrez@amd.com
24911308Santhony.gutierrez@amd.com        if (width != 1) {
25011308Santhony.gutierrez@amd.com            widthClause = csprintf("_width(%d)", width);
25111308Santhony.gutierrez@amd.com        }
25211308Santhony.gutierrez@amd.com
25311308Santhony.gutierrez@amd.com        disassembly = csprintf("%s%s %s,%s", opcode, widthClause,
25411308Santhony.gutierrez@amd.com                               cond.disassemble(), target.disassemble());
25511308Santhony.gutierrez@amd.com    }
25611308Santhony.gutierrez@amd.com
25711308Santhony.gutierrez@amd.com    template<typename TargetType>
25811308Santhony.gutierrez@amd.com    void
25911308Santhony.gutierrez@amd.com    CbrInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst)
26011308Santhony.gutierrez@amd.com    {
26111308Santhony.gutierrez@amd.com        Wavefront *w = gpuDynInst->wavefront();
26211308Santhony.gutierrez@amd.com
26311308Santhony.gutierrez@amd.com        const uint32_t curr_pc = w->pc();
26411308Santhony.gutierrez@amd.com        const uint32_t curr_rpc = w->rpc();
26511308Santhony.gutierrez@amd.com        const VectorMask curr_mask = w->execMask();
26611308Santhony.gutierrez@amd.com
26711308Santhony.gutierrez@amd.com        /**
26811308Santhony.gutierrez@amd.com         * TODO: can we move this pop outside the instruction, and
26911308Santhony.gutierrez@amd.com         * into the wavefront?
27011308Santhony.gutierrez@amd.com         */
27111308Santhony.gutierrez@amd.com        w->popFromReconvergenceStack();
27211308Santhony.gutierrez@amd.com
27311308Santhony.gutierrez@amd.com        // immediate post-dominator instruction
27411308Santhony.gutierrez@amd.com        const uint32_t rpc = static_cast<uint32_t>(ipdInstNum());
27511308Santhony.gutierrez@amd.com        if (curr_rpc != rpc) {
27611308Santhony.gutierrez@amd.com            w->pushToReconvergenceStack(rpc, curr_rpc, curr_mask);
27711308Santhony.gutierrez@amd.com        }
27811308Santhony.gutierrez@amd.com
27911308Santhony.gutierrez@amd.com        // taken branch
28011308Santhony.gutierrez@amd.com        const uint32_t true_pc = getTargetPc();
28111308Santhony.gutierrez@amd.com        VectorMask true_mask;
28211534Sjohn.kalamatianos@amd.com        for (unsigned int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
28311308Santhony.gutierrez@amd.com            true_mask[lane] = cond.get<bool>(w, lane) & curr_mask[lane];
28411308Santhony.gutierrez@amd.com        }
28511308Santhony.gutierrez@amd.com
28611308Santhony.gutierrez@amd.com        // not taken branch
28711308Santhony.gutierrez@amd.com        const uint32_t false_pc = curr_pc + 1;
28811308Santhony.gutierrez@amd.com        assert(true_pc != false_pc);
28911308Santhony.gutierrez@amd.com        if (false_pc != rpc && true_mask.count() < curr_mask.count()) {
29011308Santhony.gutierrez@amd.com            VectorMask false_mask = curr_mask & ~true_mask;
29111308Santhony.gutierrez@amd.com            w->pushToReconvergenceStack(false_pc, rpc, false_mask);
29211308Santhony.gutierrez@amd.com        }
29311308Santhony.gutierrez@amd.com
29411308Santhony.gutierrez@amd.com        if (true_pc != rpc && true_mask.count()) {
29511308Santhony.gutierrez@amd.com            w->pushToReconvergenceStack(true_pc, rpc, true_mask);
29611308Santhony.gutierrez@amd.com        }
29711308Santhony.gutierrez@amd.com        assert(w->pc() != curr_pc);
29811308Santhony.gutierrez@amd.com        w->discardFetch();
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        {
34611308Santhony.gutierrez@amd.com            o_type = Enums::OT_BRANCH;
34711308Santhony.gutierrez@amd.com            width.init(((Brig::BrigInstBr *)ib)->width, obj);
34811308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
34911308Santhony.gutierrez@amd.com            target.init(op_offs, obj);
35011308Santhony.gutierrez@amd.com            o_type = Enums::OT_BRANCH;
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
35511308Santhony.gutierrez@amd.com        bool unconditionalJumpInstruction() override { return true; }
35611308Santhony.gutierrez@amd.com
35711347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
35811347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override {
35911308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
36011308Santhony.gutierrez@amd.com            return target.isVectorRegister();
36111308Santhony.gutierrez@amd.com        }
36211347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override {
36311308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
36411308Santhony.gutierrez@amd.com            return target.isCondRegister();
36511308Santhony.gutierrez@amd.com        }
36611347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override {
36711308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
36811308Santhony.gutierrez@amd.com            return target.isScalarRegister();
36911308Santhony.gutierrez@amd.com        }
37011347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override {
37111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
37211308Santhony.gutierrez@amd.com            return true;
37311308Santhony.gutierrez@amd.com        }
37411347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override { return false; }
37511347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override {
37611308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
37711308Santhony.gutierrez@amd.com            return target.opSize();
37811308Santhony.gutierrez@amd.com        }
37911347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override {
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        w->discardFetch();
41311308Santhony.gutierrez@amd.com    }
41411308Santhony.gutierrez@amd.com
41511308Santhony.gutierrez@amd.com    class BrDirectInst : public BrInstBase<LabelOperand>
41611308Santhony.gutierrez@amd.com    {
41711308Santhony.gutierrez@amd.com      public:
41811308Santhony.gutierrez@amd.com        BrDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
41911308Santhony.gutierrez@amd.com            : BrInstBase<LabelOperand>(ib, obj)
42011308Santhony.gutierrez@amd.com        {
42111308Santhony.gutierrez@amd.com        }
42211308Santhony.gutierrez@amd.com
42311308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
42411308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
42511308Santhony.gutierrez@amd.com    };
42611308Santhony.gutierrez@amd.com
42711308Santhony.gutierrez@amd.com    class BrIndirectInst : public BrInstBase<SRegOperand>
42811308Santhony.gutierrez@amd.com    {
42911308Santhony.gutierrez@amd.com      public:
43011308Santhony.gutierrez@amd.com        BrIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
43111308Santhony.gutierrez@amd.com            : BrInstBase<SRegOperand>(ib, obj)
43211308Santhony.gutierrez@amd.com        {
43311308Santhony.gutierrez@amd.com        }
43411308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return target.isVectorRegister(); }
43511308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
43611308Santhony.gutierrez@amd.com    };
43711308Santhony.gutierrez@amd.com
43811308Santhony.gutierrez@amd.com    GPUStaticInst* decodeBr(const Brig::BrigInstBase *ib,
43911308Santhony.gutierrez@amd.com                            const BrigObject *obj);
44011308Santhony.gutierrez@amd.com} // namespace HsailISA
44111308Santhony.gutierrez@amd.com
44211308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_BRANCH_HH__
443