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