gen.py revision 12563
111308Santhony.gutierrez@amd.com#! /usr/bin/python
211308Santhony.gutierrez@amd.com
311308Santhony.gutierrez@amd.com#
411308Santhony.gutierrez@amd.com#  Copyright (c) 2015 Advanced Micro Devices, Inc.
511308Santhony.gutierrez@amd.com#  All rights reserved.
611308Santhony.gutierrez@amd.com#
711308Santhony.gutierrez@amd.com#  For use for simulation and test purposes only
811308Santhony.gutierrez@amd.com#
911308Santhony.gutierrez@amd.com#  Redistribution and use in source and binary forms, with or without
1011308Santhony.gutierrez@amd.com#  modification, are permitted provided that the following conditions are met:
1111308Santhony.gutierrez@amd.com#
1211308Santhony.gutierrez@amd.com#  1. Redistributions of source code must retain the above copyright notice,
1311308Santhony.gutierrez@amd.com#  this list of conditions and the following disclaimer.
1411308Santhony.gutierrez@amd.com#
1511308Santhony.gutierrez@amd.com#  2. Redistributions in binary form must reproduce the above copyright notice,
1611308Santhony.gutierrez@amd.com#  this list of conditions and the following disclaimer in the documentation
1711308Santhony.gutierrez@amd.com#  and/or other materials provided with the distribution.
1811308Santhony.gutierrez@amd.com#
1911308Santhony.gutierrez@amd.com#  3. Neither the name of the copyright holder nor the names of its contributors
2011308Santhony.gutierrez@amd.com#  may be used to endorse or promote products derived from this software
2111308Santhony.gutierrez@amd.com#  without specific prior written permission.
2211308Santhony.gutierrez@amd.com#
2311308Santhony.gutierrez@amd.com#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2411308Santhony.gutierrez@amd.com#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2511308Santhony.gutierrez@amd.com#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2611308Santhony.gutierrez@amd.com#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2711308Santhony.gutierrez@amd.com#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2811308Santhony.gutierrez@amd.com#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2911308Santhony.gutierrez@amd.com#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3011308Santhony.gutierrez@amd.com#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3111308Santhony.gutierrez@amd.com#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3211308Santhony.gutierrez@amd.com#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3311308Santhony.gutierrez@amd.com#  POSSIBILITY OF SUCH DAMAGE.
3411308Santhony.gutierrez@amd.com#
3511308Santhony.gutierrez@amd.com#  Author: Steve Reinhardt
3611308Santhony.gutierrez@amd.com#
3711308Santhony.gutierrez@amd.com
3812563Sgabeblack@google.comfrom __future__ import print_function
3912563Sgabeblack@google.com
4011308Santhony.gutierrez@amd.comimport sys, re
4111308Santhony.gutierrez@amd.com
4211308Santhony.gutierrez@amd.comfrom m5.util import code_formatter
4311308Santhony.gutierrez@amd.com
4411308Santhony.gutierrez@amd.comif len(sys.argv) != 4:
4512563Sgabeblack@google.com    print("Error: need 3 args (file names)")
4611308Santhony.gutierrez@amd.com    sys.exit(0)
4711308Santhony.gutierrez@amd.com
4811308Santhony.gutierrez@amd.comheader_code = code_formatter()
4911308Santhony.gutierrez@amd.comdecoder_code = code_formatter()
5011308Santhony.gutierrez@amd.comexec_code = code_formatter()
5111308Santhony.gutierrez@amd.com
5211308Santhony.gutierrez@amd.com###############
5311308Santhony.gutierrez@amd.com#
5411308Santhony.gutierrez@amd.com# Generate file prologs (includes etc.)
5511308Santhony.gutierrez@amd.com#
5611308Santhony.gutierrez@amd.com###############
5711308Santhony.gutierrez@amd.com
5811308Santhony.gutierrez@amd.comheader_code('''
5911308Santhony.gutierrez@amd.com#include "arch/hsail/insts/decl.hh"
6011308Santhony.gutierrez@amd.com#include "base/bitfield.hh"
6111308Santhony.gutierrez@amd.com#include "gpu-compute/hsail_code.hh"
6211308Santhony.gutierrez@amd.com#include "gpu-compute/wavefront.hh"
6311308Santhony.gutierrez@amd.com
6411308Santhony.gutierrez@amd.comnamespace HsailISA
6511308Santhony.gutierrez@amd.com{
6611308Santhony.gutierrez@amd.com''')
6711308Santhony.gutierrez@amd.comheader_code.indent()
6811308Santhony.gutierrez@amd.com
6911308Santhony.gutierrez@amd.comdecoder_code('''
7011308Santhony.gutierrez@amd.com#include "arch/hsail/gpu_decoder.hh"
7111308Santhony.gutierrez@amd.com#include "arch/hsail/insts/branch.hh"
7211308Santhony.gutierrez@amd.com#include "arch/hsail/insts/decl.hh"
7311308Santhony.gutierrez@amd.com#include "arch/hsail/insts/gen_decl.hh"
7411308Santhony.gutierrez@amd.com#include "arch/hsail/insts/mem.hh"
7511308Santhony.gutierrez@amd.com#include "arch/hsail/insts/mem_impl.hh"
7611308Santhony.gutierrez@amd.com#include "gpu-compute/brig_object.hh"
7711308Santhony.gutierrez@amd.com
7811308Santhony.gutierrez@amd.comnamespace HsailISA
7911308Santhony.gutierrez@amd.com{
8011308Santhony.gutierrez@amd.com    std::vector<GPUStaticInst*> Decoder::decodedInsts;
8111308Santhony.gutierrez@amd.com
8211308Santhony.gutierrez@amd.com    GPUStaticInst*
8311308Santhony.gutierrez@amd.com    Decoder::decode(MachInst machInst)
8411308Santhony.gutierrez@amd.com    {
8511308Santhony.gutierrez@amd.com        using namespace Brig;
8611308Santhony.gutierrez@amd.com
8711308Santhony.gutierrez@amd.com        const BrigInstBase *ib = machInst.brigInstBase;
8811308Santhony.gutierrez@amd.com        const BrigObject *obj = machInst.brigObj;
8911308Santhony.gutierrez@amd.com
9011308Santhony.gutierrez@amd.com        switch(ib->opcode) {
9111308Santhony.gutierrez@amd.com''')
9211308Santhony.gutierrez@amd.comdecoder_code.indent()
9311308Santhony.gutierrez@amd.comdecoder_code.indent()
9411308Santhony.gutierrez@amd.com
9511308Santhony.gutierrez@amd.comexec_code('''
9611308Santhony.gutierrez@amd.com#include "arch/hsail/insts/gen_decl.hh"
9711308Santhony.gutierrez@amd.com#include "base/intmath.hh"
9811308Santhony.gutierrez@amd.com
9911308Santhony.gutierrez@amd.comnamespace HsailISA
10011308Santhony.gutierrez@amd.com{
10111308Santhony.gutierrez@amd.com''')
10211308Santhony.gutierrez@amd.comexec_code.indent()
10311308Santhony.gutierrez@amd.com
10411308Santhony.gutierrez@amd.com###############
10511308Santhony.gutierrez@amd.com#
10611308Santhony.gutierrez@amd.com# Define code templates for class declarations (for header file)
10711308Santhony.gutierrez@amd.com#
10811308Santhony.gutierrez@amd.com###############
10911308Santhony.gutierrez@amd.com
11011738Sbrandon.potter@amd.com# Basic header template for an instruction stub.
11111738Sbrandon.potter@amd.comheader_template_stub = '''
11211738Sbrandon.potter@amd.comclass $class_name : public $base_class
11311738Sbrandon.potter@amd.com{
11411738Sbrandon.potter@amd.com  public:
11511738Sbrandon.potter@amd.com    typedef $base_class Base;
11611738Sbrandon.potter@amd.com
11711738Sbrandon.potter@amd.com    $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
11811738Sbrandon.potter@amd.com       : Base(ib, obj, "$opcode")
11911738Sbrandon.potter@amd.com    {
12011738Sbrandon.potter@amd.com    }
12111738Sbrandon.potter@amd.com
12211738Sbrandon.potter@amd.com    void execute(GPUDynInstPtr gpuDynInst);
12311738Sbrandon.potter@amd.com};
12411738Sbrandon.potter@amd.com
12511738Sbrandon.potter@amd.com'''
12611738Sbrandon.potter@amd.com
12711308Santhony.gutierrez@amd.com# Basic header template for an instruction with no template parameters.
12811308Santhony.gutierrez@amd.comheader_template_nodt = '''
12911308Santhony.gutierrez@amd.comclass $class_name : public $base_class
13011308Santhony.gutierrez@amd.com{
13111308Santhony.gutierrez@amd.com  public:
13211308Santhony.gutierrez@amd.com    typedef $base_class Base;
13311308Santhony.gutierrez@amd.com
13411308Santhony.gutierrez@amd.com    $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
13511308Santhony.gutierrez@amd.com       : Base(ib, obj, "$opcode")
13611308Santhony.gutierrez@amd.com    {
13711308Santhony.gutierrez@amd.com    }
13811308Santhony.gutierrez@amd.com
13911308Santhony.gutierrez@amd.com    void execute(GPUDynInstPtr gpuDynInst);
14011308Santhony.gutierrez@amd.com};
14111308Santhony.gutierrez@amd.com
14211308Santhony.gutierrez@amd.com'''
14311308Santhony.gutierrez@amd.com
14411308Santhony.gutierrez@amd.com# Basic header template for an instruction with a single DataType
14511308Santhony.gutierrez@amd.com# template parameter.
14611308Santhony.gutierrez@amd.comheader_template_1dt = '''
14711308Santhony.gutierrez@amd.comtemplate<typename DataType>
14811308Santhony.gutierrez@amd.comclass $class_name : public $base_class<DataType>
14911308Santhony.gutierrez@amd.com{
15011308Santhony.gutierrez@amd.com  public:
15111308Santhony.gutierrez@amd.com    typedef $base_class<DataType> Base;
15211308Santhony.gutierrez@amd.com    typedef typename DataType::CType CType;
15311308Santhony.gutierrez@amd.com
15411308Santhony.gutierrez@amd.com    $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
15511308Santhony.gutierrez@amd.com       : Base(ib, obj, "$opcode")
15611308Santhony.gutierrez@amd.com    {
15711308Santhony.gutierrez@amd.com    }
15811308Santhony.gutierrez@amd.com
15911308Santhony.gutierrez@amd.com    void execute(GPUDynInstPtr gpuDynInst);
16011308Santhony.gutierrez@amd.com};
16111308Santhony.gutierrez@amd.com
16211308Santhony.gutierrez@amd.com'''
16311308Santhony.gutierrez@amd.com
16411308Santhony.gutierrez@amd.comheader_template_1dt_noexec = '''
16511308Santhony.gutierrez@amd.comtemplate<typename DataType>
16611308Santhony.gutierrez@amd.comclass $class_name : public $base_class<DataType>
16711308Santhony.gutierrez@amd.com{
16811308Santhony.gutierrez@amd.com  public:
16911308Santhony.gutierrez@amd.com    typedef $base_class<DataType> Base;
17011308Santhony.gutierrez@amd.com    typedef typename DataType::CType CType;
17111308Santhony.gutierrez@amd.com
17211308Santhony.gutierrez@amd.com    $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
17311308Santhony.gutierrez@amd.com       : Base(ib, obj, "$opcode")
17411308Santhony.gutierrez@amd.com    {
17511308Santhony.gutierrez@amd.com    }
17611308Santhony.gutierrez@amd.com};
17711308Santhony.gutierrez@amd.com
17811308Santhony.gutierrez@amd.com'''
17911308Santhony.gutierrez@amd.com
18011308Santhony.gutierrez@amd.com# Same as header_template_1dt, except the base class has a second
18111308Santhony.gutierrez@amd.com# template parameter NumSrcOperands to allow a variable number of
18211308Santhony.gutierrez@amd.com# source operands.  Note that since this is implemented with an array,
18311308Santhony.gutierrez@amd.com# it only works for instructions where all sources are of the same
18411308Santhony.gutierrez@amd.com# type (like most arithmetics).
18511308Santhony.gutierrez@amd.comheader_template_1dt_varsrcs = '''
18611308Santhony.gutierrez@amd.comtemplate<typename DataType>
18711308Santhony.gutierrez@amd.comclass $class_name : public $base_class<DataType, $num_srcs>
18811308Santhony.gutierrez@amd.com{
18911308Santhony.gutierrez@amd.com  public:
19011308Santhony.gutierrez@amd.com    typedef $base_class<DataType, $num_srcs> Base;
19111308Santhony.gutierrez@amd.com    typedef typename DataType::CType CType;
19211308Santhony.gutierrez@amd.com
19311308Santhony.gutierrez@amd.com    $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
19411308Santhony.gutierrez@amd.com       : Base(ib, obj, "$opcode")
19511308Santhony.gutierrez@amd.com    {
19611308Santhony.gutierrez@amd.com    }
19711308Santhony.gutierrez@amd.com
19811308Santhony.gutierrez@amd.com    void execute(GPUDynInstPtr gpuDynInst);
19911308Santhony.gutierrez@amd.com};
20011308Santhony.gutierrez@amd.com
20111308Santhony.gutierrez@amd.com'''
20211308Santhony.gutierrez@amd.com
20311308Santhony.gutierrez@amd.com# Header template for instruction with two DataType template
20411308Santhony.gutierrez@amd.com# parameters, one for the dest and one for the source.  This is used
20511308Santhony.gutierrez@amd.com# by compare and convert.
20611308Santhony.gutierrez@amd.comheader_template_2dt = '''
20711308Santhony.gutierrez@amd.comtemplate<typename DestDataType, class SrcDataType>
20811308Santhony.gutierrez@amd.comclass $class_name : public $base_class<DestDataType, SrcDataType>
20911308Santhony.gutierrez@amd.com{
21011308Santhony.gutierrez@amd.com  public:
21111308Santhony.gutierrez@amd.com    typedef $base_class<DestDataType, SrcDataType> Base;
21211308Santhony.gutierrez@amd.com    typedef typename DestDataType::CType DestCType;
21311308Santhony.gutierrez@amd.com    typedef typename SrcDataType::CType SrcCType;
21411308Santhony.gutierrez@amd.com
21511308Santhony.gutierrez@amd.com    $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
21611308Santhony.gutierrez@amd.com       : Base(ib, obj, "$opcode")
21711308Santhony.gutierrez@amd.com    {
21811308Santhony.gutierrez@amd.com    }
21911308Santhony.gutierrez@amd.com
22011308Santhony.gutierrez@amd.com    void execute(GPUDynInstPtr gpuDynInst);
22111308Santhony.gutierrez@amd.com};
22211308Santhony.gutierrez@amd.com
22311308Santhony.gutierrez@amd.com'''
22411308Santhony.gutierrez@amd.com
22511308Santhony.gutierrez@amd.comheader_templates = {
22611308Santhony.gutierrez@amd.com    'ArithInst': header_template_1dt_varsrcs,
22711308Santhony.gutierrez@amd.com    'CmovInst': header_template_1dt,
22811308Santhony.gutierrez@amd.com    'ClassInst': header_template_1dt,
22911308Santhony.gutierrez@amd.com    'ShiftInst': header_template_1dt,
23011308Santhony.gutierrez@amd.com    'ExtractInsertInst': header_template_1dt,
23111308Santhony.gutierrez@amd.com    'CmpInst': header_template_2dt,
23211308Santhony.gutierrez@amd.com    'CvtInst': header_template_2dt,
23311737Sbrandon.potter@amd.com    'PopcountInst': header_template_2dt,
23411308Santhony.gutierrez@amd.com    'LdInst': '',
23511308Santhony.gutierrez@amd.com    'StInst': '',
23611308Santhony.gutierrez@amd.com    'SpecialInstNoSrc': header_template_nodt,
23711308Santhony.gutierrez@amd.com    'SpecialInst1Src': header_template_nodt,
23811308Santhony.gutierrez@amd.com    'SpecialInstNoSrcNoDest': '',
23911738Sbrandon.potter@amd.com    'Stub': header_template_stub,
24011308Santhony.gutierrez@amd.com}
24111308Santhony.gutierrez@amd.com
24211308Santhony.gutierrez@amd.com###############
24311308Santhony.gutierrez@amd.com#
24411308Santhony.gutierrez@amd.com# Define code templates for exec functions
24511308Santhony.gutierrez@amd.com#
24611308Santhony.gutierrez@amd.com###############
24711308Santhony.gutierrez@amd.com
24811308Santhony.gutierrez@amd.com# exec function body
24911738Sbrandon.potter@amd.comexec_template_stub = '''
25011738Sbrandon.potter@amd.comvoid
25111738Sbrandon.potter@amd.com$class_name::execute(GPUDynInstPtr gpuDynInst)
25211738Sbrandon.potter@amd.com{
25311738Sbrandon.potter@amd.com    fatal("instruction unimplemented %s\\n", gpuDynInst->disassemble());
25411738Sbrandon.potter@amd.com}
25511738Sbrandon.potter@amd.com
25611738Sbrandon.potter@amd.com'''
25711308Santhony.gutierrez@amd.comexec_template_nodt_nosrc = '''
25811308Santhony.gutierrez@amd.comvoid
25911308Santhony.gutierrez@amd.com$class_name::execute(GPUDynInstPtr gpuDynInst)
26011308Santhony.gutierrez@amd.com{
26111308Santhony.gutierrez@amd.com    Wavefront *w = gpuDynInst->wavefront();
26211308Santhony.gutierrez@amd.com
26311308Santhony.gutierrez@amd.com    typedef Base::DestCType DestCType;
26411308Santhony.gutierrez@amd.com
26511639Salexandru.dutu@amd.com    const VectorMask &mask = w->getPred();
26611308Santhony.gutierrez@amd.com
26711534Sjohn.kalamatianos@amd.com    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
26811308Santhony.gutierrez@amd.com        if (mask[lane]) {
26911308Santhony.gutierrez@amd.com            DestCType dest_val = $expr;
27011308Santhony.gutierrez@amd.com            this->dest.set(w, lane, dest_val);
27111308Santhony.gutierrez@amd.com        }
27211308Santhony.gutierrez@amd.com    }
27311308Santhony.gutierrez@amd.com}
27411308Santhony.gutierrez@amd.com
27511308Santhony.gutierrez@amd.com'''
27611308Santhony.gutierrez@amd.com
27711308Santhony.gutierrez@amd.comexec_template_nodt_1src = '''
27811308Santhony.gutierrez@amd.comvoid
27911308Santhony.gutierrez@amd.com$class_name::execute(GPUDynInstPtr gpuDynInst)
28011308Santhony.gutierrez@amd.com{
28111308Santhony.gutierrez@amd.com    Wavefront *w = gpuDynInst->wavefront();
28211308Santhony.gutierrez@amd.com
28311308Santhony.gutierrez@amd.com    typedef Base::DestCType DestCType;
28411308Santhony.gutierrez@amd.com    typedef Base::SrcCType  SrcCType;
28511308Santhony.gutierrez@amd.com
28611639Salexandru.dutu@amd.com    const VectorMask &mask = w->getPred();
28711308Santhony.gutierrez@amd.com
28811534Sjohn.kalamatianos@amd.com    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
28911308Santhony.gutierrez@amd.com        if (mask[lane]) {
29011308Santhony.gutierrez@amd.com            SrcCType src_val0 = this->src0.get<SrcCType>(w, lane);
29111308Santhony.gutierrez@amd.com            DestCType dest_val = $expr;
29211308Santhony.gutierrez@amd.com
29311308Santhony.gutierrez@amd.com            this->dest.set(w, lane, dest_val);
29411308Santhony.gutierrez@amd.com        }
29511308Santhony.gutierrez@amd.com    }
29611308Santhony.gutierrez@amd.com}
29711308Santhony.gutierrez@amd.com
29811308Santhony.gutierrez@amd.com'''
29911308Santhony.gutierrez@amd.com
30011308Santhony.gutierrez@amd.comexec_template_1dt_varsrcs = '''
30111308Santhony.gutierrez@amd.comtemplate<typename DataType>
30211308Santhony.gutierrez@amd.comvoid
30311308Santhony.gutierrez@amd.com$class_name<DataType>::execute(GPUDynInstPtr gpuDynInst)
30411308Santhony.gutierrez@amd.com{
30511308Santhony.gutierrez@amd.com    Wavefront *w = gpuDynInst->wavefront();
30611308Santhony.gutierrez@amd.com
30711639Salexandru.dutu@amd.com    const VectorMask &mask = w->getPred();
30811308Santhony.gutierrez@amd.com
30911534Sjohn.kalamatianos@amd.com    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
31011308Santhony.gutierrez@amd.com        if (mask[lane]) {
31111308Santhony.gutierrez@amd.com            CType dest_val;
31211308Santhony.gutierrez@amd.com            if ($dest_is_src_flag) {
31311308Santhony.gutierrez@amd.com                dest_val = this->dest.template get<CType>(w, lane);
31411308Santhony.gutierrez@amd.com            }
31511308Santhony.gutierrez@amd.com
31611308Santhony.gutierrez@amd.com            CType src_val[$num_srcs];
31711308Santhony.gutierrez@amd.com
31811308Santhony.gutierrez@amd.com            for (int i = 0; i < $num_srcs; ++i) {
31911308Santhony.gutierrez@amd.com                src_val[i] = this->src[i].template get<CType>(w, lane);
32011308Santhony.gutierrez@amd.com            }
32111308Santhony.gutierrez@amd.com
32211308Santhony.gutierrez@amd.com            dest_val = (CType)($expr);
32311308Santhony.gutierrez@amd.com
32411308Santhony.gutierrez@amd.com            this->dest.set(w, lane, dest_val);
32511308Santhony.gutierrez@amd.com        }
32611308Santhony.gutierrez@amd.com    }
32711308Santhony.gutierrez@amd.com}
32811308Santhony.gutierrez@amd.com
32911308Santhony.gutierrez@amd.com'''
33011308Santhony.gutierrez@amd.com
33111308Santhony.gutierrez@amd.comexec_template_1dt_3srcs = '''
33211308Santhony.gutierrez@amd.comtemplate<typename DataType>
33311308Santhony.gutierrez@amd.comvoid
33411308Santhony.gutierrez@amd.com$class_name<DataType>::execute(GPUDynInstPtr gpuDynInst)
33511308Santhony.gutierrez@amd.com{
33611308Santhony.gutierrez@amd.com    Wavefront *w = gpuDynInst->wavefront();
33711308Santhony.gutierrez@amd.com
33811308Santhony.gutierrez@amd.com    typedef typename Base::Src0CType Src0T;
33911308Santhony.gutierrez@amd.com    typedef typename Base::Src1CType Src1T;
34011308Santhony.gutierrez@amd.com    typedef typename Base::Src2CType Src2T;
34111308Santhony.gutierrez@amd.com
34211639Salexandru.dutu@amd.com    const VectorMask &mask = w->getPred();
34311308Santhony.gutierrez@amd.com
34411534Sjohn.kalamatianos@amd.com    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
34511308Santhony.gutierrez@amd.com        if (mask[lane]) {
34611308Santhony.gutierrez@amd.com            CType dest_val;
34711308Santhony.gutierrez@amd.com
34811308Santhony.gutierrez@amd.com            if ($dest_is_src_flag) {
34911308Santhony.gutierrez@amd.com                dest_val = this->dest.template get<CType>(w, lane);
35011308Santhony.gutierrez@amd.com            }
35111308Santhony.gutierrez@amd.com
35211308Santhony.gutierrez@amd.com            Src0T src_val0 = this->src0.template get<Src0T>(w, lane);
35311308Santhony.gutierrez@amd.com            Src1T src_val1 = this->src1.template get<Src1T>(w, lane);
35411308Santhony.gutierrez@amd.com            Src2T src_val2 = this->src2.template get<Src2T>(w, lane);
35511308Santhony.gutierrez@amd.com
35611308Santhony.gutierrez@amd.com            dest_val = $expr;
35711308Santhony.gutierrez@amd.com
35811308Santhony.gutierrez@amd.com            this->dest.set(w, lane, dest_val);
35911308Santhony.gutierrez@amd.com        }
36011308Santhony.gutierrez@amd.com    }
36111308Santhony.gutierrez@amd.com}
36211308Santhony.gutierrez@amd.com
36311308Santhony.gutierrez@amd.com'''
36411308Santhony.gutierrez@amd.com
36511308Santhony.gutierrez@amd.comexec_template_1dt_2src_1dest = '''
36611308Santhony.gutierrez@amd.comtemplate<typename DataType>
36711308Santhony.gutierrez@amd.comvoid
36811308Santhony.gutierrez@amd.com$class_name<DataType>::execute(GPUDynInstPtr gpuDynInst)
36911308Santhony.gutierrez@amd.com{
37011308Santhony.gutierrez@amd.com    Wavefront *w = gpuDynInst->wavefront();
37111308Santhony.gutierrez@amd.com
37211308Santhony.gutierrez@amd.com    typedef typename Base::DestCType DestT;
37311308Santhony.gutierrez@amd.com    typedef CType Src0T;
37411308Santhony.gutierrez@amd.com    typedef typename Base::Src1CType Src1T;
37511308Santhony.gutierrez@amd.com
37611639Salexandru.dutu@amd.com    const VectorMask &mask = w->getPred();
37711308Santhony.gutierrez@amd.com
37811534Sjohn.kalamatianos@amd.com    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
37911308Santhony.gutierrez@amd.com        if (mask[lane]) {
38011308Santhony.gutierrez@amd.com            DestT dest_val;
38111308Santhony.gutierrez@amd.com            if ($dest_is_src_flag) {
38211308Santhony.gutierrez@amd.com                dest_val = this->dest.template get<DestT>(w, lane);
38311308Santhony.gutierrez@amd.com            }
38411308Santhony.gutierrez@amd.com            Src0T src_val0 = this->src0.template get<Src0T>(w, lane);
38511308Santhony.gutierrez@amd.com            Src1T src_val1 = this->src1.template get<Src1T>(w, lane);
38611308Santhony.gutierrez@amd.com
38711308Santhony.gutierrez@amd.com            dest_val = $expr;
38811308Santhony.gutierrez@amd.com
38911308Santhony.gutierrez@amd.com            this->dest.set(w, lane, dest_val);
39011308Santhony.gutierrez@amd.com        }
39111308Santhony.gutierrez@amd.com    }
39211308Santhony.gutierrez@amd.com}
39311308Santhony.gutierrez@amd.com
39411308Santhony.gutierrez@amd.com'''
39511308Santhony.gutierrez@amd.com
39611308Santhony.gutierrez@amd.comexec_template_shift = '''
39711308Santhony.gutierrez@amd.comtemplate<typename DataType>
39811308Santhony.gutierrez@amd.comvoid
39911308Santhony.gutierrez@amd.com$class_name<DataType>::execute(GPUDynInstPtr gpuDynInst)
40011308Santhony.gutierrez@amd.com{
40111308Santhony.gutierrez@amd.com    Wavefront *w = gpuDynInst->wavefront();
40211308Santhony.gutierrez@amd.com
40311639Salexandru.dutu@amd.com    const VectorMask &mask = w->getPred();
40411534Sjohn.kalamatianos@amd.com    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
40511308Santhony.gutierrez@amd.com        if (mask[lane]) {
40611308Santhony.gutierrez@amd.com            CType dest_val;
40711308Santhony.gutierrez@amd.com
40811308Santhony.gutierrez@amd.com            if ($dest_is_src_flag) {
40911308Santhony.gutierrez@amd.com                dest_val = this->dest.template get<CType>(w, lane);
41011308Santhony.gutierrez@amd.com            }
41111308Santhony.gutierrez@amd.com
41211308Santhony.gutierrez@amd.com            CType src_val0 = this->src0.template get<CType>(w, lane);
41311308Santhony.gutierrez@amd.com            uint32_t src_val1 = this->src1.template get<uint32_t>(w, lane);
41411308Santhony.gutierrez@amd.com
41511308Santhony.gutierrez@amd.com            dest_val = $expr;
41611308Santhony.gutierrez@amd.com
41711308Santhony.gutierrez@amd.com            this->dest.set(w, lane, dest_val);
41811308Santhony.gutierrez@amd.com        }
41911308Santhony.gutierrez@amd.com    }
42011308Santhony.gutierrez@amd.com}
42111308Santhony.gutierrez@amd.com
42211308Santhony.gutierrez@amd.com'''
42311308Santhony.gutierrez@amd.com
42411308Santhony.gutierrez@amd.comexec_template_2dt = '''
42511308Santhony.gutierrez@amd.comtemplate<typename DestDataType, class SrcDataType>
42611308Santhony.gutierrez@amd.comvoid
42711308Santhony.gutierrez@amd.com$class_name<DestDataType, SrcDataType>::execute(GPUDynInstPtr gpuDynInst)
42811308Santhony.gutierrez@amd.com{
42911308Santhony.gutierrez@amd.com    Wavefront *w = gpuDynInst->wavefront();
43011308Santhony.gutierrez@amd.com
43111639Salexandru.dutu@amd.com    const VectorMask &mask = w->getPred();
43211308Santhony.gutierrez@amd.com
43311534Sjohn.kalamatianos@amd.com    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
43411308Santhony.gutierrez@amd.com        if (mask[lane]) {
43511308Santhony.gutierrez@amd.com            DestCType dest_val;
43611308Santhony.gutierrez@amd.com            SrcCType src_val[$num_srcs];
43711308Santhony.gutierrez@amd.com
43811308Santhony.gutierrez@amd.com            for (int i = 0; i < $num_srcs; ++i) {
43911308Santhony.gutierrez@amd.com                src_val[i] = this->src[i].template get<SrcCType>(w, lane);
44011308Santhony.gutierrez@amd.com            }
44111308Santhony.gutierrez@amd.com
44211308Santhony.gutierrez@amd.com            dest_val = $expr;
44311308Santhony.gutierrez@amd.com
44411308Santhony.gutierrez@amd.com            this->dest.set(w, lane, dest_val);
44511308Santhony.gutierrez@amd.com        }
44611308Santhony.gutierrez@amd.com    }
44711308Santhony.gutierrez@amd.com}
44811308Santhony.gutierrez@amd.com
44911308Santhony.gutierrez@amd.com'''
45011308Santhony.gutierrez@amd.com
45111308Santhony.gutierrez@amd.comexec_templates = {
45211308Santhony.gutierrez@amd.com    'ArithInst': exec_template_1dt_varsrcs,
45311308Santhony.gutierrez@amd.com    'CmovInst': exec_template_1dt_3srcs,
45411308Santhony.gutierrez@amd.com    'ExtractInsertInst': exec_template_1dt_3srcs,
45511308Santhony.gutierrez@amd.com    'ClassInst': exec_template_1dt_2src_1dest,
45611308Santhony.gutierrez@amd.com    'CmpInst': exec_template_2dt,
45711308Santhony.gutierrez@amd.com    'CvtInst': exec_template_2dt,
45811737Sbrandon.potter@amd.com    'PopcountInst': exec_template_2dt,
45911308Santhony.gutierrez@amd.com    'LdInst': '',
46011308Santhony.gutierrez@amd.com    'StInst': '',
46111308Santhony.gutierrez@amd.com    'SpecialInstNoSrc': exec_template_nodt_nosrc,
46211308Santhony.gutierrez@amd.com    'SpecialInst1Src': exec_template_nodt_1src,
46311308Santhony.gutierrez@amd.com    'SpecialInstNoSrcNoDest': '',
46411738Sbrandon.potter@amd.com    'Stub': exec_template_stub,
46511308Santhony.gutierrez@amd.com}
46611308Santhony.gutierrez@amd.com
46711308Santhony.gutierrez@amd.com###############
46811308Santhony.gutierrez@amd.com#
46911308Santhony.gutierrez@amd.com# Define code templates for the decoder cases
47011308Santhony.gutierrez@amd.com#
47111308Santhony.gutierrez@amd.com###############
47211308Santhony.gutierrez@amd.com
47311308Santhony.gutierrez@amd.com# decode template for nodt-opcode case
47411308Santhony.gutierrez@amd.comdecode_nodt_template = '''
47511308Santhony.gutierrez@amd.com  case BRIG_OPCODE_$brig_opcode_upper: return $constructor(ib, obj);'''
47611308Santhony.gutierrez@amd.com
47711308Santhony.gutierrez@amd.comdecode_case_prolog_class_inst = '''
47811308Santhony.gutierrez@amd.com  case BRIG_OPCODE_$brig_opcode_upper:
47911308Santhony.gutierrez@amd.com    {
48011308Santhony.gutierrez@amd.com        //const BrigOperandBase *baseOp = obj->getOperand(ib->operands[1]);
48111308Santhony.gutierrez@amd.com        BrigType16_t type = ((BrigInstSourceType*)ib)->sourceType;
48211308Santhony.gutierrez@amd.com        //switch (baseOp->kind) {
48311308Santhony.gutierrez@amd.com        //    case BRIG_OPERAND_REG:
48411308Santhony.gutierrez@amd.com        //        type = ((const BrigOperandReg*)baseOp)->type;
48511308Santhony.gutierrez@amd.com        //        break;
48611308Santhony.gutierrez@amd.com        //    case BRIG_OPERAND_IMMED:
48711308Santhony.gutierrez@amd.com        //        type = ((const BrigOperandImmed*)baseOp)->type;
48811308Santhony.gutierrez@amd.com        //        break;
48911308Santhony.gutierrez@amd.com        //    default:
49011308Santhony.gutierrez@amd.com        //        fatal("CLASS unrecognized kind of operand %d\\n",
49111308Santhony.gutierrez@amd.com        //               baseOp->kind);
49211308Santhony.gutierrez@amd.com        //}
49311308Santhony.gutierrez@amd.com        switch (type) {'''
49411308Santhony.gutierrez@amd.com
49511308Santhony.gutierrez@amd.com# common prolog for 1dt- or 2dt-opcode case: switch on data type
49611308Santhony.gutierrez@amd.comdecode_case_prolog = '''
49711308Santhony.gutierrez@amd.com  case BRIG_OPCODE_$brig_opcode_upper:
49811308Santhony.gutierrez@amd.com    {
49911308Santhony.gutierrez@amd.com        switch (ib->type) {'''
50011308Santhony.gutierrez@amd.com
50111308Santhony.gutierrez@amd.com# single-level decode case entry (for 1dt opcodes)
50211308Santhony.gutierrez@amd.comdecode_case_entry = \
50311308Santhony.gutierrez@amd.com'      case BRIG_TYPE_$type_name: return $constructor(ib, obj);'
50411308Santhony.gutierrez@amd.com
50511308Santhony.gutierrez@amd.comdecode_store_prolog = \
50611308Santhony.gutierrez@amd.com'      case BRIG_TYPE_$type_name: {'
50711308Santhony.gutierrez@amd.com
50811308Santhony.gutierrez@amd.comdecode_store_case_epilog = '''
50911308Santhony.gutierrez@amd.com    }'''
51011308Santhony.gutierrez@amd.com
51111308Santhony.gutierrez@amd.comdecode_store_case_entry = \
51211308Santhony.gutierrez@amd.com'          return $constructor(ib, obj);'
51311308Santhony.gutierrez@amd.com
51411308Santhony.gutierrez@amd.com# common epilog for type switch
51511308Santhony.gutierrez@amd.comdecode_case_epilog = '''
51611308Santhony.gutierrez@amd.com          default: fatal("$brig_opcode_upper: unrecognized type %d\\n",
51711308Santhony.gutierrez@amd.com              ib->type);
51811308Santhony.gutierrez@amd.com        }
51911308Santhony.gutierrez@amd.com    }
52011308Santhony.gutierrez@amd.com    break;'''
52111308Santhony.gutierrez@amd.com
52211308Santhony.gutierrez@amd.com# Additional templates for nested decode on a second type field (for
52311308Santhony.gutierrez@amd.com# compare and convert).  These are used in place of the
52411308Santhony.gutierrez@amd.com# decode_case_entry template to create a second-level switch on on the
52511308Santhony.gutierrez@amd.com# second type field inside each case of the first-level type switch.
52611308Santhony.gutierrez@amd.com# Because the name and location of the second type can vary, the Brig
52711308Santhony.gutierrez@amd.com# instruction type must be provided in $brig_type, and the name of the
52811308Santhony.gutierrez@amd.com# second type field must be provided in $type_field.
52911308Santhony.gutierrez@amd.comdecode_case2_prolog = '''
53011308Santhony.gutierrez@amd.com        case BRIG_TYPE_$type_name:
53111308Santhony.gutierrez@amd.com          switch (((Brig$brig_type*)ib)->$type2_field) {'''
53211308Santhony.gutierrez@amd.com
53311308Santhony.gutierrez@amd.comdecode_case2_entry = \
53411308Santhony.gutierrez@amd.com'          case BRIG_TYPE_$type2_name: return $constructor(ib, obj);'
53511308Santhony.gutierrez@amd.com
53611308Santhony.gutierrez@amd.comdecode_case2_epilog = '''
53711308Santhony.gutierrez@amd.com          default: fatal("$brig_opcode_upper: unrecognized $type2_field %d\\n",
53811308Santhony.gutierrez@amd.com                         ((Brig$brig_type*)ib)->$type2_field);
53911308Santhony.gutierrez@amd.com        }
54011308Santhony.gutierrez@amd.com        break;'''
54111308Santhony.gutierrez@amd.com
54211308Santhony.gutierrez@amd.com# Figure out how many source operands an expr needs by looking for the
54311308Santhony.gutierrez@amd.com# highest-numbered srcN value referenced.  Since sources are numbered
54411308Santhony.gutierrez@amd.com# starting at 0, the return value is N+1.
54511308Santhony.gutierrez@amd.comdef num_src_operands(expr):
54611308Santhony.gutierrez@amd.com    if expr.find('src2') != -1:
54711308Santhony.gutierrez@amd.com        return 3
54811308Santhony.gutierrez@amd.com    elif expr.find('src1') != -1:
54911308Santhony.gutierrez@amd.com        return 2
55011308Santhony.gutierrez@amd.com    elif expr.find('src0') != -1:
55111308Santhony.gutierrez@amd.com        return 1
55211308Santhony.gutierrez@amd.com    else:
55311308Santhony.gutierrez@amd.com        return 0
55411308Santhony.gutierrez@amd.com
55511308Santhony.gutierrez@amd.com###############
55611308Santhony.gutierrez@amd.com#
55711308Santhony.gutierrez@amd.com# Define final code generation methods
55811308Santhony.gutierrez@amd.com#
55911308Santhony.gutierrez@amd.com# The gen_nodt, and gen_1dt, and gen_2dt methods are the interface for
56011308Santhony.gutierrez@amd.com# generating actual instructions.
56111308Santhony.gutierrez@amd.com#
56211308Santhony.gutierrez@amd.com###############
56311308Santhony.gutierrez@amd.com
56411308Santhony.gutierrez@amd.com# Generate class declaration, exec function, and decode switch case
56511308Santhony.gutierrez@amd.com# for an brig_opcode with a single-level type switch.  The 'types'
56611308Santhony.gutierrez@amd.com# parameter is a list or tuple of types for which the instruction
56711308Santhony.gutierrez@amd.com# should be instantiated.
56811308Santhony.gutierrez@amd.comdef gen(brig_opcode, types=None, expr=None, base_class='ArithInst',
56911308Santhony.gutierrez@amd.com        type2_info=None, constructor_prefix='new ', is_store=False):
57011308Santhony.gutierrez@amd.com    brig_opcode_upper = brig_opcode.upper()
57111308Santhony.gutierrez@amd.com    class_name = brig_opcode
57211308Santhony.gutierrez@amd.com    opcode = class_name.lower()
57311308Santhony.gutierrez@amd.com
57411308Santhony.gutierrez@amd.com    if base_class == 'ArithInst':
57511308Santhony.gutierrez@amd.com        # note that expr must be provided with ArithInst so we can
57611308Santhony.gutierrez@amd.com        # derive num_srcs for the template
57711308Santhony.gutierrez@amd.com        assert expr
57811308Santhony.gutierrez@amd.com
57911308Santhony.gutierrez@amd.com    if expr:
58011308Santhony.gutierrez@amd.com        # Derive several bits of info from expr.  If expr is not used,
58111308Santhony.gutierrez@amd.com        # this info will be irrelevant.
58211308Santhony.gutierrez@amd.com        num_srcs = num_src_operands(expr)
58311308Santhony.gutierrez@amd.com        # if the RHS expression includes 'dest', then we're doing an RMW
58411308Santhony.gutierrez@amd.com        # on the reg and we need to treat it like a source
58511308Santhony.gutierrez@amd.com        dest_is_src = expr.find('dest') != -1
58611308Santhony.gutierrez@amd.com        dest_is_src_flag = str(dest_is_src).lower() # for C++
58711308Santhony.gutierrez@amd.com        if base_class in ['ShiftInst']:
58811308Santhony.gutierrez@amd.com            expr = re.sub(r'\bsrc(\d)\b', r'src_val\1', expr)
58911737Sbrandon.potter@amd.com        elif base_class in ['ArithInst', 'CmpInst', 'CvtInst', 'PopcountInst']:
59011308Santhony.gutierrez@amd.com            expr = re.sub(r'\bsrc(\d)\b', r'src_val[\1]', expr)
59111308Santhony.gutierrez@amd.com        else:
59211308Santhony.gutierrez@amd.com            expr = re.sub(r'\bsrc(\d)\b', r'src_val\1', expr)
59311308Santhony.gutierrez@amd.com        expr = re.sub(r'\bdest\b', r'dest_val', expr)
59411308Santhony.gutierrez@amd.com
59511308Santhony.gutierrez@amd.com    # Strip template arguments off of base class before looking up
59611308Santhony.gutierrez@amd.com    # appropriate templates
59711308Santhony.gutierrez@amd.com    base_class_base = re.sub(r'<.*>$', '', base_class)
59811308Santhony.gutierrez@amd.com    header_code(header_templates[base_class_base])
59911308Santhony.gutierrez@amd.com
60011738Sbrandon.potter@amd.com    if base_class.startswith('SpecialInst') or base_class.startswith('Stub'):
60111308Santhony.gutierrez@amd.com        exec_code(exec_templates[base_class_base])
60211308Santhony.gutierrez@amd.com    elif base_class.startswith('ShiftInst'):
60311308Santhony.gutierrez@amd.com        header_code(exec_template_shift)
60411308Santhony.gutierrez@amd.com    else:
60511308Santhony.gutierrez@amd.com        header_code(exec_templates[base_class_base])
60611308Santhony.gutierrez@amd.com
60711308Santhony.gutierrez@amd.com    if not types or isinstance(types, str):
60811308Santhony.gutierrez@amd.com        # Just a single type
60911308Santhony.gutierrez@amd.com        constructor = constructor_prefix + class_name
61011308Santhony.gutierrez@amd.com        decoder_code(decode_nodt_template)
61111308Santhony.gutierrez@amd.com    else:
61211308Santhony.gutierrez@amd.com        # multiple types, need at least one level of decode
61311308Santhony.gutierrez@amd.com        if brig_opcode == 'Class':
61411308Santhony.gutierrez@amd.com            decoder_code(decode_case_prolog_class_inst)
61511308Santhony.gutierrez@amd.com        else:
61611308Santhony.gutierrez@amd.com            decoder_code(decode_case_prolog)
61711308Santhony.gutierrez@amd.com        if not type2_info:
61811325Ssteve.reinhardt@amd.com            if not is_store:
61911308Santhony.gutierrez@amd.com                # single list of types, to basic one-level decode
62011308Santhony.gutierrez@amd.com                for type_name in types:
62111308Santhony.gutierrez@amd.com                    full_class_name = '%s<%s>' % (class_name, type_name.upper())
62211308Santhony.gutierrez@amd.com                    constructor = constructor_prefix + full_class_name
62311308Santhony.gutierrez@amd.com                    decoder_code(decode_case_entry)
62411308Santhony.gutierrez@amd.com            else:
62511308Santhony.gutierrez@amd.com                # single list of types, to basic one-level decode
62611308Santhony.gutierrez@amd.com                for type_name in types:
62711308Santhony.gutierrez@amd.com                    decoder_code(decode_store_prolog)
62811308Santhony.gutierrez@amd.com                    type_size = int(re.findall(r'[0-9]+', type_name)[0])
62911308Santhony.gutierrez@amd.com                    src_size = 32
63011308Santhony.gutierrez@amd.com                    type_type = type_name[0]
63111308Santhony.gutierrez@amd.com                    full_class_name = '%s<%s,%s>' % (class_name, \
63211308Santhony.gutierrez@amd.com                                                     type_name.upper(), \
63311308Santhony.gutierrez@amd.com                                                     '%s%d' % \
63411308Santhony.gutierrez@amd.com                                                     (type_type.upper(), \
63511308Santhony.gutierrez@amd.com                                                     type_size))
63611308Santhony.gutierrez@amd.com                    constructor = constructor_prefix + full_class_name
63711308Santhony.gutierrez@amd.com                    decoder_code(decode_store_case_entry)
63811308Santhony.gutierrez@amd.com                    decoder_code(decode_store_case_epilog)
63911308Santhony.gutierrez@amd.com        else:
64011308Santhony.gutierrez@amd.com            # need secondary type switch (convert, compare)
64111308Santhony.gutierrez@amd.com            # unpack extra info on second switch
64211308Santhony.gutierrez@amd.com            (type2_field, types2) = type2_info
64311308Santhony.gutierrez@amd.com            brig_type = 'Inst%s' % brig_opcode
64411308Santhony.gutierrez@amd.com            for type_name in types:
64511308Santhony.gutierrez@amd.com                decoder_code(decode_case2_prolog)
64611308Santhony.gutierrez@amd.com                fmt = '%s<%s,%%s>' % (class_name, type_name.upper())
64711308Santhony.gutierrez@amd.com                for type2_name in types2:
64811308Santhony.gutierrez@amd.com                    full_class_name = fmt % type2_name.upper()
64911308Santhony.gutierrez@amd.com                    constructor = constructor_prefix + full_class_name
65011308Santhony.gutierrez@amd.com                    decoder_code(decode_case2_entry)
65111308Santhony.gutierrez@amd.com
65211308Santhony.gutierrez@amd.com                decoder_code(decode_case2_epilog)
65311308Santhony.gutierrez@amd.com
65411308Santhony.gutierrez@amd.com        decoder_code(decode_case_epilog)
65511308Santhony.gutierrez@amd.com
65611308Santhony.gutierrez@amd.com###############
65711308Santhony.gutierrez@amd.com#
65811308Santhony.gutierrez@amd.com# Generate instructions
65911308Santhony.gutierrez@amd.com#
66011308Santhony.gutierrez@amd.com###############
66111308Santhony.gutierrez@amd.com
66211308Santhony.gutierrez@amd.com# handy abbreviations for common sets of types
66311308Santhony.gutierrez@amd.com
66411308Santhony.gutierrez@amd.com# arithmetic ops are typically defined only on 32- and 64-bit sizes
66511308Santhony.gutierrez@amd.comarith_int_types = ('S32', 'U32', 'S64', 'U64')
66611308Santhony.gutierrez@amd.comarith_float_types = ('F32', 'F64')
66711308Santhony.gutierrez@amd.comarith_types = arith_int_types + arith_float_types
66811308Santhony.gutierrez@amd.com
66911308Santhony.gutierrez@amd.combit_types = ('B1', 'B32', 'B64')
67011308Santhony.gutierrez@amd.com
67111308Santhony.gutierrez@amd.comall_int_types = ('S8', 'U8', 'S16', 'U16') + arith_int_types
67211308Santhony.gutierrez@amd.com
67311308Santhony.gutierrez@amd.com# I think you might be able to do 'f16' memory ops too, but we'll
67411308Santhony.gutierrez@amd.com# ignore them for now.
67511308Santhony.gutierrez@amd.commem_types = all_int_types + arith_float_types
67611308Santhony.gutierrez@amd.commem_atom_types = all_int_types + ('B32', 'B64')
67711308Santhony.gutierrez@amd.com
67811308Santhony.gutierrez@amd.com##### Arithmetic & logical operations
67911308Santhony.gutierrez@amd.comgen('Add', arith_types, 'src0 + src1')
68011308Santhony.gutierrez@amd.comgen('Sub', arith_types, 'src0 - src1')
68111308Santhony.gutierrez@amd.comgen('Mul', arith_types, 'src0 * src1')
68211308Santhony.gutierrez@amd.comgen('Div', arith_types, 'src0 / src1')
68311308Santhony.gutierrez@amd.comgen('Min', arith_types, 'std::min(src0, src1)')
68411308Santhony.gutierrez@amd.comgen('Max', arith_types, 'std::max(src0, src1)')
68511308Santhony.gutierrez@amd.comgen('Gcnmin', arith_types, 'std::min(src0, src1)')
68611308Santhony.gutierrez@amd.com
68711308Santhony.gutierrez@amd.comgen('CopySign', arith_float_types,
68811308Santhony.gutierrez@amd.com    'src1 < 0 ? -std::abs(src0) : std::abs(src0)')
68911308Santhony.gutierrez@amd.comgen('Sqrt', arith_float_types, 'sqrt(src0)')
69011308Santhony.gutierrez@amd.comgen('Floor', arith_float_types, 'floor(src0)')
69111308Santhony.gutierrez@amd.com
69211308Santhony.gutierrez@amd.com# "fast" sqrt... same as slow for us
69311308Santhony.gutierrez@amd.comgen('Nsqrt', arith_float_types, 'sqrt(src0)')
69411308Santhony.gutierrez@amd.comgen('Nrsqrt', arith_float_types, '1.0/sqrt(src0)')
69511308Santhony.gutierrez@amd.comgen('Nrcp', arith_float_types, '1.0/src0')
69611308Santhony.gutierrez@amd.comgen('Fract', arith_float_types,
69711308Santhony.gutierrez@amd.com    '(src0 >= 0.0)?(src0-floor(src0)):(floor(src0)-src0)')
69811308Santhony.gutierrez@amd.com
69911308Santhony.gutierrez@amd.comgen('Ncos', arith_float_types, 'cos(src0)');
70011308Santhony.gutierrez@amd.comgen('Nsin', arith_float_types, 'sin(src0)');
70111308Santhony.gutierrez@amd.com
70211308Santhony.gutierrez@amd.comgen('And', bit_types, 'src0 & src1')
70311308Santhony.gutierrez@amd.comgen('Or', bit_types,  'src0 | src1')
70411308Santhony.gutierrez@amd.comgen('Xor', bit_types, 'src0 ^ src1')
70511308Santhony.gutierrez@amd.com
70611308Santhony.gutierrez@amd.comgen('Bitselect', bit_types, '(src1 & src0) | (src2 & ~src0)')
70711737Sbrandon.potter@amd.comgen('Popcount', ('U32',), '__builtin_popcount(src0)', 'PopcountInst', \
70811737Sbrandon.potter@amd.com    ('sourceType', ('B32', 'B64')))
70911308Santhony.gutierrez@amd.com
71011308Santhony.gutierrez@amd.comgen('Shl', arith_int_types, 'src0 << (unsigned)src1', 'ShiftInst')
71111308Santhony.gutierrez@amd.comgen('Shr', arith_int_types, 'src0 >> (unsigned)src1', 'ShiftInst')
71211308Santhony.gutierrez@amd.com
71311308Santhony.gutierrez@amd.com# gen('Mul_hi', types=('s32','u32', '??'))
71411308Santhony.gutierrez@amd.com# gen('Mul24', types=('s32','u32', '??'))
71511308Santhony.gutierrez@amd.comgen('Rem', arith_int_types, 'src0 - ((src0 / src1) * src1)')
71611308Santhony.gutierrez@amd.com
71711308Santhony.gutierrez@amd.comgen('Abs', arith_types, 'std::abs(src0)')
71811308Santhony.gutierrez@amd.comgen('Neg', arith_types, '-src0')
71911308Santhony.gutierrez@amd.com
72011735Sbrandon.potter@amd.comgen('Mov', bit_types + arith_types, 'src0')
72111308Santhony.gutierrez@amd.comgen('Not', bit_types, 'heynot(src0)')
72211308Santhony.gutierrez@amd.com
72311308Santhony.gutierrez@amd.com# mad and fma differ only in rounding behavior, which we don't emulate
72411308Santhony.gutierrez@amd.com# also there's an integer form of mad, but not of fma
72511308Santhony.gutierrez@amd.comgen('Mad', arith_types, 'src0 * src1 + src2')
72611308Santhony.gutierrez@amd.comgen('Fma', arith_float_types, 'src0 * src1 + src2')
72711308Santhony.gutierrez@amd.com
72811308Santhony.gutierrez@amd.com#native floating point operations
72911308Santhony.gutierrez@amd.comgen('Nfma', arith_float_types, 'src0 * src1 + src2')
73011308Santhony.gutierrez@amd.com
73111308Santhony.gutierrez@amd.comgen('Cmov', bit_types, 'src0 ? src1 : src2', 'CmovInst')
73211308Santhony.gutierrez@amd.comgen('BitAlign', bit_types, '(src0 << src2)|(src1 >> (32 - src2))')
73311308Santhony.gutierrez@amd.comgen('ByteAlign', bit_types, '(src0 << 8 * src2)|(src1 >> (32 - 8 * src2))')
73411308Santhony.gutierrez@amd.com
73511308Santhony.gutierrez@amd.com# see base/bitfield.hh
73611308Santhony.gutierrez@amd.comgen('BitExtract', arith_int_types, 'bits(src0, src1, src1 + src2 - 1)',
73711308Santhony.gutierrez@amd.com    'ExtractInsertInst')
73811308Santhony.gutierrez@amd.com
73911308Santhony.gutierrez@amd.comgen('BitInsert', arith_int_types, 'insertBits(dest, src1, src2, src0)',
74011308Santhony.gutierrez@amd.com    'ExtractInsertInst')
74111308Santhony.gutierrez@amd.com
74211308Santhony.gutierrez@amd.com##### Compare
74311308Santhony.gutierrez@amd.comgen('Cmp', ('B1', 'S32', 'U32', 'F32'), 'compare(src0, src1, this->cmpOp)',
74411308Santhony.gutierrez@amd.com    'CmpInst', ('sourceType', arith_types + bit_types))
74511308Santhony.gutierrez@amd.comgen('Class', arith_float_types, 'fpclassify(src0,src1)','ClassInst')
74611308Santhony.gutierrez@amd.com
74711308Santhony.gutierrez@amd.com##### Conversion
74811308Santhony.gutierrez@amd.com
74911308Santhony.gutierrez@amd.com# Conversion operations are only defined on B1, not B32 or B64
75011308Santhony.gutierrez@amd.comcvt_types = ('B1',) + mem_types
75111308Santhony.gutierrez@amd.com
75211308Santhony.gutierrez@amd.comgen('Cvt', cvt_types, 'src0', 'CvtInst', ('sourceType', cvt_types))
75311308Santhony.gutierrez@amd.com
75411308Santhony.gutierrez@amd.com
75511308Santhony.gutierrez@amd.com##### Load & Store
75611308Santhony.gutierrez@amd.comgen('Lda', mem_types, base_class = 'LdInst', constructor_prefix='decode')
75711308Santhony.gutierrez@amd.comgen('Ld', mem_types, base_class = 'LdInst', constructor_prefix='decode')
75811308Santhony.gutierrez@amd.comgen('St', mem_types, base_class = 'StInst', constructor_prefix='decode',
75911308Santhony.gutierrez@amd.com    is_store=True)
76011308Santhony.gutierrez@amd.comgen('Atomic', mem_atom_types, base_class='StInst', constructor_prefix='decode')
76111308Santhony.gutierrez@amd.comgen('AtomicNoRet', mem_atom_types, base_class='StInst',
76211308Santhony.gutierrez@amd.com    constructor_prefix='decode')
76311308Santhony.gutierrez@amd.com
76411308Santhony.gutierrez@amd.comgen('Cbr', base_class = 'LdInst', constructor_prefix='decode')
76511308Santhony.gutierrez@amd.comgen('Br', base_class = 'LdInst', constructor_prefix='decode')
76611308Santhony.gutierrez@amd.com
76711308Santhony.gutierrez@amd.com##### Special operations
76811308Santhony.gutierrez@amd.comdef gen_special(brig_opcode, expr, dest_type='U32'):
76911308Santhony.gutierrez@amd.com    num_srcs = num_src_operands(expr)
77011308Santhony.gutierrez@amd.com    if num_srcs == 0:
77111308Santhony.gutierrez@amd.com        base_class = 'SpecialInstNoSrc<%s>' % dest_type
77211308Santhony.gutierrez@amd.com    elif num_srcs == 1:
77311308Santhony.gutierrez@amd.com        base_class = 'SpecialInst1Src<%s>' % dest_type
77411308Santhony.gutierrez@amd.com    else:
77511308Santhony.gutierrez@amd.com        assert false
77611308Santhony.gutierrez@amd.com
77711308Santhony.gutierrez@amd.com    gen(brig_opcode, None, expr, base_class)
77811308Santhony.gutierrez@amd.com
77911639Salexandru.dutu@amd.comgen_special('WorkItemId', 'w->workItemId[src0][lane]')
78011308Santhony.gutierrez@amd.comgen_special('WorkItemAbsId',
78111639Salexandru.dutu@amd.com    'w->workItemId[src0][lane] + (w->workGroupId[src0] * w->workGroupSz[src0])')
78211639Salexandru.dutu@amd.comgen_special('WorkGroupId', 'w->workGroupId[src0]')
78311639Salexandru.dutu@amd.comgen_special('WorkGroupSize', 'w->workGroupSz[src0]')
78411639Salexandru.dutu@amd.comgen_special('CurrentWorkGroupSize', 'w->workGroupSz[src0]')
78511639Salexandru.dutu@amd.comgen_special('GridSize', 'w->gridSz[src0]')
78611308Santhony.gutierrez@amd.comgen_special('GridGroups',
78711639Salexandru.dutu@amd.com    'divCeil(w->gridSz[src0],w->workGroupSz[src0])')
78811308Santhony.gutierrez@amd.comgen_special('LaneId', 'lane')
78911643Salexandru.dutu@amd.comgen_special('WaveId', 'w->wfId')
79011308Santhony.gutierrez@amd.comgen_special('Clock', 'w->computeUnit->shader->tick_cnt', 'U64')
79111308Santhony.gutierrez@amd.com
79211308Santhony.gutierrez@amd.com# gen_special('CU'', ')
79311308Santhony.gutierrez@amd.com
79411308Santhony.gutierrez@amd.comgen('Ret', base_class='SpecialInstNoSrcNoDest')
79511308Santhony.gutierrez@amd.comgen('Barrier', base_class='SpecialInstNoSrcNoDest')
79611308Santhony.gutierrez@amd.comgen('MemFence', base_class='SpecialInstNoSrcNoDest')
79711308Santhony.gutierrez@amd.com
79811308Santhony.gutierrez@amd.com# Map magic instructions to the BrigSyscall opcode
79911308Santhony.gutierrez@amd.com# Magic instructions are defined in magic.hh
80011308Santhony.gutierrez@amd.com#
80111308Santhony.gutierrez@amd.com# In the future, real HSA kernel system calls can be implemented and coexist
80211308Santhony.gutierrez@amd.com# with magic instructions.
80311308Santhony.gutierrez@amd.comgen('Call', base_class='SpecialInstNoSrcNoDest')
80411308Santhony.gutierrez@amd.com
80511738Sbrandon.potter@amd.com# Stubs for unimplemented instructions:
80611738Sbrandon.potter@amd.com# These may need to be implemented at some point in the future, but
80711738Sbrandon.potter@amd.com# for now we just match the instructions with their operands.
80811738Sbrandon.potter@amd.com#
80911738Sbrandon.potter@amd.com# By defining stubs for these instructions, we can work with
81011738Sbrandon.potter@amd.com# applications that have them in dead/unused code paths.
81111738Sbrandon.potter@amd.com#
81211738Sbrandon.potter@amd.com# Needed for rocm-hcc compilations for HSA backends since
81311738Sbrandon.potter@amd.com# builtins-hsail library is `cat`d onto the generated kernels.
81411738Sbrandon.potter@amd.com# The builtins-hsail library consists of handcoded hsail functions
81511738Sbrandon.potter@amd.com# that __might__ be needed by the rocm-hcc compiler in certain binaries.
81611738Sbrandon.potter@amd.comgen('Bitmask', base_class='Stub')
81711738Sbrandon.potter@amd.comgen('Bitrev', base_class='Stub')
81811738Sbrandon.potter@amd.comgen('Firstbit', base_class='Stub')
81911738Sbrandon.potter@amd.comgen('Lastbit', base_class='Stub')
82011738Sbrandon.potter@amd.comgen('Unpacklo', base_class='Stub')
82111738Sbrandon.potter@amd.comgen('Unpackhi', base_class='Stub')
82211738Sbrandon.potter@amd.comgen('Pack', base_class='Stub')
82311738Sbrandon.potter@amd.comgen('Unpack', base_class='Stub')
82411738Sbrandon.potter@amd.comgen('Lerp', base_class='Stub')
82511738Sbrandon.potter@amd.comgen('Packcvt', base_class='Stub')
82611738Sbrandon.potter@amd.comgen('Unpackcvt', base_class='Stub')
82711738Sbrandon.potter@amd.comgen('Sad', base_class='Stub')
82811738Sbrandon.potter@amd.comgen('Sadhi', base_class='Stub')
82911738Sbrandon.potter@amd.comgen('Activelanecount', base_class='Stub')
83011738Sbrandon.potter@amd.comgen('Activelaneid', base_class='Stub')
83111738Sbrandon.potter@amd.comgen('Activelanemask', base_class='Stub')
83211738Sbrandon.potter@amd.comgen('Activelanepermute', base_class='Stub')
83311738Sbrandon.potter@amd.comgen('Groupbaseptr', base_class='Stub')
83411738Sbrandon.potter@amd.comgen('Signalnoret', base_class='Stub')
83511738Sbrandon.potter@amd.com
83611308Santhony.gutierrez@amd.com###############
83711308Santhony.gutierrez@amd.com#
83811308Santhony.gutierrez@amd.com# Generate file epilogs
83911308Santhony.gutierrez@amd.com#
84011308Santhony.gutierrez@amd.com###############
84111704Santhony.gutierrez@amd.comheader_code('''
84211704Santhony.gutierrez@amd.comtemplate<>
84311704Santhony.gutierrez@amd.cominline void
84411704Santhony.gutierrez@amd.comAbs<U32>::execute(GPUDynInstPtr gpuDynInst)
84511704Santhony.gutierrez@amd.com{
84611704Santhony.gutierrez@amd.com    Wavefront *w = gpuDynInst->wavefront();
84711704Santhony.gutierrez@amd.com
84811704Santhony.gutierrez@amd.com    const VectorMask &mask = w->getPred();
84911704Santhony.gutierrez@amd.com
85011704Santhony.gutierrez@amd.com    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
85111704Santhony.gutierrez@amd.com        if (mask[lane]) {
85211704Santhony.gutierrez@amd.com            CType dest_val;
85311704Santhony.gutierrez@amd.com            CType src_val;
85411704Santhony.gutierrez@amd.com
85511704Santhony.gutierrez@amd.com            src_val = this->src[0].template get<CType>(w, lane);
85611704Santhony.gutierrez@amd.com
85711704Santhony.gutierrez@amd.com            dest_val = (CType)(src_val);
85811704Santhony.gutierrez@amd.com
85911704Santhony.gutierrez@amd.com            this->dest.set(w, lane, dest_val);
86011704Santhony.gutierrez@amd.com        }
86111704Santhony.gutierrez@amd.com    }
86211704Santhony.gutierrez@amd.com}
86311704Santhony.gutierrez@amd.com
86411704Santhony.gutierrez@amd.comtemplate<>
86511704Santhony.gutierrez@amd.cominline void
86611704Santhony.gutierrez@amd.comAbs<U64>::execute(GPUDynInstPtr gpuDynInst)
86711704Santhony.gutierrez@amd.com{
86811704Santhony.gutierrez@amd.com    Wavefront *w = gpuDynInst->wavefront();
86911704Santhony.gutierrez@amd.com
87011704Santhony.gutierrez@amd.com    const VectorMask &mask = w->getPred();
87111704Santhony.gutierrez@amd.com
87211704Santhony.gutierrez@amd.com    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
87311704Santhony.gutierrez@amd.com        if (mask[lane]) {
87411704Santhony.gutierrez@amd.com            CType dest_val;
87511704Santhony.gutierrez@amd.com            CType src_val;
87611704Santhony.gutierrez@amd.com
87711704Santhony.gutierrez@amd.com            src_val = this->src[0].template get<CType>(w, lane);
87811704Santhony.gutierrez@amd.com
87911704Santhony.gutierrez@amd.com            dest_val = (CType)(src_val);
88011704Santhony.gutierrez@amd.com
88111704Santhony.gutierrez@amd.com            this->dest.set(w, lane, dest_val);
88211704Santhony.gutierrez@amd.com        }
88311704Santhony.gutierrez@amd.com    }
88411704Santhony.gutierrez@amd.com}
88511704Santhony.gutierrez@amd.com''')
88611704Santhony.gutierrez@amd.com
88711308Santhony.gutierrez@amd.comheader_code.dedent()
88811308Santhony.gutierrez@amd.comheader_code('''
88911308Santhony.gutierrez@amd.com} // namespace HsailISA
89011308Santhony.gutierrez@amd.com''')
89111308Santhony.gutierrez@amd.com
89211308Santhony.gutierrez@amd.com# close off main decode switch
89311308Santhony.gutierrez@amd.comdecoder_code.dedent()
89411308Santhony.gutierrez@amd.comdecoder_code.dedent()
89511308Santhony.gutierrez@amd.comdecoder_code('''
89611308Santhony.gutierrez@amd.com          default: fatal("unrecognized Brig opcode %d\\n", ib->opcode);
89711308Santhony.gutierrez@amd.com        } // end switch(ib->opcode)
89811308Santhony.gutierrez@amd.com    } // end decode()
89911308Santhony.gutierrez@amd.com} // namespace HsailISA
90011308Santhony.gutierrez@amd.com''')
90111308Santhony.gutierrez@amd.com
90211308Santhony.gutierrez@amd.comexec_code.dedent()
90311308Santhony.gutierrez@amd.comexec_code('''
90411308Santhony.gutierrez@amd.com} // namespace HsailISA
90511308Santhony.gutierrez@amd.com''')
90611308Santhony.gutierrez@amd.com
90711308Santhony.gutierrez@amd.com###############
90811308Santhony.gutierrez@amd.com#
90911308Santhony.gutierrez@amd.com# Output accumulated code to files
91011308Santhony.gutierrez@amd.com#
91111308Santhony.gutierrez@amd.com###############
91211308Santhony.gutierrez@amd.comheader_code.write(sys.argv[1])
91311308Santhony.gutierrez@amd.comdecoder_code.write(sys.argv[2])
91411308Santhony.gutierrez@amd.comexec_code.write(sys.argv[3])
915