1*61046927SAndroid Build Coastguard Worker# 2*61046927SAndroid Build Coastguard Worker# Copyright (C) 2020 Collabora, Ltd. 3*61046927SAndroid Build Coastguard Worker# 4*61046927SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a 5*61046927SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the "Software"), 6*61046927SAndroid Build Coastguard Worker# to deal in the Software without restriction, including without limitation 7*61046927SAndroid Build Coastguard Worker# the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*61046927SAndroid Build Coastguard Worker# and/or sell copies of the Software, and to permit persons to whom the 9*61046927SAndroid Build Coastguard Worker# Software is furnished to do so, subject to the following conditions: 10*61046927SAndroid Build Coastguard Worker# 11*61046927SAndroid Build Coastguard Worker# The above copyright notice and this permission notice (including the next 12*61046927SAndroid Build Coastguard Worker# paragraph) shall be included in all copies or substantial portions of the 13*61046927SAndroid Build Coastguard Worker# Software. 14*61046927SAndroid Build Coastguard Worker# 15*61046927SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*61046927SAndroid Build Coastguard Worker# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*61046927SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18*61046927SAndroid Build Coastguard Worker# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19*61046927SAndroid Build Coastguard Worker# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20*61046927SAndroid Build Coastguard Worker# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21*61046927SAndroid Build Coastguard Worker# IN THE SOFTWARE. 22*61046927SAndroid Build Coastguard Worker 23*61046927SAndroid Build Coastguard Worker# Useful for autogeneration 24*61046927SAndroid Build Coastguard WorkerCOPYRIGHT = """/* 25*61046927SAndroid Build Coastguard Worker * Copyright (C) 2020 Collabora, Ltd. 26*61046927SAndroid Build Coastguard Worker * 27*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a 28*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"), 29*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation 30*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense, 31*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the 32*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions: 33*61046927SAndroid Build Coastguard Worker * 34*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next 35*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the 36*61046927SAndroid Build Coastguard Worker * Software. 37*61046927SAndroid Build Coastguard Worker * 38*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 39*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 40*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 41*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 42*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 43*61046927SAndroid Build Coastguard Worker * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 44*61046927SAndroid Build Coastguard Worker * SOFTWARE. 45*61046927SAndroid Build Coastguard Worker */ 46*61046927SAndroid Build Coastguard Worker 47*61046927SAndroid Build Coastguard Worker/* Autogenerated file, do not edit */ 48*61046927SAndroid Build Coastguard Worker 49*61046927SAndroid Build Coastguard Worker""" 50*61046927SAndroid Build Coastguard Worker 51*61046927SAndroid Build Coastguard Worker# Parse instruction set XML into a normalized form for processing 52*61046927SAndroid Build Coastguard Worker 53*61046927SAndroid Build Coastguard Workerimport xml.etree.ElementTree as ET 54*61046927SAndroid Build Coastguard Workerimport copy 55*61046927SAndroid Build Coastguard Workerimport itertools 56*61046927SAndroid Build Coastguard Workerfrom collections import OrderedDict 57*61046927SAndroid Build Coastguard Worker 58*61046927SAndroid Build Coastguard Workerdef parse_cond(cond, aliased = False): 59*61046927SAndroid Build Coastguard Worker if cond.tag == 'reserved': 60*61046927SAndroid Build Coastguard Worker return None 61*61046927SAndroid Build Coastguard Worker 62*61046927SAndroid Build Coastguard Worker if cond.attrib.get('alias', False) and not aliased: 63*61046927SAndroid Build Coastguard Worker return ['alias', parse_cond(cond, True)] 64*61046927SAndroid Build Coastguard Worker 65*61046927SAndroid Build Coastguard Worker if 'left' in cond.attrib: 66*61046927SAndroid Build Coastguard Worker return [cond.tag, cond.attrib['left'], cond.attrib['right']] 67*61046927SAndroid Build Coastguard Worker else: 68*61046927SAndroid Build Coastguard Worker return [cond.tag] + [parse_cond(x) for x in cond.findall('*')] 69*61046927SAndroid Build Coastguard Worker 70*61046927SAndroid Build Coastguard Workerdef parse_exact(obj): 71*61046927SAndroid Build Coastguard Worker return [int(obj.attrib['mask'], 0), int(obj.attrib['exact'], 0)] 72*61046927SAndroid Build Coastguard Worker 73*61046927SAndroid Build Coastguard Workerdef parse_derived(obj): 74*61046927SAndroid Build Coastguard Worker out = [] 75*61046927SAndroid Build Coastguard Worker 76*61046927SAndroid Build Coastguard Worker for deriv in obj.findall('derived'): 77*61046927SAndroid Build Coastguard Worker loc = [int(deriv.attrib['start']), int(deriv.attrib['size'])] 78*61046927SAndroid Build Coastguard Worker count = 1 << loc[1] 79*61046927SAndroid Build Coastguard Worker 80*61046927SAndroid Build Coastguard Worker opts = [parse_cond(d) for d in deriv.findall('*')] 81*61046927SAndroid Build Coastguard Worker default = [None] * count 82*61046927SAndroid Build Coastguard Worker opts_fit = (opts + default)[0:count] 83*61046927SAndroid Build Coastguard Worker 84*61046927SAndroid Build Coastguard Worker out.append([loc, opts_fit]) 85*61046927SAndroid Build Coastguard Worker 86*61046927SAndroid Build Coastguard Worker return out 87*61046927SAndroid Build Coastguard Worker 88*61046927SAndroid Build Coastguard Workerdef parse_modifiers(obj, include_pseudo): 89*61046927SAndroid Build Coastguard Worker out = [] 90*61046927SAndroid Build Coastguard Worker 91*61046927SAndroid Build Coastguard Worker for mod in obj.findall('mod'): 92*61046927SAndroid Build Coastguard Worker if mod.attrib.get('pseudo', False) and not include_pseudo: 93*61046927SAndroid Build Coastguard Worker continue 94*61046927SAndroid Build Coastguard Worker 95*61046927SAndroid Build Coastguard Worker name = mod.attrib['name'] 96*61046927SAndroid Build Coastguard Worker start = mod.attrib.get('start', None) 97*61046927SAndroid Build Coastguard Worker size = int(mod.attrib['size']) 98*61046927SAndroid Build Coastguard Worker 99*61046927SAndroid Build Coastguard Worker if start is not None: 100*61046927SAndroid Build Coastguard Worker start = int(start) 101*61046927SAndroid Build Coastguard Worker 102*61046927SAndroid Build Coastguard Worker opts = [x.text if x.tag == 'opt' else x.tag for x in mod.findall('*')] 103*61046927SAndroid Build Coastguard Worker 104*61046927SAndroid Build Coastguard Worker if len(opts) == 0: 105*61046927SAndroid Build Coastguard Worker if 'opt' in mod.attrib: 106*61046927SAndroid Build Coastguard Worker opts = ['none', mod.attrib['opt']] 107*61046927SAndroid Build Coastguard Worker 108*61046927SAndroid Build Coastguard Worker # Find suitable default 109*61046927SAndroid Build Coastguard Worker default = mod.attrib.get('default', 'none' if 'none' in opts else None) 110*61046927SAndroid Build Coastguard Worker 111*61046927SAndroid Build Coastguard Worker # Pad out as reserved 112*61046927SAndroid Build Coastguard Worker count = (1 << size) 113*61046927SAndroid Build Coastguard Worker opts = (opts + (['reserved'] * count))[0:count] 114*61046927SAndroid Build Coastguard Worker out.append([[name, start, size], default, opts]) 115*61046927SAndroid Build Coastguard Worker 116*61046927SAndroid Build Coastguard Worker return out 117*61046927SAndroid Build Coastguard Worker 118*61046927SAndroid Build Coastguard Workerdef parse_copy(enc, existing): 119*61046927SAndroid Build Coastguard Worker for node in enc.findall('copy'): 120*61046927SAndroid Build Coastguard Worker name = node.get('name') 121*61046927SAndroid Build Coastguard Worker for ex in existing: 122*61046927SAndroid Build Coastguard Worker if ex[0][0] == name: 123*61046927SAndroid Build Coastguard Worker ex[0][1] = node.get('start') 124*61046927SAndroid Build Coastguard Worker 125*61046927SAndroid Build Coastguard Workermod_names = { 126*61046927SAndroid Build Coastguard Worker 'cmp' : [['cmpf', None, None], None, ['eq', 'gt', 'ge', 'ne', 'lt', 'le', 'gtlt', 'total']], 127*61046927SAndroid Build Coastguard Worker # FIXME: Valhall can accept any integer comparision, but the old IR generator only generated 128*61046927SAndroid Build Coastguard Worker # gt and ge, and left out lt and le. For now follow the old way so we can compare generated files, 129*61046927SAndroid Build Coastguard Worker # but we should switch over to the proper way once everything is working 130*61046927SAndroid Build Coastguard Worker# 'cmpfi' : [['cmpf', None, None], None, ['eq', 'ne', 'gt', 'ge', 'lt', 'le']], 131*61046927SAndroid Build Coastguard Worker 'cmpfi' : [['cmpf', None, None], None, ['eq', 'ne', 'gt', 'ge']], 132*61046927SAndroid Build Coastguard Worker 'eq' : [['cmpf', None, None], 'ne', ['eq', 'ne']], 133*61046927SAndroid Build Coastguard Worker 'dimension' : [['dimension', None, None], None, ['1d', '2d', '3d', 'cube']], 134*61046927SAndroid Build Coastguard Worker 'fetch_component' : [['fetch_component', None, None], None, ['gather4_r', 'gather4_g', 'gather4_b', 'gather4_a']], 135*61046927SAndroid Build Coastguard Worker 'lod_mode': [['va_lod_mode', None, None], 'zero_lod', ['zero_lod', 'computed_lod', 'explicit', 'computed_bias', 'grdesc']], 136*61046927SAndroid Build Coastguard Worker 'regfmt' : [['register_format', None, None], None, ['f16', 'f32', 's32', 'u32', 's16', 'u16', 'f64', 'i64', 'auto']], 137*61046927SAndroid Build Coastguard Worker 'result_type' : [['result_type', None, None], None, ['i1', 'f1', 'm1']], 138*61046927SAndroid Build Coastguard Worker 'sample' : [['sample', None, None], 'none', ['center', 'centroid', 'sample', 'explicit', 'none']], 139*61046927SAndroid Build Coastguard Worker 'update' : [['update', None, None], None, ['store', 'retrieve', 'conditional', 'clobber']], 140*61046927SAndroid Build Coastguard Worker 'vecsize' : [['vecsize', None, None], 'none', ['none', 'v2', 'v3', 'v4']], 141*61046927SAndroid Build Coastguard Worker 'source_format' : [['source_format', None, None], None, ['flat32', 'flat16', 'f32', 'f16']], 142*61046927SAndroid Build Coastguard Worker 143*61046927SAndroid Build Coastguard Worker 'array_enable': [['array_enable', None, None], 'none', ['none', 'array_enable']], 144*61046927SAndroid Build Coastguard Worker 'integer_coordinates': [['integer_coordinates', None, None], 'none', ['none', 'integer_coordinates']], 145*61046927SAndroid Build Coastguard Worker 'shadow' : [['shadow', None, None], 'none', ['none', 'shadow']], 146*61046927SAndroid Build Coastguard Worker 'skip' : [['skip', None, None], 'none', ['none', 'skip']], 147*61046927SAndroid Build Coastguard Worker 'texel_offset': [['texel_offset', None, None], 'none', ['none', 'texel_offset']], 148*61046927SAndroid Build Coastguard Worker 'wide_indices': [['wide_indices', None, None], 'none', ['none', 'wide_indices']], 149*61046927SAndroid Build Coastguard Worker 'write_mask' : [['write_mask', None, None], 'none', ['none', 'r', 'g', 'rg', 'b', 'rb', 'gb', 'rgb', 'a', 'ra', 'ga', 'rga', 'ba', 'rba', 'gba', 'rgba']] 150*61046927SAndroid Build Coastguard Worker } 151*61046927SAndroid Build Coastguard Worker 152*61046927SAndroid Build Coastguard Workerdef parse_instruction(ins, include_pseudo): 153*61046927SAndroid Build Coastguard Worker common = { 154*61046927SAndroid Build Coastguard Worker 'srcs': [], 155*61046927SAndroid Build Coastguard Worker 'modifiers': [], 156*61046927SAndroid Build Coastguard Worker 'immediates': [], 157*61046927SAndroid Build Coastguard Worker 'swaps': [], 158*61046927SAndroid Build Coastguard Worker 'derived': [], 159*61046927SAndroid Build Coastguard Worker 'staging': ins.attrib.get('staging', '').split('=')[0], 160*61046927SAndroid Build Coastguard Worker 'staging_count': ins.attrib.get('staging', '=0').split('=')[1], 161*61046927SAndroid Build Coastguard Worker 'dests': int(ins.attrib.get('dests', '1')), 162*61046927SAndroid Build Coastguard Worker 'variable_dests': ins.attrib.get('variable_dests', False), 163*61046927SAndroid Build Coastguard Worker 'variable_srcs': ins.attrib.get('variable_srcs', False), 164*61046927SAndroid Build Coastguard Worker 'unused': ins.attrib.get('unused', False), 165*61046927SAndroid Build Coastguard Worker 'pseudo': ins.attrib.get('pseudo', False), 166*61046927SAndroid Build Coastguard Worker 'message': ins.attrib.get('message', 'none'), 167*61046927SAndroid Build Coastguard Worker 'last': ins.attrib.get('last', False), 168*61046927SAndroid Build Coastguard Worker 'table': ins.attrib.get('table', False), 169*61046927SAndroid Build Coastguard Worker } 170*61046927SAndroid Build Coastguard Worker 171*61046927SAndroid Build Coastguard Worker if 'exact' in ins.attrib: 172*61046927SAndroid Build Coastguard Worker common['exact'] = parse_exact(ins) 173*61046927SAndroid Build Coastguard Worker 174*61046927SAndroid Build Coastguard Worker extra_modifiers=[] 175*61046927SAndroid Build Coastguard Worker src_num = 0 176*61046927SAndroid Build Coastguard Worker for src in ins.findall('src'): 177*61046927SAndroid Build Coastguard Worker if src.attrib.get('pseudo', False) and not include_pseudo: 178*61046927SAndroid Build Coastguard Worker continue 179*61046927SAndroid Build Coastguard Worker 180*61046927SAndroid Build Coastguard Worker mask = int(src.attrib['mask'], 0) if ('mask' in src.attrib) else 0xFF 181*61046927SAndroid Build Coastguard Worker if src.attrib.get('start') is not None: 182*61046927SAndroid Build Coastguard Worker common['srcs'].append([int(src.attrib['start'], 0), mask]) 183*61046927SAndroid Build Coastguard Worker else: 184*61046927SAndroid Build Coastguard Worker common['srcs'].append([src_num*3, mask]) 185*61046927SAndroid Build Coastguard Worker if src.attrib.get('absneg', False): 186*61046927SAndroid Build Coastguard Worker extra_modifiers.append([['neg'+str(src_num), '0', '1'], 'neg',['none', 'neg']]) 187*61046927SAndroid Build Coastguard Worker extra_modifiers.append([['abs'+str(src_num), '0', '1'], 'abs',['none', 'abs']]) 188*61046927SAndroid Build Coastguard Worker src_num += 1 189*61046927SAndroid Build Coastguard Worker 190*61046927SAndroid Build Coastguard Worker for imm in ins.findall('immediate'): 191*61046927SAndroid Build Coastguard Worker if imm.attrib.get('pseudo', False) and not include_pseudo: 192*61046927SAndroid Build Coastguard Worker continue 193*61046927SAndroid Build Coastguard Worker 194*61046927SAndroid Build Coastguard Worker start = int(imm.attrib['start']) if 'start' in imm.attrib else None 195*61046927SAndroid Build Coastguard Worker common['immediates'].append([imm.attrib['name'], start, int(imm.attrib['size'])]) 196*61046927SAndroid Build Coastguard Worker 197*61046927SAndroid Build Coastguard Worker # FIXME valhall ISA.xml uses <imm/> instead of <immediate/> 198*61046927SAndroid Build Coastguard Worker for imm in ins.findall('imm'): 199*61046927SAndroid Build Coastguard Worker if imm.attrib.get('pseudo', False) and not include_pseudo: 200*61046927SAndroid Build Coastguard Worker continue 201*61046927SAndroid Build Coastguard Worker 202*61046927SAndroid Build Coastguard Worker base_name = imm.attrib['name'] 203*61046927SAndroid Build Coastguard Worker name = imm.attrib.get('ir_name', base_name) 204*61046927SAndroid Build Coastguard Worker if not name: 205*61046927SAndroid Build Coastguard Worker continue 206*61046927SAndroid Build Coastguard Worker 207*61046927SAndroid Build Coastguard Worker start = int(imm.attrib['start']) if 'start' in imm.attrib else None 208*61046927SAndroid Build Coastguard Worker common['immediates'].append([name, start, int(imm.attrib['size'])]) 209*61046927SAndroid Build Coastguard Worker 210*61046927SAndroid Build Coastguard Worker staging_read = False 211*61046927SAndroid Build Coastguard Worker staging_write = False 212*61046927SAndroid Build Coastguard Worker for sr in ins.findall('sr'): 213*61046927SAndroid Build Coastguard Worker if sr.attrib.get('read', False): 214*61046927SAndroid Build Coastguard Worker staging_read = True 215*61046927SAndroid Build Coastguard Worker if sr.attrib.get('write', False): 216*61046927SAndroid Build Coastguard Worker staging_write = True 217*61046927SAndroid Build Coastguard Worker 218*61046927SAndroid Build Coastguard Worker if staging_read: 219*61046927SAndroid Build Coastguard Worker common['staging'] = 'r' 220*61046927SAndroid Build Coastguard Worker if staging_write: 221*61046927SAndroid Build Coastguard Worker common['staging'] += 'w' 222*61046927SAndroid Build Coastguard Worker for sr in ins.findall('sr_count'): 223*61046927SAndroid Build Coastguard Worker size = sr.attrib.get('count', 'sr_count') 224*61046927SAndroid Build Coastguard Worker common['staging_count'] = size 225*61046927SAndroid Build Coastguard Worker 226*61046927SAndroid Build Coastguard Worker for m in ins.findall('*'): 227*61046927SAndroid Build Coastguard Worker name = m.tag 228*61046927SAndroid Build Coastguard Worker if name == 'cmp': 229*61046927SAndroid Build Coastguard Worker if m.attrib.get('int_only', False): 230*61046927SAndroid Build Coastguard Worker name = 'cmpfi' 231*61046927SAndroid Build Coastguard Worker elif m.attrib.get('eqne_only', False): 232*61046927SAndroid Build Coastguard Worker name = 'cmpfeq' 233*61046927SAndroid Build Coastguard Worker if name == 'va_mod': 234*61046927SAndroid Build Coastguard Worker name = m.attrib.get('name', '') 235*61046927SAndroid Build Coastguard Worker if name in mod_names: 236*61046927SAndroid Build Coastguard Worker extra_modifiers.append(mod_names[name]) 237*61046927SAndroid Build Coastguard Worker 238*61046927SAndroid Build Coastguard Worker common['derived'] = parse_derived(ins) 239*61046927SAndroid Build Coastguard Worker common['modifiers'] = parse_modifiers(ins, include_pseudo) + extra_modifiers 240*61046927SAndroid Build Coastguard Worker 241*61046927SAndroid Build Coastguard Worker for swap in ins.findall('swap'): 242*61046927SAndroid Build Coastguard Worker lr = [int(swap.get('left')), int(swap.get('right'))] 243*61046927SAndroid Build Coastguard Worker cond = parse_cond(swap.findall('*')[0]) 244*61046927SAndroid Build Coastguard Worker rewrites = {} 245*61046927SAndroid Build Coastguard Worker 246*61046927SAndroid Build Coastguard Worker for rw in swap.findall('rewrite'): 247*61046927SAndroid Build Coastguard Worker mp = {} 248*61046927SAndroid Build Coastguard Worker 249*61046927SAndroid Build Coastguard Worker for m in rw.findall('map'): 250*61046927SAndroid Build Coastguard Worker mp[m.attrib['from']] = m.attrib['to'] 251*61046927SAndroid Build Coastguard Worker 252*61046927SAndroid Build Coastguard Worker rewrites[rw.attrib['name']] = mp 253*61046927SAndroid Build Coastguard Worker 254*61046927SAndroid Build Coastguard Worker common['swaps'].append([lr, cond, rewrites]) 255*61046927SAndroid Build Coastguard Worker 256*61046927SAndroid Build Coastguard Worker encodings = ins.findall('encoding') 257*61046927SAndroid Build Coastguard Worker variants = [] 258*61046927SAndroid Build Coastguard Worker 259*61046927SAndroid Build Coastguard Worker if len(encodings) == 0: 260*61046927SAndroid Build Coastguard Worker variants = [[None, common]] 261*61046927SAndroid Build Coastguard Worker else: 262*61046927SAndroid Build Coastguard Worker for enc in encodings: 263*61046927SAndroid Build Coastguard Worker variant = copy.deepcopy(common) 264*61046927SAndroid Build Coastguard Worker assert(len(variant['derived']) == 0) 265*61046927SAndroid Build Coastguard Worker 266*61046927SAndroid Build Coastguard Worker variant['exact'] = parse_exact(enc) 267*61046927SAndroid Build Coastguard Worker variant['derived'] = parse_derived(enc) 268*61046927SAndroid Build Coastguard Worker parse_copy(enc, variant['modifiers']) 269*61046927SAndroid Build Coastguard Worker 270*61046927SAndroid Build Coastguard Worker cond = parse_cond(enc.findall('*')[0]) 271*61046927SAndroid Build Coastguard Worker variants.append([cond, variant]) 272*61046927SAndroid Build Coastguard Worker 273*61046927SAndroid Build Coastguard Worker return variants 274*61046927SAndroid Build Coastguard Worker 275*61046927SAndroid Build Coastguard Workerdef ins_name(ins, group = False): 276*61046927SAndroid Build Coastguard Worker # a historical artifact: the first character of the name should contain 277*61046927SAndroid Build Coastguard Worker # a single character tag to indicate the unit: '+' for add, '*' for fma 278*61046927SAndroid Build Coastguard Worker # bifrost has only those two units, valhall has others but for those 279*61046927SAndroid Build Coastguard Worker # it doesn't matter (pretend they are '+') 280*61046927SAndroid Build Coastguard Worker if not group: 281*61046927SAndroid Build Coastguard Worker group = ins 282*61046927SAndroid Build Coastguard Worker 283*61046927SAndroid Build Coastguard Worker base_name = ins.attrib['name'] 284*61046927SAndroid Build Coastguard Worker if group.attrib['unit'] == 'fma': 285*61046927SAndroid Build Coastguard Worker tagged_name = '*' + base_name 286*61046927SAndroid Build Coastguard Worker else: 287*61046927SAndroid Build Coastguard Worker tagged_name = '+' + base_name 288*61046927SAndroid Build Coastguard Worker return tagged_name 289*61046927SAndroid Build Coastguard Worker 290*61046927SAndroid Build Coastguard Workerdef parse_instructions(xml, include_unused = False, include_pseudo = False): 291*61046927SAndroid Build Coastguard Worker final = {} 292*61046927SAndroid Build Coastguard Worker 293*61046927SAndroid Build Coastguard Worker # look at groups of instructions 294*61046927SAndroid Build Coastguard Worker groups = ET.parse(xml).getroot().findall('group') 295*61046927SAndroid Build Coastguard Worker for gr in groups: 296*61046927SAndroid Build Coastguard Worker if gr.attrib.get('unused', False) and not include_unused: 297*61046927SAndroid Build Coastguard Worker continue 298*61046927SAndroid Build Coastguard Worker if gr.attrib.get('pseudo', False) and not include_pseudo: 299*61046927SAndroid Build Coastguard Worker continue 300*61046927SAndroid Build Coastguard Worker group_base = parse_instruction(gr, include_pseudo) 301*61046927SAndroid Build Coastguard Worker for ins in gr.findall('ins'): 302*61046927SAndroid Build Coastguard Worker parsed = copy.deepcopy(group_base) 303*61046927SAndroid Build Coastguard Worker tagged_name = ins_name(ins, gr) 304*61046927SAndroid Build Coastguard Worker final[tagged_name] = parsed 305*61046927SAndroid Build Coastguard Worker 306*61046927SAndroid Build Coastguard Worker # now look at individual instructions 307*61046927SAndroid Build Coastguard Worker instructions = ET.parse(xml).getroot().findall('ins') 308*61046927SAndroid Build Coastguard Worker 309*61046927SAndroid Build Coastguard Worker for ins in instructions: 310*61046927SAndroid Build Coastguard Worker parsed = parse_instruction(ins, include_pseudo) 311*61046927SAndroid Build Coastguard Worker 312*61046927SAndroid Build Coastguard Worker # Some instructions are for useful disassembly only and can be stripped 313*61046927SAndroid Build Coastguard Worker # out of the compiler, particularly useful for release builds 314*61046927SAndroid Build Coastguard Worker if parsed[0][1]["unused"] and not include_unused: 315*61046927SAndroid Build Coastguard Worker continue 316*61046927SAndroid Build Coastguard Worker 317*61046927SAndroid Build Coastguard Worker # On the other hand, some instructions are only for the IR, not disassembly 318*61046927SAndroid Build Coastguard Worker if parsed[0][1]["pseudo"] and not include_pseudo: 319*61046927SAndroid Build Coastguard Worker continue 320*61046927SAndroid Build Coastguard Worker 321*61046927SAndroid Build Coastguard Worker tagged_name = ins_name(ins) 322*61046927SAndroid Build Coastguard Worker final[tagged_name] = parsed 323*61046927SAndroid Build Coastguard Worker 324*61046927SAndroid Build Coastguard Worker return final 325*61046927SAndroid Build Coastguard Worker 326*61046927SAndroid Build Coastguard Worker# Expand out an opcode name to something C-escaped 327*61046927SAndroid Build Coastguard Worker 328*61046927SAndroid Build Coastguard Workerdef opname_to_c(name): 329*61046927SAndroid Build Coastguard Worker return name.lower().replace('*', 'fma_').replace('+', 'add_').replace('.', '_') 330*61046927SAndroid Build Coastguard Worker 331*61046927SAndroid Build Coastguard Worker# Expand out distinct states to distrinct instructions, with a placeholder 332*61046927SAndroid Build Coastguard Worker# condition for instructions with a single state 333*61046927SAndroid Build Coastguard Worker 334*61046927SAndroid Build Coastguard Workerdef expand_states(instructions): 335*61046927SAndroid Build Coastguard Worker out = {} 336*61046927SAndroid Build Coastguard Worker 337*61046927SAndroid Build Coastguard Worker for ins in instructions: 338*61046927SAndroid Build Coastguard Worker c = instructions[ins] 339*61046927SAndroid Build Coastguard Worker 340*61046927SAndroid Build Coastguard Worker for ((test, desc), i) in zip(c, range(len(c))): 341*61046927SAndroid Build Coastguard Worker # Construct a name for the state 342*61046927SAndroid Build Coastguard Worker name = ins + (('.' + str(i)) if len(c) > 1 else '') 343*61046927SAndroid Build Coastguard Worker 344*61046927SAndroid Build Coastguard Worker out[name] = (ins, test if test is not None else [], desc) 345*61046927SAndroid Build Coastguard Worker 346*61046927SAndroid Build Coastguard Worker return out 347*61046927SAndroid Build Coastguard Worker 348*61046927SAndroid Build Coastguard Worker# Drop keys used for packing to simplify IR representation, so we can check for 349*61046927SAndroid Build Coastguard Worker# equivalence easier 350*61046927SAndroid Build Coastguard Worker 351*61046927SAndroid Build Coastguard Workerdef simplify_to_ir(ins): 352*61046927SAndroid Build Coastguard Worker return { 353*61046927SAndroid Build Coastguard Worker 'staging': ins['staging'], 354*61046927SAndroid Build Coastguard Worker 'srcs': len(ins['srcs']), 355*61046927SAndroid Build Coastguard Worker 'dests': ins['dests'], 356*61046927SAndroid Build Coastguard Worker 'variable_dests': ins['variable_dests'], 357*61046927SAndroid Build Coastguard Worker 'variable_srcs': ins['variable_srcs'], 358*61046927SAndroid Build Coastguard Worker 'modifiers': [[m[0][0], m[2]] for m in ins['modifiers']], 359*61046927SAndroid Build Coastguard Worker 'immediates': [m[0] for m in ins['immediates']] 360*61046927SAndroid Build Coastguard Worker } 361*61046927SAndroid Build Coastguard Worker 362*61046927SAndroid Build Coastguard Worker# Converstions to integers default to rounding-to-zero 363*61046927SAndroid Build Coastguard Worker# All other opcodes default to rounding to nearest even 364*61046927SAndroid Build Coastguard Workerdef default_round_to_zero(name): 365*61046927SAndroid Build Coastguard Worker # 8-bit int to float is exact 366*61046927SAndroid Build Coastguard Worker subs = ['_TO_U', '_TO_S', '_TO_V2U', '_TO_V2S', '_TO_V4U', '_TO_V4S'] 367*61046927SAndroid Build Coastguard Worker return any([x in name for x in subs]) 368*61046927SAndroid Build Coastguard Worker 369*61046927SAndroid Build Coastguard Workerdef combine_ir_variants(instructions, key): 370*61046927SAndroid Build Coastguard Worker seen = [op for op in instructions.keys() if op[1:] == key] 371*61046927SAndroid Build Coastguard Worker variant_objs = [[simplify_to_ir(Q[1]) for Q in instructions[x]] for x in seen] 372*61046927SAndroid Build Coastguard Worker variants = sum(variant_objs, []) 373*61046927SAndroid Build Coastguard Worker 374*61046927SAndroid Build Coastguard Worker # Accumulate modifiers across variants 375*61046927SAndroid Build Coastguard Worker modifiers = {} 376*61046927SAndroid Build Coastguard Worker 377*61046927SAndroid Build Coastguard Worker for s in variants[0:]: 378*61046927SAndroid Build Coastguard Worker # Check consistency 379*61046927SAndroid Build Coastguard Worker assert(s['srcs'] == variants[0]['srcs']) 380*61046927SAndroid Build Coastguard Worker assert(s['dests'] == variants[0]['dests']) 381*61046927SAndroid Build Coastguard Worker assert(s['immediates'] == variants[0]['immediates']) 382*61046927SAndroid Build Coastguard Worker assert(s['staging'] == variants[0]['staging']) 383*61046927SAndroid Build Coastguard Worker 384*61046927SAndroid Build Coastguard Worker for name, opts in s['modifiers']: 385*61046927SAndroid Build Coastguard Worker if name not in modifiers: 386*61046927SAndroid Build Coastguard Worker modifiers[name] = copy.deepcopy(opts) 387*61046927SAndroid Build Coastguard Worker else: 388*61046927SAndroid Build Coastguard Worker modifiers[name] += opts 389*61046927SAndroid Build Coastguard Worker 390*61046927SAndroid Build Coastguard Worker # Great, we've checked srcs/immediates are consistent and we've summed over 391*61046927SAndroid Build Coastguard Worker # modifiers 392*61046927SAndroid Build Coastguard Worker return { 393*61046927SAndroid Build Coastguard Worker 'key': key, 394*61046927SAndroid Build Coastguard Worker 'srcs': variants[0]['srcs'], 395*61046927SAndroid Build Coastguard Worker 'dests': variants[0]['dests'], 396*61046927SAndroid Build Coastguard Worker 'variable_dests': variants[0]['variable_dests'], 397*61046927SAndroid Build Coastguard Worker 'variable_srcs': variants[0]['variable_srcs'], 398*61046927SAndroid Build Coastguard Worker 'staging': variants[0]['staging'], 399*61046927SAndroid Build Coastguard Worker 'immediates': sorted(variants[0]['immediates']), 400*61046927SAndroid Build Coastguard Worker 'modifiers': modifiers, 401*61046927SAndroid Build Coastguard Worker 'v': len(variants), 402*61046927SAndroid Build Coastguard Worker 'ir': variants, 403*61046927SAndroid Build Coastguard Worker 'rtz': default_round_to_zero(key) 404*61046927SAndroid Build Coastguard Worker } 405*61046927SAndroid Build Coastguard Worker 406*61046927SAndroid Build Coastguard Worker# Partition instructions to mnemonics, considering units and variants 407*61046927SAndroid Build Coastguard Worker# equivalent. 408*61046927SAndroid Build Coastguard Worker 409*61046927SAndroid Build Coastguard Workerdef partition_mnemonics(instructions): 410*61046927SAndroid Build Coastguard Worker key_func = lambda x: x[1:] 411*61046927SAndroid Build Coastguard Worker sorted_instrs = sorted(instructions.keys(), key = key_func) 412*61046927SAndroid Build Coastguard Worker partitions = itertools.groupby(sorted_instrs, key_func) 413*61046927SAndroid Build Coastguard Worker return { k: combine_ir_variants(instructions, k) for k, v in partitions } 414*61046927SAndroid Build Coastguard Worker 415*61046927SAndroid Build Coastguard Worker# Generate modifier lists, by accumulating all the possible modifiers, and 416*61046927SAndroid Build Coastguard Worker# deduplicating thus assigning canonical enum values. We don't try _too_ hard 417*61046927SAndroid Build Coastguard Worker# to be clever, but by preserving as much of the original orderings as 418*61046927SAndroid Build Coastguard Worker# possible, later instruction encoding is simplified a bit. Probably a micro 419*61046927SAndroid Build Coastguard Worker# optimization but we have to pick _some_ ordering, might as well choose the 420*61046927SAndroid Build Coastguard Worker# most convenient. 421*61046927SAndroid Build Coastguard Worker# 422*61046927SAndroid Build Coastguard Worker# THIS MUST BE DETERMINISTIC 423*61046927SAndroid Build Coastguard Worker 424*61046927SAndroid Build Coastguard Workerdef order_modifiers(ir_instructions): 425*61046927SAndroid Build Coastguard Worker out = {} 426*61046927SAndroid Build Coastguard Worker 427*61046927SAndroid Build Coastguard Worker # modifier name -> (list of option strings) 428*61046927SAndroid Build Coastguard Worker modifier_lists = {} 429*61046927SAndroid Build Coastguard Worker 430*61046927SAndroid Build Coastguard Worker for ins in sorted(ir_instructions): 431*61046927SAndroid Build Coastguard Worker modifiers = ir_instructions[ins]["modifiers"] 432*61046927SAndroid Build Coastguard Worker 433*61046927SAndroid Build Coastguard Worker for name in modifiers: 434*61046927SAndroid Build Coastguard Worker name_ = name[0:-1] if name[-1] in "0123" else name 435*61046927SAndroid Build Coastguard Worker 436*61046927SAndroid Build Coastguard Worker if name_ not in modifier_lists: 437*61046927SAndroid Build Coastguard Worker modifier_lists[name_] = copy.deepcopy(modifiers[name]) 438*61046927SAndroid Build Coastguard Worker else: 439*61046927SAndroid Build Coastguard Worker modifier_lists[name_] += modifiers[name] 440*61046927SAndroid Build Coastguard Worker 441*61046927SAndroid Build Coastguard Worker for mod in modifier_lists: 442*61046927SAndroid Build Coastguard Worker lst = list(OrderedDict.fromkeys(modifier_lists[mod])) 443*61046927SAndroid Build Coastguard Worker 444*61046927SAndroid Build Coastguard Worker # Ensure none is false for booleans so the builder makes sense 445*61046927SAndroid Build Coastguard Worker if len(lst) == 2 and lst[1] == "none": 446*61046927SAndroid Build Coastguard Worker lst.reverse() 447*61046927SAndroid Build Coastguard Worker elif mod == "table": 448*61046927SAndroid Build Coastguard Worker # We really need a zero sentinel to materialize DTSEL 449*61046927SAndroid Build Coastguard Worker assert(lst[2] == "none") 450*61046927SAndroid Build Coastguard Worker lst[2] = lst[0] 451*61046927SAndroid Build Coastguard Worker lst[0] = "none" 452*61046927SAndroid Build Coastguard Worker 453*61046927SAndroid Build Coastguard Worker out[mod] = lst 454*61046927SAndroid Build Coastguard Worker 455*61046927SAndroid Build Coastguard Worker return out 456*61046927SAndroid Build Coastguard Worker 457*61046927SAndroid Build Coastguard Worker# Count sources for a simplified (IR) instruction, including a source for a 458*61046927SAndroid Build Coastguard Worker# staging register if necessary 459*61046927SAndroid Build Coastguard Workerdef src_count(op): 460*61046927SAndroid Build Coastguard Worker staging = 1 if (op["staging"] in ["r", "rw"]) else 0 461*61046927SAndroid Build Coastguard Worker return op["srcs"] + staging 462*61046927SAndroid Build Coastguard Worker 463*61046927SAndroid Build Coastguard Worker# Parses out the size part of an opocde name 464*61046927SAndroid Build Coastguard Workerdef typesize(opcode): 465*61046927SAndroid Build Coastguard Worker if opcode[-3:] == '128': 466*61046927SAndroid Build Coastguard Worker return 128 467*61046927SAndroid Build Coastguard Worker if opcode[-2:] == '48': 468*61046927SAndroid Build Coastguard Worker return 48 469*61046927SAndroid Build Coastguard Worker elif opcode[-1] == '8': 470*61046927SAndroid Build Coastguard Worker return 8 471*61046927SAndroid Build Coastguard Worker else: 472*61046927SAndroid Build Coastguard Worker try: 473*61046927SAndroid Build Coastguard Worker return int(opcode[-2:]) 474*61046927SAndroid Build Coastguard Worker except: 475*61046927SAndroid Build Coastguard Worker return 32 476