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