pan/va/disasm: Clean up hardcoded values

A lot of masks and shifts were hard-coded in the disassembler. This
commit tries to move them to shared logic.

Reviewed-by: Christoph Pillmayer <christoph.pillmayer@arm.com>
Acked-by: Lorenzo Rossi <lorenzo.rossi@collabora.com>
Acked-by: Eric R. Smith <eric.smith@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40199>
This commit is contained in:
Lars-Ivar Hesselberg Simonsen 2026-03-02 14:59:01 +01:00 committed by Marge Bot
parent 614d07c986
commit 43c6f51a29
3 changed files with 69 additions and 47 deletions

View file

@ -215,7 +215,7 @@ def parse_asm(line):
for mod in parts[1:]:
# Encode the modifier
if mod in src.offset and src.bits[mod] == 1:
if mod in src.offset and src.mask[mod] == 0x1:
encoded |= (1 << src.offset[mod])
elif src.halfswizzle and mod in enums[f'half_swizzles_{src.size}_bit'].bare_values:
die_if(swizzled, "Multiple swizzles specified")
@ -320,7 +320,7 @@ def parse_asm(line):
# Encode FAU page
if fau.page:
encoded |= (fau.page << 57)
encoded |= (fau.page << ins.offset['fau_page'])
# Encode modifiers
has_flow = False
@ -331,7 +331,7 @@ def parse_asm(line):
if mod in enums['flow'].bare_values:
die_if(has_flow, "Multiple flow control modifiers specified")
has_flow = True
encoded |= (enums['flow'].bare_values.index(mod) << 59)
encoded |= (enums['flow'].bare_values.index(mod) << ins.offset['flow'])
else:
candidates = [c for c in ins.modifiers if mod in c.bare_values]

View file

@ -43,11 +43,8 @@ static const uint32_t va_immediates[32] = {
};
static inline void
va_print_src(FILE *fp, uint8_t src, unsigned fau_page)
va_print_src(FILE *fp, unsigned type, unsigned value, unsigned fau_page)
{
unsigned type = (src >> 6);
unsigned value = (src & 0x3F);
if (type == VA_SRC_IMM_TYPE) {
if (value >= 32) {
if (fau_page == 0)
@ -72,16 +69,13 @@ va_print_src(FILE *fp, uint8_t src, unsigned fau_page)
}
static inline void
va_print_float_src(FILE *fp, uint8_t src, unsigned fau_page, bool neg, bool abs)
va_print_float_src(FILE *fp, unsigned type, unsigned value, unsigned fau_page, bool neg, bool abs)
{
unsigned type = (src >> 6);
unsigned value = (src & 0x3F);
if (type == VA_SRC_IMM_TYPE) {
assert(value < 32 && "overflow in LUT");
fprintf(fp, "0x%X", va_immediates[value]);
} else {
va_print_src(fp, src, fau_page);
va_print_src(fp, type, value, fau_page);
}
if (neg)
@ -92,10 +86,8 @@ va_print_float_src(FILE *fp, uint8_t src, unsigned fau_page, bool neg, bool abs)
}
static inline void
va_print_dest(FILE *fp, uint8_t dest, bool can_mask)
va_print_dest(FILE *fp, unsigned mask, unsigned value, bool can_mask)
{
unsigned mask = (dest >> 6);
unsigned value = (dest & 0x3F);
fprintf(fp, "r%u", value);
/* Should write at least one component */
@ -118,12 +110,11 @@ va_print_dest(FILE *fp, uint8_t dest, bool can_mask)
% endif
% endif
% endfor
assert((instr & (1ull << 63)) == 0 /* reserved */);
fprintf(fp, "%s ", valhall_flow[instr >> 59]);
% if len(op.dests) > 0:
fprintf(fp, "%s ", valhall_flow[(instr >> ${op.offset['flow']}) & ${hex(op.mask['flow'])}]);
% for i, dest in enumerate(op.dests):
<% no_comma = False %>
va_print_dest(fp, (instr >> 40), true);
% endif
va_print_dest(fp, (instr >> ${dest.offset['mode']}) & ${hex(dest.mask['mode'])}, (instr >> ${dest.offset['value']}) & ${hex(dest.mask['value'])}, true);
% endfor
% for index, sr in enumerate(op.staging):
% if not no_comma:
fputs(", ", fp);
@ -132,19 +123,19 @@ va_print_dest(FILE *fp, uint8_t dest, bool can_mask)
no_comma = False
if sr.count != 0:
sr_count = sr.count
elif "staging_register_write_count" in [x.name for x in op.modifiers] and sr.write:
sr_count = "(((instr >> 36) & MASK(3)) + 1)"
elif "staging_register_count" in [x.name for x in op.modifiers]:
sr_count = "((instr >> 33) & MASK(3))"
sr_count = sr.count;
else:
assert(0)
for mod in op.modifiers:
if mod.name == "staging_register_write_count" and sr.write:
sr_count = f"(((instr >> {mod.start}) & {hex((1 << mod.size) - 1)}) + 1)";
elif mod.name == "staging_register_count":
sr_count = f"((instr >> {mod.start}) & {hex((1 << mod.size) - 1)})";
%>
// assert(((instr >> ${sr.start}) & 0xC0) == ${sr.encoded_flags});
fprintf(fp, "@");
for (unsigned i = 0; i < ${sr_count}; ++i) {
fprintf(fp, "%sr%u", (i == 0) ? "" : ":",
(uint32_t) (((instr >> ${sr.start}) & 0x3F) + i));
(uint32_t) (((instr >> ${sr.offset['value']}) & ${hex(sr.mask['value'])}) + i));
}
% endfor
% for i, src in enumerate(op.srcs):
@ -153,32 +144,35 @@ va_print_dest(FILE *fp, uint8_t dest, bool can_mask)
% endif
<% no_comma = False %>
% if src.absneg:
va_print_float_src(fp, instr >> ${src.start}, fau_page,
va_print_float_src(fp, (instr >> ${src.offset['mode']}) & ${hex(src.mask['mode'])}, (instr >> ${src.offset['value']}) & ${hex(src.mask['value'])},
(instr >> ${op.offset['fau_page']}) & ${hex(op.mask['fau_page'])},
instr & BIT(${src.offset['neg']}),
instr & BIT(${src.offset['abs']}));
% elif src.is_float:
va_print_float_src(fp, instr >> ${src.start}, fau_page, false, false);
va_print_float_src(fp, (instr >> ${src.offset['mode']}) & ${src.mask['mode']}, (instr >> ${src.offset['value']}) & ${hex(src.mask['value'])},
(instr >> ${op.offset['fau_page']}) & ${hex(op.mask['fau_page'])}, false, false);
% else:
va_print_src(fp, instr >> ${src.start}, fau_page);
va_print_src(fp, (instr >> ${src.offset['mode']}) & ${src.mask['mode']}, (instr >> ${src.offset['value']}) & ${hex(src.mask['value'])},
(instr >> ${op.offset['fau_page']}) & ${hex(op.mask['fau_page'])});
% endif
% if src.swizzle:
% if src.size == 32:
fputs(valhall_widen[(instr >> ${src.offset['swizzle']}) & 3], fp);
fputs(valhall_widen[(instr >> ${src.offset['swizzle']}) & ${hex(src.mask['swizzle'])}], fp);
% else:
fputs(valhall_swizzles_16_bit[(instr >> ${src.offset['swizzle']}) & 3], fp);
fputs(valhall_swizzles_16_bit[(instr >> ${src.offset['swizzle']}) & ${hex(src.mask['swizzle'])}], fp);
% endif
% endif
% if src.lanes:
fputs(valhall_lanes_8_bit[(instr >> ${src.offset['widen']}) & 0xF], fp);
fputs(valhall_lanes_8_bit[(instr >> ${src.offset['widen']}) & ${hex(src.mask['widen'])}], fp);
% elif src.halfswizzle:
fputs(valhall_half_swizzles_8_bit[(instr >> ${src.offset['widen']}) & 0xF], fp);
fputs(valhall_half_swizzles_8_bit[(instr >> ${src.offset['widen']}) & ${hex(src.mask['widen'])}], fp);
% elif src.widen:
fputs(valhall_swizzles_${src.size}_bit[(instr >> ${src.offset['widen']}) & 0xF], fp);
fputs(valhall_swizzles_${src.size}_bit[(instr >> ${src.offset['widen']}) & ${hex(src.mask['widen'])}], fp);
% elif src.combine:
fputs(valhall_combine[(instr >> ${src.offset['combine']}) & 0x7], fp);
fputs(valhall_combine[(instr >> ${src.offset['combine']}) & ${hex(src.mask['combine'])}], fp);
% endif
% if src.lane:
fputs(valhall_lane_${src.size}_bit[(instr >> ${src.lane}) & 0x3], fp);
fputs(valhall_lane_${src.size}_bit[(instr >> ${src.offset['lane']}) & ${hex(src.mask['lane'])}], fp);
% endif
% if 'not' in src.offset:
if (instr & BIT(${src.offset['not']})) fputs(".not", fp);
@ -216,7 +210,6 @@ void
va_disasm_instr(FILE *fp, uint64_t instr)
{
unsigned opcode;
unsigned fau_page = (instr >> 57) & MASK(2);
${recurse_subcodes(OPCODES)}
}

View file

@ -21,6 +21,9 @@ def xmlbool(s):
assert(s.lower() in ["false", "true"])
return False if s.lower() == "false" else True
def bitmask(size):
return (1 << size) - 1
class EnumValue:
def __init__(self, value, default):
self.value = value
@ -92,32 +95,46 @@ class Source:
self.name = name
self.offset = {}
self.bits = {}
self.mask = {}
self.offset['mode'] = self.start + 6
self.mask['mode'] = bitmask(2)
self.offset['value'] = self.start
self.mask['value'] = bitmask(6)
if absneg:
self.offset['neg'] = 32 + 2 + ((2 - index) * 2)
self.offset['abs'] = 33 + 2 + ((2 - index) * 2)
self.bits['neg'] = 1
self.bits['abs'] = 1
self.mask['neg'] = bitmask(1)
self.mask['abs'] = bitmask(1)
if notted:
self.offset['not'] = 35
self.bits['not'] = 1
self.mask['not'] = bitmask(1)
if widen or lanes or halfswizzle:
self.offset['widen'] = 26 if index == 1 else 36
self.bits['widen'] = 4 # XXX: too much?
self.mask['widen'] = bitmask(4)
if lane:
self.offset['lane'] = self.lane
self.bits['lane'] = 2 if size in (8, 32) else 1
self.mask['lane'] = bitmask(2) if size in (8, 32) else bitmask(1)
if swizzle:
assert(size in [16, 32])
self.offset['swizzle'] = 24 + ((2 - index) * 2)
self.bits['swizzle'] = 2
self.mask['swizzle'] = bitmask(2)
if combine:
self.offset['combine'] = 37
self.bits['combine'] = 3
self.mask['combine'] = bitmask(3)
class Dest:
def __init__(self, name = ""):
self.name = name
self.start = 40
self.offset = {}
self.mask = {}
self.offset['mode'] = self.start + 6
self.mask['mode'] = bitmask(2)
self.offset['value'] = self.start
self.mask['value'] = bitmask(6)
class Staging:
def __init__(self, read = False, write = False, count = 0, flags = 'true', name = ""):
@ -127,9 +144,13 @@ class Staging:
self.count = count
self.flags = (flags != 'false')
self.start = 40
if write and not self.flags:
self.start = 16
self.offset = {}
self.mask = {}
self.offset['value'] = self.start
self.mask['value'] = bitmask(6)
# For compatibility
self.absneg = False
@ -175,6 +196,14 @@ class Instruction:
self.unit = unit
self.is_signed = len(name.split(".")) > 1 and ('s' in name.split(".")[1])
self.offset = {}
self.mask = {}
self.offset['flow'] = 59
self.mask['flow'] = bitmask(4)
self.offset['fau_page'] = 57
self.mask['fau_page'] = bitmask(2)
# Message-passing instruction <===> not ALU instruction
self.message = unit not in ["FMA", "CVT", "SFU"]