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#include "arch/hsail/operand.hh" 3711308Santhony.gutierrez@amd.com 3811308Santhony.gutierrez@amd.comusing namespace Brig; 3911308Santhony.gutierrez@amd.com 4011308Santhony.gutierrez@amd.combool 4111308Santhony.gutierrez@amd.comBaseRegOperand::init(unsigned opOffset, const BrigObject *obj, 4211308Santhony.gutierrez@amd.com unsigned &maxRegIdx, char _regFileChar) 4311308Santhony.gutierrez@amd.com{ 4411308Santhony.gutierrez@amd.com regFileChar = _regFileChar; 4511308Santhony.gutierrez@amd.com const BrigOperand *brigOp = obj->getOperand(opOffset); 4611308Santhony.gutierrez@amd.com 4711308Santhony.gutierrez@amd.com if (brigOp->kind != BRIG_KIND_OPERAND_REGISTER) 4811308Santhony.gutierrez@amd.com return false; 4911308Santhony.gutierrez@amd.com 5011308Santhony.gutierrez@amd.com const BrigOperandRegister *brigRegOp = (const BrigOperandRegister*)brigOp; 5111308Santhony.gutierrez@amd.com 5211308Santhony.gutierrez@amd.com regIdx = brigRegOp->regNum; 5311308Santhony.gutierrez@amd.com 5411308Santhony.gutierrez@amd.com DPRINTF(GPUReg, "Operand: regNum: %d, kind: %d\n", regIdx, 5511308Santhony.gutierrez@amd.com brigRegOp->regKind); 5611308Santhony.gutierrez@amd.com 5711308Santhony.gutierrez@amd.com maxRegIdx = std::max(maxRegIdx, regIdx); 5811308Santhony.gutierrez@amd.com 5911308Santhony.gutierrez@amd.com return true; 6011308Santhony.gutierrez@amd.com} 6111308Santhony.gutierrez@amd.com 6211308Santhony.gutierrez@amd.comvoid 6311308Santhony.gutierrez@amd.comListOperand::init(unsigned opOffset, const BrigObject *obj) 6411308Santhony.gutierrez@amd.com{ 6511308Santhony.gutierrez@amd.com const BrigOperand *brigOp = (const BrigOperand*)obj->getOperand(opOffset); 6611308Santhony.gutierrez@amd.com 6711308Santhony.gutierrez@amd.com switch (brigOp->kind) { 6811308Santhony.gutierrez@amd.com case BRIG_KIND_OPERAND_CODE_LIST: 6911308Santhony.gutierrez@amd.com { 7011308Santhony.gutierrez@amd.com const BrigOperandCodeList *opList = 7111308Santhony.gutierrez@amd.com (const BrigOperandCodeList*)brigOp; 7211308Santhony.gutierrez@amd.com 7311308Santhony.gutierrez@amd.com const Brig::BrigData *oprnd_data = 7411308Santhony.gutierrez@amd.com obj->getBrigBaseData(opList->elements); 7511308Santhony.gutierrez@amd.com 7611308Santhony.gutierrez@amd.com // Note: for calls Dest list of operands could be size of 0. 7711308Santhony.gutierrez@amd.com elementCount = oprnd_data->byteCount / 4; 7811308Santhony.gutierrez@amd.com 7911308Santhony.gutierrez@amd.com DPRINTF(GPUReg, "Operand Code List: # elements: %d\n", 8011308Santhony.gutierrez@amd.com elementCount); 8111308Santhony.gutierrez@amd.com 8211308Santhony.gutierrez@amd.com for (int i = 0; i < elementCount; ++i) { 8311308Santhony.gutierrez@amd.com unsigned *data_offset = 8411308Santhony.gutierrez@amd.com (unsigned*)obj->getData(opList->elements + 4 * (i + 1)); 8511308Santhony.gutierrez@amd.com 8611308Santhony.gutierrez@amd.com const BrigDirectiveVariable *p = 8711308Santhony.gutierrez@amd.com (const BrigDirectiveVariable*)obj-> 8811308Santhony.gutierrez@amd.com getCodeSectionEntry(*data_offset); 8911308Santhony.gutierrez@amd.com 9011308Santhony.gutierrez@amd.com StorageElement *se = obj->currentCode->storageMap-> 9111308Santhony.gutierrez@amd.com findSymbol(BRIG_SEGMENT_ARG, p); 9211308Santhony.gutierrez@amd.com 9311308Santhony.gutierrez@amd.com assert(se); 9411308Santhony.gutierrez@amd.com callArgs.push_back(se); 9511308Santhony.gutierrez@amd.com } 9611308Santhony.gutierrez@amd.com } 9711308Santhony.gutierrez@amd.com break; 9811308Santhony.gutierrez@amd.com default: 9911308Santhony.gutierrez@amd.com fatal("ListOperand: bad operand kind %d\n", brigOp->kind); 10011308Santhony.gutierrez@amd.com } 10111308Santhony.gutierrez@amd.com} 10211308Santhony.gutierrez@amd.com 10311308Santhony.gutierrez@amd.comstd::string 10411308Santhony.gutierrez@amd.comListOperand::disassemble() 10511308Santhony.gutierrez@amd.com{ 10611308Santhony.gutierrez@amd.com std::string res_str(""); 10711308Santhony.gutierrez@amd.com 10811308Santhony.gutierrez@amd.com for (auto it : callArgs) { 10911308Santhony.gutierrez@amd.com res_str += csprintf("%s ", it->name.c_str()); 11011308Santhony.gutierrez@amd.com } 11111308Santhony.gutierrez@amd.com 11211308Santhony.gutierrez@amd.com return res_str; 11311308Santhony.gutierrez@amd.com} 11411308Santhony.gutierrez@amd.com 11511308Santhony.gutierrez@amd.comvoid 11611308Santhony.gutierrez@amd.comFunctionRefOperand::init(unsigned opOffset, const BrigObject *obj) 11711308Santhony.gutierrez@amd.com{ 11811308Santhony.gutierrez@amd.com const BrigOperand *baseOp = obj->getOperand(opOffset); 11911308Santhony.gutierrez@amd.com 12011308Santhony.gutierrez@amd.com if (baseOp->kind != BRIG_KIND_OPERAND_CODE_REF) { 12111308Santhony.gutierrez@amd.com fatal("FunctionRefOperand: bad operand kind %d\n", baseOp->kind); 12211308Santhony.gutierrez@amd.com } 12311308Santhony.gutierrez@amd.com 12411308Santhony.gutierrez@amd.com const BrigOperandCodeRef *brigOp = (const BrigOperandCodeRef*)baseOp; 12511308Santhony.gutierrez@amd.com 12611308Santhony.gutierrez@amd.com const BrigDirectiveExecutable *p = 12711308Santhony.gutierrez@amd.com (const BrigDirectiveExecutable*)obj->getCodeSectionEntry(brigOp->ref); 12811308Santhony.gutierrez@amd.com 12911308Santhony.gutierrez@amd.com func_name = obj->getString(p->name); 13011308Santhony.gutierrez@amd.com} 13111308Santhony.gutierrez@amd.com 13211308Santhony.gutierrez@amd.comstd::string 13311308Santhony.gutierrez@amd.comFunctionRefOperand::disassemble() 13411308Santhony.gutierrez@amd.com{ 13511308Santhony.gutierrez@amd.com DPRINTF(GPUReg, "Operand Func-ref name: %s\n", func_name); 13611308Santhony.gutierrez@amd.com 13711308Santhony.gutierrez@amd.com return csprintf("%s", func_name); 13811308Santhony.gutierrez@amd.com} 13911308Santhony.gutierrez@amd.com 14011308Santhony.gutierrez@amd.combool 14111308Santhony.gutierrez@amd.comBaseRegOperand::init_from_vect(unsigned opOffset, const BrigObject *obj, 14211308Santhony.gutierrez@amd.com int at, unsigned &maxRegIdx, char _regFileChar) 14311308Santhony.gutierrez@amd.com{ 14411308Santhony.gutierrez@amd.com regFileChar = _regFileChar; 14511308Santhony.gutierrez@amd.com const BrigOperand *brigOp = obj->getOperand(opOffset); 14611308Santhony.gutierrez@amd.com 14711308Santhony.gutierrez@amd.com if (brigOp->kind != BRIG_KIND_OPERAND_OPERAND_LIST) 14811308Santhony.gutierrez@amd.com return false; 14911308Santhony.gutierrez@amd.com 15011308Santhony.gutierrez@amd.com 15111308Santhony.gutierrez@amd.com const Brig::BrigOperandOperandList *brigRegVecOp = 15211308Santhony.gutierrez@amd.com (const Brig::BrigOperandOperandList*)brigOp; 15311308Santhony.gutierrez@amd.com 15411308Santhony.gutierrez@amd.com unsigned *data_offset = 15511308Santhony.gutierrez@amd.com (unsigned*)obj->getData(brigRegVecOp->elements + 4 * (at + 1)); 15611308Santhony.gutierrez@amd.com 15711308Santhony.gutierrez@amd.com const BrigOperand *p = 15811308Santhony.gutierrez@amd.com (const BrigOperand*)obj->getOperand(*data_offset); 15911308Santhony.gutierrez@amd.com if (p->kind != BRIG_KIND_OPERAND_REGISTER) { 16011308Santhony.gutierrez@amd.com return false; 16111308Santhony.gutierrez@amd.com } 16211308Santhony.gutierrez@amd.com 16311308Santhony.gutierrez@amd.com const BrigOperandRegister *brigRegOp =(const BrigOperandRegister*)p; 16411308Santhony.gutierrez@amd.com 16511308Santhony.gutierrez@amd.com regIdx = brigRegOp->regNum; 16611308Santhony.gutierrez@amd.com 16711308Santhony.gutierrez@amd.com DPRINTF(GPUReg, "Operand: regNum: %d, kind: %d \n", regIdx, 16811308Santhony.gutierrez@amd.com brigRegOp->regKind); 16911308Santhony.gutierrez@amd.com 17011308Santhony.gutierrez@amd.com maxRegIdx = std::max(maxRegIdx, regIdx); 17111308Santhony.gutierrez@amd.com 17211308Santhony.gutierrez@amd.com return true; 17311308Santhony.gutierrez@amd.com} 17411308Santhony.gutierrez@amd.com 17511308Santhony.gutierrez@amd.comvoid 17611308Santhony.gutierrez@amd.comBaseRegOperand::initWithStrOffset(unsigned strOffset, const BrigObject *obj, 17711308Santhony.gutierrez@amd.com unsigned &maxRegIdx, char _regFileChar) 17811308Santhony.gutierrez@amd.com{ 17911308Santhony.gutierrez@amd.com const char *name = obj->getString(strOffset); 18011308Santhony.gutierrez@amd.com char *endptr; 18111308Santhony.gutierrez@amd.com regIdx = strtoul(name + 2, &endptr, 10); 18211308Santhony.gutierrez@amd.com 18311308Santhony.gutierrez@amd.com if (name[0] != '$' || name[1] != _regFileChar) { 18411308Santhony.gutierrez@amd.com fatal("register operand parse error on \"%s\"\n", name); 18511308Santhony.gutierrez@amd.com } 18611308Santhony.gutierrez@amd.com 18711308Santhony.gutierrez@amd.com maxRegIdx = std::max(maxRegIdx, regIdx); 18811308Santhony.gutierrez@amd.com} 18911308Santhony.gutierrez@amd.com 19011308Santhony.gutierrez@amd.comunsigned SRegOperand::maxRegIdx; 19111308Santhony.gutierrez@amd.comunsigned DRegOperand::maxRegIdx; 19211308Santhony.gutierrez@amd.comunsigned CRegOperand::maxRegIdx; 19311308Santhony.gutierrez@amd.com 19411308Santhony.gutierrez@amd.comstd::string 19511308Santhony.gutierrez@amd.comSRegOperand::disassemble() 19611308Santhony.gutierrez@amd.com{ 19711308Santhony.gutierrez@amd.com return csprintf("$s%d", regIdx); 19811308Santhony.gutierrez@amd.com} 19911308Santhony.gutierrez@amd.com 20011308Santhony.gutierrez@amd.comstd::string 20111308Santhony.gutierrez@amd.comDRegOperand::disassemble() 20211308Santhony.gutierrez@amd.com{ 20311308Santhony.gutierrez@amd.com return csprintf("$d%d", regIdx); 20411308Santhony.gutierrez@amd.com} 20511308Santhony.gutierrez@amd.com 20611308Santhony.gutierrez@amd.comstd::string 20711308Santhony.gutierrez@amd.comCRegOperand::disassemble() 20811308Santhony.gutierrez@amd.com{ 20911308Santhony.gutierrez@amd.com return csprintf("$c%d", regIdx); 21011308Santhony.gutierrez@amd.com} 21111308Santhony.gutierrez@amd.com 21211308Santhony.gutierrez@amd.comBrigRegOperandInfo 21311308Santhony.gutierrez@amd.comfindRegDataType(unsigned opOffset, const BrigObject *obj) 21411308Santhony.gutierrez@amd.com{ 21511308Santhony.gutierrez@amd.com const BrigOperand *baseOp = obj->getOperand(opOffset); 21611308Santhony.gutierrez@amd.com 21711308Santhony.gutierrez@amd.com switch (baseOp->kind) { 21811308Santhony.gutierrez@amd.com case BRIG_KIND_OPERAND_REGISTER: 21911308Santhony.gutierrez@amd.com { 22011308Santhony.gutierrez@amd.com const BrigOperandRegister *op = (BrigOperandRegister*)baseOp; 22111308Santhony.gutierrez@amd.com 22211308Santhony.gutierrez@amd.com return BrigRegOperandInfo((BrigKind16_t)baseOp->kind, 22311308Santhony.gutierrez@amd.com (BrigRegisterKind)op->regKind); 22411308Santhony.gutierrez@amd.com } 22511308Santhony.gutierrez@amd.com break; 22611308Santhony.gutierrez@amd.com 22711736Sbrandon.potter@amd.com case BRIG_KIND_OPERAND_WAVESIZE: 22811736Sbrandon.potter@amd.com { 22911736Sbrandon.potter@amd.com BrigRegisterKind reg_kind = BRIG_REGISTER_KIND_DOUBLE; 23011736Sbrandon.potter@amd.com return BrigRegOperandInfo((BrigKind16_t)baseOp->kind, reg_kind); 23111736Sbrandon.potter@amd.com } 23211736Sbrandon.potter@amd.com 23311308Santhony.gutierrez@amd.com case BRIG_KIND_OPERAND_OPERAND_LIST: 23411308Santhony.gutierrez@amd.com { 23511736Sbrandon.potter@amd.com const BrigOperandOperandList *op = 23611736Sbrandon.potter@amd.com (BrigOperandOperandList*)baseOp; 23711736Sbrandon.potter@amd.com const BrigData *data_p = (BrigData*)obj->getData(op->elements); 23811308Santhony.gutierrez@amd.com 23911308Santhony.gutierrez@amd.com 24011736Sbrandon.potter@amd.com int num_operands = 0; 24111736Sbrandon.potter@amd.com BrigRegisterKind reg_kind = (BrigRegisterKind)0; 24211736Sbrandon.potter@amd.com for (int offset = 0; offset < data_p->byteCount; offset += 4) { 24311736Sbrandon.potter@amd.com const BrigOperand *op_p = (const BrigOperand *) 24411736Sbrandon.potter@amd.com obj->getOperand(((int *)data_p->bytes)[offset/4]); 24511308Santhony.gutierrez@amd.com 24611736Sbrandon.potter@amd.com if (op_p->kind == BRIG_KIND_OPERAND_REGISTER) { 24711736Sbrandon.potter@amd.com const BrigOperandRegister *brigRegOp = 24811736Sbrandon.potter@amd.com (const BrigOperandRegister*)op_p; 24911736Sbrandon.potter@amd.com reg_kind = (BrigRegisterKind)brigRegOp->regKind; 25011736Sbrandon.potter@amd.com } else if (op_p->kind == BRIG_KIND_OPERAND_CONSTANT_BYTES) { 25111736Sbrandon.potter@amd.com uint16_t num_bytes = 25211736Sbrandon.potter@amd.com ((Brig::BrigOperandConstantBytes*)op_p)->base.byteCount 25311736Sbrandon.potter@amd.com - sizeof(BrigBase); 25411736Sbrandon.potter@amd.com if (num_bytes == sizeof(uint32_t)) { 25511736Sbrandon.potter@amd.com reg_kind = BRIG_REGISTER_KIND_SINGLE; 25611736Sbrandon.potter@amd.com } else if (num_bytes == sizeof(uint64_t)) { 25711736Sbrandon.potter@amd.com reg_kind = BRIG_REGISTER_KIND_DOUBLE; 25811736Sbrandon.potter@amd.com } else { 25911736Sbrandon.potter@amd.com fatal("OperandList: bad operand size %d\n", num_bytes); 26011736Sbrandon.potter@amd.com } 26111736Sbrandon.potter@amd.com } else if (op_p->kind == BRIG_KIND_OPERAND_WAVESIZE) { 26211736Sbrandon.potter@amd.com reg_kind = BRIG_REGISTER_KIND_DOUBLE; 26311736Sbrandon.potter@amd.com } else { 26411736Sbrandon.potter@amd.com fatal("OperandList: bad operand kind %d\n", op_p->kind); 26511736Sbrandon.potter@amd.com } 26611308Santhony.gutierrez@amd.com 26711736Sbrandon.potter@amd.com num_operands++; 26811736Sbrandon.potter@amd.com } 26911736Sbrandon.potter@amd.com assert(baseOp->kind == BRIG_KIND_OPERAND_OPERAND_LIST); 27011308Santhony.gutierrez@amd.com 27111736Sbrandon.potter@amd.com return BrigRegOperandInfo((BrigKind16_t)baseOp->kind, reg_kind); 27211308Santhony.gutierrez@amd.com } 27311308Santhony.gutierrez@amd.com break; 27411308Santhony.gutierrez@amd.com 27511308Santhony.gutierrez@amd.com case BRIG_KIND_OPERAND_ADDRESS: 27611308Santhony.gutierrez@amd.com { 27711308Santhony.gutierrez@amd.com const BrigOperandAddress *op = (BrigOperandAddress*)baseOp; 27811308Santhony.gutierrez@amd.com 27911308Santhony.gutierrez@amd.com if (!op->reg) { 28011308Santhony.gutierrez@amd.com BrigType type = BRIG_TYPE_NONE; 28111308Santhony.gutierrez@amd.com 28211308Santhony.gutierrez@amd.com if (op->symbol) { 28311308Santhony.gutierrez@amd.com const BrigDirective *dir = (BrigDirective*) 28411308Santhony.gutierrez@amd.com obj->getCodeSectionEntry(op->symbol); 28511308Santhony.gutierrez@amd.com 28611308Santhony.gutierrez@amd.com assert(dir->kind == BRIG_KIND_DIRECTIVE_VARIABLE); 28711308Santhony.gutierrez@amd.com 28811308Santhony.gutierrez@amd.com const BrigDirectiveVariable *sym = 28911308Santhony.gutierrez@amd.com (const BrigDirectiveVariable*)dir; 29011308Santhony.gutierrez@amd.com 29111308Santhony.gutierrez@amd.com type = (BrigType)sym->type; 29211308Santhony.gutierrez@amd.com } 29311308Santhony.gutierrez@amd.com return BrigRegOperandInfo(BRIG_KIND_OPERAND_ADDRESS, 29411308Santhony.gutierrez@amd.com (BrigType)type); 29511308Santhony.gutierrez@amd.com } else { 29611308Santhony.gutierrez@amd.com const BrigOperandAddress *b = (const BrigOperandAddress*)baseOp; 29711308Santhony.gutierrez@amd.com const BrigOperand *reg = obj->getOperand(b->reg); 29811308Santhony.gutierrez@amd.com const BrigOperandRegister *rop = (BrigOperandRegister*)reg; 29911308Santhony.gutierrez@amd.com 30011308Santhony.gutierrez@amd.com return BrigRegOperandInfo(BRIG_KIND_OPERAND_REGISTER, 30111308Santhony.gutierrez@amd.com (BrigRegisterKind)rop->regKind); 30211308Santhony.gutierrez@amd.com } 30311308Santhony.gutierrez@amd.com } 30411308Santhony.gutierrez@amd.com break; 30511308Santhony.gutierrez@amd.com 30611308Santhony.gutierrez@amd.com default: 30711308Santhony.gutierrez@amd.com fatal("AddrOperand: bad operand kind %d\n", baseOp->kind); 30811308Santhony.gutierrez@amd.com break; 30911308Santhony.gutierrez@amd.com } 31011308Santhony.gutierrez@amd.com} 31111308Santhony.gutierrez@amd.com 31211308Santhony.gutierrez@amd.comvoid 31311308Santhony.gutierrez@amd.comAddrOperandBase::parseAddr(const BrigOperandAddress *op, const BrigObject *obj) 31411308Santhony.gutierrez@amd.com{ 31511308Santhony.gutierrez@amd.com assert(op->base.kind == BRIG_KIND_OPERAND_ADDRESS); 31611308Santhony.gutierrez@amd.com 31711308Santhony.gutierrez@amd.com const BrigDirective *d = 31811308Santhony.gutierrez@amd.com (BrigDirective*)obj->getCodeSectionEntry(op->symbol); 31911308Santhony.gutierrez@amd.com 32011739Sbrandon.potter@amd.com /** 32111739Sbrandon.potter@amd.com * HSAIL does not properly handle immediate offsets for instruction types 32211739Sbrandon.potter@amd.com * that utilize them. It currently only supports instructions that use 32311739Sbrandon.potter@amd.com * variables instead. Again, these pop up in code that is never executed 32411739Sbrandon.potter@amd.com * (i.e. the HCC AMP codes) so we just hack it here to let us pass through 32511739Sbrandon.potter@amd.com * the HSAIL object initialization. If such code is ever called, we would 32611739Sbrandon.potter@amd.com * have to implement this properly. 32711739Sbrandon.potter@amd.com */ 32811739Sbrandon.potter@amd.com if (d->kind != BRIG_KIND_DIRECTIVE_VARIABLE) { 32911739Sbrandon.potter@amd.com warn("HSAIL implementation does not support instructions with " 33011739Sbrandon.potter@amd.com "address calculations where the operand is not a variable\n"); 33111739Sbrandon.potter@amd.com } 33211739Sbrandon.potter@amd.com 33311308Santhony.gutierrez@amd.com const BrigDirectiveVariable *sym = (BrigDirectiveVariable*)d; 33411308Santhony.gutierrez@amd.com name = obj->getString(sym->name); 33511308Santhony.gutierrez@amd.com 33611308Santhony.gutierrez@amd.com if (sym->segment != BRIG_SEGMENT_ARG) { 33711308Santhony.gutierrez@amd.com storageElement = 33811308Santhony.gutierrez@amd.com obj->currentCode->storageMap->findSymbol(sym->segment, name); 33911308Santhony.gutierrez@amd.com offset = 0; 34011308Santhony.gutierrez@amd.com } else { 34111308Santhony.gutierrez@amd.com // sym->name does not work for BRIG_SEGMENT_ARG for the following case: 34211308Santhony.gutierrez@amd.com // 34311308Santhony.gutierrez@amd.com // void foo(int a); 34411308Santhony.gutierrez@amd.com // void bar(double a); 34511308Santhony.gutierrez@amd.com // 34611308Santhony.gutierrez@amd.com // foo(...) --> arg_u32 %param_p0; 34711308Santhony.gutierrez@amd.com // st_arg_u32 $s0, [%param_p0]; 34811308Santhony.gutierrez@amd.com // call &foo (%param_p0); 34911308Santhony.gutierrez@amd.com // bar(...) --> arg_f64 %param_p0; 35011308Santhony.gutierrez@amd.com // st_arg_u64 $d0, [%param_p0]; 35111308Santhony.gutierrez@amd.com // call &foo (%param_p0); 35211308Santhony.gutierrez@amd.com // 35311308Santhony.gutierrez@amd.com // Both functions use the same variable name (param_p0)!!! 35411308Santhony.gutierrez@amd.com // 35511308Santhony.gutierrez@amd.com // Maybe this is a bug in the compiler (I don't know). 35611308Santhony.gutierrez@amd.com // 35711308Santhony.gutierrez@amd.com // Solution: 35811308Santhony.gutierrez@amd.com // Use directive pointer (BrigDirectiveVariable) to differentiate 2 35911308Santhony.gutierrez@amd.com // versions of param_p0. 36011308Santhony.gutierrez@amd.com // 36111308Santhony.gutierrez@amd.com // Note this solution is kind of stupid, because we are pulling stuff 36211308Santhony.gutierrez@amd.com // out of the brig binary via the directive pointer and putting it into 36311308Santhony.gutierrez@amd.com // the symbol table, but now we are indexing the symbol table by the 36411308Santhony.gutierrez@amd.com // brig directive pointer! It makes the symbol table sort of pointless. 36511308Santhony.gutierrez@amd.com // But I don't want to mess with the rest of the infrastructure, so 36611308Santhony.gutierrez@amd.com // let's go with this for now. 36711308Santhony.gutierrez@amd.com // 36811308Santhony.gutierrez@amd.com // When we update the compiler again, we should see if this problem goes 36911308Santhony.gutierrez@amd.com // away. If so, we can fold some of this functionality into the code for 37011308Santhony.gutierrez@amd.com // kernel arguments. If not, maybe we can index the symbol name on a 37111308Santhony.gutierrez@amd.com // hash of the variable AND function name 37211308Santhony.gutierrez@amd.com storageElement = obj->currentCode-> 37311308Santhony.gutierrez@amd.com storageMap->findSymbol((Brig::BrigSegment)sym->segment, sym); 37411308Santhony.gutierrez@amd.com 37511308Santhony.gutierrez@amd.com assert(storageElement); 37611308Santhony.gutierrez@amd.com } 37711308Santhony.gutierrez@amd.com} 37811308Santhony.gutierrez@amd.com 37911308Santhony.gutierrez@amd.comuint64_t 38011308Santhony.gutierrez@amd.comAddrOperandBase::calcUniformBase() 38111308Santhony.gutierrez@amd.com{ 38211308Santhony.gutierrez@amd.com // start with offset, will be 0 if not specified 38311308Santhony.gutierrez@amd.com uint64_t address = offset; 38411308Santhony.gutierrez@amd.com 38511308Santhony.gutierrez@amd.com // add in symbol value if specified 38611308Santhony.gutierrez@amd.com if (storageElement) { 38711308Santhony.gutierrez@amd.com address += storageElement->offset; 38811308Santhony.gutierrez@amd.com } 38911308Santhony.gutierrez@amd.com 39011308Santhony.gutierrez@amd.com return address; 39111308Santhony.gutierrez@amd.com} 39211308Santhony.gutierrez@amd.com 39311308Santhony.gutierrez@amd.comstd::string 39411308Santhony.gutierrez@amd.comAddrOperandBase::disassemble(std::string reg_disassembly) 39511308Santhony.gutierrez@amd.com{ 39611308Santhony.gutierrez@amd.com std::string disasm; 39711308Santhony.gutierrez@amd.com 39811308Santhony.gutierrez@amd.com if (offset || reg_disassembly != "") { 39911308Santhony.gutierrez@amd.com disasm += "["; 40011308Santhony.gutierrez@amd.com 40111308Santhony.gutierrez@amd.com if (reg_disassembly != "") { 40211308Santhony.gutierrez@amd.com disasm += reg_disassembly; 40311308Santhony.gutierrez@amd.com 40411308Santhony.gutierrez@amd.com if (offset > 0) { 40511308Santhony.gutierrez@amd.com disasm += "+"; 40611308Santhony.gutierrez@amd.com } 40711308Santhony.gutierrez@amd.com } 40811308Santhony.gutierrez@amd.com 40911308Santhony.gutierrez@amd.com if (offset) { 41011308Santhony.gutierrez@amd.com disasm += csprintf("%d", offset); 41111308Santhony.gutierrez@amd.com } 41211308Santhony.gutierrez@amd.com 41311308Santhony.gutierrez@amd.com disasm += "]"; 41411308Santhony.gutierrez@amd.com } else if (name) { 41511308Santhony.gutierrez@amd.com disasm += csprintf("[%s]", name); 41611308Santhony.gutierrez@amd.com } 41711308Santhony.gutierrez@amd.com 41811308Santhony.gutierrez@amd.com return disasm; 41911308Santhony.gutierrez@amd.com} 42011308Santhony.gutierrez@amd.com 42111308Santhony.gutierrez@amd.comvoid 42211308Santhony.gutierrez@amd.comNoRegAddrOperand::init(unsigned opOffset, const BrigObject *obj) 42311308Santhony.gutierrez@amd.com{ 42411308Santhony.gutierrez@amd.com const BrigOperand *baseOp = obj->getOperand(opOffset); 42511308Santhony.gutierrez@amd.com 42611308Santhony.gutierrez@amd.com if (baseOp->kind == BRIG_KIND_OPERAND_ADDRESS) { 42711308Santhony.gutierrez@amd.com BrigOperandAddress *addrOp = (BrigOperandAddress*)baseOp; 42811308Santhony.gutierrez@amd.com parseAddr(addrOp, obj); 42911308Santhony.gutierrez@amd.com offset = (uint64_t(addrOp->offset.hi) << 32) | 43011308Santhony.gutierrez@amd.com uint64_t(addrOp->offset.lo); 43111308Santhony.gutierrez@amd.com } else { 43211308Santhony.gutierrez@amd.com fatal("NoRegAddrOperand: bad operand kind %d\n", baseOp->kind); 43311308Santhony.gutierrez@amd.com } 43411308Santhony.gutierrez@amd.com 43511308Santhony.gutierrez@amd.com} 43611308Santhony.gutierrez@amd.com 43711308Santhony.gutierrez@amd.comstd::string 43811308Santhony.gutierrez@amd.comNoRegAddrOperand::disassemble() 43911308Santhony.gutierrez@amd.com{ 44011308Santhony.gutierrez@amd.com return AddrOperandBase::disassemble(std::string("")); 44111308Santhony.gutierrez@amd.com} 44211308Santhony.gutierrez@amd.com 44311308Santhony.gutierrez@amd.comvoid 44411308Santhony.gutierrez@amd.comLabelOperand::init(unsigned opOffset, const BrigObject *obj) 44511308Santhony.gutierrez@amd.com{ 44611308Santhony.gutierrez@amd.com const BrigOperandCodeRef *op = 44711308Santhony.gutierrez@amd.com (const BrigOperandCodeRef*)obj->getOperand(opOffset); 44811308Santhony.gutierrez@amd.com 44911308Santhony.gutierrez@amd.com assert(op->base.kind == BRIG_KIND_OPERAND_CODE_REF); 45011308Santhony.gutierrez@amd.com 45111308Santhony.gutierrez@amd.com const BrigDirective *dir = 45211308Santhony.gutierrez@amd.com (const BrigDirective*)obj->getCodeSectionEntry(op->ref); 45311308Santhony.gutierrez@amd.com 45411308Santhony.gutierrez@amd.com assert(dir->kind == BRIG_KIND_DIRECTIVE_LABEL); 45511308Santhony.gutierrez@amd.com label = obj->currentCode->refLabel((BrigDirectiveLabel*)dir, obj); 45611308Santhony.gutierrez@amd.com} 45711308Santhony.gutierrez@amd.com 45811308Santhony.gutierrez@amd.comuint32_t 45911308Santhony.gutierrez@amd.comLabelOperand::getTarget(Wavefront *w, int lane) 46011308Santhony.gutierrez@amd.com{ 46111308Santhony.gutierrez@amd.com return label->get(); 46211308Santhony.gutierrez@amd.com} 46311308Santhony.gutierrez@amd.com 46411308Santhony.gutierrez@amd.comstd::string 46511308Santhony.gutierrez@amd.comLabelOperand::disassemble() 46611308Santhony.gutierrez@amd.com{ 46711308Santhony.gutierrez@amd.com return label->name; 46811308Santhony.gutierrez@amd.com} 469