1b8e80941Smrg#encoding=utf-8
2b8e80941Smrg
3b8e80941Smrgfrom __future__ import (
4b8e80941Smrg    absolute_import, division, print_function, unicode_literals
5b8e80941Smrg)
6b8e80941Smrgimport argparse
7b8e80941Smrgimport ast
8b8e80941Smrgimport xml.parsers.expat
9b8e80941Smrgimport re
10b8e80941Smrgimport sys
11b8e80941Smrgimport copy
12b8e80941Smrgimport textwrap
13b8e80941Smrg
14b8e80941Smrglicense =  """/*
15b8e80941Smrg * Copyright (C) 2016 Intel Corporation
16b8e80941Smrg *
17b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
18b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
19b8e80941Smrg * to deal in the Software without restriction, including without limitation
20b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
22b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
23b8e80941Smrg *
24b8e80941Smrg * The above copyright notice and this permission notice (including the next
25b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
26b8e80941Smrg * Software.
27b8e80941Smrg *
28b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
31b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
34b8e80941Smrg * IN THE SOFTWARE.
35b8e80941Smrg */
36b8e80941Smrg"""
37b8e80941Smrg
38b8e80941Smrgpack_header = """%(license)s
39b8e80941Smrg
40b8e80941Smrg/* Instructions, enums and structures for %(platform)s.
41b8e80941Smrg *
42b8e80941Smrg * This file has been generated, do not hand edit.
43b8e80941Smrg */
44b8e80941Smrg
45b8e80941Smrg#ifndef %(guard)s
46b8e80941Smrg#define %(guard)s
47b8e80941Smrg
48b8e80941Smrg#include <stdio.h>
49b8e80941Smrg#include <stdint.h>
50b8e80941Smrg#include <stdbool.h>
51b8e80941Smrg#include <assert.h>
52b8e80941Smrg#include <math.h>
53b8e80941Smrg
54b8e80941Smrg#ifndef __gen_validate_value
55b8e80941Smrg#define __gen_validate_value(x)
56b8e80941Smrg#endif
57b8e80941Smrg
58b8e80941Smrg#ifndef __gen_field_functions
59b8e80941Smrg#define __gen_field_functions
60b8e80941Smrg
61b8e80941Smrg#ifdef NDEBUG
62b8e80941Smrg#define NDEBUG_UNUSED __attribute__((unused))
63b8e80941Smrg#else
64b8e80941Smrg#define NDEBUG_UNUSED
65b8e80941Smrg#endif
66b8e80941Smrg
67b8e80941Smrgunion __gen_value {
68b8e80941Smrg   float f;
69b8e80941Smrg   uint32_t dw;
70b8e80941Smrg};
71b8e80941Smrg
72b8e80941Smrgstatic inline uint64_t
73b8e80941Smrg__gen_mbo(uint32_t start, uint32_t end)
74b8e80941Smrg{
75b8e80941Smrg   return (~0ull >> (64 - (end - start + 1))) << start;
76b8e80941Smrg}
77b8e80941Smrg
78b8e80941Smrgstatic inline uint64_t
79b8e80941Smrg__gen_uint(uint64_t v, uint32_t start, NDEBUG_UNUSED uint32_t end)
80b8e80941Smrg{
81b8e80941Smrg   __gen_validate_value(v);
82b8e80941Smrg
83b8e80941Smrg#ifndef NDEBUG
84b8e80941Smrg   const int width = end - start + 1;
85b8e80941Smrg   if (width < 64) {
86b8e80941Smrg      const uint64_t max = (1ull << width) - 1;
87b8e80941Smrg      assert(v <= max);
88b8e80941Smrg   }
89b8e80941Smrg#endif
90b8e80941Smrg
91b8e80941Smrg   return v << start;
92b8e80941Smrg}
93b8e80941Smrg
94b8e80941Smrgstatic inline uint64_t
95b8e80941Smrg__gen_sint(int64_t v, uint32_t start, uint32_t end)
96b8e80941Smrg{
97b8e80941Smrg   const int width = end - start + 1;
98b8e80941Smrg
99b8e80941Smrg   __gen_validate_value(v);
100b8e80941Smrg
101b8e80941Smrg#ifndef NDEBUG
102b8e80941Smrg   if (width < 64) {
103b8e80941Smrg      const int64_t max = (1ll << (width - 1)) - 1;
104b8e80941Smrg      const int64_t min = -(1ll << (width - 1));
105b8e80941Smrg      assert(min <= v && v <= max);
106b8e80941Smrg   }
107b8e80941Smrg#endif
108b8e80941Smrg
109b8e80941Smrg   const uint64_t mask = ~0ull >> (64 - width);
110b8e80941Smrg
111b8e80941Smrg   return (v & mask) << start;
112b8e80941Smrg}
113b8e80941Smrg
114b8e80941Smrgstatic inline uint64_t
115b8e80941Smrg__gen_offset(uint64_t v, NDEBUG_UNUSED uint32_t start, NDEBUG_UNUSED uint32_t end)
116b8e80941Smrg{
117b8e80941Smrg   __gen_validate_value(v);
118b8e80941Smrg#ifndef NDEBUG
119b8e80941Smrg   uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start;
120b8e80941Smrg
121b8e80941Smrg   assert((v & ~mask) == 0);
122b8e80941Smrg#endif
123b8e80941Smrg
124b8e80941Smrg   return v;
125b8e80941Smrg}
126b8e80941Smrg
127b8e80941Smrgstatic inline uint32_t
128b8e80941Smrg__gen_float(float v)
129b8e80941Smrg{
130b8e80941Smrg   __gen_validate_value(v);
131b8e80941Smrg   return ((union __gen_value) { .f = (v) }).dw;
132b8e80941Smrg}
133b8e80941Smrg
134b8e80941Smrgstatic inline uint64_t
135b8e80941Smrg__gen_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits)
136b8e80941Smrg{
137b8e80941Smrg   __gen_validate_value(v);
138b8e80941Smrg
139b8e80941Smrg   const float factor = (1 << fract_bits);
140b8e80941Smrg
141b8e80941Smrg#ifndef NDEBUG
142b8e80941Smrg   const float max = ((1 << (end - start)) - 1) / factor;
143b8e80941Smrg   const float min = -(1 << (end - start)) / factor;
144b8e80941Smrg   assert(min <= v && v <= max);
145b8e80941Smrg#endif
146b8e80941Smrg
147b8e80941Smrg   const int64_t int_val = llroundf(v * factor);
148b8e80941Smrg   const uint64_t mask = ~0ull >> (64 - (end - start + 1));
149b8e80941Smrg
150b8e80941Smrg   return (int_val & mask) << start;
151b8e80941Smrg}
152b8e80941Smrg
153b8e80941Smrgstatic inline uint64_t
154b8e80941Smrg__gen_ufixed(float v, uint32_t start, NDEBUG_UNUSED uint32_t end, uint32_t fract_bits)
155b8e80941Smrg{
156b8e80941Smrg   __gen_validate_value(v);
157b8e80941Smrg
158b8e80941Smrg   const float factor = (1 << fract_bits);
159b8e80941Smrg
160b8e80941Smrg#ifndef NDEBUG
161b8e80941Smrg   const float max = ((1 << (end - start + 1)) - 1) / factor;
162b8e80941Smrg   const float min = 0.0f;
163b8e80941Smrg   assert(min <= v && v <= max);
164b8e80941Smrg#endif
165b8e80941Smrg
166b8e80941Smrg   const uint64_t uint_val = llroundf(v * factor);
167b8e80941Smrg
168b8e80941Smrg   return uint_val << start;
169b8e80941Smrg}
170b8e80941Smrg
171b8e80941Smrg#ifndef __gen_address_type
172b8e80941Smrg#error #define __gen_address_type before including this file
173b8e80941Smrg#endif
174b8e80941Smrg
175b8e80941Smrg#ifndef __gen_user_data
176b8e80941Smrg#error #define __gen_combine_address before including this file
177b8e80941Smrg#endif
178b8e80941Smrg
179b8e80941Smrg#undef NDEBUG_UNUSED
180b8e80941Smrg
181b8e80941Smrg#endif
182b8e80941Smrg
183b8e80941Smrg"""
184b8e80941Smrg
185b8e80941Smrgdef to_alphanum(name):
186b8e80941Smrg    substitutions = {
187b8e80941Smrg        ' ': '',
188b8e80941Smrg        '/': '',
189b8e80941Smrg        '[': '',
190b8e80941Smrg        ']': '',
191b8e80941Smrg        '(': '',
192b8e80941Smrg        ')': '',
193b8e80941Smrg        '-': '',
194b8e80941Smrg        ':': '',
195b8e80941Smrg        '.': '',
196b8e80941Smrg        ',': '',
197b8e80941Smrg        '=': '',
198b8e80941Smrg        '>': '',
199b8e80941Smrg        '#': '',
200b8e80941Smrg        'α': 'alpha',
201b8e80941Smrg        '&': '',
202b8e80941Smrg        '*': '',
203b8e80941Smrg        '"': '',
204b8e80941Smrg        '+': '',
205b8e80941Smrg        '\'': '',
206b8e80941Smrg    }
207b8e80941Smrg
208b8e80941Smrg    for i, j in substitutions.items():
209b8e80941Smrg        name = name.replace(i, j)
210b8e80941Smrg
211b8e80941Smrg    return name
212b8e80941Smrg
213b8e80941Smrgdef safe_name(name):
214b8e80941Smrg    name = to_alphanum(name)
215b8e80941Smrg    if not name[0].isalpha():
216b8e80941Smrg        name = '_' + name
217b8e80941Smrg
218b8e80941Smrg    return name
219b8e80941Smrg
220b8e80941Smrgdef num_from_str(num_str):
221b8e80941Smrg    if num_str.lower().startswith('0x'):
222b8e80941Smrg        return int(num_str, base=16)
223b8e80941Smrg
224b8e80941Smrg    assert not num_str.startswith('0'), 'octals numbers not allowed'
225b8e80941Smrg    return int(num_str)
226b8e80941Smrg
227b8e80941Smrgclass Field(object):
228b8e80941Smrg    ufixed_pattern = re.compile(r"u(\d+)\.(\d+)")
229b8e80941Smrg    sfixed_pattern = re.compile(r"s(\d+)\.(\d+)")
230b8e80941Smrg
231b8e80941Smrg    def __init__(self, parser, attrs):
232b8e80941Smrg        self.parser = parser
233b8e80941Smrg        if "name" in attrs:
234b8e80941Smrg            self.name = safe_name(attrs["name"])
235b8e80941Smrg        self.start = int(attrs["start"])
236b8e80941Smrg        self.end = int(attrs["end"])
237b8e80941Smrg        self.type = attrs["type"]
238b8e80941Smrg
239b8e80941Smrg        assert self.start <= self.end, \
240b8e80941Smrg               'field {} has end ({}) < start ({})'.format(self.name, self.end,
241b8e80941Smrg                                                           self.start)
242b8e80941Smrg        if self.type == 'bool':
243b8e80941Smrg            assert self.end == self.start, \
244b8e80941Smrg                   'bool field ({}) is too wide'.format(self.name)
245b8e80941Smrg
246b8e80941Smrg        if "prefix" in attrs:
247b8e80941Smrg            self.prefix = attrs["prefix"]
248b8e80941Smrg        else:
249b8e80941Smrg            self.prefix = None
250b8e80941Smrg
251b8e80941Smrg        if "default" in attrs:
252b8e80941Smrg            # Base 0 recognizes 0x, 0o, 0b prefixes in addition to decimal ints.
253b8e80941Smrg            self.default = int(attrs["default"], base=0)
254b8e80941Smrg        else:
255b8e80941Smrg            self.default = None
256b8e80941Smrg
257b8e80941Smrg        ufixed_match = Field.ufixed_pattern.match(self.type)
258b8e80941Smrg        if ufixed_match:
259b8e80941Smrg            self.type = 'ufixed'
260b8e80941Smrg            self.fractional_size = int(ufixed_match.group(2))
261b8e80941Smrg
262b8e80941Smrg        sfixed_match = Field.sfixed_pattern.match(self.type)
263b8e80941Smrg        if sfixed_match:
264b8e80941Smrg            self.type = 'sfixed'
265b8e80941Smrg            self.fractional_size = int(sfixed_match.group(2))
266b8e80941Smrg
267b8e80941Smrg    def is_builtin_type(self):
268b8e80941Smrg        builtins =  [ 'address', 'bool', 'float', 'ufixed',
269b8e80941Smrg                      'offset', 'sfixed', 'offset', 'int', 'uint', 'mbo' ]
270b8e80941Smrg        return self.type in builtins
271b8e80941Smrg
272b8e80941Smrg    def is_struct_type(self):
273b8e80941Smrg        return self.type in self.parser.structs
274b8e80941Smrg
275b8e80941Smrg    def is_enum_type(self):
276b8e80941Smrg        return self.type in self.parser.enums
277b8e80941Smrg
278b8e80941Smrg    def emit_template_struct(self, dim):
279b8e80941Smrg        if self.type == 'address':
280b8e80941Smrg            type = '__gen_address_type'
281b8e80941Smrg        elif self.type == 'bool':
282b8e80941Smrg            type = 'bool'
283b8e80941Smrg        elif self.type == 'float':
284b8e80941Smrg            type = 'float'
285b8e80941Smrg        elif self.type == 'ufixed':
286b8e80941Smrg            type = 'float'
287b8e80941Smrg        elif self.type == 'sfixed':
288b8e80941Smrg            type = 'float'
289b8e80941Smrg        elif self.type == 'uint' and self.end - self.start > 32:
290b8e80941Smrg            type = 'uint64_t'
291b8e80941Smrg        elif self.type == 'offset':
292b8e80941Smrg            type = 'uint64_t'
293b8e80941Smrg        elif self.type == 'int':
294b8e80941Smrg            type = 'int32_t'
295b8e80941Smrg        elif self.type == 'uint':
296b8e80941Smrg            type = 'uint32_t'
297b8e80941Smrg        elif self.is_struct_type():
298b8e80941Smrg            type = 'struct ' + self.parser.gen_prefix(safe_name(self.type))
299b8e80941Smrg        elif self.is_enum_type():
300b8e80941Smrg            type = 'enum ' + self.parser.gen_prefix(safe_name(self.type))
301b8e80941Smrg        elif self.type == 'mbo':
302b8e80941Smrg            return
303b8e80941Smrg        else:
304b8e80941Smrg            print("#error unhandled type: %s" % self.type)
305b8e80941Smrg            return
306b8e80941Smrg
307b8e80941Smrg        print("   %-36s %s%s;" % (type, self.name, dim))
308b8e80941Smrg
309b8e80941Smrg        prefix = ""
310b8e80941Smrg        if self.values and self.default is None:
311b8e80941Smrg            if self.prefix:
312b8e80941Smrg                prefix = self.prefix + "_"
313b8e80941Smrg
314b8e80941Smrg        for value in self.values:
315b8e80941Smrg            print("#define %-40s %d" % (prefix + value.name, value.value))
316b8e80941Smrg
317b8e80941Smrgclass Group(object):
318b8e80941Smrg    def __init__(self, parser, parent, start, count, size):
319b8e80941Smrg        self.parser = parser
320b8e80941Smrg        self.parent = parent
321b8e80941Smrg        self.start = start
322b8e80941Smrg        self.count = count
323b8e80941Smrg        self.size = size
324b8e80941Smrg        self.fields = []
325b8e80941Smrg
326b8e80941Smrg    def emit_template_struct(self, dim):
327b8e80941Smrg        if self.count == 0:
328b8e80941Smrg            print("   /* variable length fields follow */")
329b8e80941Smrg        else:
330b8e80941Smrg            if self.count > 1:
331b8e80941Smrg                dim = "%s[%d]" % (dim, self.count)
332b8e80941Smrg
333b8e80941Smrg            for field in self.fields:
334b8e80941Smrg                field.emit_template_struct(dim)
335b8e80941Smrg
336b8e80941Smrg    class DWord:
337b8e80941Smrg        def __init__(self):
338b8e80941Smrg            self.size = 32
339b8e80941Smrg            self.fields = []
340b8e80941Smrg            self.address = None
341b8e80941Smrg
342b8e80941Smrg    def collect_dwords(self, dwords, start, dim):
343b8e80941Smrg        for field in self.fields:
344b8e80941Smrg            if isinstance(field, Group):
345b8e80941Smrg                if field.count == 1:
346b8e80941Smrg                    field.collect_dwords(dwords, start + field.start, dim)
347b8e80941Smrg                else:
348b8e80941Smrg                    for i in range(field.count):
349b8e80941Smrg                        field.collect_dwords(dwords,
350b8e80941Smrg                                             start + field.start + i * field.size,
351b8e80941Smrg                                             "%s[%d]" % (dim, i))
352b8e80941Smrg                continue
353b8e80941Smrg
354b8e80941Smrg            index = (start + field.start) // 32
355b8e80941Smrg            if not index in dwords:
356b8e80941Smrg                dwords[index] = self.DWord()
357b8e80941Smrg
358b8e80941Smrg            clone = copy.copy(field)
359b8e80941Smrg            clone.start = clone.start + start
360b8e80941Smrg            clone.end = clone.end + start
361b8e80941Smrg            clone.dim = dim
362b8e80941Smrg            dwords[index].fields.append(clone)
363b8e80941Smrg
364b8e80941Smrg            if field.type == "address":
365b8e80941Smrg                # assert dwords[index].address == None
366b8e80941Smrg                dwords[index].address = field
367b8e80941Smrg
368b8e80941Smrg            # Coalesce all the dwords covered by this field. The two cases we
369b8e80941Smrg            # handle are where multiple fields are in a 64 bit word (typically
370b8e80941Smrg            # and address and a few bits) or where a single struct field
371b8e80941Smrg            # completely covers multiple dwords.
372b8e80941Smrg            while index < (start + field.end) // 32:
373b8e80941Smrg                if index + 1 in dwords and not dwords[index] == dwords[index + 1]:
374b8e80941Smrg                    dwords[index].fields.extend(dwords[index + 1].fields)
375b8e80941Smrg                dwords[index].size = 64
376b8e80941Smrg                dwords[index + 1] = dwords[index]
377b8e80941Smrg                index = index + 1
378b8e80941Smrg
379b8e80941Smrg    def collect_dwords_and_length(self):
380b8e80941Smrg        dwords = {}
381b8e80941Smrg        self.collect_dwords(dwords, 0, "")
382b8e80941Smrg
383b8e80941Smrg        # Determine number of dwords in this group. If we have a size, use
384b8e80941Smrg        # that, since that'll account for MBZ dwords at the end of a group
385b8e80941Smrg        # (like dword 8 on BDW+ 3DSTATE_HS). Otherwise, use the largest dword
386b8e80941Smrg        # index we've seen plus one.
387b8e80941Smrg        if self.size > 0:
388b8e80941Smrg            length = self.size // 32
389b8e80941Smrg        elif dwords:
390b8e80941Smrg            length = max(dwords.keys()) + 1
391b8e80941Smrg        else:
392b8e80941Smrg            length = 0
393b8e80941Smrg
394b8e80941Smrg        return (dwords, length)
395b8e80941Smrg
396b8e80941Smrg    def emit_pack_function(self, dwords, length):
397b8e80941Smrg        for index in range(length):
398b8e80941Smrg            # Handle MBZ dwords
399b8e80941Smrg            if not index in dwords:
400b8e80941Smrg                print("")
401b8e80941Smrg                print("   dw[%d] = 0;" % index)
402b8e80941Smrg                continue
403b8e80941Smrg
404b8e80941Smrg            # For 64 bit dwords, we aliased the two dword entries in the dword
405b8e80941Smrg            # dict it occupies. Now that we're emitting the pack function,
406b8e80941Smrg            # skip the duplicate entries.
407b8e80941Smrg            dw = dwords[index]
408b8e80941Smrg            if index > 0 and index - 1 in dwords and dw == dwords[index - 1]:
409b8e80941Smrg                continue
410b8e80941Smrg
411b8e80941Smrg            # Special case: only one field and it's a struct at the beginning
412b8e80941Smrg            # of the dword. In this case we pack directly into the
413b8e80941Smrg            # destination. This is the only way we handle embedded structs
414b8e80941Smrg            # larger than 32 bits.
415b8e80941Smrg            if len(dw.fields) == 1:
416b8e80941Smrg                field = dw.fields[0]
417b8e80941Smrg                name = field.name + field.dim
418b8e80941Smrg                if field.is_struct_type() and field.start % 32 == 0:
419b8e80941Smrg                    print("")
420b8e80941Smrg                    print("   %s_pack(data, &dw[%d], &values->%s);" %
421b8e80941Smrg                          (self.parser.gen_prefix(safe_name(field.type)), index, name))
422b8e80941Smrg                    continue
423b8e80941Smrg
424b8e80941Smrg            # Pack any fields of struct type first so we have integer values
425b8e80941Smrg            # to the dword for those fields.
426b8e80941Smrg            field_index = 0
427b8e80941Smrg            for field in dw.fields:
428b8e80941Smrg                if isinstance(field, Field) and field.is_struct_type():
429b8e80941Smrg                    name = field.name + field.dim
430b8e80941Smrg                    print("")
431b8e80941Smrg                    print("   uint32_t v%d_%d;" % (index, field_index))
432b8e80941Smrg                    print("   %s_pack(data, &v%d_%d, &values->%s);" %
433b8e80941Smrg                          (self.parser.gen_prefix(safe_name(field.type)), index, field_index, name))
434b8e80941Smrg                    field_index = field_index + 1
435b8e80941Smrg
436b8e80941Smrg            print("")
437b8e80941Smrg            dword_start = index * 32
438b8e80941Smrg            if dw.address == None:
439b8e80941Smrg                address_count = 0
440b8e80941Smrg            else:
441b8e80941Smrg                address_count = 1
442b8e80941Smrg
443b8e80941Smrg            if dw.size == 32 and dw.address == None:
444b8e80941Smrg                v = None
445b8e80941Smrg                print("   dw[%d] =" % index)
446b8e80941Smrg            elif len(dw.fields) > address_count:
447b8e80941Smrg                v = "v%d" % index
448b8e80941Smrg                print("   const uint%d_t %s =" % (dw.size, v))
449b8e80941Smrg            else:
450b8e80941Smrg                v = "0"
451b8e80941Smrg
452b8e80941Smrg            field_index = 0
453b8e80941Smrg            non_address_fields = []
454b8e80941Smrg            for field in dw.fields:
455b8e80941Smrg                if field.type != "mbo":
456b8e80941Smrg                    name = field.name + field.dim
457b8e80941Smrg
458b8e80941Smrg                if field.type == "mbo":
459b8e80941Smrg                    non_address_fields.append("__gen_mbo(%d, %d)" % \
460b8e80941Smrg                        (field.start - dword_start, field.end - dword_start))
461b8e80941Smrg                elif field.type == "address":
462b8e80941Smrg                    pass
463b8e80941Smrg                elif field.type == "uint":
464b8e80941Smrg                    non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \
465b8e80941Smrg                        (name, field.start - dword_start, field.end - dword_start))
466b8e80941Smrg                elif field.is_enum_type():
467b8e80941Smrg                    non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \
468b8e80941Smrg                        (name, field.start - dword_start, field.end - dword_start))
469b8e80941Smrg                elif field.type == "int":
470b8e80941Smrg                    non_address_fields.append("__gen_sint(values->%s, %d, %d)" % \
471b8e80941Smrg                        (name, field.start - dword_start, field.end - dword_start))
472b8e80941Smrg                elif field.type == "bool":
473b8e80941Smrg                    non_address_fields.append("__gen_uint(values->%s, %d, %d)" % \
474b8e80941Smrg                        (name, field.start - dword_start, field.end - dword_start))
475b8e80941Smrg                elif field.type == "float":
476b8e80941Smrg                    non_address_fields.append("__gen_float(values->%s)" % name)
477b8e80941Smrg                elif field.type == "offset":
478b8e80941Smrg                    non_address_fields.append("__gen_offset(values->%s, %d, %d)" % \
479b8e80941Smrg                        (name, field.start - dword_start, field.end - dword_start))
480b8e80941Smrg                elif field.type == 'ufixed':
481b8e80941Smrg                    non_address_fields.append("__gen_ufixed(values->%s, %d, %d, %d)" % \
482b8e80941Smrg                        (name, field.start - dword_start, field.end - dword_start, field.fractional_size))
483b8e80941Smrg                elif field.type == 'sfixed':
484b8e80941Smrg                    non_address_fields.append("__gen_sfixed(values->%s, %d, %d, %d)" % \
485b8e80941Smrg                        (name, field.start - dword_start, field.end - dword_start, field.fractional_size))
486b8e80941Smrg                elif field.is_struct_type():
487b8e80941Smrg                    non_address_fields.append("__gen_uint(v%d_%d, %d, %d)" % \
488b8e80941Smrg                        (index, field_index, field.start - dword_start, field.end - dword_start))
489b8e80941Smrg                    field_index = field_index + 1
490b8e80941Smrg                else:
491b8e80941Smrg                    non_address_fields.append("/* unhandled field %s, type %s */\n" % \
492b8e80941Smrg                                              (name, field.type))
493b8e80941Smrg
494b8e80941Smrg            if non_address_fields:
495b8e80941Smrg                print(" |\n".join("      " + f for f in non_address_fields) + ";")
496b8e80941Smrg
497b8e80941Smrg            if dw.size == 32:
498b8e80941Smrg                if dw.address:
499b8e80941Smrg                    print("   dw[%d] = __gen_combine_address(data, &dw[%d], values->%s, %s);" % (index, index, dw.address.name + field.dim, v))
500b8e80941Smrg                continue
501b8e80941Smrg
502b8e80941Smrg            if dw.address:
503b8e80941Smrg                v_address = "v%d_address" % index
504b8e80941Smrg                print("   const uint64_t %s =\n      __gen_combine_address(data, &dw[%d], values->%s, %s);" %
505b8e80941Smrg                      (v_address, index, dw.address.name + field.dim, v))
506b8e80941Smrg                if len(dw.fields) > address_count:
507b8e80941Smrg                    print("   dw[%d] = %s;" % (index, v_address))
508b8e80941Smrg                    print("   dw[%d] = (%s >> 32) | (%s >> 32);" % (index + 1, v_address, v))
509b8e80941Smrg                    continue
510b8e80941Smrg                else:
511b8e80941Smrg                    v = v_address
512b8e80941Smrg            print("   dw[%d] = %s;" % (index, v))
513b8e80941Smrg            print("   dw[%d] = %s >> 32;" % (index + 1, v))
514b8e80941Smrg
515b8e80941Smrgclass Value(object):
516b8e80941Smrg    def __init__(self, attrs):
517b8e80941Smrg        self.name = safe_name(attrs["name"])
518b8e80941Smrg        self.value = ast.literal_eval(attrs["value"])
519b8e80941Smrg
520b8e80941Smrgclass Parser(object):
521b8e80941Smrg    def __init__(self):
522b8e80941Smrg        self.parser = xml.parsers.expat.ParserCreate()
523b8e80941Smrg        self.parser.StartElementHandler = self.start_element
524b8e80941Smrg        self.parser.EndElementHandler = self.end_element
525b8e80941Smrg
526b8e80941Smrg        self.instruction = None
527b8e80941Smrg        self.structs = {}
528b8e80941Smrg        # Set of enum names we've seen.
529b8e80941Smrg        self.enums = set()
530b8e80941Smrg        self.registers = {}
531b8e80941Smrg
532b8e80941Smrg    def gen_prefix(self, name):
533b8e80941Smrg        if name[0] == "_":
534b8e80941Smrg            return 'GEN%s%s' % (self.gen, name)
535b8e80941Smrg        return 'GEN%s_%s' % (self.gen, name)
536b8e80941Smrg
537b8e80941Smrg    def gen_guard(self):
538b8e80941Smrg        return self.gen_prefix("PACK_H")
539b8e80941Smrg
540b8e80941Smrg    def start_element(self, name, attrs):
541b8e80941Smrg        if name == "genxml":
542b8e80941Smrg            self.platform = attrs["name"]
543b8e80941Smrg            self.gen = attrs["gen"].replace('.', '')
544b8e80941Smrg            print(pack_header % {'license': license, 'platform': self.platform, 'guard': self.gen_guard()})
545b8e80941Smrg        elif name in ("instruction", "struct", "register"):
546b8e80941Smrg            if name == "instruction":
547b8e80941Smrg                self.instruction = safe_name(attrs["name"])
548b8e80941Smrg                self.length_bias = int(attrs["bias"])
549b8e80941Smrg                if "engine" in attrs:
550b8e80941Smrg                    self.instruction_engines = set(attrs["engine"].split('|'))
551b8e80941Smrg                else:
552b8e80941Smrg                    # When an instruction doesn't have the engine specified,
553b8e80941Smrg                    # it is considered to be for all engines, so 'None' is used
554b8e80941Smrg                    # to signify that the instruction belongs to all engines.
555b8e80941Smrg                    self.instruction_engines = None
556b8e80941Smrg            elif name == "struct":
557b8e80941Smrg                self.struct = safe_name(attrs["name"])
558b8e80941Smrg                self.structs[attrs["name"]] = 1
559b8e80941Smrg            elif name == "register":
560b8e80941Smrg                self.register = safe_name(attrs["name"])
561b8e80941Smrg                self.reg_num = num_from_str(attrs["num"])
562b8e80941Smrg                self.registers[attrs["name"]] = 1
563b8e80941Smrg            if "length" in attrs:
564b8e80941Smrg                self.length = int(attrs["length"])
565b8e80941Smrg                size = self.length * 32
566b8e80941Smrg            else:
567b8e80941Smrg                self.length = None
568b8e80941Smrg                size = 0
569b8e80941Smrg            self.group = Group(self, None, 0, 1, size)
570b8e80941Smrg
571b8e80941Smrg        elif name == "group":
572b8e80941Smrg            group = Group(self, self.group,
573b8e80941Smrg                          int(attrs["start"]), int(attrs["count"]), int(attrs["size"]))
574b8e80941Smrg            self.group.fields.append(group)
575b8e80941Smrg            self.group = group
576b8e80941Smrg        elif name == "field":
577b8e80941Smrg            self.group.fields.append(Field(self, attrs))
578b8e80941Smrg            self.values = []
579b8e80941Smrg        elif name == "enum":
580b8e80941Smrg            self.values = []
581b8e80941Smrg            self.enum = safe_name(attrs["name"])
582b8e80941Smrg            self.enums.add(attrs["name"])
583b8e80941Smrg            if "prefix" in attrs:
584b8e80941Smrg                self.prefix = safe_name(attrs["prefix"])
585b8e80941Smrg            else:
586b8e80941Smrg                self.prefix= None
587b8e80941Smrg        elif name == "value":
588b8e80941Smrg            self.values.append(Value(attrs))
589b8e80941Smrg
590b8e80941Smrg    def end_element(self, name):
591b8e80941Smrg        if name  == "instruction":
592b8e80941Smrg            self.emit_instruction()
593b8e80941Smrg            self.instruction = None
594b8e80941Smrg            self.group = None
595b8e80941Smrg        elif name == "struct":
596b8e80941Smrg            self.emit_struct()
597b8e80941Smrg            self.struct = None
598b8e80941Smrg            self.group = None
599b8e80941Smrg        elif name == "register":
600b8e80941Smrg            self.emit_register()
601b8e80941Smrg            self.register = None
602b8e80941Smrg            self.reg_num = None
603b8e80941Smrg            self.group = None
604b8e80941Smrg        elif name == "group":
605b8e80941Smrg            self.group = self.group.parent
606b8e80941Smrg        elif name  == "field":
607b8e80941Smrg            self.group.fields[-1].values = self.values
608b8e80941Smrg        elif name  == "enum":
609b8e80941Smrg            self.emit_enum()
610b8e80941Smrg            self.enum = None
611b8e80941Smrg        elif name == "genxml":
612b8e80941Smrg            print('#endif /* %s */' % self.gen_guard())
613b8e80941Smrg
614b8e80941Smrg    def emit_template_struct(self, name, group):
615b8e80941Smrg        print("struct %s {" % self.gen_prefix(name))
616b8e80941Smrg        group.emit_template_struct("")
617b8e80941Smrg        print("};\n")
618b8e80941Smrg
619b8e80941Smrg    def emit_pack_function(self, name, group):
620b8e80941Smrg        name = self.gen_prefix(name)
621b8e80941Smrg        print(textwrap.dedent("""\
622b8e80941Smrg            static inline void
623b8e80941Smrg            %s_pack(__attribute__((unused)) __gen_user_data *data,
624b8e80941Smrg                  %s__attribute__((unused)) void * restrict dst,
625b8e80941Smrg                  %s__attribute__((unused)) const struct %s * restrict values)
626b8e80941Smrg            {""") % (name, ' ' * len(name), ' ' * len(name), name))
627b8e80941Smrg
628b8e80941Smrg        (dwords, length) = group.collect_dwords_and_length()
629b8e80941Smrg        if length:
630b8e80941Smrg            # Cast dst to make header C++ friendly
631b8e80941Smrg            print("   uint32_t * restrict dw = (uint32_t * restrict) dst;")
632b8e80941Smrg
633b8e80941Smrg            group.emit_pack_function(dwords, length)
634b8e80941Smrg
635b8e80941Smrg        print("}\n")
636b8e80941Smrg
637b8e80941Smrg    def emit_instruction(self):
638b8e80941Smrg        name = self.instruction
639b8e80941Smrg        if self.instruction_engines and not self.instruction_engines & self.engines:
640b8e80941Smrg            return
641b8e80941Smrg
642b8e80941Smrg        if not self.length is None:
643b8e80941Smrg            print('#define %-33s %6d' %
644b8e80941Smrg                  (self.gen_prefix(name + "_length"), self.length))
645b8e80941Smrg        print('#define %-33s %6d' %
646b8e80941Smrg              (self.gen_prefix(name + "_length_bias"), self.length_bias))
647b8e80941Smrg
648b8e80941Smrg        default_fields = []
649b8e80941Smrg        for field in self.group.fields:
650b8e80941Smrg            if not isinstance(field, Field):
651b8e80941Smrg                continue
652b8e80941Smrg            if field.default is None:
653b8e80941Smrg                continue
654b8e80941Smrg            default_fields.append("   .%-35s = %6d" % (field.name, field.default))
655b8e80941Smrg
656b8e80941Smrg        if default_fields:
657b8e80941Smrg            print('#define %-40s\\' % (self.gen_prefix(name + '_header')))
658b8e80941Smrg            print(",  \\\n".join(default_fields))
659b8e80941Smrg            print('')
660b8e80941Smrg
661b8e80941Smrg        self.emit_template_struct(self.instruction, self.group)
662b8e80941Smrg
663b8e80941Smrg        self.emit_pack_function(self.instruction, self.group)
664b8e80941Smrg
665b8e80941Smrg    def emit_register(self):
666b8e80941Smrg        name = self.register
667b8e80941Smrg        if not self.reg_num is None:
668b8e80941Smrg            print('#define %-33s 0x%04x' %
669b8e80941Smrg                  (self.gen_prefix(name + "_num"), self.reg_num))
670b8e80941Smrg
671b8e80941Smrg        if not self.length is None:
672b8e80941Smrg            print('#define %-33s %6d' %
673b8e80941Smrg                  (self.gen_prefix(name + "_length"), self.length))
674b8e80941Smrg
675b8e80941Smrg        self.emit_template_struct(self.register, self.group)
676b8e80941Smrg        self.emit_pack_function(self.register, self.group)
677b8e80941Smrg
678b8e80941Smrg    def emit_struct(self):
679b8e80941Smrg        name = self.struct
680b8e80941Smrg        if not self.length is None:
681b8e80941Smrg            print('#define %-33s %6d' %
682b8e80941Smrg                  (self.gen_prefix(name + "_length"), self.length))
683b8e80941Smrg
684b8e80941Smrg        self.emit_template_struct(self.struct, self.group)
685b8e80941Smrg        self.emit_pack_function(self.struct, self.group)
686b8e80941Smrg
687b8e80941Smrg    def emit_enum(self):
688b8e80941Smrg        print('enum %s {' % self.gen_prefix(self.enum))
689b8e80941Smrg        for value in self.values:
690b8e80941Smrg            if self.prefix:
691b8e80941Smrg                name = self.prefix + "_" + value.name
692b8e80941Smrg            else:
693b8e80941Smrg                name = value.name
694b8e80941Smrg            print('   %-36s = %6d,' % (name.upper(), value.value))
695b8e80941Smrg        print('};\n')
696b8e80941Smrg
697b8e80941Smrg    def parse(self, filename):
698b8e80941Smrg        file = open(filename, "rb")
699b8e80941Smrg        self.parser.ParseFile(file)
700b8e80941Smrg        file.close()
701b8e80941Smrg
702b8e80941Smrgdef parse_args():
703b8e80941Smrg    p = argparse.ArgumentParser()
704b8e80941Smrg    p.add_argument('xml_source', metavar='XML_SOURCE',
705b8e80941Smrg                   help="Input xml file")
706b8e80941Smrg    p.add_argument('--engines', nargs='?', type=str, default='render',
707b8e80941Smrg                   help="Comma-separated list of engines whose instructions should be parsed (default: %(default)s)")
708b8e80941Smrg
709b8e80941Smrg    pargs = p.parse_args()
710b8e80941Smrg
711b8e80941Smrg    if pargs.engines is None:
712b8e80941Smrg        print("No engines specified")
713b8e80941Smrg        sys.exit(1)
714b8e80941Smrg
715b8e80941Smrg    return pargs
716b8e80941Smrg
717b8e80941Smrgdef main():
718b8e80941Smrg    pargs = parse_args()
719b8e80941Smrg
720b8e80941Smrg    input_file = pargs.xml_source
721b8e80941Smrg    engines = pargs.engines.split(',')
722b8e80941Smrg    valid_engines = [ 'render', 'blitter', 'video' ]
723b8e80941Smrg    if set(engines) - set(valid_engines):
724b8e80941Smrg        print("Invalid engine specified, valid engines are:\n")
725b8e80941Smrg        for e in valid_engines:
726b8e80941Smrg            print("\t%s" % e)
727b8e80941Smrg        sys.exit(1)
728b8e80941Smrg
729b8e80941Smrg    p = Parser()
730b8e80941Smrg    p.engines = set(engines)
731b8e80941Smrg    p.parse(input_file)
732b8e80941Smrg
733b8e80941Smrgif __name__ == '__main__':
734b8e80941Smrg    main()
735