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", 23 "swap", "neg", "abs", "not", "sign", "extend", "divzero", "clamp", "sem", 24 "not_result", "skip", "round", "ftz"]) 25 26TEMPLATE = """ 27#ifndef _BI_BUILDER_H_ 28#define _BI_BUILDER_H_ 29 30#include "compiler.h" 31 32<% 33# For <32-bit loads/stores, the default extend `none` with a natural sized 34# input is not encodeable! To avoid a footgun, swap the default to `zext` which 35# will work as expected 36ZEXT_DEFAULT = set(["LOAD.i8", "LOAD.i16", "LOAD.i24", "STORE.i8", "STORE.i16", "STORE.i24"]) 37 38def nirtypes(opcode): 39 split = opcode.split('.', 1) 40 if len(split) < 2: 41 split = opcode.split('_') 42 43 if len(split) <= 1: 44 return None 45 46 assert len(split) > 1 47 48 type = split[1] 49 if type[0] == 'v': 50 type = type[2:] 51 52 if type[0] == 'f': 53 return ['nir_type_float'] 54 elif type[0] == 's': 55 return ['nir_type_int'] 56 elif type[0] == 'u': 57 return ['nir_type_uint'] 58 elif type[0] == 'i': 59 return ['nir_type_uint', 'nir_type_int'] 60 else: 61 return None 62 63def condition(opcode, typecheck, sizecheck): 64 cond = '' 65 if typecheck == True: 66 cond += '(' 67 types = nirtypes(opcode) 68 assert types != None 69 for T in types: 70 cond += "{}type == {}".format(' || ' if cond[-1] != '(' else '', T) 71 cond += ')' 72 73 if sizecheck == True: 74 cond += "{}bitsize == {}".format(' && ' if cond != '' else '', typesize(opcode)) 75 76 cmpf_mods = ops[opcode]["modifiers"]["cmpf"] if "cmpf" in ops[opcode]["modifiers"] else None 77 if "cmpf" in ops[opcode]["modifiers"]: 78 cond += "{}(".format(' && ' if cond != '' else '') 79 for cmpf in ops[opcode]["modifiers"]["cmpf"]: 80 if cmpf != 'reserved': 81 cond += "{}cmpf == BI_CMPF_{}".format(' || ' if cond[-1] != '(' else '', cmpf.upper()) 82 cond += ')' 83 84 return 'true' if cond == '' else cond 85 86def to_suffix(op): 87 return "_to" if op["dests"] > 0 else "" 88 89%> 90 91% for opcode in ops: 92static inline 93bi_instr * bi_${opcode.replace('.', '_').lower()}${to_suffix(ops[opcode])}(${signature(ops[opcode], modifiers)}) 94{ 95<% 96 op = ops[opcode] 97 nr_dests = "nr_dests" if op["variable_dests"] else op["dests"] 98 nr_srcs = "nr_srcs" if op["variable_srcs"] else src_count(op) 99%> 100 size_t size = sizeof(bi_instr) + sizeof(bi_index) * (${nr_dests} + ${nr_srcs}); 101 bi_instr *I = (bi_instr *) rzalloc_size(b->shader, size); 102 103 I->op = BI_OPCODE_${opcode.replace('.', '_').upper()}; 104 I->nr_dests = ${nr_dests}; 105 I->nr_srcs = ${nr_srcs}; 106 I->dest = (bi_index *) (&I[1]); 107 I->src = I->dest + ${nr_dests}; 108 109% if not op["variable_dests"]: 110% for dest in range(op["dests"]): 111 I->dest[${dest}] = dest${dest}; 112% endfor 113%endif 114 115% if not op["variable_srcs"]: 116% for src in range(src_count(op)): 117 I->src[${src}] = src${src}; 118% endfor 119% endif 120 121% for mod in ops[opcode]["modifiers"]: 122% if not should_skip(mod, opcode): 123 I->${mod} = ${mod}; 124% endif 125% endfor 126% if ops[opcode]["rtz"]: 127 I->round = BI_ROUND_RTZ; 128% endif 129% for imm in ops[opcode]["immediates"]: 130 I->${imm} = ${imm}; 131% endfor 132% if opcode in ZEXT_DEFAULT: 133 I->extend = BI_EXTEND_ZEXT; 134% endif 135 bi_builder_insert(&b->cursor, I); 136 return I; 137} 138 139% if ops[opcode]["dests"] == 1 and not ops[opcode]["variable_dests"]: 140static inline 141bi_index bi_${opcode.replace('.', '_').lower()}(${signature(ops[opcode], modifiers, no_dests=True)}) 142{ 143 return (bi_${opcode.replace('.', '_').lower()}_to(${arguments(ops[opcode])}))->dest[0]; 144} 145 146%endif 147<% 148 common_op = opcode.split('.')[0] 149 variants = [a for a in ops.keys() if a.split('.')[0] == common_op] 150 signatures = [signature(ops[op], modifiers, no_dests=True) for op in variants] 151 homogenous = all([sig == signatures[0] for sig in signatures]) 152 types = [nirtypes(x) for x in variants] 153 typeful = False 154 for t in types: 155 if t != types[0]: 156 typeful = True 157 158 sizes = [typesize(x) for x in variants] 159 sized = False 160 for size in sizes: 161 if size != sizes[0]: 162 sized = True 163 164 last = opcode == variants[-1] 165%> 166% if homogenous and len(variants) > 1 and last: 167% for (suffix, temp, dests, ret) in (('_to', False, 1, 'instr *'), ('', True, 0, 'index')): 168% if not temp or ops[opcode]["dests"] > 0: 169static inline 170bi_${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)}) 171{ 172% for i, variant in enumerate(variants): 173 ${"{}if ({})".format("else " if i > 0 else "", condition(variant, typeful, sized))} 174 return (bi_${variant.replace('.', '_').lower()}${to_suffix(ops[opcode])}(${arguments(ops[opcode], temp_dest = temp)}))${"->dest[0]" if temp else ""}; 175% endfor 176 else 177 unreachable("Invalid parameters for ${common_op}"); 178} 179 180%endif 181%endfor 182%endif 183%endfor 184#endif""" 185 186import sys 187from bifrost_isa import * 188from mako.template import Template 189 190instructions = {} 191for arg in sys.argv[1:]: 192 new_instructions = parse_instructions(arg, include_pseudo = True) 193 instructions.update(new_instructions) 194 195ir_instructions = partition_mnemonics(instructions) 196modifier_lists = order_modifiers(ir_instructions) 197 198# Generate type signature for a builder routine 199 200def should_skip(mod, op): 201 # FROUND and HADD only make sense in context of a round mode, so override 202 # the usual skip 203 if mod == "round" and ("FROUND" in op or "HADD" in op): 204 return False 205 206 return mod in SKIP or mod[0:-1] in SKIP 207 208def modifier_signature(op): 209 return sorted([m for m in op["modifiers"].keys() if not should_skip(m, op["key"])]) 210 211def signature(op, modifiers, typeful = False, sized = False, no_dests = False): 212 return ", ".join( 213 ["bi_builder *b"] + 214 (["nir_alu_type type"] if typeful == True else []) + 215 (["unsigned bitsize"] if sized == True else []) + 216 (["unsigned nr_dests"] if op["variable_dests"] else 217 ["bi_index dest{}".format(i) for i in range(0 if no_dests else op["dests"])]) + 218 (["unsigned nr_srcs"] if op["variable_srcs"] else 219 ["bi_index src{}".format(i) for i in range(src_count(op))]) + 220 ["{} {}".format( 221 "bool" if len(modifiers[T[0:-1]] if T[-1] in "0123" else modifiers[T]) == 2 else 222 "enum bi_" + T[0:-1] if T[-1] in "0123" else 223 "enum bi_" + T, 224 T) for T in modifier_signature(op)] + 225 ["uint32_t {}".format(imm) for imm in op["immediates"]]) 226 227def arguments(op, temp_dest = True): 228 dest_pattern = "bi_temp(b->shader)" if temp_dest else 'dest{}' 229 dests = [dest_pattern.format(i) for i in range(op["dests"])] 230 srcs = ["src{}".format(i) for i in range(src_count(op))] 231 232 # Variable source/destinations just pass in the count 233 if op["variable_dests"]: 234 dests = ["nr_dests"] 235 236 if op["variable_srcs"]: 237 srcs = ["nr_srcs"] 238 239 return ", ".join(["b"] + dests + srcs + modifier_signature(op) + op["immediates"]) 240 241print(Template(COPYRIGHT + TEMPLATE).render(ops = ir_instructions, modifiers = 242 modifier_lists, signature = signature, arguments = arguments, src_count = 243 src_count, typesize = typesize, should_skip = should_skip)) 244