From e213a864e5758be5698f0383d677d94e1db27e59 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 24 Aug 2020 13:36:22 -0400 Subject: [PATCH] panfrost: Add padded type for instance fields Mali has a special 5:3 encoding representing a subset of the natural numbers, of the form: a * (2^b) for a odd and b natural/zero. It is used for padding out instance sizes, as well as in attribute records so it's worth representing as a native type as opposed to having manual packs/unpacks in various places. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/panfrost/lib/gen_pack.py | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/panfrost/lib/gen_pack.py b/src/panfrost/lib/gen_pack.py index e91769c193c..3fdef5c981e 100644 --- a/src/panfrost/lib/gen_pack.py +++ b/src/panfrost/lib/gen_pack.py @@ -81,6 +81,23 @@ __gen_sint(int32_t v, uint32_t start, uint32_t end) return ((uint32_t) v) << start; } +static inline uint32_t +__gen_padded(uint32_t v, uint32_t start, uint32_t end) +{ + unsigned shift = __builtin_ctz(v); + unsigned odd = v >> (shift + 1); + +#ifndef NDEBUG + assert((v >> shift) & 1); + assert(shift <= 31); + assert(odd <= 7); + assert((end - start + 1) == 8); +#endif + + return __gen_uint(shift | (odd << 5), start, end); +} + + static inline uint64_t __gen_unpack_uint(const uint8_t *restrict cl, uint32_t start, uint32_t end) { @@ -105,6 +122,16 @@ __gen_unpack_sint(const uint8_t *restrict cl, uint32_t start, uint32_t end) return (val << (64 - size)) >> (64 - size); } +static inline uint64_t +__gen_unpack_padded(const uint8_t *restrict cl, uint32_t start, uint32_t end) +{ + unsigned val = __gen_unpack_uint(cl, start, end); + unsigned shift = val & 0b11111; + unsigned odd = val >> 5; + + return (2*odd + 1) << shift; +} + #define pan_pack(dst, T, name) \ for (struct MALI_ ## T name = { MALI_ ## T ## _header }, \ *_loop_terminate = (void *) (dst); \ @@ -224,7 +251,7 @@ class Field(object): type = 'uint64_t' elif self.type == 'int': type = 'int32_t' - elif self.type == 'uint': + elif self.type in ['uint', 'padded']: type = 'uint32_t' elif self.type in self.parser.structs: type = 'struct ' + self.parser.gen_prefix(safe_name(self.type.upper())) @@ -358,6 +385,9 @@ class Group(object): if field.type == "uint" or field.type == "address": s = "__gen_uint(%s, %d, %d)" % \ (value, start, end) + elif field.type == "padded": + s = "__gen_padded(%s, %d, %d)" % \ + (value, start, end) elif field.type in self.parser.enums: s = "__gen_uint(%s, %d, %d)" % \ (value, start, end) @@ -437,6 +467,8 @@ class Group(object): convert = "__gen_unpack_uint" elif field.type == "int": convert = "__gen_unpack_sint" + elif field.type == "padded": + convert = "__gen_unpack_padded" elif field.type == "bool": convert = "__gen_unpack_uint" elif field.type == "float": -- 2.30.2