From 9bfd9bbcb3a675150ea59eacdf0ea335c9f5d377 Mon Sep 17 00:00:00 2001
From: "Kristian H. Kristensen" <hoegsberg@gmail.com>
Date: Mon, 28 Nov 2016 21:03:10 -0800
Subject: [PATCH] intel/genxml: Add unpack functions

Useful for people writing Intel GPU simulators...

Signed-off-by: Kristian H. Kristensen <hoegsberg@gmail.com>
---
 src/intel/genxml/gen_pack_header.py | 117 ++++++++++++++++++++++++++++
 1 file changed, 117 insertions(+)

diff --git a/src/intel/genxml/gen_pack_header.py b/src/intel/genxml/gen_pack_header.py
index e6cea8646f..f31cdb4292 100644
--- a/src/intel/genxml/gen_pack_header.py
+++ b/src/intel/genxml/gen_pack_header.py
@@ -161,6 +161,46 @@ __gen_ufixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits)
    return uint_val << start;
 }
 
+static inline uint64_t
+__gen_unpack_uint(uint64_t dw, uint32_t start, uint32_t end)
+{
+   uint64_t mask = (~0ul >> (64 - (end - start + 1)));
+
+   return (dw >> start) & mask;
+}
+
+static inline int64_t
+__gen_unpack_sint(uint64_t dw, uint32_t start, uint32_t end)
+{
+   return ((int64_t) dw << (63 - end)) >> (64 - (end - start + 1));
+}
+
+static inline uint64_t
+__gen_unpack_float(uint64_t dw)
+{
+   return ((union __gen_value) { .dw = (dw) }).f;
+}
+
+static inline uint64_t
+__gen_unpack_offset(uint64_t dw, uint32_t start, uint32_t end)
+{
+   uint64_t mask = (~0ul >> (64 - (end - start + 1))) << start;
+
+   return dw & mask;
+}
+
+static inline float
+__gen_unpack_ufixed(uint64_t dw, uint32_t start, uint32_t end, uint32_t fract_bits)
+{
+   return (float) __gen_unpack_uint(dw, start, end) / (1 << fract_bits);
+}
+
+static inline float
+__gen_unpack_sfixed(uint64_t dw, uint32_t start, uint32_t end, uint32_t fract_bits)
+{
+   return (float) __gen_unpack_sint(dw, start, end) / (1 << fract_bits);
+}
+
 #ifndef __gen_address_type
 #error #define __gen_address_type before including this file
 #endif
@@ -491,6 +531,69 @@ class Group(object):
             print("   dw[%d] = %s;" % (index, v))
             print("   dw[%d] = %s >> 32;" % (index + 1, v))
 
+    def emit_unpack_function(self, start):
+        dwords = {}
+        self.collect_dwords(dwords, 0, "")
+
+        for index in dwords.keys():
+            dw = dwords[index]
+            if index > 0 and index - 1 in dwords and dw == dwords[index - 1]:
+                continue
+
+            print("")
+            print("   const uint32_t dw%d __attribute__((unused)) = dw[%d];" % (index, index))
+
+            dword_start = index * 32
+
+            # Unpack any fields of struct type first
+            field_index = 0
+            for field in dw.fields:
+                if type(field) is Field and field.is_struct_type():
+                    name = field.name + field.dim
+                    print("   uint32_t v%d_%d = __gen_unpack_uint(dw%d, %d, %d);" %
+                          (index, field_index, index, field.start - dword_start, field.end - dword_start))
+                    field_index = field_index + 1
+
+            field_index = 0
+            for field in dw.fields:
+                if field.type != "mbo":
+                    name = field.name + field.dim
+
+                if field.type == "address":
+                    print("   const uint64_t qw%d __attribute__((unused)) = *(uint64_t *) &dw[%d];" % (index, index))
+                    print("   values->%s = __gen_unpack_address(qw%d, 0, 63);" % \
+                          (name, index))
+                elif field.type == "uint":
+                    print("   values->%s = __gen_unpack_uint(dw%d, %d, %d);" % \
+                          (name, index, field.start - dword_start, field.end - dword_start))
+                elif field.is_enum_type():
+                    print("   values->%s = __gen_unpack_uint(dw%d, %d, %d);" % \
+                          (name, index, field.start - dword_start, field.end - dword_start))
+                elif field.type == "int":
+                    print("   values->%s = __gen_unpack_sint(dw%d, %d, %d);" % \
+                          (name, index, field.start - dword_start, field.end - dword_start))
+                elif field.type == "bool":
+                    print("   values->%s = __gen_unpack_uint(dw%d, %d, %d);" % \
+                          (name, index, field.start - dword_start, field.end - dword_start))
+                elif field.type == "float":
+                    print("   values->%s = __gen_unpack_float(dw%d);" % (name, index))
+                elif field.type == "offset":
+                    print("   values->%s = __gen_unpack_offset(dw%d, %d, %d);" % \
+                          (name, index, field.start - dword_start, field.end - dword_start))
+                elif field.type == 'ufixed':
+                    print("   values->%s = __gen_unpack_ufixed(dw%d, %d, %d, %d);" % \
+                          (name, index, field.start - dword_start, field.end - dword_start, field.fractional_size))
+                elif field.type == 'sfixed':
+                    print("   values->%s = __gen_unpack_sfixed(dw%d, %d, %d, %d);" % \
+                          (name, index, field.start - dword_start, field.end - dword_start, field.fractional_size))
+                elif field.is_struct_type():
+                    print("   %s_unpack(&v%d_%d, &values->%s);" % \
+                          (self.parser.gen_prefix(safe_name(field.type)), index, field_index, name))
+                    field_index = field_index + 1
+                else:
+                    print("/* unhandled field %s, type %s */\n" % (name, field.type))
+                    s = None
+
 class Value(object):
     def __init__(self, attrs):
         self.name = safe_name(attrs["name"])
@@ -607,6 +710,17 @@ class Parser(object):
 
         print("}\n")
 
+    def emit_unpack_function(self, name, group):
+        name = self.gen_prefix(name)
+        print("#ifdef __gen_unpack_address")
+        print("static inline void\n%s_unpack(const void * restrict src,\n%sstruct %s * restrict values)\n{" %
+              (name, ' ' * (len(name) + 8), name))
+        print("   const uint32_t *dw = (const uint32_t *) src;")
+
+        group.emit_unpack_function(0)
+
+        print("}\n#endif\n")
+
     def emit_instruction(self):
         name = self.instruction
         if not self.length == None:
@@ -631,6 +745,7 @@ class Parser(object):
         self.emit_template_struct(self.instruction, self.group)
 
         self.emit_pack_function(self.instruction, self.group)
+        self.emit_unpack_function(self.instruction, self.group)
 
     def emit_register(self):
         name = self.register
@@ -644,6 +759,7 @@ class Parser(object):
 
         self.emit_template_struct(self.register, self.group)
         self.emit_pack_function(self.register, self.group)
+        self.emit_unpack_function(self.register, self.group)
 
     def emit_struct(self):
         name = self.struct
@@ -653,6 +769,7 @@ class Parser(object):
 
         self.emit_template_struct(self.struct, self.group)
         self.emit_pack_function(self.struct, self.group)
+        self.emit_unpack_function(self.struct, self.group)
 
     def emit_enum(self):
         print('enum %s {' % self.gen_prefix(self.enum))
-- 
2.25.1

