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