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