111308Santhony.gutierrez@amd.com/* 211308Santhony.gutierrez@amd.com * Copyright (c) 2012-2015 Advanced Micro Devices, Inc. 311308Santhony.gutierrez@amd.com * All rights reserved. 411308Santhony.gutierrez@amd.com * 511308Santhony.gutierrez@amd.com * For use for simulation and test purposes only 611308Santhony.gutierrez@amd.com * 711308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 811308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are met: 911308Santhony.gutierrez@amd.com * 1011308Santhony.gutierrez@amd.com * 1. Redistributions of source code must retain the above copyright notice, 1111308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer. 1211308Santhony.gutierrez@amd.com * 1311308Santhony.gutierrez@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice, 1411308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer in the documentation 1511308Santhony.gutierrez@amd.com * and/or other materials provided with the distribution. 1611308Santhony.gutierrez@amd.com * 1711308Santhony.gutierrez@amd.com * 3. Neither the name of the copyright holder nor the names of its contributors 1811308Santhony.gutierrez@amd.com * may be used to endorse or promote products derived from this software 1911308Santhony.gutierrez@amd.com * without specific prior written permission. 2011308Santhony.gutierrez@amd.com * 2111308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2211308Santhony.gutierrez@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2311308Santhony.gutierrez@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2411308Santhony.gutierrez@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2511308Santhony.gutierrez@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2611308Santhony.gutierrez@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2711308Santhony.gutierrez@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2811308Santhony.gutierrez@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2911308Santhony.gutierrez@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3011308Santhony.gutierrez@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3111308Santhony.gutierrez@amd.com * POSSIBILITY OF SUCH DAMAGE. 3211308Santhony.gutierrez@amd.com * 3311308Santhony.gutierrez@amd.com * Author: Steve Reinhardt 3411308Santhony.gutierrez@amd.com */ 3511308Santhony.gutierrez@amd.com 3611308Santhony.gutierrez@amd.com#ifndef __ARCH_HSAIL_INSTS_BRANCH_HH__ 3711308Santhony.gutierrez@amd.com#define __ARCH_HSAIL_INSTS_BRANCH_HH__ 3811308Santhony.gutierrez@amd.com 3911308Santhony.gutierrez@amd.com#include "arch/hsail/insts/gpu_static_inst.hh" 4011308Santhony.gutierrez@amd.com#include "arch/hsail/operand.hh" 4111308Santhony.gutierrez@amd.com#include "gpu-compute/gpu_dyn_inst.hh" 4211308Santhony.gutierrez@amd.com#include "gpu-compute/wavefront.hh" 4311308Santhony.gutierrez@amd.com 4411308Santhony.gutierrez@amd.comnamespace HsailISA 4511308Santhony.gutierrez@amd.com{ 4611308Santhony.gutierrez@amd.com 4711308Santhony.gutierrez@amd.com // The main difference between a direct branch and an indirect branch 4811308Santhony.gutierrez@amd.com // is whether the target is a register or a label, so we can share a 4911308Santhony.gutierrez@amd.com // lot of code if we template the base implementation on that type. 5011308Santhony.gutierrez@amd.com template<typename TargetType> 5111308Santhony.gutierrez@amd.com class BrnInstBase : public HsailGPUStaticInst 5211308Santhony.gutierrez@amd.com { 5311308Santhony.gutierrez@amd.com public: 5411347Sandreas.hansson@arm.com void generateDisassembly() override; 5511308Santhony.gutierrez@amd.com 5611308Santhony.gutierrez@amd.com Brig::BrigWidth8_t width; 5711308Santhony.gutierrez@amd.com TargetType target; 5811308Santhony.gutierrez@amd.com 5911308Santhony.gutierrez@amd.com BrnInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj) 6011308Santhony.gutierrez@amd.com : HsailGPUStaticInst(obj, "brn") 6111308Santhony.gutierrez@amd.com { 6211692Santhony.gutierrez@amd.com setFlag(Branch); 6311692Santhony.gutierrez@amd.com setFlag(UnconditionalJump); 6411308Santhony.gutierrez@amd.com width = ((Brig::BrigInstBr*)ib)->width; 6511308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 6611308Santhony.gutierrez@amd.com target.init(op_offs, obj); 6711308Santhony.gutierrez@amd.com } 6811308Santhony.gutierrez@amd.com 6911308Santhony.gutierrez@amd.com uint32_t getTargetPc() override { return target.getTarget(0, 0); } 7011308Santhony.gutierrez@amd.com 7111347Sandreas.hansson@arm.com bool isVectorRegister(int operandIndex) override { 7211308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 7311308Santhony.gutierrez@amd.com return target.isVectorRegister(); 7411308Santhony.gutierrez@amd.com } 7511347Sandreas.hansson@arm.com bool isCondRegister(int operandIndex) override { 7611308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 7711308Santhony.gutierrez@amd.com return target.isCondRegister(); 7811308Santhony.gutierrez@amd.com } 7911347Sandreas.hansson@arm.com bool isScalarRegister(int operandIndex) override { 8011308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 8111308Santhony.gutierrez@amd.com return target.isScalarRegister(); 8211308Santhony.gutierrez@amd.com } 8311308Santhony.gutierrez@amd.com 8411347Sandreas.hansson@arm.com bool isSrcOperand(int operandIndex) override { 8511308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 8611308Santhony.gutierrez@amd.com return true; 8711308Santhony.gutierrez@amd.com } 8811308Santhony.gutierrez@amd.com 8911347Sandreas.hansson@arm.com bool isDstOperand(int operandIndex) override { 9011308Santhony.gutierrez@amd.com return false; 9111308Santhony.gutierrez@amd.com } 9211308Santhony.gutierrez@amd.com 9311347Sandreas.hansson@arm.com int getOperandSize(int operandIndex) override { 9411308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 9511308Santhony.gutierrez@amd.com return target.opSize(); 9611308Santhony.gutierrez@amd.com } 9711308Santhony.gutierrez@amd.com 9811699Santhony.gutierrez@amd.com int 9911699Santhony.gutierrez@amd.com getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override 10011699Santhony.gutierrez@amd.com { 10111308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 10211308Santhony.gutierrez@amd.com return target.regIndex(); 10311308Santhony.gutierrez@amd.com } 10411308Santhony.gutierrez@amd.com 10511347Sandreas.hansson@arm.com int getNumOperands() override { 10611308Santhony.gutierrez@amd.com return 1; 10711308Santhony.gutierrez@amd.com } 10811308Santhony.gutierrez@amd.com 10911347Sandreas.hansson@arm.com void execute(GPUDynInstPtr gpuDynInst) override; 11011308Santhony.gutierrez@amd.com }; 11111308Santhony.gutierrez@amd.com 11211308Santhony.gutierrez@amd.com template<typename TargetType> 11311308Santhony.gutierrez@amd.com void 11411308Santhony.gutierrez@amd.com BrnInstBase<TargetType>::generateDisassembly() 11511308Santhony.gutierrez@amd.com { 11611308Santhony.gutierrez@amd.com std::string widthClause; 11711308Santhony.gutierrez@amd.com 11811308Santhony.gutierrez@amd.com if (width != 1) { 11911308Santhony.gutierrez@amd.com widthClause = csprintf("_width(%d)", width); 12011308Santhony.gutierrez@amd.com } 12111308Santhony.gutierrez@amd.com 12211308Santhony.gutierrez@amd.com disassembly = csprintf("%s%s %s", opcode, widthClause, 12311308Santhony.gutierrez@amd.com target.disassemble()); 12411308Santhony.gutierrez@amd.com } 12511308Santhony.gutierrez@amd.com 12611308Santhony.gutierrez@amd.com template<typename TargetType> 12711308Santhony.gutierrez@amd.com void 12811308Santhony.gutierrez@amd.com BrnInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst) 12911308Santhony.gutierrez@amd.com { 13011308Santhony.gutierrez@amd.com Wavefront *w = gpuDynInst->wavefront(); 13111308Santhony.gutierrez@amd.com 13211308Santhony.gutierrez@amd.com if (getTargetPc() == w->rpc()) { 13311308Santhony.gutierrez@amd.com w->popFromReconvergenceStack(); 13411308Santhony.gutierrez@amd.com } else { 13511308Santhony.gutierrez@amd.com // Rpc and execution mask remain the same 13611308Santhony.gutierrez@amd.com w->pc(getTargetPc()); 13711308Santhony.gutierrez@amd.com } 13811308Santhony.gutierrez@amd.com } 13911308Santhony.gutierrez@amd.com 14011308Santhony.gutierrez@amd.com class BrnDirectInst : public BrnInstBase<LabelOperand> 14111308Santhony.gutierrez@amd.com { 14211308Santhony.gutierrez@amd.com public: 14311308Santhony.gutierrez@amd.com BrnDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 14411308Santhony.gutierrez@amd.com : BrnInstBase<LabelOperand>(ib, obj) 14511308Santhony.gutierrez@amd.com { 14611308Santhony.gutierrez@amd.com } 14711308Santhony.gutierrez@amd.com int numSrcRegOperands() { return 0; } 14811308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 14911308Santhony.gutierrez@amd.com }; 15011308Santhony.gutierrez@amd.com 15111308Santhony.gutierrez@amd.com class BrnIndirectInst : public BrnInstBase<SRegOperand> 15211308Santhony.gutierrez@amd.com { 15311308Santhony.gutierrez@amd.com public: 15411308Santhony.gutierrez@amd.com BrnIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 15511308Santhony.gutierrez@amd.com : BrnInstBase<SRegOperand>(ib, obj) 15611308Santhony.gutierrez@amd.com { 15711308Santhony.gutierrez@amd.com } 15811308Santhony.gutierrez@amd.com int numSrcRegOperands() { return target.isVectorRegister(); } 15911308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 16011308Santhony.gutierrez@amd.com }; 16111308Santhony.gutierrez@amd.com 16211308Santhony.gutierrez@amd.com GPUStaticInst* decodeBrn(const Brig::BrigInstBase *ib, 16311308Santhony.gutierrez@amd.com const BrigObject *obj); 16411308Santhony.gutierrez@amd.com 16511308Santhony.gutierrez@amd.com template<typename TargetType> 16611308Santhony.gutierrez@amd.com class CbrInstBase : public HsailGPUStaticInst 16711308Santhony.gutierrez@amd.com { 16811308Santhony.gutierrez@amd.com public: 16911347Sandreas.hansson@arm.com void generateDisassembly() override; 17011308Santhony.gutierrez@amd.com 17111308Santhony.gutierrez@amd.com Brig::BrigWidth8_t width; 17211308Santhony.gutierrez@amd.com CRegOperand cond; 17311308Santhony.gutierrez@amd.com TargetType target; 17411308Santhony.gutierrez@amd.com 17511308Santhony.gutierrez@amd.com CbrInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj) 17611308Santhony.gutierrez@amd.com : HsailGPUStaticInst(obj, "cbr") 17711308Santhony.gutierrez@amd.com { 17811692Santhony.gutierrez@amd.com setFlag(Branch); 17911308Santhony.gutierrez@amd.com width = ((Brig::BrigInstBr *)ib)->width; 18011308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 18111308Santhony.gutierrez@amd.com cond.init(op_offs, obj); 18211308Santhony.gutierrez@amd.com op_offs = obj->getOperandPtr(ib->operands, 1); 18311308Santhony.gutierrez@amd.com target.init(op_offs, obj); 18411308Santhony.gutierrez@amd.com } 18511308Santhony.gutierrez@amd.com 18611308Santhony.gutierrez@amd.com uint32_t getTargetPc() override { return target.getTarget(0, 0); } 18711308Santhony.gutierrez@amd.com 18811347Sandreas.hansson@arm.com void execute(GPUDynInstPtr gpuDynInst) override; 18911308Santhony.gutierrez@amd.com // Assumption: Target is operand 0, Condition Register is operand 1 19011347Sandreas.hansson@arm.com bool isVectorRegister(int operandIndex) override { 19111308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 19211308Santhony.gutierrez@amd.com if (!operandIndex) 19311308Santhony.gutierrez@amd.com return target.isVectorRegister(); 19411308Santhony.gutierrez@amd.com else 19511308Santhony.gutierrez@amd.com return false; 19611308Santhony.gutierrez@amd.com } 19711347Sandreas.hansson@arm.com bool isCondRegister(int operandIndex) override { 19811308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 19911308Santhony.gutierrez@amd.com if (!operandIndex) 20011308Santhony.gutierrez@amd.com return target.isCondRegister(); 20111308Santhony.gutierrez@amd.com else 20211308Santhony.gutierrez@amd.com return true; 20311308Santhony.gutierrez@amd.com } 20411347Sandreas.hansson@arm.com bool isScalarRegister(int operandIndex) override { 20511308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 20611308Santhony.gutierrez@amd.com if (!operandIndex) 20711308Santhony.gutierrez@amd.com return target.isScalarRegister(); 20811308Santhony.gutierrez@amd.com else 20911308Santhony.gutierrez@amd.com return false; 21011308Santhony.gutierrez@amd.com } 21111347Sandreas.hansson@arm.com bool isSrcOperand(int operandIndex) override { 21211308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 21311308Santhony.gutierrez@amd.com if (operandIndex == 0) 21411308Santhony.gutierrez@amd.com return true; 21511308Santhony.gutierrez@amd.com return false; 21611308Santhony.gutierrez@amd.com } 21711308Santhony.gutierrez@amd.com // both Condition Register and Target are source operands 21811347Sandreas.hansson@arm.com bool isDstOperand(int operandIndex) override { 21911308Santhony.gutierrez@amd.com return false; 22011308Santhony.gutierrez@amd.com } 22111347Sandreas.hansson@arm.com int getOperandSize(int operandIndex) override { 22211308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 22311308Santhony.gutierrez@amd.com if (!operandIndex) 22411308Santhony.gutierrez@amd.com return target.opSize(); 22511308Santhony.gutierrez@amd.com else 22611308Santhony.gutierrez@amd.com return 1; 22711308Santhony.gutierrez@amd.com } 22811699Santhony.gutierrez@amd.com int 22911699Santhony.gutierrez@amd.com getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override 23011699Santhony.gutierrez@amd.com { 23111308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 23211308Santhony.gutierrez@amd.com if (!operandIndex) 23311308Santhony.gutierrez@amd.com return target.regIndex(); 23411308Santhony.gutierrez@amd.com else 23511308Santhony.gutierrez@amd.com return -1; 23611308Santhony.gutierrez@amd.com } 23711308Santhony.gutierrez@amd.com 23811308Santhony.gutierrez@amd.com // Operands = Target, Condition Register 23911347Sandreas.hansson@arm.com int getNumOperands() override { 24011308Santhony.gutierrez@amd.com return 2; 24111308Santhony.gutierrez@amd.com } 24211308Santhony.gutierrez@amd.com }; 24311308Santhony.gutierrez@amd.com 24411308Santhony.gutierrez@amd.com template<typename TargetType> 24511308Santhony.gutierrez@amd.com void 24611308Santhony.gutierrez@amd.com CbrInstBase<TargetType>::generateDisassembly() 24711308Santhony.gutierrez@amd.com { 24811308Santhony.gutierrez@amd.com std::string widthClause; 24911308Santhony.gutierrez@amd.com 25011308Santhony.gutierrez@amd.com if (width != 1) { 25111308Santhony.gutierrez@amd.com widthClause = csprintf("_width(%d)", width); 25211308Santhony.gutierrez@amd.com } 25311308Santhony.gutierrez@amd.com 25411308Santhony.gutierrez@amd.com disassembly = csprintf("%s%s %s,%s", opcode, widthClause, 25511308Santhony.gutierrez@amd.com cond.disassemble(), target.disassemble()); 25611308Santhony.gutierrez@amd.com } 25711308Santhony.gutierrez@amd.com 25811308Santhony.gutierrez@amd.com template<typename TargetType> 25911308Santhony.gutierrez@amd.com void 26011308Santhony.gutierrez@amd.com CbrInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst) 26111308Santhony.gutierrez@amd.com { 26211308Santhony.gutierrez@amd.com Wavefront *w = gpuDynInst->wavefront(); 26311308Santhony.gutierrez@amd.com 26411697Santhony.gutierrez@amd.com const uint32_t curr_pc M5_VAR_USED = w->pc(); 26511308Santhony.gutierrez@amd.com const uint32_t curr_rpc = w->rpc(); 26611308Santhony.gutierrez@amd.com const VectorMask curr_mask = w->execMask(); 26711308Santhony.gutierrez@amd.com 26811308Santhony.gutierrez@amd.com /** 26911308Santhony.gutierrez@amd.com * TODO: can we move this pop outside the instruction, and 27011308Santhony.gutierrez@amd.com * into the wavefront? 27111308Santhony.gutierrez@amd.com */ 27211308Santhony.gutierrez@amd.com w->popFromReconvergenceStack(); 27311308Santhony.gutierrez@amd.com 27411308Santhony.gutierrez@amd.com // immediate post-dominator instruction 27511308Santhony.gutierrez@amd.com const uint32_t rpc = static_cast<uint32_t>(ipdInstNum()); 27611308Santhony.gutierrez@amd.com if (curr_rpc != rpc) { 27711308Santhony.gutierrez@amd.com w->pushToReconvergenceStack(rpc, curr_rpc, curr_mask); 27811308Santhony.gutierrez@amd.com } 27911308Santhony.gutierrez@amd.com 28011308Santhony.gutierrez@amd.com // taken branch 28111308Santhony.gutierrez@amd.com const uint32_t true_pc = getTargetPc(); 28211308Santhony.gutierrez@amd.com VectorMask true_mask; 28311534Sjohn.kalamatianos@amd.com for (unsigned int lane = 0; lane < w->computeUnit->wfSize(); ++lane) { 28411308Santhony.gutierrez@amd.com true_mask[lane] = cond.get<bool>(w, lane) & curr_mask[lane]; 28511308Santhony.gutierrez@amd.com } 28611308Santhony.gutierrez@amd.com 28711308Santhony.gutierrez@amd.com // not taken branch 28811697Santhony.gutierrez@amd.com const uint32_t false_pc = nextInstAddr(); 28911308Santhony.gutierrez@amd.com assert(true_pc != false_pc); 29011308Santhony.gutierrez@amd.com if (false_pc != rpc && true_mask.count() < curr_mask.count()) { 29111308Santhony.gutierrez@amd.com VectorMask false_mask = curr_mask & ~true_mask; 29211308Santhony.gutierrez@amd.com w->pushToReconvergenceStack(false_pc, rpc, false_mask); 29311308Santhony.gutierrez@amd.com } 29411308Santhony.gutierrez@amd.com 29511308Santhony.gutierrez@amd.com if (true_pc != rpc && true_mask.count()) { 29611308Santhony.gutierrez@amd.com w->pushToReconvergenceStack(true_pc, rpc, true_mask); 29711308Santhony.gutierrez@amd.com } 29811308Santhony.gutierrez@amd.com assert(w->pc() != curr_pc); 29911308Santhony.gutierrez@amd.com } 30011308Santhony.gutierrez@amd.com 30111308Santhony.gutierrez@amd.com 30211308Santhony.gutierrez@amd.com class CbrDirectInst : public CbrInstBase<LabelOperand> 30311308Santhony.gutierrez@amd.com { 30411308Santhony.gutierrez@amd.com public: 30511308Santhony.gutierrez@amd.com CbrDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 30611308Santhony.gutierrez@amd.com : CbrInstBase<LabelOperand>(ib, obj) 30711308Santhony.gutierrez@amd.com { 30811308Santhony.gutierrez@amd.com } 30911308Santhony.gutierrez@amd.com // the source operand of a conditional branch is a Condition 31011308Santhony.gutierrez@amd.com // Register which is not stored in the VRF 31111308Santhony.gutierrez@amd.com // so we do not count it as a source-register operand 31211308Santhony.gutierrez@amd.com // even though, formally, it is one. 31311308Santhony.gutierrez@amd.com int numSrcRegOperands() { return 0; } 31411308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 31511308Santhony.gutierrez@amd.com }; 31611308Santhony.gutierrez@amd.com 31711308Santhony.gutierrez@amd.com class CbrIndirectInst : public CbrInstBase<SRegOperand> 31811308Santhony.gutierrez@amd.com { 31911308Santhony.gutierrez@amd.com public: 32011308Santhony.gutierrez@amd.com CbrIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 32111308Santhony.gutierrez@amd.com : CbrInstBase<SRegOperand>(ib, obj) 32211308Santhony.gutierrez@amd.com { 32311308Santhony.gutierrez@amd.com } 32411308Santhony.gutierrez@amd.com // one source operand of the conditional indirect branch is a Condition 32511308Santhony.gutierrez@amd.com // register which is not stored in the VRF so we do not count it 32611308Santhony.gutierrez@amd.com // as a source-register operand even though, formally, it is one. 32711308Santhony.gutierrez@amd.com int numSrcRegOperands() { return target.isVectorRegister(); } 32811308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 32911308Santhony.gutierrez@amd.com }; 33011308Santhony.gutierrez@amd.com 33111308Santhony.gutierrez@amd.com GPUStaticInst* decodeCbr(const Brig::BrigInstBase *ib, 33211308Santhony.gutierrez@amd.com const BrigObject *obj); 33311308Santhony.gutierrez@amd.com 33411308Santhony.gutierrez@amd.com template<typename TargetType> 33511308Santhony.gutierrez@amd.com class BrInstBase : public HsailGPUStaticInst 33611308Santhony.gutierrez@amd.com { 33711308Santhony.gutierrez@amd.com public: 33811347Sandreas.hansson@arm.com void generateDisassembly() override; 33911308Santhony.gutierrez@amd.com 34011308Santhony.gutierrez@amd.com ImmOperand<uint32_t> width; 34111308Santhony.gutierrez@amd.com TargetType target; 34211308Santhony.gutierrez@amd.com 34311308Santhony.gutierrez@amd.com BrInstBase(const Brig::BrigInstBase *ib, const BrigObject *obj) 34411308Santhony.gutierrez@amd.com : HsailGPUStaticInst(obj, "br") 34511308Santhony.gutierrez@amd.com { 34611692Santhony.gutierrez@amd.com setFlag(Branch); 34711692Santhony.gutierrez@amd.com setFlag(UnconditionalJump); 34811308Santhony.gutierrez@amd.com width.init(((Brig::BrigInstBr *)ib)->width, obj); 34911308Santhony.gutierrez@amd.com unsigned op_offs = obj->getOperandPtr(ib->operands, 0); 35011308Santhony.gutierrez@amd.com target.init(op_offs, obj); 35111308Santhony.gutierrez@amd.com } 35211308Santhony.gutierrez@amd.com 35311308Santhony.gutierrez@amd.com uint32_t getTargetPc() override { return target.getTarget(0, 0); } 35411308Santhony.gutierrez@amd.com 35511347Sandreas.hansson@arm.com void execute(GPUDynInstPtr gpuDynInst) override; 35611347Sandreas.hansson@arm.com bool isVectorRegister(int operandIndex) override { 35711308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 35811308Santhony.gutierrez@amd.com return target.isVectorRegister(); 35911308Santhony.gutierrez@amd.com } 36011347Sandreas.hansson@arm.com bool isCondRegister(int operandIndex) override { 36111308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 36211308Santhony.gutierrez@amd.com return target.isCondRegister(); 36311308Santhony.gutierrez@amd.com } 36411347Sandreas.hansson@arm.com bool isScalarRegister(int operandIndex) override { 36511308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 36611308Santhony.gutierrez@amd.com return target.isScalarRegister(); 36711308Santhony.gutierrez@amd.com } 36811347Sandreas.hansson@arm.com bool isSrcOperand(int operandIndex) override { 36911308Santhony.gutierrez@amd.com assert((operandIndex >= 0) && (operandIndex < getNumOperands())); 37011308Santhony.gutierrez@amd.com return true; 37111308Santhony.gutierrez@amd.com } 37211347Sandreas.hansson@arm.com bool isDstOperand(int operandIndex) override { return false; } 37311347Sandreas.hansson@arm.com int getOperandSize(int operandIndex) override { 37411308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 37511308Santhony.gutierrez@amd.com return target.opSize(); 37611308Santhony.gutierrez@amd.com } 37711699Santhony.gutierrez@amd.com int 37811699Santhony.gutierrez@amd.com getRegisterIndex(int operandIndex, GPUDynInstPtr gpuDynInst) override 37911699Santhony.gutierrez@amd.com { 38011308Santhony.gutierrez@amd.com assert(operandIndex >= 0 && operandIndex < getNumOperands()); 38111308Santhony.gutierrez@amd.com return target.regIndex(); 38211308Santhony.gutierrez@amd.com } 38311347Sandreas.hansson@arm.com int getNumOperands() override { return 1; } 38411308Santhony.gutierrez@amd.com }; 38511308Santhony.gutierrez@amd.com 38611308Santhony.gutierrez@amd.com template<typename TargetType> 38711308Santhony.gutierrez@amd.com void 38811308Santhony.gutierrez@amd.com BrInstBase<TargetType>::generateDisassembly() 38911308Santhony.gutierrez@amd.com { 39011308Santhony.gutierrez@amd.com std::string widthClause; 39111308Santhony.gutierrez@amd.com 39211308Santhony.gutierrez@amd.com if (width.bits != 1) { 39311308Santhony.gutierrez@amd.com widthClause = csprintf("_width(%d)", width.bits); 39411308Santhony.gutierrez@amd.com } 39511308Santhony.gutierrez@amd.com 39611308Santhony.gutierrez@amd.com disassembly = csprintf("%s%s %s", opcode, widthClause, 39711308Santhony.gutierrez@amd.com target.disassemble()); 39811308Santhony.gutierrez@amd.com } 39911308Santhony.gutierrez@amd.com 40011308Santhony.gutierrez@amd.com template<typename TargetType> 40111308Santhony.gutierrez@amd.com void 40211308Santhony.gutierrez@amd.com BrInstBase<TargetType>::execute(GPUDynInstPtr gpuDynInst) 40311308Santhony.gutierrez@amd.com { 40411308Santhony.gutierrez@amd.com Wavefront *w = gpuDynInst->wavefront(); 40511308Santhony.gutierrez@amd.com 40611308Santhony.gutierrez@amd.com if (getTargetPc() == w->rpc()) { 40711308Santhony.gutierrez@amd.com w->popFromReconvergenceStack(); 40811308Santhony.gutierrez@amd.com } else { 40911308Santhony.gutierrez@amd.com // Rpc and execution mask remain the same 41011308Santhony.gutierrez@amd.com w->pc(getTargetPc()); 41111308Santhony.gutierrez@amd.com } 41211308Santhony.gutierrez@amd.com } 41311308Santhony.gutierrez@amd.com 41411308Santhony.gutierrez@amd.com class BrDirectInst : public BrInstBase<LabelOperand> 41511308Santhony.gutierrez@amd.com { 41611308Santhony.gutierrez@amd.com public: 41711308Santhony.gutierrez@amd.com BrDirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 41811308Santhony.gutierrez@amd.com : BrInstBase<LabelOperand>(ib, obj) 41911308Santhony.gutierrez@amd.com { 42011308Santhony.gutierrez@amd.com } 42111308Santhony.gutierrez@amd.com 42211308Santhony.gutierrez@amd.com int numSrcRegOperands() { return 0; } 42311308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 42411308Santhony.gutierrez@amd.com }; 42511308Santhony.gutierrez@amd.com 42611308Santhony.gutierrez@amd.com class BrIndirectInst : public BrInstBase<SRegOperand> 42711308Santhony.gutierrez@amd.com { 42811308Santhony.gutierrez@amd.com public: 42911308Santhony.gutierrez@amd.com BrIndirectInst(const Brig::BrigInstBase *ib, const BrigObject *obj) 43011308Santhony.gutierrez@amd.com : BrInstBase<SRegOperand>(ib, obj) 43111308Santhony.gutierrez@amd.com { 43211308Santhony.gutierrez@amd.com } 43311308Santhony.gutierrez@amd.com int numSrcRegOperands() { return target.isVectorRegister(); } 43411308Santhony.gutierrez@amd.com int numDstRegOperands() { return 0; } 43511308Santhony.gutierrez@amd.com }; 43611308Santhony.gutierrez@amd.com 43711308Santhony.gutierrez@amd.com GPUStaticInst* decodeBr(const Brig::BrigInstBase *ib, 43811308Santhony.gutierrez@amd.com const BrigObject *obj); 43911308Santhony.gutierrez@amd.com} // namespace HsailISA 44011308Santhony.gutierrez@amd.com 44111308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_INSTS_BRANCH_HH__ 442