• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2020 Collabora, Ltd.
2#
3# Permission is hereby granted, free of charge, to any person obtaining a
4# copy of this software and associated documentation files (the "Software"),
5# to deal in the Software without restriction, including without limitation
6# the rights to use, copy, modify, merge, publish, distribute, sublicense,
7# and/or sell copies of the Software, and to permit persons to whom the
8# Software is furnished to do so, subject to the following conditions:
9#
10# The above copyright notice and this permission notice (including the next
11# paragraph) shall be included in all copies or substantial portions of the
12# Software.
13#
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20# IN THE SOFTWARE.
21
22SKIP = set(["lane", "lane_dest", "lanes", "lanes", "replicate", "swz", "widen", "swap", "neg", "abs", "not", "sign", "extend", "divzero", "clamp", "sem", "not_result", "skip"])
23
24TEMPLATE = """
25#ifndef _BI_BUILDER_H_
26#define _BI_BUILDER_H_
27
28#include "compiler.h"
29
30<%
31# For <32-bit loads/stores, the default extend `none` with a natural sized
32# input is not encodeable! To avoid a footgun, swap the default to `zext` which
33# will work as expected
34ZEXT_DEFAULT = set(["LOAD.i8", "LOAD.i16", "LOAD.i24", "STORE.i8", "STORE.i16", "STORE.i24"])
35
36def nirtypes(opcode):
37    split = opcode.split('.', 1)
38    if len(split) < 2:
39        split = opcode.split('_')
40
41    if len(split) <= 1:
42        return None
43
44    assert len(split) > 1
45
46    type = split[1]
47    if type[0] == 'v':
48        type = type[2:]
49
50    if type[0] == 'f':
51        return ['nir_type_float']
52    elif type[0] == 's':
53        return ['nir_type_int']
54    elif type[0] == 'u':
55        return ['nir_type_uint']
56    elif type[0] == 'i':
57        return ['nir_type_uint', 'nir_type_int']
58    else:
59        return None
60
61def condition(opcode, typecheck, sizecheck):
62    cond = ''
63    if typecheck == True:
64        cond += '('
65        types = nirtypes(opcode)
66        assert types != None
67        for T in types:
68            cond += "{}type == {}".format(' || ' if cond[-1] != '(' else '', T)
69        cond += ')'
70
71    if sizecheck == True:
72        cond += "{}bitsize == {}".format(' && ' if cond != '' else '', typesize(opcode))
73
74    cmpf_mods = ops[opcode]["modifiers"]["cmpf"] if "cmpf" in ops[opcode]["modifiers"] else None
75    if "cmpf" in ops[opcode]["modifiers"]:
76        cond += "{}(".format(' && ' if cond != '' else '')
77        for cmpf in ops[opcode]["modifiers"]["cmpf"]:
78            if cmpf != 'reserved':
79                cond += "{}cmpf == BI_CMPF_{}".format(' || ' if cond[-1] != '(' else '', cmpf.upper())
80        cond += ')'
81
82    return 'true' if cond == '' else cond
83
84def to_suffix(op):
85    return "_to" if op["dests"] > 0 else ""
86
87%>
88
89% for opcode in ops:
90static inline
91bi_instr * bi_${opcode.replace('.', '_').lower()}${to_suffix(ops[opcode])}(${signature(ops[opcode], modifiers)})
92{
93    bi_instr *I = rzalloc(b->shader, bi_instr);
94    I->op = BI_OPCODE_${opcode.replace('.', '_').upper()};
95% for dest in range(ops[opcode]["dests"]):
96    I->dest[${dest}] = dest${dest};
97% endfor
98% for src in range(src_count(ops[opcode])):
99    I->src[${src}] = src${src};
100% endfor
101% for mod in ops[opcode]["modifiers"]:
102% if mod[0:-1] not in SKIP and mod not in SKIP:
103    I->${mod} = ${mod};
104% endif
105% endfor
106% for imm in ops[opcode]["immediates"]:
107    I->${imm} = ${imm};
108% endfor
109% if opcode in ZEXT_DEFAULT:
110    I->extend = BI_EXTEND_ZEXT;
111% endif
112    bi_builder_insert(&b->cursor, I);
113    return I;
114}
115
116% if ops[opcode]["dests"] == 1:
117static inline
118bi_index bi_${opcode.replace('.', '_').lower()}(${signature(ops[opcode], modifiers, no_dests=True)})
119{
120    return (bi_${opcode.replace('.', '_').lower()}_to(${arguments(ops[opcode])}))->dest[0];
121}
122
123%endif
124<%
125    common_op = opcode.split('.')[0]
126    variants = [a for a in ops.keys() if a.split('.')[0] == common_op]
127    signatures = [signature(ops[op], modifiers, no_dests=True) for op in variants]
128    homogenous = all([sig == signatures[0] for sig in signatures])
129    types = [nirtypes(x) for x in variants]
130    typeful = False
131    for t in types:
132        if t != types[0]:
133            typeful = True
134
135    sizes = [typesize(x) for x in variants]
136    sized = False
137    for size in sizes:
138        if size != sizes[0]:
139            sized = True
140
141    last = opcode == variants[-1]
142%>
143% if homogenous and len(variants) > 1 and last:
144% for (suffix, temp, dests, ret) in (('_to', False, 1, 'instr *'), ('', True, 0, 'index')):
145% if not temp or ops[opcode]["dests"] > 0:
146static inline
147bi_${ret} bi_${common_op.replace('.', '_').lower()}${suffix if ops[opcode]['dests'] > 0 else ''}(${signature(ops[opcode], modifiers, typeful=typeful, sized=sized, no_dests=not dests)})
148{
149% for i, variant in enumerate(variants):
150    ${"{}if ({})".format("else " if i > 0 else "", condition(variant, typeful, sized))}
151        return (bi_${variant.replace('.', '_').lower()}${to_suffix(ops[opcode])}(${arguments(ops[opcode], temp_dest = temp)}))${"->dest[0]" if temp else ""};
152% endfor
153    else
154        unreachable("Invalid parameters for ${common_op}");
155}
156
157%endif
158%endfor
159%endif
160%endfor
161#endif"""
162
163import sys
164from bifrost_isa import *
165from mako.template import Template
166
167instructions = parse_instructions(sys.argv[1], include_pseudo = True)
168ir_instructions = partition_mnemonics(instructions)
169modifier_lists = order_modifiers(ir_instructions)
170
171# Generate type signature for a builder routine
172
173def should_skip(mod):
174    return mod in SKIP or mod[0:-1] in SKIP
175
176def modifier_signature(op):
177    return sorted([m for m in op["modifiers"].keys() if not should_skip(m)])
178
179def signature(op, modifiers, typeful = False, sized = False, no_dests = False):
180    return ", ".join(
181        ["bi_builder *b"] +
182        (["nir_alu_type type"] if typeful == True else []) +
183        (["unsigned bitsize"] if sized == True else []) +
184        ["bi_index dest{}".format(i) for i in range(0 if no_dests else op["dests"])] +
185        ["bi_index src{}".format(i) for i in range(src_count(op))] +
186        ["{} {}".format(
187        "bool" if len(modifiers[T[0:-1]] if T[-1] in "0123" else modifiers[T]) == 2 else
188        "enum bi_" + T[0:-1] if T[-1] in "0123" else
189        "enum bi_" + T,
190        T) for T in modifier_signature(op)] +
191        ["uint32_t {}".format(imm) for imm in op["immediates"]])
192
193def arguments(op, temp_dest = True):
194    return ", ".join(
195        ["b"] +
196        ["bi_temp(b->shader)" if temp_dest else 'dest{}'.format(i) for i in range(op["dests"])] +
197        ["src{}".format(i) for i in range(src_count(op))] +
198        modifier_signature(op) +
199        op["immediates"])
200
201print(Template(COPYRIGHT + TEMPLATE).render(ops = ir_instructions, modifiers = modifier_lists, signature = signature, arguments = arguments, src_count = src_count, typesize = typesize, SKIP = SKIP))
202