branch.hh revision 11697
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 } 13711308Santhony.gutierrez@amd.com 13811308Santhony.gutierrez@amd.com class BrnDirectInst : public BrnInstBase<LabelOperand> 13911308Santhony.gutierrez@amd.com { 14011308Santhony.gutierrez@amd.com public: 14111308Santhony.gutierrez@amd.com BrnDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 14211308Santhony.gutierrez@amd.com : BrnInstBase<LabelOperand>(ib, obj) 14311308Santhony.gutierrez@amd.com { 14411308Santhony.gutierrez@amd.com } 14511308Santhony.gutierrez@amd.com int numSrcRegOperands() { return 0; } 14611308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 14711308Santhony.gutierrez@amd.com }; 14811308Santhony.gutierrez@amd.com 14911308Santhony.gutierrez@amd.com class BrnIndirectInst : public BrnInstBase<SRegOperand> 15011308Santhony.gutierrez@amd.com { 15111308Santhony.gutierrez@amd.com public: 15211308Santhony.gutierrez@amd.com BrnIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 15311308Santhony.gutierrez@amd.com : BrnInstBase<SRegOperand>(ib, obj) 15411308Santhony.gutierrez@amd.com { 15511308Santhony.gutierrez@amd.com } 15611308Santhony.gutierrez@amd.com int numSrcRegOperands() { return target.isVectorRegister(); } 15711308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 15811308Santhony.gutierrez@amd.com }; 15911308Santhony.gutierrez@amd.com 16011308Santhony.gutierrez@amd.com GPUStaticInst* decodeBrn(const Brig::BrigInstBase *ib, 16111308Santhony.gutierrez@amd.com const BrigObject *obj); 16211308Santhony.gutierrez@amd.com 16311308Santhony.gutierrez@amd.com template<typename TargetType> 16411308Santhony.gutierrez@amd.com class CbrInstBase : public HsailGPUStaticInst 16511308Santhony.gutierrez@amd.com { 16611308Santhony.gutierrez@amd.com public: 16711347Sandreas.hansson@arm.com void generateDisassembly() override; 16811308Santhony.gutierrez@amd.com 16911308Santhony.gutierrez@amd.com Brig::BrigWidth8_t width; 17011308Santhony.gutierrez@amd.com CRegOperand cond; 17111308Santhony.gutierrez@amd.com TargetType target; 17211308Santhony.gutierrez@amd.com 17311308Santhony.gutierrez@amd.com CbrInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj) 17411308Santhony.gutierrez@amd.com : HsailGPUStaticInst(obj, "cbr") 17511308Santhony.gutierrez@amd.com { 17611692Santhony.gutierrez@amd.com setFlag(Branch); 17711308Santhony.gutierrez@amd.com width = ((Brig::BrigInstBr *)ib)->width; 17811308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 17911308Santhony.gutierrez@amd.com cond.init(op_offs, obj); 18011308Santhony.gutierrez@amd.com op_offs = obj->getOperandPtr(ib->operands, 1); 18111308Santhony.gutierrez@amd.com target.init(op_offs, obj); 18211308Santhony.gutierrez@amd.com } 18311308Santhony.gutierrez@amd.com 18411308Santhony.gutierrez@amd.com uint32_t getTargetPc() override { return target.getTarget(0, 0); } 18511308Santhony.gutierrez@amd.com 18611347Sandreas.hansson@arm.com void execute(GPUDynInstPtr gpuDynInst) override; 18711308Santhony.gutierrez@amd.com // Assumption: Target is operand 0, Condition Register is operand 1 18811347Sandreas.hansson@arm.com bool isVectorRegister(int operandIndex) override { 18911308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 19011308Santhony.gutierrez@amd.com if (!operandIndex) 19111308Santhony.gutierrez@amd.com return target.isVectorRegister(); 19211308Santhony.gutierrez@amd.com else 19311308Santhony.gutierrez@amd.com return false; 19411308Santhony.gutierrez@amd.com } 19511347Sandreas.hansson@arm.com bool isCondRegister(int operandIndex) override { 19611308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 19711308Santhony.gutierrez@amd.com if (!operandIndex) 19811308Santhony.gutierrez@amd.com return target.isCondRegister(); 19911308Santhony.gutierrez@amd.com else 20011308Santhony.gutierrez@amd.com return true; 20111308Santhony.gutierrez@amd.com } 20211347Sandreas.hansson@arm.com bool isScalarRegister(int operandIndex) override { 20311308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 20411308Santhony.gutierrez@amd.com if (!operandIndex) 20511308Santhony.gutierrez@amd.com return target.isScalarRegister(); 20611308Santhony.gutierrez@amd.com else 20711308Santhony.gutierrez@amd.com return false; 20811308Santhony.gutierrez@amd.com } 20911347Sandreas.hansson@arm.com bool isSrcOperand(int operandIndex) override { 21011308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 21111308Santhony.gutierrez@amd.com if (operandIndex == 0) 21211308Santhony.gutierrez@amd.com return true; 21311308Santhony.gutierrez@amd.com return false; 21411308Santhony.gutierrez@amd.com } 21511308Santhony.gutierrez@amd.com // both Condition Register and Target are source operands 21611347Sandreas.hansson@arm.com bool isDstOperand(int operandIndex) override { 21711308Santhony.gutierrez@amd.com return false; 21811308Santhony.gutierrez@amd.com } 21911347Sandreas.hansson@arm.com int getOperandSize(int operandIndex) override { 22011308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 22111308Santhony.gutierrez@amd.com if (!operandIndex) 22211308Santhony.gutierrez@amd.com return target.opSize(); 22311308Santhony.gutierrez@amd.com else 22411308Santhony.gutierrez@amd.com return 1; 22511308Santhony.gutierrez@amd.com } 22611347Sandreas.hansson@arm.com int getRegisterIndex(int operandIndex) override { 22711308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 22811308Santhony.gutierrez@amd.com if (!operandIndex) 22911308Santhony.gutierrez@amd.com return target.regIndex(); 23011308Santhony.gutierrez@amd.com else 23111308Santhony.gutierrez@amd.com return -1; 23211308Santhony.gutierrez@amd.com } 23311308Santhony.gutierrez@amd.com 23411308Santhony.gutierrez@amd.com // Operands = Target, Condition Register 23511347Sandreas.hansson@arm.com int getNumOperands() override { 23611308Santhony.gutierrez@amd.com return 2; 23711308Santhony.gutierrez@amd.com } 23811308Santhony.gutierrez@amd.com }; 23911308Santhony.gutierrez@amd.com 24011308Santhony.gutierrez@amd.com template<typename TargetType> 24111308Santhony.gutierrez@amd.com void 24211308Santhony.gutierrez@amd.com CbrInstBase<TargetType>::generateDisassembly() 24311308Santhony.gutierrez@amd.com { 24411308Santhony.gutierrez@amd.com std::string widthClause; 24511308Santhony.gutierrez@amd.com 24611308Santhony.gutierrez@amd.com if (width != 1) { 24711308Santhony.gutierrez@amd.com widthClause = csprintf("_width(%d)", width); 24811308Santhony.gutierrez@amd.com } 24911308Santhony.gutierrez@amd.com 25011308Santhony.gutierrez@amd.com disassembly = csprintf("%s%s %s,%s", opcode, widthClause, 25111308Santhony.gutierrez@amd.com cond.disassemble(), target.disassemble()); 25211308Santhony.gutierrez@amd.com } 25311308Santhony.gutierrez@amd.com 25411308Santhony.gutierrez@amd.com template<typename TargetType> 25511308Santhony.gutierrez@amd.com void 25611308Santhony.gutierrez@amd.com CbrInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst) 25711308Santhony.gutierrez@amd.com { 25811308Santhony.gutierrez@amd.com Wavefront *w = gpuDynInst->wavefront(); 25911308Santhony.gutierrez@amd.com 26011697Santhony.gutierrez@amd.com const uint32_t curr_pc M5_VAR_USED = w->pc(); 26111308Santhony.gutierrez@amd.com const uint32_t curr_rpc = w->rpc(); 26211308Santhony.gutierrez@amd.com const VectorMask curr_mask = w->execMask(); 26311308Santhony.gutierrez@amd.com 26411308Santhony.gutierrez@amd.com /** 26511308Santhony.gutierrez@amd.com * TODO: can we move this pop outside the instruction, and 26611308Santhony.gutierrez@amd.com * into the wavefront? 26711308Santhony.gutierrez@amd.com */ 26811308Santhony.gutierrez@amd.com w->popFromReconvergenceStack(); 26911308Santhony.gutierrez@amd.com 27011308Santhony.gutierrez@amd.com // immediate post-dominator instruction 27111308Santhony.gutierrez@amd.com const uint32_t rpc = static_cast<uint32_t>(ipdInstNum()); 27211308Santhony.gutierrez@amd.com if (curr_rpc != rpc) { 27311308Santhony.gutierrez@amd.com w->pushToReconvergenceStack(rpc, curr_rpc, curr_mask); 27411308Santhony.gutierrez@amd.com } 27511308Santhony.gutierrez@amd.com 27611308Santhony.gutierrez@amd.com // taken branch 27711308Santhony.gutierrez@amd.com const uint32_t true_pc = getTargetPc(); 27811308Santhony.gutierrez@amd.com VectorMask true_mask; 27911534Sjohn.kalamatianos@amd.com for (unsigned int lane = 0; lane < w->computeUnit->wfSize(); ++lane) { 28011308Santhony.gutierrez@amd.com true_mask[lane] = cond.get<bool>(w, lane) & curr_mask[lane]; 28111308Santhony.gutierrez@amd.com } 28211308Santhony.gutierrez@amd.com 28311308Santhony.gutierrez@amd.com // not taken branch 28411697Santhony.gutierrez@amd.com const uint32_t false_pc = nextInstAddr(); 28511308Santhony.gutierrez@amd.com assert(true_pc != false_pc); 28611308Santhony.gutierrez@amd.com if (false_pc != rpc && true_mask.count() < curr_mask.count()) { 28711308Santhony.gutierrez@amd.com VectorMask false_mask = curr_mask & ~true_mask; 28811308Santhony.gutierrez@amd.com w->pushToReconvergenceStack(false_pc, rpc, false_mask); 28911308Santhony.gutierrez@amd.com } 29011308Santhony.gutierrez@amd.com 29111308Santhony.gutierrez@amd.com if (true_pc != rpc && true_mask.count()) { 29211308Santhony.gutierrez@amd.com w->pushToReconvergenceStack(true_pc, rpc, true_mask); 29311308Santhony.gutierrez@amd.com } 29411308Santhony.gutierrez@amd.com assert(w->pc() != curr_pc); 29511308Santhony.gutierrez@amd.com } 29611308Santhony.gutierrez@amd.com 29711308Santhony.gutierrez@amd.com 29811308Santhony.gutierrez@amd.com class CbrDirectInst : public CbrInstBase<LabelOperand> 29911308Santhony.gutierrez@amd.com { 30011308Santhony.gutierrez@amd.com public: 30111308Santhony.gutierrez@amd.com CbrDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 30211308Santhony.gutierrez@amd.com : CbrInstBase<LabelOperand>(ib, obj) 30311308Santhony.gutierrez@amd.com { 30411308Santhony.gutierrez@amd.com } 30511308Santhony.gutierrez@amd.com // the source operand of a conditional branch is a Condition 30611308Santhony.gutierrez@amd.com // Register which is not stored in the VRF 30711308Santhony.gutierrez@amd.com // so we do not count it as a source-register operand 30811308Santhony.gutierrez@amd.com // even though, formally, it is one. 30911308Santhony.gutierrez@amd.com int numSrcRegOperands() { return 0; } 31011308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 31111308Santhony.gutierrez@amd.com }; 31211308Santhony.gutierrez@amd.com 31311308Santhony.gutierrez@amd.com class CbrIndirectInst : public CbrInstBase<SRegOperand> 31411308Santhony.gutierrez@amd.com { 31511308Santhony.gutierrez@amd.com public: 31611308Santhony.gutierrez@amd.com CbrIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 31711308Santhony.gutierrez@amd.com : CbrInstBase<SRegOperand>(ib, obj) 31811308Santhony.gutierrez@amd.com { 31911308Santhony.gutierrez@amd.com } 32011308Santhony.gutierrez@amd.com // one source operand of the conditional indirect branch is a Condition 32111308Santhony.gutierrez@amd.com // register which is not stored in the VRF so we do not count it 32211308Santhony.gutierrez@amd.com // as a source-register operand even though, formally, it is one. 32311308Santhony.gutierrez@amd.com int numSrcRegOperands() { return target.isVectorRegister(); } 32411308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 32511308Santhony.gutierrez@amd.com }; 32611308Santhony.gutierrez@amd.com 32711308Santhony.gutierrez@amd.com GPUStaticInst* decodeCbr(const Brig::BrigInstBase *ib, 32811308Santhony.gutierrez@amd.com const BrigObject *obj); 32911308Santhony.gutierrez@amd.com 33011308Santhony.gutierrez@amd.com template<typename TargetType> 33111308Santhony.gutierrez@amd.com class BrInstBase : public HsailGPUStaticInst 33211308Santhony.gutierrez@amd.com { 33311308Santhony.gutierrez@amd.com public: 33411347Sandreas.hansson@arm.com void generateDisassembly() override; 33511308Santhony.gutierrez@amd.com 33611308Santhony.gutierrez@amd.com ImmOperand<uint32_t> width; 33711308Santhony.gutierrez@amd.com TargetType target; 33811308Santhony.gutierrez@amd.com 33911308Santhony.gutierrez@amd.com BrInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj) 34011308Santhony.gutierrez@amd.com : HsailGPUStaticInst(obj, "br") 34111308Santhony.gutierrez@amd.com { 34211692Santhony.gutierrez@amd.com setFlag(Branch); 34311692Santhony.gutierrez@amd.com setFlag(UnconditionalJump); 34411308Santhony.gutierrez@amd.com width.init(((Brig::BrigInstBr *)ib)->width, obj); 34511308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 34611308Santhony.gutierrez@amd.com target.init(op_offs, obj); 34711308Santhony.gutierrez@amd.com } 34811308Santhony.gutierrez@amd.com 34911308Santhony.gutierrez@amd.com uint32_t getTargetPc() override { return target.getTarget(0, 0); } 35011308Santhony.gutierrez@amd.com 35111347Sandreas.hansson@arm.com void execute(GPUDynInstPtr gpuDynInst) override; 35211347Sandreas.hansson@arm.com bool isVectorRegister(int operandIndex) override { 35311308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 35411308Santhony.gutierrez@amd.com return target.isVectorRegister(); 35511308Santhony.gutierrez@amd.com } 35611347Sandreas.hansson@arm.com bool isCondRegister(int operandIndex) override { 35711308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 35811308Santhony.gutierrez@amd.com return target.isCondRegister(); 35911308Santhony.gutierrez@amd.com } 36011347Sandreas.hansson@arm.com bool isScalarRegister(int operandIndex) override { 36111308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 36211308Santhony.gutierrez@amd.com return target.isScalarRegister(); 36311308Santhony.gutierrez@amd.com } 36411347Sandreas.hansson@arm.com bool isSrcOperand(int operandIndex) override { 36511308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 36611308Santhony.gutierrez@amd.com return true; 36711308Santhony.gutierrez@amd.com } 36811347Sandreas.hansson@arm.com bool isDstOperand(int operandIndex) override { return false; } 36911347Sandreas.hansson@arm.com int getOperandSize(int operandIndex) override { 37011308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 37111308Santhony.gutierrez@amd.com return target.opSize(); 37211308Santhony.gutierrez@amd.com } 37311347Sandreas.hansson@arm.com int getRegisterIndex(int operandIndex) override { 37411308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 37511308Santhony.gutierrez@amd.com return target.regIndex(); 37611308Santhony.gutierrez@amd.com } 37711347Sandreas.hansson@arm.com int getNumOperands() override { return 1; } 37811308Santhony.gutierrez@amd.com }; 37911308Santhony.gutierrez@amd.com 38011308Santhony.gutierrez@amd.com template<typename TargetType> 38111308Santhony.gutierrez@amd.com void 38211308Santhony.gutierrez@amd.com BrInstBase<TargetType>::generateDisassembly() 38311308Santhony.gutierrez@amd.com { 38411308Santhony.gutierrez@amd.com std::string widthClause; 38511308Santhony.gutierrez@amd.com 38611308Santhony.gutierrez@amd.com if (width.bits != 1) { 38711308Santhony.gutierrez@amd.com widthClause = csprintf("_width(%d)", width.bits); 38811308Santhony.gutierrez@amd.com } 38911308Santhony.gutierrez@amd.com 39011308Santhony.gutierrez@amd.com disassembly = csprintf("%s%s %s", opcode, widthClause, 39111308Santhony.gutierrez@amd.com target.disassemble()); 39211308Santhony.gutierrez@amd.com } 39311308Santhony.gutierrez@amd.com 39411308Santhony.gutierrez@amd.com template<typename TargetType> 39511308Santhony.gutierrez@amd.com void 39611308Santhony.gutierrez@amd.com BrInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst) 39711308Santhony.gutierrez@amd.com { 39811308Santhony.gutierrez@amd.com Wavefront *w = gpuDynInst->wavefront(); 39911308Santhony.gutierrez@amd.com 40011308Santhony.gutierrez@amd.com if (getTargetPc() == w->rpc()) { 40111308Santhony.gutierrez@amd.com w->popFromReconvergenceStack(); 40211308Santhony.gutierrez@amd.com } else { 40311308Santhony.gutierrez@amd.com // Rpc and execution mask remain the same 40411308Santhony.gutierrez@amd.com w->pc(getTargetPc()); 40511308Santhony.gutierrez@amd.com } 40611308Santhony.gutierrez@amd.com } 40711308Santhony.gutierrez@amd.com 40811308Santhony.gutierrez@amd.com class BrDirectInst : public BrInstBase<LabelOperand> 40911308Santhony.gutierrez@amd.com { 41011308Santhony.gutierrez@amd.com public: 41111308Santhony.gutierrez@amd.com BrDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 41211308Santhony.gutierrez@amd.com : BrInstBase<LabelOperand>(ib, obj) 41311308Santhony.gutierrez@amd.com { 41411308Santhony.gutierrez@amd.com } 41511308Santhony.gutierrez@amd.com 41611308Santhony.gutierrez@amd.com int numSrcRegOperands() { return 0; } 41711308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 41811308Santhony.gutierrez@amd.com }; 41911308Santhony.gutierrez@amd.com 42011308Santhony.gutierrez@amd.com class BrIndirectInst : public BrInstBase<SRegOperand> 42111308Santhony.gutierrez@amd.com { 42211308Santhony.gutierrez@amd.com public: 42311308Santhony.gutierrez@amd.com BrIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 42411308Santhony.gutierrez@amd.com : BrInstBase<SRegOperand>(ib, obj) 42511308Santhony.gutierrez@amd.com { 42611308Santhony.gutierrez@amd.com } 42711308Santhony.gutierrez@amd.com int numSrcRegOperands() { return target.isVectorRegister(); } 42811308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 42911308Santhony.gutierrez@amd.com }; 43011308Santhony.gutierrez@amd.com 43111308Santhony.gutierrez@amd.com GPUStaticInst* decodeBr(const Brig::BrigInstBase *ib, 43211308Santhony.gutierrez@amd.com const BrigObject *obj); 43311308Santhony.gutierrez@amd.com} // namespace HsailISA 43411308Santhony.gutierrez@amd.com 43511308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_BRANCH_HH__ 436