1*61046927SAndroid Build Coastguard Worker#encoding=utf-8 2*61046927SAndroid Build Coastguard Worker 3*61046927SAndroid Build Coastguard Worker# Copyright (C) 2016 Intel Corporation 4*61046927SAndroid Build Coastguard Worker# Copyright (C) 2016 Broadcom 5*61046927SAndroid Build Coastguard Worker# Copyright (C) 2020 Collabora, Ltd. 6*61046927SAndroid Build Coastguard Worker# 7*61046927SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a 8*61046927SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the "Software"), 9*61046927SAndroid Build Coastguard Worker# to deal in the Software without restriction, including without limitation 10*61046927SAndroid Build Coastguard Worker# the rights to use, copy, modify, merge, publish, distribute, sublicense, 11*61046927SAndroid Build Coastguard Worker# and/or sell copies of the Software, and to permit persons to whom the 12*61046927SAndroid Build Coastguard Worker# Software is furnished to do so, subject to the following conditions: 13*61046927SAndroid Build Coastguard Worker# 14*61046927SAndroid Build Coastguard Worker# The above copyright notice and this permission notice (including the next 15*61046927SAndroid Build Coastguard Worker# paragraph) shall be included in all copies or substantial portions of the 16*61046927SAndroid Build Coastguard Worker# Software. 17*61046927SAndroid Build Coastguard Worker# 18*61046927SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19*61046927SAndroid Build Coastguard Worker# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20*61046927SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21*61046927SAndroid Build Coastguard Worker# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22*61046927SAndroid Build Coastguard Worker# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23*61046927SAndroid Build Coastguard Worker# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24*61046927SAndroid Build Coastguard Worker# IN THE SOFTWARE. 25*61046927SAndroid Build Coastguard Worker 26*61046927SAndroid Build Coastguard Workerimport os 27*61046927SAndroid Build Coastguard Workerimport textwrap 28*61046927SAndroid Build Coastguard Workerimport xml.etree.ElementTree as ET 29*61046927SAndroid Build Coastguard Workerimport sys 30*61046927SAndroid Build Coastguard Worker 31*61046927SAndroid Build Coastguard Worker# All instructions in the ISA 32*61046927SAndroid Build Coastguard Workerinstructions = [] 33*61046927SAndroid Build Coastguard Worker 34*61046927SAndroid Build Coastguard WorkerMODIFIERS = {} 35*61046927SAndroid Build Coastguard Workerenums = {} 36*61046927SAndroid Build Coastguard Workerimmediates = [] 37*61046927SAndroid Build Coastguard Worker 38*61046927SAndroid Build Coastguard Workerdef xmlbool(s): 39*61046927SAndroid Build Coastguard Worker assert(s.lower() in ["false", "true"]) 40*61046927SAndroid Build Coastguard Worker return False if s.lower() == "false" else True 41*61046927SAndroid Build Coastguard Worker 42*61046927SAndroid Build Coastguard Workerclass EnumValue: 43*61046927SAndroid Build Coastguard Worker def __init__(self, value, default): 44*61046927SAndroid Build Coastguard Worker self.value = value 45*61046927SAndroid Build Coastguard Worker self.default = default 46*61046927SAndroid Build Coastguard Worker 47*61046927SAndroid Build Coastguard Workerclass Enum: 48*61046927SAndroid Build Coastguard Worker def __init__(self, name, values): 49*61046927SAndroid Build Coastguard Worker self.name = name 50*61046927SAndroid Build Coastguard Worker self.values = values 51*61046927SAndroid Build Coastguard Worker self.bare_values = [x.value for x in values] 52*61046927SAndroid Build Coastguard Worker 53*61046927SAndroid Build Coastguard Worker defaults = [x.value for x in values if x.default] 54*61046927SAndroid Build Coastguard Worker if len(defaults) > 0: 55*61046927SAndroid Build Coastguard Worker assert(len(defaults) == 1) 56*61046927SAndroid Build Coastguard Worker self.default = defaults[0] 57*61046927SAndroid Build Coastguard Worker 58*61046927SAndroid Build Coastguard Workerdef build_enum(el): 59*61046927SAndroid Build Coastguard Worker values = [] 60*61046927SAndroid Build Coastguard Worker 61*61046927SAndroid Build Coastguard Worker for child in el: 62*61046927SAndroid Build Coastguard Worker if child.tag == 'value': 63*61046927SAndroid Build Coastguard Worker is_default = child.attrib.get('default', False) 64*61046927SAndroid Build Coastguard Worker values.append(EnumValue(child.text, is_default)) 65*61046927SAndroid Build Coastguard Worker elif child.tag == 'reserved': 66*61046927SAndroid Build Coastguard Worker values.append(EnumValue("reserved", False)) 67*61046927SAndroid Build Coastguard Worker 68*61046927SAndroid Build Coastguard Worker return Enum(el.attrib['name'], values) 69*61046927SAndroid Build Coastguard Worker 70*61046927SAndroid Build Coastguard Workerclass Modifier: 71*61046927SAndroid Build Coastguard Worker def __init__(self, name, start, size, implied = False, force_enum = None): 72*61046927SAndroid Build Coastguard Worker self.name = name 73*61046927SAndroid Build Coastguard Worker self.start = start 74*61046927SAndroid Build Coastguard Worker self.size = size 75*61046927SAndroid Build Coastguard Worker self.implied = implied 76*61046927SAndroid Build Coastguard Worker self.is_enum = (force_enum is not None) or size > 1 77*61046927SAndroid Build Coastguard Worker self.enum = force_enum or name 78*61046927SAndroid Build Coastguard Worker 79*61046927SAndroid Build Coastguard Worker if not self.is_enum: 80*61046927SAndroid Build Coastguard Worker self.bare_values = ['', name] 81*61046927SAndroid Build Coastguard Worker self.default = 0 82*61046927SAndroid Build Coastguard Worker else: 83*61046927SAndroid Build Coastguard Worker self.bare_values = [x.value for x in enums[self.enum].values] 84*61046927SAndroid Build Coastguard Worker defaults = [x for x in enums[self.enum].values if x.default] 85*61046927SAndroid Build Coastguard Worker assert(len(defaults) <= 1) 86*61046927SAndroid Build Coastguard Worker 87*61046927SAndroid Build Coastguard Worker if len(defaults) > 0: 88*61046927SAndroid Build Coastguard Worker self.default = self.bare_values.index(defaults[0].value) 89*61046927SAndroid Build Coastguard Worker else: 90*61046927SAndroid Build Coastguard Worker self.default = None 91*61046927SAndroid Build Coastguard Worker 92*61046927SAndroid Build Coastguard Workerdef Flag(name, start): 93*61046927SAndroid Build Coastguard Worker return Modifier(name, start, 1) 94*61046927SAndroid Build Coastguard Worker 95*61046927SAndroid Build Coastguard Worker# Model a single instruction 96*61046927SAndroid Build Coastguard Workerclass Source: 97*61046927SAndroid Build Coastguard Worker def __init__(self, index, size, is_float = False, swizzle = False, 98*61046927SAndroid Build Coastguard Worker halfswizzle = False, widen = False, lanes = False, combine = False, lane = None, absneg = False, notted = False, name = ""): 99*61046927SAndroid Build Coastguard Worker self.is_float = is_float or absneg 100*61046927SAndroid Build Coastguard Worker self.start = (index * 8) 101*61046927SAndroid Build Coastguard Worker self.size = size 102*61046927SAndroid Build Coastguard Worker self.absneg = absneg 103*61046927SAndroid Build Coastguard Worker self.notted = notted 104*61046927SAndroid Build Coastguard Worker self.swizzle = swizzle 105*61046927SAndroid Build Coastguard Worker self.halfswizzle = halfswizzle 106*61046927SAndroid Build Coastguard Worker self.widen = widen 107*61046927SAndroid Build Coastguard Worker self.lanes = lanes 108*61046927SAndroid Build Coastguard Worker self.lane = lane 109*61046927SAndroid Build Coastguard Worker self.combine = combine 110*61046927SAndroid Build Coastguard Worker self.name = name 111*61046927SAndroid Build Coastguard Worker 112*61046927SAndroid Build Coastguard Worker self.offset = {} 113*61046927SAndroid Build Coastguard Worker self.bits = {} 114*61046927SAndroid Build Coastguard Worker if absneg: 115*61046927SAndroid Build Coastguard Worker self.offset['neg'] = 32 + 2 + ((2 - index) * 2) 116*61046927SAndroid Build Coastguard Worker self.offset['abs'] = 33 + 2 + ((2 - index) * 2) 117*61046927SAndroid Build Coastguard Worker self.bits['neg'] = 1 118*61046927SAndroid Build Coastguard Worker self.bits['abs'] = 1 119*61046927SAndroid Build Coastguard Worker if notted: 120*61046927SAndroid Build Coastguard Worker self.offset['not'] = 35 121*61046927SAndroid Build Coastguard Worker self.bits['not'] = 1 122*61046927SAndroid Build Coastguard Worker if widen or lanes or halfswizzle: 123*61046927SAndroid Build Coastguard Worker self.offset['widen'] = 26 if index == 1 else 36 124*61046927SAndroid Build Coastguard Worker self.bits['widen'] = 4 # XXX: too much? 125*61046927SAndroid Build Coastguard Worker if lane: 126*61046927SAndroid Build Coastguard Worker self.offset['lane'] = self.lane 127*61046927SAndroid Build Coastguard Worker self.bits['lane'] = 2 if size in (8, 32) else 1 128*61046927SAndroid Build Coastguard Worker if swizzle: 129*61046927SAndroid Build Coastguard Worker assert(size in [16, 32]) 130*61046927SAndroid Build Coastguard Worker self.offset['swizzle'] = 24 + ((2 - index) * 2) 131*61046927SAndroid Build Coastguard Worker self.bits['swizzle'] = 2 132*61046927SAndroid Build Coastguard Worker if combine: 133*61046927SAndroid Build Coastguard Worker self.offset['combine'] = 37 134*61046927SAndroid Build Coastguard Worker self.bits['combine'] = 3 135*61046927SAndroid Build Coastguard Worker 136*61046927SAndroid Build Coastguard Workerclass Dest: 137*61046927SAndroid Build Coastguard Worker def __init__(self, name = ""): 138*61046927SAndroid Build Coastguard Worker self.name = name 139*61046927SAndroid Build Coastguard Worker 140*61046927SAndroid Build Coastguard Workerclass Staging: 141*61046927SAndroid Build Coastguard Worker def __init__(self, read = False, write = False, count = 0, flags = 'true', name = ""): 142*61046927SAndroid Build Coastguard Worker self.name = name 143*61046927SAndroid Build Coastguard Worker self.read = read 144*61046927SAndroid Build Coastguard Worker self.write = write 145*61046927SAndroid Build Coastguard Worker self.count = count 146*61046927SAndroid Build Coastguard Worker self.flags = (flags != 'false') 147*61046927SAndroid Build Coastguard Worker self.start = 40 148*61046927SAndroid Build Coastguard Worker 149*61046927SAndroid Build Coastguard Worker if write and not self.flags: 150*61046927SAndroid Build Coastguard Worker self.start = 16 151*61046927SAndroid Build Coastguard Worker 152*61046927SAndroid Build Coastguard Worker # For compatibility 153*61046927SAndroid Build Coastguard Worker self.absneg = False 154*61046927SAndroid Build Coastguard Worker self.swizzle = False 155*61046927SAndroid Build Coastguard Worker self.notted = False 156*61046927SAndroid Build Coastguard Worker self.widen = False 157*61046927SAndroid Build Coastguard Worker self.lanes = False 158*61046927SAndroid Build Coastguard Worker self.lane = False 159*61046927SAndroid Build Coastguard Worker self.halfswizzle = False 160*61046927SAndroid Build Coastguard Worker self.combine = False 161*61046927SAndroid Build Coastguard Worker self.size = 32 162*61046927SAndroid Build Coastguard Worker 163*61046927SAndroid Build Coastguard Worker if not self.flags: 164*61046927SAndroid Build Coastguard Worker self.encoded_flags = 0 165*61046927SAndroid Build Coastguard Worker elif flags == 'rw': 166*61046927SAndroid Build Coastguard Worker self.encoded_flags = 0xc0 167*61046927SAndroid Build Coastguard Worker else: 168*61046927SAndroid Build Coastguard Worker assert(flags == 'true') 169*61046927SAndroid Build Coastguard Worker self.encoded_flags = (0x80 if write else 0) | (0x40 if read else 0) 170*61046927SAndroid Build Coastguard Worker 171*61046927SAndroid Build Coastguard Workerclass Immediate: 172*61046927SAndroid Build Coastguard Worker def __init__(self, name, start, size, signed): 173*61046927SAndroid Build Coastguard Worker self.name = name 174*61046927SAndroid Build Coastguard Worker self.start = start 175*61046927SAndroid Build Coastguard Worker self.size = size 176*61046927SAndroid Build Coastguard Worker self.signed = signed 177*61046927SAndroid Build Coastguard Worker 178*61046927SAndroid Build Coastguard Workerclass Instruction: 179*61046927SAndroid Build Coastguard Worker def __init__(self, name, opcode, opcode2, srcs = [], dests = [], immediates = [], modifiers = [], staging = None, unit = None): 180*61046927SAndroid Build Coastguard Worker self.name = name 181*61046927SAndroid Build Coastguard Worker self.srcs = srcs 182*61046927SAndroid Build Coastguard Worker self.dests = dests 183*61046927SAndroid Build Coastguard Worker self.opcode = opcode 184*61046927SAndroid Build Coastguard Worker self.opcode2 = opcode2 or 0 185*61046927SAndroid Build Coastguard Worker self.immediates = immediates 186*61046927SAndroid Build Coastguard Worker self.modifiers = modifiers 187*61046927SAndroid Build Coastguard Worker self.staging = staging 188*61046927SAndroid Build Coastguard Worker self.unit = unit 189*61046927SAndroid Build Coastguard Worker self.is_signed = len(name.split(".")) > 1 and ('s' in name.split(".")[1]) 190*61046927SAndroid Build Coastguard Worker 191*61046927SAndroid Build Coastguard Worker # Message-passing instruction <===> not ALU instruction 192*61046927SAndroid Build Coastguard Worker self.message = unit not in ["FMA", "CVT", "SFU"] 193*61046927SAndroid Build Coastguard Worker 194*61046927SAndroid Build Coastguard Worker self.secondary_shift = max(len(self.srcs) * 8, 16) 195*61046927SAndroid Build Coastguard Worker self.secondary_mask = 0xF if opcode2 is not None else 0x0 196*61046927SAndroid Build Coastguard Worker if "left" in [x.name for x in self.modifiers]: 197*61046927SAndroid Build Coastguard Worker self.secondary_mask |= 0x100 198*61046927SAndroid Build Coastguard Worker if len(srcs) == 3 and (srcs[1].widen or srcs[1].lanes or srcs[1].swizzle): 199*61046927SAndroid Build Coastguard Worker self.secondary_mask &= ~0xC # conflicts 200*61046927SAndroid Build Coastguard Worker if opcode == 0x90: 201*61046927SAndroid Build Coastguard Worker # XXX: XMLify this, but disambiguates sign of conversions 202*61046927SAndroid Build Coastguard Worker self.secondary_mask |= 0x10 203*61046927SAndroid Build Coastguard Worker if name.startswith("LOAD.i") or name.startswith("STORE.i") or name.startswith("LD_BUFFER.i"): 204*61046927SAndroid Build Coastguard Worker self.secondary_shift = 27 # Alias with memory_size 205*61046927SAndroid Build Coastguard Worker self.secondary_mask = 0x7 206*61046927SAndroid Build Coastguard Worker if "descriptor_type" in [x.name for x in self.modifiers]: 207*61046927SAndroid Build Coastguard Worker self.secondary_mask = 0x3 208*61046927SAndroid Build Coastguard Worker self.secondary_shift = 37 209*61046927SAndroid Build Coastguard Worker elif "memory_width" in [x.name for x in self.modifiers]: 210*61046927SAndroid Build Coastguard Worker self.secondary_mask = 0x7 211*61046927SAndroid Build Coastguard Worker self.secondary_shift = 27 212*61046927SAndroid Build Coastguard Worker 213*61046927SAndroid Build Coastguard Worker assert(len(dests) == 0 or not staging) 214*61046927SAndroid Build Coastguard Worker assert(not opcode2 or (opcode2 & self.secondary_mask) == opcode2) 215*61046927SAndroid Build Coastguard Worker 216*61046927SAndroid Build Coastguard Worker def __str__(self): 217*61046927SAndroid Build Coastguard Worker return self.name 218*61046927SAndroid Build Coastguard Worker 219*61046927SAndroid Build Coastguard Worker# Build a single source from XML 220*61046927SAndroid Build Coastguard Workerdef build_source(el, i, size): 221*61046927SAndroid Build Coastguard Worker lane = el.get('lane', None) 222*61046927SAndroid Build Coastguard Worker if lane == "true": 223*61046927SAndroid Build Coastguard Worker lane = 38 if i == 0 else 36 224*61046927SAndroid Build Coastguard Worker elif lane is not None: 225*61046927SAndroid Build Coastguard Worker lane = int(lane) 226*61046927SAndroid Build Coastguard Worker 227*61046927SAndroid Build Coastguard Worker return Source(i, int(el.get('size', size)), 228*61046927SAndroid Build Coastguard Worker absneg = el.get('absneg', False), 229*61046927SAndroid Build Coastguard Worker is_float = el.get('float', False), 230*61046927SAndroid Build Coastguard Worker swizzle = el.get('swizzle', False), 231*61046927SAndroid Build Coastguard Worker halfswizzle = el.get('halfswizzle', False), 232*61046927SAndroid Build Coastguard Worker widen = el.get('widen', False), 233*61046927SAndroid Build Coastguard Worker lanes = el.get('lanes', False), 234*61046927SAndroid Build Coastguard Worker combine = el.get('combine', False), 235*61046927SAndroid Build Coastguard Worker lane = lane, 236*61046927SAndroid Build Coastguard Worker notted = el.get('not', False), 237*61046927SAndroid Build Coastguard Worker name = el.text or "") 238*61046927SAndroid Build Coastguard Worker 239*61046927SAndroid Build Coastguard Workerdef build_imm(el): 240*61046927SAndroid Build Coastguard Worker return Immediate(el.attrib['name'], int(el.attrib['start']), 241*61046927SAndroid Build Coastguard Worker int(el.attrib['size']), bool(el.attrib.get('signed', False))) 242*61046927SAndroid Build Coastguard Worker 243*61046927SAndroid Build Coastguard Workerdef build_staging(i, el): 244*61046927SAndroid Build Coastguard Worker r = xmlbool(el.attrib.get('read', 'false')) 245*61046927SAndroid Build Coastguard Worker w = xmlbool(el.attrib.get('write', 'false')) 246*61046927SAndroid Build Coastguard Worker count = int(el.attrib.get('count', '0')) 247*61046927SAndroid Build Coastguard Worker flags = el.attrib.get('flags', 'true') 248*61046927SAndroid Build Coastguard Worker 249*61046927SAndroid Build Coastguard Worker return Staging(r, w, count, flags, el.text or '') 250*61046927SAndroid Build Coastguard Worker 251*61046927SAndroid Build Coastguard Workerdef build_modifier(el): 252*61046927SAndroid Build Coastguard Worker name = el.attrib['name'] 253*61046927SAndroid Build Coastguard Worker start = int(el.attrib['start']) 254*61046927SAndroid Build Coastguard Worker size = int(el.attrib['size']) 255*61046927SAndroid Build Coastguard Worker implied = xmlbool(el.get('implied', 'false')) 256*61046927SAndroid Build Coastguard Worker 257*61046927SAndroid Build Coastguard Worker return Modifier(name, start, size, implied) 258*61046927SAndroid Build Coastguard Worker 259*61046927SAndroid Build Coastguard Worker# Build a single instruction from XML and group based overrides 260*61046927SAndroid Build Coastguard Workerdef build_instr(el, overrides = {}): 261*61046927SAndroid Build Coastguard Worker # Get overridables 262*61046927SAndroid Build Coastguard Worker name = overrides.get('name') or el.attrib.get('name') 263*61046927SAndroid Build Coastguard Worker opcode = overrides.get('opcode') or el.attrib.get('opcode') 264*61046927SAndroid Build Coastguard Worker opcode2 = overrides.get('opcode2') or el.attrib.get('opcode2') 265*61046927SAndroid Build Coastguard Worker unit = overrides.get('unit') or el.attrib.get('unit') 266*61046927SAndroid Build Coastguard Worker opcode = int(opcode, base=0) 267*61046927SAndroid Build Coastguard Worker opcode2 = int(opcode2, base=0) if opcode2 else None 268*61046927SAndroid Build Coastguard Worker 269*61046927SAndroid Build Coastguard Worker # Get explicit sources/dests 270*61046927SAndroid Build Coastguard Worker tsize = typesize(name) 271*61046927SAndroid Build Coastguard Worker sources = [] 272*61046927SAndroid Build Coastguard Worker i = 0 273*61046927SAndroid Build Coastguard Worker 274*61046927SAndroid Build Coastguard Worker for src in el.findall('src'): 275*61046927SAndroid Build Coastguard Worker if (src.attrib.get('pseudo', False)): 276*61046927SAndroid Build Coastguard Worker continue 277*61046927SAndroid Build Coastguard Worker built = build_source(src, i, tsize) 278*61046927SAndroid Build Coastguard Worker sources += [built] 279*61046927SAndroid Build Coastguard Worker 280*61046927SAndroid Build Coastguard Worker # 64-bit sources in a 32-bit (message) instruction count as two slots 281*61046927SAndroid Build Coastguard Worker # Affects BLEND, ST_CVT 282*61046927SAndroid Build Coastguard Worker if tsize != 64 and built.size == 64: 283*61046927SAndroid Build Coastguard Worker i = i + 2 284*61046927SAndroid Build Coastguard Worker else: 285*61046927SAndroid Build Coastguard Worker i = i + 1 286*61046927SAndroid Build Coastguard Worker 287*61046927SAndroid Build Coastguard Worker dests = [Dest(dest.text or '') for dest in el.findall('dest')] 288*61046927SAndroid Build Coastguard Worker 289*61046927SAndroid Build Coastguard Worker # Get implicit ones 290*61046927SAndroid Build Coastguard Worker sources = sources + ([Source(i, int(tsize)) for i in range(int(el.attrib.get('srcs', 0)))]) 291*61046927SAndroid Build Coastguard Worker dests = dests + ([Dest()] * int(el.attrib.get('dests', 0))) 292*61046927SAndroid Build Coastguard Worker 293*61046927SAndroid Build Coastguard Worker # Get staging registers 294*61046927SAndroid Build Coastguard Worker staging = [build_staging(i, el) for i, el in enumerate(el.findall('sr'))] 295*61046927SAndroid Build Coastguard Worker 296*61046927SAndroid Build Coastguard Worker # Get immediates 297*61046927SAndroid Build Coastguard Worker imms = [build_imm(imm) for imm in el.findall('imm')] 298*61046927SAndroid Build Coastguard Worker 299*61046927SAndroid Build Coastguard Worker modifiers = [] 300*61046927SAndroid Build Coastguard Worker for mod in el: 301*61046927SAndroid Build Coastguard Worker if (mod.tag in MODIFIERS) and not (mod.attrib.get('pseudo', False)): 302*61046927SAndroid Build Coastguard Worker modifiers.append(MODIFIERS[mod.tag]) 303*61046927SAndroid Build Coastguard Worker elif mod.tag =='va_mod': 304*61046927SAndroid Build Coastguard Worker modifiers.append(build_modifier(mod)) 305*61046927SAndroid Build Coastguard Worker 306*61046927SAndroid Build Coastguard Worker instr = Instruction(name, opcode, opcode2, srcs = sources, dests = dests, immediates = imms, modifiers = modifiers, staging = staging, unit = unit) 307*61046927SAndroid Build Coastguard Worker 308*61046927SAndroid Build Coastguard Worker instructions.append(instr) 309*61046927SAndroid Build Coastguard Worker 310*61046927SAndroid Build Coastguard Worker# Build all the instructions in a group by duplicating the group itself with 311*61046927SAndroid Build Coastguard Worker# overrides for each distinct instruction 312*61046927SAndroid Build Coastguard Workerdef build_group(el): 313*61046927SAndroid Build Coastguard Worker for ins in el.findall('ins'): 314*61046927SAndroid Build Coastguard Worker build_instr(el, overrides = { 315*61046927SAndroid Build Coastguard Worker 'name': ins.attrib['name'], 316*61046927SAndroid Build Coastguard Worker 'opcode': ins.attrib.get('opcode'), 317*61046927SAndroid Build Coastguard Worker 'opcode2': ins.attrib.get('opcode2'), 318*61046927SAndroid Build Coastguard Worker 'unit': ins.attrib.get('unit'), 319*61046927SAndroid Build Coastguard Worker }) 320*61046927SAndroid Build Coastguard Worker 321*61046927SAndroid Build Coastguard Workerdef to_alphanum(name): 322*61046927SAndroid Build Coastguard Worker substitutions = { 323*61046927SAndroid Build Coastguard Worker ' ': '_', 324*61046927SAndroid Build Coastguard Worker '/': '_', 325*61046927SAndroid Build Coastguard Worker '[': '', 326*61046927SAndroid Build Coastguard Worker ']': '', 327*61046927SAndroid Build Coastguard Worker '(': '', 328*61046927SAndroid Build Coastguard Worker ')': '', 329*61046927SAndroid Build Coastguard Worker '-': '_', 330*61046927SAndroid Build Coastguard Worker ':': '', 331*61046927SAndroid Build Coastguard Worker '.': '', 332*61046927SAndroid Build Coastguard Worker ',': '', 333*61046927SAndroid Build Coastguard Worker '=': '', 334*61046927SAndroid Build Coastguard Worker '>': '', 335*61046927SAndroid Build Coastguard Worker '#': '', 336*61046927SAndroid Build Coastguard Worker '&': '', 337*61046927SAndroid Build Coastguard Worker '*': '', 338*61046927SAndroid Build Coastguard Worker '"': '', 339*61046927SAndroid Build Coastguard Worker '+': '', 340*61046927SAndroid Build Coastguard Worker '\'': '', 341*61046927SAndroid Build Coastguard Worker } 342*61046927SAndroid Build Coastguard Worker 343*61046927SAndroid Build Coastguard Worker for i, j in substitutions.items(): 344*61046927SAndroid Build Coastguard Worker name = name.replace(i, j) 345*61046927SAndroid Build Coastguard Worker 346*61046927SAndroid Build Coastguard Worker return name 347*61046927SAndroid Build Coastguard Worker 348*61046927SAndroid Build Coastguard Workerdef safe_name(name): 349*61046927SAndroid Build Coastguard Worker name = to_alphanum(name) 350*61046927SAndroid Build Coastguard Worker if not name[0].isalpha(): 351*61046927SAndroid Build Coastguard Worker name = '_' + name 352*61046927SAndroid Build Coastguard Worker 353*61046927SAndroid Build Coastguard Worker return name.lower() 354*61046927SAndroid Build Coastguard Worker 355*61046927SAndroid Build Coastguard Worker# Parses out the size part of an opcode name 356*61046927SAndroid Build Coastguard Workerdef typesize(opcode): 357*61046927SAndroid Build Coastguard Worker if opcode[-3:] == '128': 358*61046927SAndroid Build Coastguard Worker return 128 359*61046927SAndroid Build Coastguard Worker if opcode[-2:] == '48': 360*61046927SAndroid Build Coastguard Worker return 48 361*61046927SAndroid Build Coastguard Worker elif opcode[-1] == '8': 362*61046927SAndroid Build Coastguard Worker return 8 363*61046927SAndroid Build Coastguard Worker else: 364*61046927SAndroid Build Coastguard Worker try: 365*61046927SAndroid Build Coastguard Worker return int(opcode[-2:]) 366*61046927SAndroid Build Coastguard Worker except: 367*61046927SAndroid Build Coastguard Worker return 32 368*61046927SAndroid Build Coastguard Worker 369*61046927SAndroid Build Coastguard Worker# Parse the ISA 370*61046927SAndroid Build Coastguard Workerdef valhall_parse_isa(xmlfile = False): 371*61046927SAndroid Build Coastguard Worker global MODIFIERS 372*61046927SAndroid Build Coastguard Worker global enums 373*61046927SAndroid Build Coastguard Worker global immediates 374*61046927SAndroid Build Coastguard Worker global root 375*61046927SAndroid Build Coastguard Worker 376*61046927SAndroid Build Coastguard Worker xmlfile = os.path.join(os.path.dirname(__file__), 'ISA.xml') 377*61046927SAndroid Build Coastguard Worker tree = ET.parse(xmlfile) 378*61046927SAndroid Build Coastguard Worker root = tree.getroot() 379*61046927SAndroid Build Coastguard Worker 380*61046927SAndroid Build Coastguard Worker # All immediates in the ISA 381*61046927SAndroid Build Coastguard Worker ilut = root.findall('lut')[0] 382*61046927SAndroid Build Coastguard Worker assert(ilut.attrib['name'] == "Immediates") 383*61046927SAndroid Build Coastguard Worker immediates = [int(imm.text, base=0) for imm in ilut.findall('constant')] 384*61046927SAndroid Build Coastguard Worker 385*61046927SAndroid Build Coastguard Worker for child in root.findall('enum'): 386*61046927SAndroid Build Coastguard Worker enums[safe_name(child.attrib['name'])] = build_enum(child) 387*61046927SAndroid Build Coastguard Worker 388*61046927SAndroid Build Coastguard Worker MODIFIERS = { 389*61046927SAndroid Build Coastguard Worker # Texture instructions share a common encoding 390*61046927SAndroid Build Coastguard Worker "wide_indices": Flag("wide_indices", 8), 391*61046927SAndroid Build Coastguard Worker "array_enable": Flag("array_enable", 10), 392*61046927SAndroid Build Coastguard Worker "texel_offset": Flag("texel_offset", 11), 393*61046927SAndroid Build Coastguard Worker "shadow": Flag("shadow", 12), 394*61046927SAndroid Build Coastguard Worker "integer_coordinates": Flag("integer_coordinates", 13), 395*61046927SAndroid Build Coastguard Worker "fetch_component": Modifier("fetch_component", 14, 2), 396*61046927SAndroid Build Coastguard Worker "lod_mode": Modifier("lod_mode", 13, 3), 397*61046927SAndroid Build Coastguard Worker "lod_bias_disable": Modifier("lod_mode", 13, 1), 398*61046927SAndroid Build Coastguard Worker "lod_clamp_disable": Modifier("lod_mode", 14, 1), 399*61046927SAndroid Build Coastguard Worker "write_mask": Modifier("write_mask", 22, 4), 400*61046927SAndroid Build Coastguard Worker "register_type": Modifier("register_type", 26, 2), 401*61046927SAndroid Build Coastguard Worker "dimension": Modifier("dimension", 28, 2), 402*61046927SAndroid Build Coastguard Worker "skip": Flag("skip", 39), 403*61046927SAndroid Build Coastguard Worker "register_width": Modifier("register_width", 46, 1, force_enum = "register_width"), 404*61046927SAndroid Build Coastguard Worker "secondary_register_width": Modifier("secondary_register_width", 47, 1, force_enum = "register_width"), 405*61046927SAndroid Build Coastguard Worker "vartex_register_width": Modifier("varying_texture_register_width", 24, 2), 406*61046927SAndroid Build Coastguard Worker 407*61046927SAndroid Build Coastguard Worker "atom_opc": Modifier("atomic_operation", 22, 4), 408*61046927SAndroid Build Coastguard Worker "atom_opc_1": Modifier("atomic_operation_with_1", 22, 4), 409*61046927SAndroid Build Coastguard Worker "inactive_result": Modifier("inactive_result", 22, 4), 410*61046927SAndroid Build Coastguard Worker "memory_access": Modifier("memory_access", 24, 2), 411*61046927SAndroid Build Coastguard Worker "regfmt": Modifier("register_format", 24, 3), 412*61046927SAndroid Build Coastguard Worker "source_format": Modifier("source_format", 24, 4), 413*61046927SAndroid Build Coastguard Worker "vecsize": Modifier("vector_size", 28, 2), 414*61046927SAndroid Build Coastguard Worker 415*61046927SAndroid Build Coastguard Worker "slot": Modifier("slot", 30, 3), 416*61046927SAndroid Build Coastguard Worker "roundmode": Modifier("round_mode", 30, 2), 417*61046927SAndroid Build Coastguard Worker "result_type": Modifier("result_type", 30, 2), 418*61046927SAndroid Build Coastguard Worker "saturate": Flag("saturate", 30), 419*61046927SAndroid Build Coastguard Worker "not_result": Flag("not_result", 30), 420*61046927SAndroid Build Coastguard Worker 421*61046927SAndroid Build Coastguard Worker "lane_op": Modifier("lane_operation", 32, 2), 422*61046927SAndroid Build Coastguard Worker "cmp": Modifier("condition", 32, 3), 423*61046927SAndroid Build Coastguard Worker "clamp": Modifier("clamp", 32, 2), 424*61046927SAndroid Build Coastguard Worker "sr_count": Modifier("staging_register_count", 33, 3, implied = True), 425*61046927SAndroid Build Coastguard Worker "sample_and_update": Modifier("sample_and_update_mode", 33, 3), 426*61046927SAndroid Build Coastguard Worker "sr_write_count": Modifier("staging_register_write_count", 36, 3, implied = True), 427*61046927SAndroid Build Coastguard Worker 428*61046927SAndroid Build Coastguard Worker "conservative": Flag("conservative", 35), 429*61046927SAndroid Build Coastguard Worker "subgroup": Modifier("subgroup_size", 36, 4), 430*61046927SAndroid Build Coastguard Worker "update": Modifier("update_mode", 36, 2), 431*61046927SAndroid Build Coastguard Worker "sample": Modifier("sample_mode", 38, 2), 432*61046927SAndroid Build Coastguard Worker } 433*61046927SAndroid Build Coastguard Worker 434*61046927SAndroid Build Coastguard Worker for child in root: 435*61046927SAndroid Build Coastguard Worker if child.tag == 'group': 436*61046927SAndroid Build Coastguard Worker build_group(child) 437*61046927SAndroid Build Coastguard Worker elif child.tag == 'ins': 438*61046927SAndroid Build Coastguard Worker build_instr(child) 439*61046927SAndroid Build Coastguard Worker 440*61046927SAndroid Build Coastguard Worker instruction_dict = { ins.name: ins for ins in instructions } 441*61046927SAndroid Build Coastguard Worker 442*61046927SAndroid Build Coastguard Worker # Validate there are no duplicated instructions 443*61046927SAndroid Build Coastguard Worker if len(instruction_dict) != len(instructions): 444*61046927SAndroid Build Coastguard Worker import collections 445*61046927SAndroid Build Coastguard Worker counts = collections.Counter([i.name for i in instructions]) 446*61046927SAndroid Build Coastguard Worker for c in counts: 447*61046927SAndroid Build Coastguard Worker if counts[c] != 1: 448*61046927SAndroid Build Coastguard Worker print(f'{c} appeared {counts[c]} times.') 449*61046927SAndroid Build Coastguard Worker 450*61046927SAndroid Build Coastguard Worker assert(len(instruction_dict) == len(instructions)) 451*61046927SAndroid Build Coastguard Worker 452*61046927SAndroid Build Coastguard Worker return (instructions, immediates, enums, typesize, safe_name) 453