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