branch.hh revision 11692
111308Santhony.gutierrez@amd.com/*
211308Santhony.gutierrez@amd.com * Copyright (c) 2012-2015 Advanced Micro Devices, Inc.
311308Santhony.gutierrez@amd.com * All rights reserved.
411308Santhony.gutierrez@amd.com *
511308Santhony.gutierrez@amd.com * For use for simulation and test purposes only
611308Santhony.gutierrez@amd.com *
711308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without
811308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are met:
911308Santhony.gutierrez@amd.com *
1011308Santhony.gutierrez@amd.com * 1. Redistributions of source code must retain the above copyright notice,
1111308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer.
1211308Santhony.gutierrez@amd.com *
1311308Santhony.gutierrez@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice,
1411308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer in the documentation
1511308Santhony.gutierrez@amd.com * and/or other materials provided with the distribution.
1611308Santhony.gutierrez@amd.com *
1711308Santhony.gutierrez@amd.com * 3. Neither the name of the copyright holder nor the names of its contributors
1811308Santhony.gutierrez@amd.com * may be used to endorse or promote products derived from this software
1911308Santhony.gutierrez@amd.com * without specific prior written permission.
2011308Santhony.gutierrez@amd.com *
2111308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2211308Santhony.gutierrez@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2311308Santhony.gutierrez@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2411308Santhony.gutierrez@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2511308Santhony.gutierrez@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2611308Santhony.gutierrez@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2711308Santhony.gutierrez@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2811308Santhony.gutierrez@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2911308Santhony.gutierrez@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3011308Santhony.gutierrez@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3111308Santhony.gutierrez@amd.com * POSSIBILITY OF SUCH DAMAGE.
3211308Santhony.gutierrez@amd.com *
3311308Santhony.gutierrez@amd.com * Author: Steve Reinhardt
3411308Santhony.gutierrez@amd.com */
3511308Santhony.gutierrez@amd.com
3611308Santhony.gutierrez@amd.com#ifndef __ARCH_HSAIL_INSTS_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
9811347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override {
9911308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
10011308Santhony.gutierrez@amd.com            return target.regIndex();
10111308Santhony.gutierrez@amd.com        }
10211308Santhony.gutierrez@amd.com
10311347Sandreas.hansson@arm.com        int getNumOperands() override {
10411308Santhony.gutierrez@amd.com            return 1;
10511308Santhony.gutierrez@amd.com        }
10611308Santhony.gutierrez@amd.com
10711347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
10811308Santhony.gutierrez@amd.com    };
10911308Santhony.gutierrez@amd.com
11011308Santhony.gutierrez@amd.com    template<typename TargetType>
11111308Santhony.gutierrez@amd.com    void
11211308Santhony.gutierrez@amd.com    BrnInstBase<TargetType>::generateDisassembly()
11311308Santhony.gutierrez@amd.com    {
11411308Santhony.gutierrez@amd.com        std::string widthClause;
11511308Santhony.gutierrez@amd.com
11611308Santhony.gutierrez@amd.com        if (width != 1) {
11711308Santhony.gutierrez@amd.com            widthClause = csprintf("_width(%d)", width);
11811308Santhony.gutierrez@amd.com        }
11911308Santhony.gutierrez@amd.com
12011308Santhony.gutierrez@amd.com        disassembly = csprintf("%s%s %s", opcode, widthClause,
12111308Santhony.gutierrez@amd.com                               target.disassemble());
12211308Santhony.gutierrez@amd.com    }
12311308Santhony.gutierrez@amd.com
12411308Santhony.gutierrez@amd.com    template<typename TargetType>
12511308Santhony.gutierrez@amd.com    void
12611308Santhony.gutierrez@amd.com    BrnInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst)
12711308Santhony.gutierrez@amd.com    {
12811308Santhony.gutierrez@amd.com        Wavefront *w = gpuDynInst->wavefront();
12911308Santhony.gutierrez@amd.com
13011308Santhony.gutierrez@amd.com        if (getTargetPc() == w->rpc()) {
13111308Santhony.gutierrez@amd.com            w->popFromReconvergenceStack();
13211308Santhony.gutierrez@amd.com        } else {
13311308Santhony.gutierrez@amd.com            // Rpc and execution mask remain the same
13411308Santhony.gutierrez@amd.com            w->pc(getTargetPc());
13511308Santhony.gutierrez@amd.com        }
13611308Santhony.gutierrez@amd.com        w->discardFetch();
13711308Santhony.gutierrez@amd.com    }
13811308Santhony.gutierrez@amd.com
13911308Santhony.gutierrez@amd.com    class BrnDirectInst : public BrnInstBase<LabelOperand>
14011308Santhony.gutierrez@amd.com    {
14111308Santhony.gutierrez@amd.com      public:
14211308Santhony.gutierrez@amd.com        BrnDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
14311308Santhony.gutierrez@amd.com            : BrnInstBase<LabelOperand>(ib, obj)
14411308Santhony.gutierrez@amd.com        {
14511308Santhony.gutierrez@amd.com        }
14611308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
14711308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
14811308Santhony.gutierrez@amd.com    };
14911308Santhony.gutierrez@amd.com
15011308Santhony.gutierrez@amd.com    class BrnIndirectInst : public BrnInstBase<SRegOperand>
15111308Santhony.gutierrez@amd.com    {
15211308Santhony.gutierrez@amd.com      public:
15311308Santhony.gutierrez@amd.com        BrnIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
15411308Santhony.gutierrez@amd.com            : BrnInstBase<SRegOperand>(ib, obj)
15511308Santhony.gutierrez@amd.com        {
15611308Santhony.gutierrez@amd.com        }
15711308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return target.isVectorRegister(); }
15811308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
15911308Santhony.gutierrez@amd.com    };
16011308Santhony.gutierrez@amd.com
16111308Santhony.gutierrez@amd.com    GPUStaticInst* decodeBrn(const Brig::BrigInstBase *ib,
16211308Santhony.gutierrez@amd.com                             const BrigObject *obj);
16311308Santhony.gutierrez@amd.com
16411308Santhony.gutierrez@amd.com    template<typename TargetType>
16511308Santhony.gutierrez@amd.com    class CbrInstBase : public HsailGPUStaticInst
16611308Santhony.gutierrez@amd.com    {
16711308Santhony.gutierrez@amd.com      public:
16811347Sandreas.hansson@arm.com        void generateDisassembly() override;
16911308Santhony.gutierrez@amd.com
17011308Santhony.gutierrez@amd.com        Brig::BrigWidth8_t width;
17111308Santhony.gutierrez@amd.com        CRegOperand cond;
17211308Santhony.gutierrez@amd.com        TargetType target;
17311308Santhony.gutierrez@amd.com
17411308Santhony.gutierrez@amd.com        CbrInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj)
17511308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, "cbr")
17611308Santhony.gutierrez@amd.com        {
17711692Santhony.gutierrez@amd.com            setFlag(Branch);
17811308Santhony.gutierrez@amd.com            width = ((Brig::BrigInstBr *)ib)->width;
17911308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
18011308Santhony.gutierrez@amd.com            cond.init(op_offs, obj);
18111308Santhony.gutierrez@amd.com            op_offs = obj->getOperandPtr(ib->operands, 1);
18211308Santhony.gutierrez@amd.com            target.init(op_offs, obj);
18311308Santhony.gutierrez@amd.com        }
18411308Santhony.gutierrez@amd.com
18511308Santhony.gutierrez@amd.com        uint32_t getTargetPc() override { return target.getTarget(0, 0); }
18611308Santhony.gutierrez@amd.com
18711347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
18811308Santhony.gutierrez@amd.com        // Assumption: Target is operand 0, Condition Register is operand 1
18911347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override {
19011308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
19111308Santhony.gutierrez@amd.com            if (!operandIndex)
19211308Santhony.gutierrez@amd.com                return target.isVectorRegister();
19311308Santhony.gutierrez@amd.com            else
19411308Santhony.gutierrez@amd.com                return false;
19511308Santhony.gutierrez@amd.com        }
19611347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override {
19711308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
19811308Santhony.gutierrez@amd.com            if (!operandIndex)
19911308Santhony.gutierrez@amd.com                return target.isCondRegister();
20011308Santhony.gutierrez@amd.com            else
20111308Santhony.gutierrez@amd.com                return true;
20211308Santhony.gutierrez@amd.com        }
20311347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override {
20411308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
20511308Santhony.gutierrez@amd.com            if (!operandIndex)
20611308Santhony.gutierrez@amd.com                return target.isScalarRegister();
20711308Santhony.gutierrez@amd.com            else
20811308Santhony.gutierrez@amd.com                return false;
20911308Santhony.gutierrez@amd.com        }
21011347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override {
21111308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
21211308Santhony.gutierrez@amd.com            if (operandIndex == 0)
21311308Santhony.gutierrez@amd.com                return true;
21411308Santhony.gutierrez@amd.com            return false;
21511308Santhony.gutierrez@amd.com        }
21611308Santhony.gutierrez@amd.com        // both Condition Register and Target are source operands
21711347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override {
21811308Santhony.gutierrez@amd.com            return false;
21911308Santhony.gutierrez@amd.com        }
22011347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override {
22111308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
22211308Santhony.gutierrez@amd.com            if (!operandIndex)
22311308Santhony.gutierrez@amd.com                return target.opSize();
22411308Santhony.gutierrez@amd.com            else
22511308Santhony.gutierrez@amd.com                return 1;
22611308Santhony.gutierrez@amd.com        }
22711347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override {
22811308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
22911308Santhony.gutierrez@amd.com            if (!operandIndex)
23011308Santhony.gutierrez@amd.com                return target.regIndex();
23111308Santhony.gutierrez@amd.com            else
23211308Santhony.gutierrez@amd.com                return -1;
23311308Santhony.gutierrez@amd.com         }
23411308Santhony.gutierrez@amd.com
23511308Santhony.gutierrez@amd.com        // Operands = Target, Condition Register
23611347Sandreas.hansson@arm.com        int getNumOperands() override {
23711308Santhony.gutierrez@amd.com            return 2;
23811308Santhony.gutierrez@amd.com        }
23911308Santhony.gutierrez@amd.com    };
24011308Santhony.gutierrez@amd.com
24111308Santhony.gutierrez@amd.com    template<typename TargetType>
24211308Santhony.gutierrez@amd.com    void
24311308Santhony.gutierrez@amd.com    CbrInstBase<TargetType>::generateDisassembly()
24411308Santhony.gutierrez@amd.com    {
24511308Santhony.gutierrez@amd.com        std::string widthClause;
24611308Santhony.gutierrez@amd.com
24711308Santhony.gutierrez@amd.com        if (width != 1) {
24811308Santhony.gutierrez@amd.com            widthClause = csprintf("_width(%d)", width);
24911308Santhony.gutierrez@amd.com        }
25011308Santhony.gutierrez@amd.com
25111308Santhony.gutierrez@amd.com        disassembly = csprintf("%s%s %s,%s", opcode, widthClause,
25211308Santhony.gutierrez@amd.com                               cond.disassemble(), target.disassemble());
25311308Santhony.gutierrez@amd.com    }
25411308Santhony.gutierrez@amd.com
25511308Santhony.gutierrez@amd.com    template<typename TargetType>
25611308Santhony.gutierrez@amd.com    void
25711308Santhony.gutierrez@amd.com    CbrInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst)
25811308Santhony.gutierrez@amd.com    {
25911308Santhony.gutierrez@amd.com        Wavefront *w = gpuDynInst->wavefront();
26011308Santhony.gutierrez@amd.com
26111308Santhony.gutierrez@amd.com        const uint32_t curr_pc = w->pc();
26211308Santhony.gutierrez@amd.com        const uint32_t curr_rpc = w->rpc();
26311308Santhony.gutierrez@amd.com        const VectorMask curr_mask = w->execMask();
26411308Santhony.gutierrez@amd.com
26511308Santhony.gutierrez@amd.com        /**
26611308Santhony.gutierrez@amd.com         * TODO: can we move this pop outside the instruction, and
26711308Santhony.gutierrez@amd.com         * into the wavefront?
26811308Santhony.gutierrez@amd.com         */
26911308Santhony.gutierrez@amd.com        w->popFromReconvergenceStack();
27011308Santhony.gutierrez@amd.com
27111308Santhony.gutierrez@amd.com        // immediate post-dominator instruction
27211308Santhony.gutierrez@amd.com        const uint32_t rpc = static_cast<uint32_t>(ipdInstNum());
27311308Santhony.gutierrez@amd.com        if (curr_rpc != rpc) {
27411308Santhony.gutierrez@amd.com            w->pushToReconvergenceStack(rpc, curr_rpc, curr_mask);
27511308Santhony.gutierrez@amd.com        }
27611308Santhony.gutierrez@amd.com
27711308Santhony.gutierrez@amd.com        // taken branch
27811308Santhony.gutierrez@amd.com        const uint32_t true_pc = getTargetPc();
27911308Santhony.gutierrez@amd.com        VectorMask true_mask;
28011534Sjohn.kalamatianos@amd.com        for (unsigned int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
28111308Santhony.gutierrez@amd.com            true_mask[lane] = cond.get<bool>(w, lane) & curr_mask[lane];
28211308Santhony.gutierrez@amd.com        }
28311308Santhony.gutierrez@amd.com
28411308Santhony.gutierrez@amd.com        // not taken branch
28511308Santhony.gutierrez@amd.com        const uint32_t false_pc = curr_pc + 1;
28611308Santhony.gutierrez@amd.com        assert(true_pc != false_pc);
28711308Santhony.gutierrez@amd.com        if (false_pc != rpc && true_mask.count() < curr_mask.count()) {
28811308Santhony.gutierrez@amd.com            VectorMask false_mask = curr_mask & ~true_mask;
28911308Santhony.gutierrez@amd.com            w->pushToReconvergenceStack(false_pc, rpc, false_mask);
29011308Santhony.gutierrez@amd.com        }
29111308Santhony.gutierrez@amd.com
29211308Santhony.gutierrez@amd.com        if (true_pc != rpc && true_mask.count()) {
29311308Santhony.gutierrez@amd.com            w->pushToReconvergenceStack(true_pc, rpc, true_mask);
29411308Santhony.gutierrez@amd.com        }
29511308Santhony.gutierrez@amd.com        assert(w->pc() != curr_pc);
29611308Santhony.gutierrez@amd.com        w->discardFetch();
29711308Santhony.gutierrez@amd.com    }
29811308Santhony.gutierrez@amd.com
29911308Santhony.gutierrez@amd.com
30011308Santhony.gutierrez@amd.com    class CbrDirectInst : public CbrInstBase<LabelOperand>
30111308Santhony.gutierrez@amd.com    {
30211308Santhony.gutierrez@amd.com      public:
30311308Santhony.gutierrez@amd.com        CbrDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
30411308Santhony.gutierrez@amd.com            : CbrInstBase<LabelOperand>(ib, obj)
30511308Santhony.gutierrez@amd.com        {
30611308Santhony.gutierrez@amd.com        }
30711308Santhony.gutierrez@amd.com        // the source operand of a conditional branch is a Condition
30811308Santhony.gutierrez@amd.com        // Register which is not stored in the VRF
30911308Santhony.gutierrez@amd.com        // so we do not count it as a source-register operand
31011308Santhony.gutierrez@amd.com        // even though, formally, it is one.
31111308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
31211308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
31311308Santhony.gutierrez@amd.com    };
31411308Santhony.gutierrez@amd.com
31511308Santhony.gutierrez@amd.com    class CbrIndirectInst : public CbrInstBase<SRegOperand>
31611308Santhony.gutierrez@amd.com    {
31711308Santhony.gutierrez@amd.com      public:
31811308Santhony.gutierrez@amd.com        CbrIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
31911308Santhony.gutierrez@amd.com            : CbrInstBase<SRegOperand>(ib, obj)
32011308Santhony.gutierrez@amd.com        {
32111308Santhony.gutierrez@amd.com        }
32211308Santhony.gutierrez@amd.com        // one source operand of the conditional indirect branch is a Condition
32311308Santhony.gutierrez@amd.com        // register which is not stored in the VRF so we do not count it
32411308Santhony.gutierrez@amd.com        // as a source-register operand even though, formally, it is one.
32511308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return target.isVectorRegister(); }
32611308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
32711308Santhony.gutierrez@amd.com    };
32811308Santhony.gutierrez@amd.com
32911308Santhony.gutierrez@amd.com    GPUStaticInst* decodeCbr(const Brig::BrigInstBase *ib,
33011308Santhony.gutierrez@amd.com                             const BrigObject *obj);
33111308Santhony.gutierrez@amd.com
33211308Santhony.gutierrez@amd.com    template<typename TargetType>
33311308Santhony.gutierrez@amd.com    class BrInstBase : public HsailGPUStaticInst
33411308Santhony.gutierrez@amd.com    {
33511308Santhony.gutierrez@amd.com      public:
33611347Sandreas.hansson@arm.com        void generateDisassembly() override;
33711308Santhony.gutierrez@amd.com
33811308Santhony.gutierrez@amd.com        ImmOperand<uint32_t> width;
33911308Santhony.gutierrez@amd.com        TargetType target;
34011308Santhony.gutierrez@amd.com
34111308Santhony.gutierrez@amd.com        BrInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj)
34211308Santhony.gutierrez@amd.com           : HsailGPUStaticInst(obj, "br")
34311308Santhony.gutierrez@amd.com        {
34411692Santhony.gutierrez@amd.com            setFlag(Branch);
34511692Santhony.gutierrez@amd.com            setFlag(UnconditionalJump);
34611308Santhony.gutierrez@amd.com            width.init(((Brig::BrigInstBr *)ib)->width, obj);
34711308Santhony.gutierrez@amd.com            unsigned op_offs = obj->getOperandPtr(ib->operands, 0);
34811308Santhony.gutierrez@amd.com            target.init(op_offs, obj);
34911308Santhony.gutierrez@amd.com        }
35011308Santhony.gutierrez@amd.com
35111308Santhony.gutierrez@amd.com        uint32_t getTargetPc() override { return target.getTarget(0, 0); }
35211308Santhony.gutierrez@amd.com
35311347Sandreas.hansson@arm.com        void execute(GPUDynInstPtr gpuDynInst) override;
35411347Sandreas.hansson@arm.com        bool isVectorRegister(int operandIndex) override {
35511308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
35611308Santhony.gutierrez@amd.com            return target.isVectorRegister();
35711308Santhony.gutierrez@amd.com        }
35811347Sandreas.hansson@arm.com        bool isCondRegister(int operandIndex) override {
35911308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
36011308Santhony.gutierrez@amd.com            return target.isCondRegister();
36111308Santhony.gutierrez@amd.com        }
36211347Sandreas.hansson@arm.com        bool isScalarRegister(int operandIndex) override {
36311308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
36411308Santhony.gutierrez@amd.com            return target.isScalarRegister();
36511308Santhony.gutierrez@amd.com        }
36611347Sandreas.hansson@arm.com        bool isSrcOperand(int operandIndex) override {
36711308Santhony.gutierrez@amd.com            assert((operandIndex >= 0) && (operandIndex < getNumOperands()));
36811308Santhony.gutierrez@amd.com            return true;
36911308Santhony.gutierrez@amd.com        }
37011347Sandreas.hansson@arm.com        bool isDstOperand(int operandIndex) override { return false; }
37111347Sandreas.hansson@arm.com        int getOperandSize(int operandIndex) override {
37211308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
37311308Santhony.gutierrez@amd.com            return target.opSize();
37411308Santhony.gutierrez@amd.com        }
37511347Sandreas.hansson@arm.com        int getRegisterIndex(int operandIndex) override {
37611308Santhony.gutierrez@amd.com            assert(operandIndex >= 0 && operandIndex < getNumOperands());
37711308Santhony.gutierrez@amd.com            return target.regIndex();
37811308Santhony.gutierrez@amd.com        }
37911347Sandreas.hansson@arm.com        int getNumOperands() override { return 1; }
38011308Santhony.gutierrez@amd.com    };
38111308Santhony.gutierrez@amd.com
38211308Santhony.gutierrez@amd.com    template<typename TargetType>
38311308Santhony.gutierrez@amd.com    void
38411308Santhony.gutierrez@amd.com    BrInstBase<TargetType>::generateDisassembly()
38511308Santhony.gutierrez@amd.com    {
38611308Santhony.gutierrez@amd.com        std::string widthClause;
38711308Santhony.gutierrez@amd.com
38811308Santhony.gutierrez@amd.com        if (width.bits != 1) {
38911308Santhony.gutierrez@amd.com            widthClause = csprintf("_width(%d)", width.bits);
39011308Santhony.gutierrez@amd.com        }
39111308Santhony.gutierrez@amd.com
39211308Santhony.gutierrez@amd.com        disassembly = csprintf("%s%s %s", opcode, widthClause,
39311308Santhony.gutierrez@amd.com                               target.disassemble());
39411308Santhony.gutierrez@amd.com    }
39511308Santhony.gutierrez@amd.com
39611308Santhony.gutierrez@amd.com    template<typename TargetType>
39711308Santhony.gutierrez@amd.com    void
39811308Santhony.gutierrez@amd.com    BrInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst)
39911308Santhony.gutierrez@amd.com    {
40011308Santhony.gutierrez@amd.com        Wavefront *w = gpuDynInst->wavefront();
40111308Santhony.gutierrez@amd.com
40211308Santhony.gutierrez@amd.com        if (getTargetPc() == w->rpc()) {
40311308Santhony.gutierrez@amd.com            w->popFromReconvergenceStack();
40411308Santhony.gutierrez@amd.com        } else {
40511308Santhony.gutierrez@amd.com            // Rpc and execution mask remain the same
40611308Santhony.gutierrez@amd.com            w->pc(getTargetPc());
40711308Santhony.gutierrez@amd.com        }
40811308Santhony.gutierrez@amd.com        w->discardFetch();
40911308Santhony.gutierrez@amd.com    }
41011308Santhony.gutierrez@amd.com
41111308Santhony.gutierrez@amd.com    class BrDirectInst : public BrInstBase<LabelOperand>
41211308Santhony.gutierrez@amd.com    {
41311308Santhony.gutierrez@amd.com      public:
41411308Santhony.gutierrez@amd.com        BrDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
41511308Santhony.gutierrez@amd.com            : BrInstBase<LabelOperand>(ib, obj)
41611308Santhony.gutierrez@amd.com        {
41711308Santhony.gutierrez@amd.com        }
41811308Santhony.gutierrez@amd.com
41911308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return 0; }
42011308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
42111308Santhony.gutierrez@amd.com    };
42211308Santhony.gutierrez@amd.com
42311308Santhony.gutierrez@amd.com    class BrIndirectInst : public BrInstBase<SRegOperand>
42411308Santhony.gutierrez@amd.com    {
42511308Santhony.gutierrez@amd.com      public:
42611308Santhony.gutierrez@amd.com        BrIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj)
42711308Santhony.gutierrez@amd.com            : BrInstBase<SRegOperand>(ib, obj)
42811308Santhony.gutierrez@amd.com        {
42911308Santhony.gutierrez@amd.com        }
43011308Santhony.gutierrez@amd.com        int numSrcRegOperands() { return target.isVectorRegister(); }
43111308Santhony.gutierrez@amd.com        int numDstRegOperands() { return 0; }
43211308Santhony.gutierrez@amd.com    };
43311308Santhony.gutierrez@amd.com
43411308Santhony.gutierrez@amd.com    GPUStaticInst* decodeBr(const Brig::BrigInstBase *ib,
43511308Santhony.gutierrez@amd.com                            const BrigObject *obj);
43611308Santhony.gutierrez@amd.com} // namespace HsailISA
43711308Santhony.gutierrez@amd.com
43811308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_BRANCH_HH__
439