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_OPERAND_HH__
3711308Santhony.gutierrez@amd.com#define __ARCH_HSAIL_OPERAND_HH__
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.com/**
4011308Santhony.gutierrez@amd.com *  @file operand.hh
4111308Santhony.gutierrez@amd.com *
4211308Santhony.gutierrez@amd.com *  Defines classes encapsulating HSAIL instruction operands.
4311308Santhony.gutierrez@amd.com */
4411308Santhony.gutierrez@amd.com
4511534Sjohn.kalamatianos@amd.com#include <limits>
4611308Santhony.gutierrez@amd.com#include <string>
4711308Santhony.gutierrez@amd.com
4811308Santhony.gutierrez@amd.com#include "arch/hsail/Brig.h"
4911308Santhony.gutierrez@amd.com#include "base/trace.hh"
5011308Santhony.gutierrez@amd.com#include "base/types.hh"
5111308Santhony.gutierrez@amd.com#include "debug/GPUReg.hh"
5211308Santhony.gutierrez@amd.com#include "enums/RegisterType.hh"
5311308Santhony.gutierrez@amd.com#include "gpu-compute/brig_object.hh"
5411308Santhony.gutierrez@amd.com#include "gpu-compute/compute_unit.hh"
5511308Santhony.gutierrez@amd.com#include "gpu-compute/hsail_code.hh"
5611308Santhony.gutierrez@amd.com#include "gpu-compute/shader.hh"
5711308Santhony.gutierrez@amd.com#include "gpu-compute/vector_register_file.hh"
5811308Santhony.gutierrez@amd.com#include "gpu-compute/wavefront.hh"
5911308Santhony.gutierrez@amd.com
6011308Santhony.gutierrez@amd.comclass Label;
6111308Santhony.gutierrez@amd.comclass StorageElement;
6211308Santhony.gutierrez@amd.com
6311308Santhony.gutierrez@amd.comclass BaseOperand
6411308Santhony.gutierrez@amd.com{
6511308Santhony.gutierrez@amd.com  public:
6611308Santhony.gutierrez@amd.com    Enums::RegisterType registerType;
6711308Santhony.gutierrez@amd.com    uint32_t regOperandSize;
6811308Santhony.gutierrez@amd.com    BaseOperand() { registerType = Enums::RT_NONE; regOperandSize = 0; }
6911308Santhony.gutierrez@amd.com    bool isVectorRegister() { return registerType == Enums::RT_VECTOR; }
7011308Santhony.gutierrez@amd.com    bool isScalarRegister() { return registerType == Enums::RT_SCALAR; }
7111308Santhony.gutierrez@amd.com    bool isCondRegister() { return registerType == Enums::RT_CONDITION; }
7211308Santhony.gutierrez@amd.com    unsigned int regIndex() { return 0; }
7311308Santhony.gutierrez@amd.com    uint32_t opSize() { return regOperandSize; }
7411308Santhony.gutierrez@amd.com    virtual ~BaseOperand() { }
7511308Santhony.gutierrez@amd.com};
7611308Santhony.gutierrez@amd.com
7711308Santhony.gutierrez@amd.comclass BrigRegOperandInfo
7811308Santhony.gutierrez@amd.com{
7911308Santhony.gutierrez@amd.com  public:
8011308Santhony.gutierrez@amd.com    Brig::BrigKind16_t kind;
8111308Santhony.gutierrez@amd.com    Brig::BrigType type;
8211308Santhony.gutierrez@amd.com    Brig::BrigRegisterKind regKind;
8311308Santhony.gutierrez@amd.com
8411308Santhony.gutierrez@amd.com    BrigRegOperandInfo(Brig::BrigKind16_t _kind,
8511308Santhony.gutierrez@amd.com                       Brig::BrigRegisterKind _regKind)
8611308Santhony.gutierrez@amd.com        : kind(_kind), regKind(_regKind)
8711308Santhony.gutierrez@amd.com    {
8811308Santhony.gutierrez@amd.com    }
8911308Santhony.gutierrez@amd.com
9011308Santhony.gutierrez@amd.com    BrigRegOperandInfo(Brig::BrigKind16_t _kind, Brig::BrigType _type)
9111308Santhony.gutierrez@amd.com        : kind(_kind), type(_type)
9211308Santhony.gutierrez@amd.com    {
9311308Santhony.gutierrez@amd.com    }
9411308Santhony.gutierrez@amd.com
9511308Santhony.gutierrez@amd.com    BrigRegOperandInfo() : kind(Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES),
9611308Santhony.gutierrez@amd.com                           type(Brig::BRIG_TYPE_NONE)
9711308Santhony.gutierrez@amd.com    {
9811308Santhony.gutierrez@amd.com    }
9911308Santhony.gutierrez@amd.com};
10011308Santhony.gutierrez@amd.com
10111308Santhony.gutierrez@amd.comBrigRegOperandInfo findRegDataType(unsigned opOffset, const BrigObject *obj);
10211308Santhony.gutierrez@amd.com
10311308Santhony.gutierrez@amd.comclass BaseRegOperand : public BaseOperand
10411308Santhony.gutierrez@amd.com{
10511308Santhony.gutierrez@amd.com  public:
10611308Santhony.gutierrez@amd.com    unsigned regIdx;
10711308Santhony.gutierrez@amd.com    char regFileChar;
10811308Santhony.gutierrez@amd.com
10911308Santhony.gutierrez@amd.com    bool init(unsigned opOffset, const BrigObject *obj,
11011308Santhony.gutierrez@amd.com              unsigned &maxRegIdx, char _regFileChar);
11111308Santhony.gutierrez@amd.com
11211308Santhony.gutierrez@amd.com    bool init_from_vect(unsigned opOffset, const BrigObject *obj, int at,
11311308Santhony.gutierrez@amd.com                        unsigned &maxRegIdx, char _regFileChar);
11411308Santhony.gutierrez@amd.com
11511308Santhony.gutierrez@amd.com    void initWithStrOffset(unsigned strOffset, const BrigObject *obj,
11611308Santhony.gutierrez@amd.com                           unsigned &maxRegIdx, char _regFileChar);
11711308Santhony.gutierrez@amd.com    unsigned int regIndex() { return regIdx; }
11811308Santhony.gutierrez@amd.com};
11911308Santhony.gutierrez@amd.com
12011308Santhony.gutierrez@amd.comclass SRegOperand : public BaseRegOperand
12111308Santhony.gutierrez@amd.com{
12211308Santhony.gutierrez@amd.com  public:
12311308Santhony.gutierrez@amd.com    static unsigned maxRegIdx;
12411308Santhony.gutierrez@amd.com
12511308Santhony.gutierrez@amd.com    bool
12611308Santhony.gutierrez@amd.com    init(unsigned opOffset, const BrigObject *obj)
12711308Santhony.gutierrez@amd.com    {
12811308Santhony.gutierrez@amd.com        regOperandSize = sizeof(uint32_t);
12911308Santhony.gutierrez@amd.com        registerType = Enums::RT_VECTOR;
13011308Santhony.gutierrez@amd.com
13111308Santhony.gutierrez@amd.com        return BaseRegOperand::init(opOffset, obj, maxRegIdx, 's');
13211308Santhony.gutierrez@amd.com    }
13311308Santhony.gutierrez@amd.com
13411308Santhony.gutierrez@amd.com    bool
13511308Santhony.gutierrez@amd.com    init_from_vect(unsigned opOffset, const BrigObject *obj, int at)
13611308Santhony.gutierrez@amd.com    {
13711308Santhony.gutierrez@amd.com        regOperandSize = sizeof(uint32_t);
13811308Santhony.gutierrez@amd.com        registerType = Enums::RT_VECTOR;
13911308Santhony.gutierrez@amd.com
14011308Santhony.gutierrez@amd.com        return BaseRegOperand::init_from_vect(opOffset, obj, at, maxRegIdx,
14111308Santhony.gutierrez@amd.com                                              's');
14211308Santhony.gutierrez@amd.com    }
14311308Santhony.gutierrez@amd.com
14411308Santhony.gutierrez@amd.com    void
14511308Santhony.gutierrez@amd.com    initWithStrOffset(unsigned strOffset, const BrigObject *obj)
14611308Santhony.gutierrez@amd.com    {
14711308Santhony.gutierrez@amd.com        regOperandSize = sizeof(uint32_t);
14811308Santhony.gutierrez@amd.com        registerType = Enums::RT_VECTOR;
14911308Santhony.gutierrez@amd.com
15011308Santhony.gutierrez@amd.com        return BaseRegOperand::initWithStrOffset(strOffset, obj, maxRegIdx,
15111308Santhony.gutierrez@amd.com                                                 's');
15211308Santhony.gutierrez@amd.com    }
15311308Santhony.gutierrez@amd.com
15411308Santhony.gutierrez@amd.com    template<typename OperandType>
15511308Santhony.gutierrez@amd.com    OperandType
15611308Santhony.gutierrez@amd.com    get(Wavefront *w, int lane)
15711308Santhony.gutierrez@amd.com    {
15811308Santhony.gutierrez@amd.com        assert(sizeof(OperandType) <= sizeof(uint32_t));
15911308Santhony.gutierrez@amd.com        assert(regIdx < w->maxSpVgprs);
16011308Santhony.gutierrez@amd.com        // if OperandType is smaller than 32-bit, we truncate the value
16111308Santhony.gutierrez@amd.com        OperandType ret;
16211308Santhony.gutierrez@amd.com        uint32_t vgprIdx;
16311308Santhony.gutierrez@amd.com
16411308Santhony.gutierrez@amd.com        switch (sizeof(OperandType)) {
16511308Santhony.gutierrez@amd.com          case 1: // 1 byte operand
16611308Santhony.gutierrez@amd.com              vgprIdx = w->remap(regIdx, 1, 1);
16711308Santhony.gutierrez@amd.com              ret = (w->computeUnit->vrf[w->simdId]->
16811308Santhony.gutierrez@amd.com                      read<uint32_t>(vgprIdx, lane)) & 0xff;
16911308Santhony.gutierrez@amd.com            break;
17011308Santhony.gutierrez@amd.com          case 2: // 2 byte operand
17111308Santhony.gutierrez@amd.com              vgprIdx = w->remap(regIdx, 2, 1);
17211308Santhony.gutierrez@amd.com              ret = (w->computeUnit->vrf[w->simdId]->
17311308Santhony.gutierrez@amd.com                      read<uint32_t>(vgprIdx, lane)) & 0xffff;
17411308Santhony.gutierrez@amd.com            break;
17511308Santhony.gutierrez@amd.com          case 4: // 4 byte operand
17611308Santhony.gutierrez@amd.com              vgprIdx = w->remap(regIdx,sizeof(OperandType), 1);
17711308Santhony.gutierrez@amd.com              ret = w->computeUnit->vrf[w->simdId]->
17811308Santhony.gutierrez@amd.com                  read<OperandType>(vgprIdx, lane);
17911308Santhony.gutierrez@amd.com            break;
18011308Santhony.gutierrez@amd.com          default:
18111308Santhony.gutierrez@amd.com            panic("Bad OperandType\n");
18211308Santhony.gutierrez@amd.com            break;
18311308Santhony.gutierrez@amd.com        }
18411308Santhony.gutierrez@amd.com
18511308Santhony.gutierrez@amd.com        return (OperandType)ret;
18611308Santhony.gutierrez@amd.com    }
18711308Santhony.gutierrez@amd.com
18811308Santhony.gutierrez@amd.com    // special get method for compatibility with LabelOperand
18911308Santhony.gutierrez@amd.com    uint32_t
19011308Santhony.gutierrez@amd.com    getTarget(Wavefront *w, int lane)
19111308Santhony.gutierrez@amd.com    {
19211308Santhony.gutierrez@amd.com        return get<uint32_t>(w, lane);
19311308Santhony.gutierrez@amd.com    }
19411308Santhony.gutierrez@amd.com
19511308Santhony.gutierrez@amd.com    template<typename OperandType>
19611308Santhony.gutierrez@amd.com    void set(Wavefront *w, int lane, OperandType &val);
19711308Santhony.gutierrez@amd.com    std::string disassemble();
19811308Santhony.gutierrez@amd.com};
19911308Santhony.gutierrez@amd.com
20011308Santhony.gutierrez@amd.comtemplate<typename OperandType>
20111308Santhony.gutierrez@amd.comvoid
20211308Santhony.gutierrez@amd.comSRegOperand::set(Wavefront *w, int lane, OperandType &val)
20311308Santhony.gutierrez@amd.com{
20411308Santhony.gutierrez@amd.com    DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $s%d <- %d\n",
20511308Santhony.gutierrez@amd.com            w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx, val);
20611308Santhony.gutierrez@amd.com
20711308Santhony.gutierrez@amd.com    assert(sizeof(OperandType) == sizeof(uint32_t));
20811308Santhony.gutierrez@amd.com    assert(regIdx < w->maxSpVgprs);
20911308Santhony.gutierrez@amd.com    uint32_t vgprIdx = w->remap(regIdx, sizeof(OperandType), 1);
21011308Santhony.gutierrez@amd.com    w->computeUnit->vrf[w->simdId]->write<OperandType>(vgprIdx,val,lane);
21111308Santhony.gutierrez@amd.com}
21211308Santhony.gutierrez@amd.com
21311308Santhony.gutierrez@amd.comtemplate<>
21411308Santhony.gutierrez@amd.cominline void
21511308Santhony.gutierrez@amd.comSRegOperand::set(Wavefront *w, int lane, uint64_t &val)
21611308Santhony.gutierrez@amd.com{
21711308Santhony.gutierrez@amd.com    DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $s%d <- %d\n",
21811308Santhony.gutierrez@amd.com            w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx, val);
21911308Santhony.gutierrez@amd.com
22011308Santhony.gutierrez@amd.com    assert(regIdx < w->maxSpVgprs);
22111308Santhony.gutierrez@amd.com    uint32_t vgprIdx = w->remap(regIdx, sizeof(uint32_t), 1);
22211308Santhony.gutierrez@amd.com    w->computeUnit->vrf[w->simdId]->write<uint32_t>(vgprIdx, val, lane);
22311308Santhony.gutierrez@amd.com}
22411308Santhony.gutierrez@amd.com
22511308Santhony.gutierrez@amd.comclass DRegOperand : public BaseRegOperand
22611308Santhony.gutierrez@amd.com{
22711308Santhony.gutierrez@amd.com  public:
22811308Santhony.gutierrez@amd.com    static unsigned maxRegIdx;
22911308Santhony.gutierrez@amd.com
23011308Santhony.gutierrez@amd.com    bool
23111308Santhony.gutierrez@amd.com    init(unsigned opOffset, const BrigObject *obj)
23211308Santhony.gutierrez@amd.com    {
23311308Santhony.gutierrez@amd.com        regOperandSize = sizeof(uint64_t);
23411308Santhony.gutierrez@amd.com        registerType = Enums::RT_VECTOR;
23511308Santhony.gutierrez@amd.com
23611308Santhony.gutierrez@amd.com        return BaseRegOperand::init(opOffset, obj, maxRegIdx, 'd');
23711308Santhony.gutierrez@amd.com    }
23811308Santhony.gutierrez@amd.com
23911308Santhony.gutierrez@amd.com    bool
24011308Santhony.gutierrez@amd.com    init_from_vect(unsigned opOffset, const BrigObject *obj, int at)
24111308Santhony.gutierrez@amd.com    {
24211308Santhony.gutierrez@amd.com        regOperandSize = sizeof(uint64_t);
24311308Santhony.gutierrez@amd.com        registerType = Enums::RT_VECTOR;
24411308Santhony.gutierrez@amd.com
24511308Santhony.gutierrez@amd.com        return BaseRegOperand::init_from_vect(opOffset, obj, at, maxRegIdx,
24611308Santhony.gutierrez@amd.com                                              'd');
24711308Santhony.gutierrez@amd.com    }
24811308Santhony.gutierrez@amd.com
24911308Santhony.gutierrez@amd.com    void
25011308Santhony.gutierrez@amd.com    initWithStrOffset(unsigned strOffset, const BrigObject *obj)
25111308Santhony.gutierrez@amd.com    {
25211308Santhony.gutierrez@amd.com        regOperandSize = sizeof(uint64_t);
25311308Santhony.gutierrez@amd.com        registerType = Enums::RT_VECTOR;
25411308Santhony.gutierrez@amd.com
25511308Santhony.gutierrez@amd.com        return BaseRegOperand::initWithStrOffset(strOffset, obj, maxRegIdx,
25611308Santhony.gutierrez@amd.com                                                 'd');
25711308Santhony.gutierrez@amd.com    }
25811308Santhony.gutierrez@amd.com
25911308Santhony.gutierrez@amd.com    template<typename OperandType>
26011308Santhony.gutierrez@amd.com    OperandType
26111308Santhony.gutierrez@amd.com    get(Wavefront *w, int lane)
26211308Santhony.gutierrez@amd.com    {
26311308Santhony.gutierrez@amd.com        assert(sizeof(OperandType) <= sizeof(uint64_t));
26411308Santhony.gutierrez@amd.com        // TODO: this check is valid only for HSAIL
26511308Santhony.gutierrez@amd.com        assert(regIdx < w->maxDpVgprs);
26611308Santhony.gutierrez@amd.com        uint32_t vgprIdx = w->remap(regIdx, sizeof(OperandType), 1);
26711308Santhony.gutierrez@amd.com
26811308Santhony.gutierrez@amd.com        return w->computeUnit->vrf[w->simdId]->read<OperandType>(vgprIdx,lane);
26911308Santhony.gutierrez@amd.com    }
27011308Santhony.gutierrez@amd.com
27111308Santhony.gutierrez@amd.com    template<typename OperandType>
27211308Santhony.gutierrez@amd.com    void
27311308Santhony.gutierrez@amd.com    set(Wavefront *w, int lane, OperandType &val)
27411308Santhony.gutierrez@amd.com    {
27511308Santhony.gutierrez@amd.com        DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $d%d <- %d\n",
27611308Santhony.gutierrez@amd.com                w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx,
27711308Santhony.gutierrez@amd.com                val);
27811308Santhony.gutierrez@amd.com
27911308Santhony.gutierrez@amd.com        assert(sizeof(OperandType) <= sizeof(uint64_t));
28011308Santhony.gutierrez@amd.com        // TODO: this check is valid only for HSAIL
28111308Santhony.gutierrez@amd.com        assert(regIdx < w->maxDpVgprs);
28211308Santhony.gutierrez@amd.com        uint32_t vgprIdx = w->remap(regIdx, sizeof(OperandType), 1);
28311308Santhony.gutierrez@amd.com        w->computeUnit->vrf[w->simdId]->write<OperandType>(vgprIdx,val,lane);
28411308Santhony.gutierrez@amd.com    }
28511308Santhony.gutierrez@amd.com
28611308Santhony.gutierrez@amd.com    std::string disassemble();
28711308Santhony.gutierrez@amd.com};
28811308Santhony.gutierrez@amd.com
28911308Santhony.gutierrez@amd.comclass CRegOperand : public BaseRegOperand
29011308Santhony.gutierrez@amd.com{
29111308Santhony.gutierrez@amd.com  public:
29211308Santhony.gutierrez@amd.com    static unsigned maxRegIdx;
29311308Santhony.gutierrez@amd.com
29411308Santhony.gutierrez@amd.com    bool
29511308Santhony.gutierrez@amd.com    init(unsigned opOffset, const BrigObject *obj)
29611308Santhony.gutierrez@amd.com    {
29711308Santhony.gutierrez@amd.com        regOperandSize = sizeof(uint8_t);
29811308Santhony.gutierrez@amd.com        registerType = Enums::RT_CONDITION;
29911308Santhony.gutierrez@amd.com
30011308Santhony.gutierrez@amd.com        return BaseRegOperand::init(opOffset, obj, maxRegIdx, 'c');
30111308Santhony.gutierrez@amd.com    }
30211308Santhony.gutierrez@amd.com
30311308Santhony.gutierrez@amd.com    bool
30411308Santhony.gutierrez@amd.com    init_from_vect(unsigned opOffset, const BrigObject *obj, int at)
30511308Santhony.gutierrez@amd.com    {
30611308Santhony.gutierrez@amd.com        regOperandSize = sizeof(uint8_t);
30711308Santhony.gutierrez@amd.com        registerType = Enums::RT_CONDITION;
30811308Santhony.gutierrez@amd.com
30911308Santhony.gutierrez@amd.com        return BaseRegOperand::init_from_vect(opOffset, obj, at, maxRegIdx,
31011308Santhony.gutierrez@amd.com                                              'c');
31111308Santhony.gutierrez@amd.com    }
31211308Santhony.gutierrez@amd.com
31311308Santhony.gutierrez@amd.com    void
31411308Santhony.gutierrez@amd.com    initWithStrOffset(unsigned strOffset, const BrigObject *obj)
31511308Santhony.gutierrez@amd.com    {
31611308Santhony.gutierrez@amd.com        regOperandSize = sizeof(uint8_t);
31711308Santhony.gutierrez@amd.com        registerType = Enums::RT_CONDITION;
31811308Santhony.gutierrez@amd.com
31911308Santhony.gutierrez@amd.com        return BaseRegOperand::initWithStrOffset(strOffset, obj, maxRegIdx,
32011308Santhony.gutierrez@amd.com                                                 'c');
32111308Santhony.gutierrez@amd.com    }
32211308Santhony.gutierrez@amd.com
32311308Santhony.gutierrez@amd.com    template<typename OperandType>
32411308Santhony.gutierrez@amd.com    OperandType
32511308Santhony.gutierrez@amd.com    get(Wavefront *w, int lane)
32611308Santhony.gutierrez@amd.com    {
32711308Santhony.gutierrez@amd.com        assert(regIdx < w->condRegState->numRegs());
32811308Santhony.gutierrez@amd.com
32911308Santhony.gutierrez@amd.com        return w->condRegState->read<OperandType>((int)regIdx, lane);
33011308Santhony.gutierrez@amd.com    }
33111308Santhony.gutierrez@amd.com
33211308Santhony.gutierrez@amd.com    template<typename OperandType>
33311308Santhony.gutierrez@amd.com    void
33411308Santhony.gutierrez@amd.com    set(Wavefront *w, int lane, OperandType &val)
33511308Santhony.gutierrez@amd.com    {
33611308Santhony.gutierrez@amd.com        DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: $c%d <- %d\n",
33711308Santhony.gutierrez@amd.com                w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane, regIdx,
33811308Santhony.gutierrez@amd.com                val);
33911308Santhony.gutierrez@amd.com
34011308Santhony.gutierrez@amd.com        assert(regIdx < w->condRegState->numRegs());
34111308Santhony.gutierrez@amd.com        w->condRegState->write<OperandType>(regIdx,lane,val);
34211308Santhony.gutierrez@amd.com    }
34311308Santhony.gutierrez@amd.com
34411308Santhony.gutierrez@amd.com    std::string disassemble();
34511308Santhony.gutierrez@amd.com};
34611308Santhony.gutierrez@amd.com
34711308Santhony.gutierrez@amd.comtemplate<typename T>
34811308Santhony.gutierrez@amd.comclass ImmOperand : public BaseOperand
34911308Santhony.gutierrez@amd.com{
35011534Sjohn.kalamatianos@amd.com  private:
35111534Sjohn.kalamatianos@amd.com    uint16_t kind;
35211308Santhony.gutierrez@amd.com  public:
35311308Santhony.gutierrez@amd.com    T bits;
35411308Santhony.gutierrez@amd.com
35511308Santhony.gutierrez@amd.com    bool init(unsigned opOffset, const BrigObject *obj);
35611308Santhony.gutierrez@amd.com    bool init_from_vect(unsigned opOffset, const BrigObject *obj, int at);
35711308Santhony.gutierrez@amd.com    std::string disassemble();
35811308Santhony.gutierrez@amd.com
35911308Santhony.gutierrez@amd.com    template<typename OperandType>
36011308Santhony.gutierrez@amd.com    OperandType
36111534Sjohn.kalamatianos@amd.com    get(Wavefront *w)
36211308Santhony.gutierrez@amd.com    {
36311308Santhony.gutierrez@amd.com        assert(sizeof(OperandType) <= sizeof(T));
36411534Sjohn.kalamatianos@amd.com        panic_if(w == nullptr, "WF pointer needs to be set");
36511308Santhony.gutierrez@amd.com
36611534Sjohn.kalamatianos@amd.com        switch (kind) {
36711534Sjohn.kalamatianos@amd.com          // immediate operand is WF size
36811534Sjohn.kalamatianos@amd.com          case Brig::BRIG_KIND_OPERAND_WAVESIZE:
36911534Sjohn.kalamatianos@amd.com            return (OperandType)w->computeUnit->wfSize();
37011534Sjohn.kalamatianos@amd.com            break;
37111534Sjohn.kalamatianos@amd.com
37211534Sjohn.kalamatianos@amd.com          default:
37311534Sjohn.kalamatianos@amd.com            return *(OperandType*)&bits;
37411534Sjohn.kalamatianos@amd.com            break;
37511534Sjohn.kalamatianos@amd.com        }
37611308Santhony.gutierrez@amd.com    }
37711308Santhony.gutierrez@amd.com
37811308Santhony.gutierrez@amd.com    // This version of get() takes a WF* and a lane id for
37911308Santhony.gutierrez@amd.com    // compatibility with the register-based get() methods.
38011308Santhony.gutierrez@amd.com    template<typename OperandType>
38111308Santhony.gutierrez@amd.com    OperandType
38211308Santhony.gutierrez@amd.com    get(Wavefront *w, int lane)
38311308Santhony.gutierrez@amd.com    {
38411534Sjohn.kalamatianos@amd.com        return get<OperandType>(w);
38511308Santhony.gutierrez@amd.com    }
38611308Santhony.gutierrez@amd.com};
38711308Santhony.gutierrez@amd.com
38811308Santhony.gutierrez@amd.comtemplate<typename T>
38911308Santhony.gutierrez@amd.combool
39011308Santhony.gutierrez@amd.comImmOperand<T>::init(unsigned opOffset, const BrigObject *obj)
39111308Santhony.gutierrez@amd.com{
39211308Santhony.gutierrez@amd.com    const Brig::BrigOperand *brigOp = obj->getOperand(opOffset);
39311308Santhony.gutierrez@amd.com
39411308Santhony.gutierrez@amd.com    switch (brigOp->kind) {
39511308Santhony.gutierrez@amd.com      // this is immediate operand
39611308Santhony.gutierrez@amd.com      case Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES:
39711308Santhony.gutierrez@amd.com        {
39811308Santhony.gutierrez@amd.com            DPRINTF(GPUReg, "sizeof(T): %lu, byteCount: %d\n", sizeof(T),
39911308Santhony.gutierrez@amd.com                    brigOp->byteCount);
40011308Santhony.gutierrez@amd.com
40111308Santhony.gutierrez@amd.com            auto cbptr = (Brig::BrigOperandConstantBytes*)brigOp;
40211308Santhony.gutierrez@amd.com
40311308Santhony.gutierrez@amd.com            bits = *((T*)(obj->getData(cbptr->bytes + 4)));
40411534Sjohn.kalamatianos@amd.com            kind = brigOp->kind;
40511308Santhony.gutierrez@amd.com            return true;
40611308Santhony.gutierrez@amd.com        }
40711308Santhony.gutierrez@amd.com        break;
40811308Santhony.gutierrez@amd.com
40911308Santhony.gutierrez@amd.com      case Brig::BRIG_KIND_OPERAND_WAVESIZE:
41011534Sjohn.kalamatianos@amd.com        kind = brigOp->kind;
41111534Sjohn.kalamatianos@amd.com        bits = std::numeric_limits<unsigned long long>::digits;
41211308Santhony.gutierrez@amd.com        return true;
41311308Santhony.gutierrez@amd.com
41411308Santhony.gutierrez@amd.com      default:
41511534Sjohn.kalamatianos@amd.com        kind = Brig::BRIG_KIND_NONE;
41611308Santhony.gutierrez@amd.com        return false;
41711308Santhony.gutierrez@amd.com    }
41811308Santhony.gutierrez@amd.com}
41911308Santhony.gutierrez@amd.com
42011308Santhony.gutierrez@amd.comtemplate <typename T>
42111308Santhony.gutierrez@amd.combool
42211308Santhony.gutierrez@amd.comImmOperand<T>::init_from_vect(unsigned opOffset, const BrigObject *obj, int at)
42311308Santhony.gutierrez@amd.com{
42411308Santhony.gutierrez@amd.com    const Brig::BrigOperand *brigOp = obj->getOperand(opOffset);
42511308Santhony.gutierrez@amd.com
42611308Santhony.gutierrez@amd.com    if (brigOp->kind != Brig::BRIG_KIND_OPERAND_OPERAND_LIST) {
42711534Sjohn.kalamatianos@amd.com        kind = Brig::BRIG_KIND_NONE;
42811308Santhony.gutierrez@amd.com        return false;
42911308Santhony.gutierrez@amd.com    }
43011308Santhony.gutierrez@amd.com
43111308Santhony.gutierrez@amd.com
43211308Santhony.gutierrez@amd.com    const Brig::BrigOperandOperandList *brigVecOp =
43311308Santhony.gutierrez@amd.com         (const Brig::BrigOperandOperandList *)brigOp;
43411308Santhony.gutierrez@amd.com
43511308Santhony.gutierrez@amd.com    unsigned *data_offset =
43611308Santhony.gutierrez@amd.com        (unsigned *)obj->getData(brigVecOp->elements + 4 * (at + 1));
43711308Santhony.gutierrez@amd.com
43811308Santhony.gutierrez@amd.com    const Brig::BrigOperand *p =
43911308Santhony.gutierrez@amd.com        (const Brig::BrigOperand *)obj->getOperand(*data_offset);
44011308Santhony.gutierrez@amd.com
44111308Santhony.gutierrez@amd.com    if (p->kind != Brig::BRIG_KIND_OPERAND_CONSTANT_BYTES) {
44211534Sjohn.kalamatianos@amd.com        kind = Brig::BRIG_KIND_NONE;
44311308Santhony.gutierrez@amd.com        return false;
44411308Santhony.gutierrez@amd.com    }
44511308Santhony.gutierrez@amd.com
44611308Santhony.gutierrez@amd.com    return init(*data_offset, obj);
44711308Santhony.gutierrez@amd.com}
44811308Santhony.gutierrez@amd.comtemplate<typename T>
44911308Santhony.gutierrez@amd.comstd::string
45011308Santhony.gutierrez@amd.comImmOperand<T>::disassemble()
45111308Santhony.gutierrez@amd.com{
45211308Santhony.gutierrez@amd.com    return csprintf("0x%08x", bits);
45311308Santhony.gutierrez@amd.com}
45411308Santhony.gutierrez@amd.com
45511308Santhony.gutierrez@amd.comtemplate<typename RegOperand, typename T>
45611308Santhony.gutierrez@amd.comclass RegOrImmOperand : public BaseOperand
45711308Santhony.gutierrez@amd.com{
45811308Santhony.gutierrez@amd.com  private:
45911308Santhony.gutierrez@amd.com    bool is_imm;
46011308Santhony.gutierrez@amd.com
46111308Santhony.gutierrez@amd.com  public:
46211308Santhony.gutierrez@amd.com    void setImm(const bool value) { is_imm = value; }
46311308Santhony.gutierrez@amd.com
46411308Santhony.gutierrez@amd.com    ImmOperand<T> imm_op;
46511308Santhony.gutierrez@amd.com    RegOperand reg_op;
46611308Santhony.gutierrez@amd.com
46711308Santhony.gutierrez@amd.com    RegOrImmOperand() { is_imm = false; }
46811308Santhony.gutierrez@amd.com    void init(unsigned opOffset, const BrigObject *obj);
46911308Santhony.gutierrez@amd.com    void init_from_vect(unsigned opOffset, const BrigObject *obj, int at);
47011308Santhony.gutierrez@amd.com    std::string disassemble();
47111308Santhony.gutierrez@amd.com
47211308Santhony.gutierrez@amd.com    template<typename OperandType>
47311308Santhony.gutierrez@amd.com    OperandType
47411308Santhony.gutierrez@amd.com    get(Wavefront *w, int lane)
47511308Santhony.gutierrez@amd.com    {
47611534Sjohn.kalamatianos@amd.com        return is_imm ?  imm_op.template get<OperandType>(w) :
47711308Santhony.gutierrez@amd.com                         reg_op.template get<OperandType>(w, lane);
47811308Santhony.gutierrez@amd.com    }
47911308Santhony.gutierrez@amd.com
48011308Santhony.gutierrez@amd.com    uint32_t
48111308Santhony.gutierrez@amd.com    opSize()
48211308Santhony.gutierrez@amd.com    {
48311308Santhony.gutierrez@amd.com        if (!is_imm) {
48411308Santhony.gutierrez@amd.com            return reg_op.opSize();
48511308Santhony.gutierrez@amd.com        }
48611308Santhony.gutierrez@amd.com
48711308Santhony.gutierrez@amd.com        return 0;
48811308Santhony.gutierrez@amd.com    }
48911308Santhony.gutierrez@amd.com
49011308Santhony.gutierrez@amd.com    bool
49111308Santhony.gutierrez@amd.com    isVectorRegister()
49211308Santhony.gutierrez@amd.com    {
49311308Santhony.gutierrez@amd.com        if (!is_imm) {
49411308Santhony.gutierrez@amd.com            return reg_op.registerType == Enums::RT_VECTOR;
49511308Santhony.gutierrez@amd.com        }
49611308Santhony.gutierrez@amd.com        return false;
49711308Santhony.gutierrez@amd.com    }
49811308Santhony.gutierrez@amd.com
49911308Santhony.gutierrez@amd.com    bool
50011308Santhony.gutierrez@amd.com    isCondRegister()
50111308Santhony.gutierrez@amd.com    {
50211308Santhony.gutierrez@amd.com        if (!is_imm) {
50311308Santhony.gutierrez@amd.com            return reg_op.registerType == Enums::RT_CONDITION;
50411308Santhony.gutierrez@amd.com        }
50511308Santhony.gutierrez@amd.com
50611308Santhony.gutierrez@amd.com        return false;
50711308Santhony.gutierrez@amd.com    }
50811308Santhony.gutierrez@amd.com
50911308Santhony.gutierrez@amd.com    bool
51011308Santhony.gutierrez@amd.com    isScalarRegister()
51111308Santhony.gutierrez@amd.com    {
51211308Santhony.gutierrez@amd.com        if (!is_imm) {
51311308Santhony.gutierrez@amd.com            return reg_op.registerType == Enums::RT_SCALAR;
51411308Santhony.gutierrez@amd.com        }
51511308Santhony.gutierrez@amd.com
51611308Santhony.gutierrez@amd.com        return false;
51711308Santhony.gutierrez@amd.com    }
51811308Santhony.gutierrez@amd.com
51911308Santhony.gutierrez@amd.com    unsigned int
52011308Santhony.gutierrez@amd.com    regIndex()
52111308Santhony.gutierrez@amd.com    {
52211308Santhony.gutierrez@amd.com        if (!is_imm) {
52311308Santhony.gutierrez@amd.com            return reg_op.regIndex();
52411308Santhony.gutierrez@amd.com        }
52511308Santhony.gutierrez@amd.com        return 0;
52611308Santhony.gutierrez@amd.com    }
52711308Santhony.gutierrez@amd.com};
52811308Santhony.gutierrez@amd.com
52911308Santhony.gutierrez@amd.comtemplate<typename RegOperand, typename T>
53011308Santhony.gutierrez@amd.comvoid
53111308Santhony.gutierrez@amd.comRegOrImmOperand<RegOperand, T>::init(unsigned opOffset, const BrigObject *obj)
53211308Santhony.gutierrez@amd.com{
53311308Santhony.gutierrez@amd.com    is_imm = false;
53411308Santhony.gutierrez@amd.com
53511308Santhony.gutierrez@amd.com    if (reg_op.init(opOffset, obj)) {
53611308Santhony.gutierrez@amd.com        return;
53711308Santhony.gutierrez@amd.com    }
53811308Santhony.gutierrez@amd.com
53911308Santhony.gutierrez@amd.com    if (imm_op.init(opOffset, obj)) {
54011308Santhony.gutierrez@amd.com        is_imm = true;
54111308Santhony.gutierrez@amd.com        return;
54211308Santhony.gutierrez@amd.com    }
54311308Santhony.gutierrez@amd.com
54411308Santhony.gutierrez@amd.com    fatal("RegOrImmOperand::init(): bad operand kind %d\n",
54511308Santhony.gutierrez@amd.com          obj->getOperand(opOffset)->kind);
54611308Santhony.gutierrez@amd.com}
54711308Santhony.gutierrez@amd.com
54811308Santhony.gutierrez@amd.comtemplate<typename RegOperand, typename T>
54911308Santhony.gutierrez@amd.comvoid
55011308Santhony.gutierrez@amd.comRegOrImmOperand<RegOperand, T>::init_from_vect(unsigned opOffset,
55111308Santhony.gutierrez@amd.com                                               const BrigObject *obj, int at)
55211308Santhony.gutierrez@amd.com{
55311308Santhony.gutierrez@amd.com    if (reg_op.init_from_vect(opOffset, obj, at)) {
55411308Santhony.gutierrez@amd.com        is_imm = false;
55511308Santhony.gutierrez@amd.com
55611308Santhony.gutierrez@amd.com        return;
55711308Santhony.gutierrez@amd.com    }
55811308Santhony.gutierrez@amd.com
55911308Santhony.gutierrez@amd.com    if (imm_op.init_from_vect(opOffset, obj, at)) {
56011308Santhony.gutierrez@amd.com        is_imm = true;
56111308Santhony.gutierrez@amd.com
56211308Santhony.gutierrez@amd.com        return;
56311308Santhony.gutierrez@amd.com    }
56411308Santhony.gutierrez@amd.com
56511308Santhony.gutierrez@amd.com    fatal("RegOrImmOperand::init(): bad operand kind %d\n",
56611308Santhony.gutierrez@amd.com          obj->getOperand(opOffset)->kind);
56711308Santhony.gutierrez@amd.com}
56811308Santhony.gutierrez@amd.com
56911308Santhony.gutierrez@amd.comtemplate<typename RegOperand, typename T>
57011308Santhony.gutierrez@amd.comstd::string
57111308Santhony.gutierrez@amd.comRegOrImmOperand<RegOperand, T>::disassemble()
57211308Santhony.gutierrez@amd.com{
57311308Santhony.gutierrez@amd.com    return is_imm ? imm_op.disassemble() : reg_op.disassemble();
57411308Santhony.gutierrez@amd.com}
57511308Santhony.gutierrez@amd.com
57611308Santhony.gutierrez@amd.comtypedef RegOrImmOperand<SRegOperand, uint32_t> SRegOrImmOperand;
57711308Santhony.gutierrez@amd.comtypedef RegOrImmOperand<DRegOperand, uint64_t> DRegOrImmOperand;
57811308Santhony.gutierrez@amd.comtypedef RegOrImmOperand<CRegOperand, bool> CRegOrImmOperand;
57911308Santhony.gutierrez@amd.com
58011308Santhony.gutierrez@amd.comclass AddrOperandBase : public BaseOperand
58111308Santhony.gutierrez@amd.com{
58211308Santhony.gutierrez@amd.com  protected:
58311308Santhony.gutierrez@amd.com    // helper function for init()
58411308Santhony.gutierrez@amd.com    void parseAddr(const Brig::BrigOperandAddress *op, const BrigObject *obj);
58511308Santhony.gutierrez@amd.com
58611308Santhony.gutierrez@amd.com    // helper function for disassemble()
58711308Santhony.gutierrez@amd.com    std::string disassemble(std::string reg_disassembly);
58811308Santhony.gutierrez@amd.com    uint64_t calcUniformBase();
58911308Santhony.gutierrez@amd.com
59011308Santhony.gutierrez@amd.com  public:
59111534Sjohn.kalamatianos@amd.com    virtual void calcVector(Wavefront *w, std::vector<Addr> &addrVec) = 0;
59211308Santhony.gutierrez@amd.com    virtual uint64_t calcLane(Wavefront *w, int lane=0) = 0;
59311308Santhony.gutierrez@amd.com
59411733Santhony.gutierrez@amd.com    int64_t offset;
59511308Santhony.gutierrez@amd.com    const char *name = nullptr;
59611308Santhony.gutierrez@amd.com    StorageElement *storageElement;
59711308Santhony.gutierrez@amd.com};
59811308Santhony.gutierrez@amd.com
59911308Santhony.gutierrez@amd.comtemplate<typename RegOperandType>
60011308Santhony.gutierrez@amd.comclass RegAddrOperand : public AddrOperandBase
60111308Santhony.gutierrez@amd.com{
60211308Santhony.gutierrez@amd.com  public:
60311308Santhony.gutierrez@amd.com    RegOperandType reg;
60411308Santhony.gutierrez@amd.com    void init(unsigned opOffset, const BrigObject *obj);
60511308Santhony.gutierrez@amd.com    uint64_t calcUniform();
60611534Sjohn.kalamatianos@amd.com    void calcVector(Wavefront *w, std::vector<Addr> &addrVec);
60711308Santhony.gutierrez@amd.com    uint64_t calcLane(Wavefront *w, int lane=0);
60811308Santhony.gutierrez@amd.com    uint32_t opSize() { return reg.opSize(); }
60911308Santhony.gutierrez@amd.com    bool isVectorRegister() { return reg.registerType == Enums::RT_VECTOR; }
61011308Santhony.gutierrez@amd.com    bool isCondRegister() { return reg.registerType == Enums::RT_CONDITION; }
61111308Santhony.gutierrez@amd.com    bool isScalarRegister() { return reg.registerType == Enums::RT_SCALAR; }
61211308Santhony.gutierrez@amd.com    unsigned int regIndex() { return reg.regIndex(); }
61311308Santhony.gutierrez@amd.com    std::string disassemble();
61411308Santhony.gutierrez@amd.com};
61511308Santhony.gutierrez@amd.com
61611308Santhony.gutierrez@amd.comtemplate<typename RegOperandType>
61711308Santhony.gutierrez@amd.comvoid
61811308Santhony.gutierrez@amd.comRegAddrOperand<RegOperandType>::init(unsigned opOffset, const BrigObject *obj)
61911308Santhony.gutierrez@amd.com{
62011308Santhony.gutierrez@amd.com    using namespace Brig;
62111308Santhony.gutierrez@amd.com
62211308Santhony.gutierrez@amd.com    const BrigOperand *baseOp = obj->getOperand(opOffset);
62311308Santhony.gutierrez@amd.com
62411308Santhony.gutierrez@amd.com    switch (baseOp->kind) {
62511308Santhony.gutierrez@amd.com      case BRIG_KIND_OPERAND_ADDRESS:
62611308Santhony.gutierrez@amd.com        {
62711308Santhony.gutierrez@amd.com            const BrigOperandAddress *op = (BrigOperandAddress*)baseOp;
62811308Santhony.gutierrez@amd.com            storageElement = nullptr;
62911308Santhony.gutierrez@amd.com
63011308Santhony.gutierrez@amd.com            reg.init(op->reg, obj);
63111308Santhony.gutierrez@amd.com
63211308Santhony.gutierrez@amd.com            if (reg.regFileChar == 's') {
63311733Santhony.gutierrez@amd.com                // if the address expression is 32b, then the hi
63411733Santhony.gutierrez@amd.com                // bits of the offset must be set to 0 in the BRIG
63511733Santhony.gutierrez@amd.com                assert(!op->offset.hi);
63611733Santhony.gutierrez@amd.com                /**
63711733Santhony.gutierrez@amd.com                 * the offset field of an HSAIL instruction may be negative
63811733Santhony.gutierrez@amd.com                 * so here we cast the raw bits we get from the BRIG file to
63911733Santhony.gutierrez@amd.com                 * a signed type to avoid address calculation errors
64011733Santhony.gutierrez@amd.com                 */
64111733Santhony.gutierrez@amd.com                offset = (int32_t)(op->offset.lo);
64211308Santhony.gutierrez@amd.com                reg.regOperandSize = sizeof(uint32_t);
64311308Santhony.gutierrez@amd.com                registerType = Enums::RT_VECTOR;
64411308Santhony.gutierrez@amd.com            }
64511308Santhony.gutierrez@amd.com            else if (reg.regFileChar == 'd') {
64611733Santhony.gutierrez@amd.com                offset = (int64_t)(((uint64_t)(op->offset.hi) << 32)
64711733Santhony.gutierrez@amd.com                    | (uint64_t)(op->offset.lo));
64811308Santhony.gutierrez@amd.com                reg.regOperandSize = sizeof(uint64_t);
64911308Santhony.gutierrez@amd.com                registerType = Enums::RT_VECTOR;
65011308Santhony.gutierrez@amd.com            }
65111308Santhony.gutierrez@amd.com        }
65211308Santhony.gutierrez@amd.com        break;
65311308Santhony.gutierrez@amd.com
65411308Santhony.gutierrez@amd.com      default:
65511308Santhony.gutierrez@amd.com        fatal("RegAddrOperand: bad operand kind %d\n", baseOp->kind);
65611308Santhony.gutierrez@amd.com        break;
65711308Santhony.gutierrez@amd.com    }
65811308Santhony.gutierrez@amd.com}
65911308Santhony.gutierrez@amd.com
66011308Santhony.gutierrez@amd.comtemplate<typename RegOperandType>
66111308Santhony.gutierrez@amd.comuint64_t
66211308Santhony.gutierrez@amd.comRegAddrOperand<RegOperandType>::calcUniform()
66311308Santhony.gutierrez@amd.com{
66411308Santhony.gutierrez@amd.com    fatal("can't do calcUniform() on register-based address\n");
66511308Santhony.gutierrez@amd.com
66611308Santhony.gutierrez@amd.com    return 0;
66711308Santhony.gutierrez@amd.com}
66811308Santhony.gutierrez@amd.com
66911308Santhony.gutierrez@amd.comtemplate<typename RegOperandType>
67011308Santhony.gutierrez@amd.comvoid
67111534Sjohn.kalamatianos@amd.comRegAddrOperand<RegOperandType>::calcVector(Wavefront *w,
67211534Sjohn.kalamatianos@amd.com                                           std::vector<Addr> &addrVec)
67311308Santhony.gutierrez@amd.com{
67411308Santhony.gutierrez@amd.com    Addr address = calcUniformBase();
67511308Santhony.gutierrez@amd.com
67611534Sjohn.kalamatianos@amd.com    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
67711308Santhony.gutierrez@amd.com        if (w->execMask(lane)) {
67811308Santhony.gutierrez@amd.com            if (reg.regFileChar == 's') {
67911308Santhony.gutierrez@amd.com                addrVec[lane] = address + reg.template get<uint32_t>(w, lane);
68011308Santhony.gutierrez@amd.com            } else {
68111308Santhony.gutierrez@amd.com                addrVec[lane] = address + reg.template get<Addr>(w, lane);
68211308Santhony.gutierrez@amd.com            }
68311308Santhony.gutierrez@amd.com        }
68411308Santhony.gutierrez@amd.com    }
68511308Santhony.gutierrez@amd.com}
68611308Santhony.gutierrez@amd.com
68711308Santhony.gutierrez@amd.comtemplate<typename RegOperandType>
68811308Santhony.gutierrez@amd.comuint64_t
68911308Santhony.gutierrez@amd.comRegAddrOperand<RegOperandType>::calcLane(Wavefront *w, int lane)
69011308Santhony.gutierrez@amd.com{
69111308Santhony.gutierrez@amd.com    Addr address = calcUniformBase();
69211308Santhony.gutierrez@amd.com
69311308Santhony.gutierrez@amd.com    return address + reg.template get<Addr>(w, lane);
69411308Santhony.gutierrez@amd.com}
69511308Santhony.gutierrez@amd.com
69611308Santhony.gutierrez@amd.comtemplate<typename RegOperandType>
69711308Santhony.gutierrez@amd.comstd::string
69811308Santhony.gutierrez@amd.comRegAddrOperand<RegOperandType>::disassemble()
69911308Santhony.gutierrez@amd.com{
70011308Santhony.gutierrez@amd.com    return AddrOperandBase::disassemble(reg.disassemble());
70111308Santhony.gutierrez@amd.com}
70211308Santhony.gutierrez@amd.com
70311308Santhony.gutierrez@amd.comtypedef RegAddrOperand<SRegOperand> SRegAddrOperand;
70411308Santhony.gutierrez@amd.comtypedef RegAddrOperand<DRegOperand> DRegAddrOperand;
70511308Santhony.gutierrez@amd.com
70611308Santhony.gutierrez@amd.comclass NoRegAddrOperand : public AddrOperandBase
70711308Santhony.gutierrez@amd.com{
70811308Santhony.gutierrez@amd.com  public:
70911308Santhony.gutierrez@amd.com    void init(unsigned opOffset, const BrigObject *obj);
71011308Santhony.gutierrez@amd.com    uint64_t calcUniform();
71111534Sjohn.kalamatianos@amd.com    void calcVector(Wavefront *w, std::vector<Addr> &addrVec);
71211308Santhony.gutierrez@amd.com    uint64_t calcLane(Wavefront *w, int lane=0);
71311308Santhony.gutierrez@amd.com    std::string disassemble();
71411308Santhony.gutierrez@amd.com};
71511308Santhony.gutierrez@amd.com
71611308Santhony.gutierrez@amd.cominline uint64_t
71711308Santhony.gutierrez@amd.comNoRegAddrOperand::calcUniform()
71811308Santhony.gutierrez@amd.com{
71911308Santhony.gutierrez@amd.com    return AddrOperandBase::calcUniformBase();
72011308Santhony.gutierrez@amd.com}
72111308Santhony.gutierrez@amd.com
72211308Santhony.gutierrez@amd.cominline uint64_t
72311308Santhony.gutierrez@amd.comNoRegAddrOperand::calcLane(Wavefront *w, int lane)
72411308Santhony.gutierrez@amd.com{
72511308Santhony.gutierrez@amd.com    return calcUniform();
72611308Santhony.gutierrez@amd.com}
72711308Santhony.gutierrez@amd.com
72811308Santhony.gutierrez@amd.cominline void
72911534Sjohn.kalamatianos@amd.comNoRegAddrOperand::calcVector(Wavefront *w, std::vector<Addr> &addrVec)
73011308Santhony.gutierrez@amd.com{
73111308Santhony.gutierrez@amd.com    uint64_t address = calcUniformBase();
73211308Santhony.gutierrez@amd.com
73311534Sjohn.kalamatianos@amd.com    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane)
73411308Santhony.gutierrez@amd.com        addrVec[lane] = address;
73511308Santhony.gutierrez@amd.com}
73611308Santhony.gutierrez@amd.com
73711308Santhony.gutierrez@amd.comclass LabelOperand : public BaseOperand
73811308Santhony.gutierrez@amd.com{
73911308Santhony.gutierrez@amd.com  public:
74011308Santhony.gutierrez@amd.com    Label *label;
74111308Santhony.gutierrez@amd.com
74211308Santhony.gutierrez@amd.com    void init(unsigned opOffset, const BrigObject *obj);
74311308Santhony.gutierrez@amd.com    std::string disassemble();
74411308Santhony.gutierrez@amd.com
74511308Santhony.gutierrez@amd.com    // special get method for compatibility with SRegOperand
74611308Santhony.gutierrez@amd.com    uint32_t getTarget(Wavefront *w, int lane);
74711308Santhony.gutierrez@amd.com
74811308Santhony.gutierrez@amd.com};
74911308Santhony.gutierrez@amd.com
75011308Santhony.gutierrez@amd.comclass ListOperand : public BaseOperand
75111308Santhony.gutierrez@amd.com{
75211308Santhony.gutierrez@amd.com  public:
75311308Santhony.gutierrez@amd.com    int elementCount;
75411308Santhony.gutierrez@amd.com    std::vector<StorageElement*> callArgs;
75511308Santhony.gutierrez@amd.com
75611308Santhony.gutierrez@amd.com    int
75711308Santhony.gutierrez@amd.com    getSrcOperand(int idx)
75811308Santhony.gutierrez@amd.com    {
75911308Santhony.gutierrez@amd.com        DPRINTF(GPUReg, "getSrcOperand, idx: %d, sz_args: %d\n", idx,
76011308Santhony.gutierrez@amd.com                callArgs.size());
76111308Santhony.gutierrez@amd.com
76211308Santhony.gutierrez@amd.com        return callArgs.at(idx)->offset;
76311308Santhony.gutierrez@amd.com    }
76411308Santhony.gutierrez@amd.com
76511308Santhony.gutierrez@amd.com    void init(unsigned opOffset, const BrigObject *obj);
76611308Santhony.gutierrez@amd.com
76711308Santhony.gutierrez@amd.com    std::string disassemble();
76811308Santhony.gutierrez@amd.com
76911308Santhony.gutierrez@amd.com    template<typename OperandType>
77011308Santhony.gutierrez@amd.com    OperandType
77111308Santhony.gutierrez@amd.com    get(Wavefront *w, int lane, int arg_idx)
77211308Santhony.gutierrez@amd.com    {
77311308Santhony.gutierrez@amd.com        return w->readCallArgMem<OperandType>(lane, getSrcOperand(arg_idx));
77411308Santhony.gutierrez@amd.com    }
77511308Santhony.gutierrez@amd.com
77611308Santhony.gutierrez@amd.com    template<typename OperandType>
77711308Santhony.gutierrez@amd.com    void
77811308Santhony.gutierrez@amd.com    set(Wavefront *w, int lane, OperandType val)
77911308Santhony.gutierrez@amd.com    {
78011308Santhony.gutierrez@amd.com        w->writeCallArgMem<OperandType>(lane, getSrcOperand(0), val);
78111308Santhony.gutierrez@amd.com        DPRINTF(GPUReg, "CU%d, WF[%d][%d], lane %d: arg[%d] <- %d\n",
78211308Santhony.gutierrez@amd.com                w->computeUnit->cu_id, w->simdId, w->wfSlotId, lane,
78311308Santhony.gutierrez@amd.com                getSrcOperand(0), val);
78411308Santhony.gutierrez@amd.com    }
78511308Santhony.gutierrez@amd.com};
78611308Santhony.gutierrez@amd.com
78711308Santhony.gutierrez@amd.comclass FunctionRefOperand : public BaseOperand
78811308Santhony.gutierrez@amd.com{
78911308Santhony.gutierrez@amd.com  public:
79011308Santhony.gutierrez@amd.com    const char *func_name;
79111308Santhony.gutierrez@amd.com
79211308Santhony.gutierrez@amd.com    void init(unsigned opOffset, const BrigObject *obj);
79311308Santhony.gutierrez@amd.com    std::string disassemble();
79411308Santhony.gutierrez@amd.com};
79511308Santhony.gutierrez@amd.com
79611308Santhony.gutierrez@amd.com#endif // __ARCH_HSAIL_OPERAND_HH__
797