diff --git a/regs/bits/us_alu_alpha_addr.txt b/regs/bits/us_alu_alpha_addr.txt index 9a2acdc..131e1ae 100644 --- a/regs/bits/us_alu_alpha_addr.txt +++ b/regs/bits/us_alu_alpha_addr.txt @@ -64,7 +64,7 @@ ADDR2_REL 29 0x0 Specifies whether the loop register is added to 01 - RELATIVE: Add aL before lookup. SRCP_OP 31:30 0x0 Specifies how the pre-subtract value (SRCP) is computed. POSSIBLE VALUES: - 00 - 1.0-2.0*A0 - 01 - A1-A0 - 02 - A1+A0 - 03 - 1.0-A0 + 00 - neg2: 1.0-2.0*A0 + 01 - sub: A1-A0 + 02 - add: A1+A0 + 03 - neg: 1.0-A0 diff --git a/regs/bits/us_alu_rgb_addr.txt b/regs/bits/us_alu_rgb_addr.txt index c7eb295..9ce067a 100644 --- a/regs/bits/us_alu_rgb_addr.txt +++ b/regs/bits/us_alu_rgb_addr.txt @@ -65,7 +65,7 @@ ADDR2_REL 29 0x0 Specifies whether the loop register is added to SRCP_OP 31:30 0x0 Specifies how the pre-subtract value (SRCP) is computed. POSSIBLE VALUES: - 00 - 1.0-2.0*RGB0 - 01 - RGB1-RGB0 - 02 - RGB1+RGB0 - 03 - 1.0-RGB0 + 00 - neg2: 1.0-2.0*RGB0 + 01 - sub: RGB1-RGB0 + 02 - add: RGB1+RGB0 + 03 - neg: 1.0-RGB0 diff --git a/regs/us_disassemble.py b/regs/us_disassemble.py index 3592f81..652176d 100644 --- a/regs/us_disassemble.py +++ b/regs/us_disassemble.py @@ -45,8 +45,10 @@ fc = [ ] def parse_registers(): + base = path.dirname(__file__) + for register in register_names: - filename = path.join("bits", register.lower() + ".txt") + filename = path.join(base, "bits", register.lower() + ".txt") l = list(parse_bits.parse_file_fields(filename)) yield register, OrderedDict( (d.field_name, d) for d in parse_bits.aggregate(l) @@ -142,5 +144,4 @@ if __name__ == "__main__": buf = f.read() code = [parse_hex(c.strip()) for c in buf.split(',') if c.strip()] for i in range(len(code) // 6): - disassemble(code, i * 6) diff --git a/regs/us_disassemble2.py b/regs/us_disassemble2.py new file mode 100644 index 0000000..b15e9ed --- /dev/null +++ b/regs/us_disassemble2.py @@ -0,0 +1,186 @@ +import sys +from os import path +import parse_bits +from collections import OrderedDict +from functools import partial +from pprint import pprint + +class BaseRegister: + def get(self, n, *, descriptor): + if type(descriptor.bits) is int: + return (n >> descriptor.bits) & 1 + else: + high, low = descriptor.bits + assert high > low + mask_length = (high - low) + 1 + mask = (1 << mask_length) - 1 + return (n >> low) & mask + + def get_name(self, n, *, descriptor): + value = self.get(n, descriptor=descriptor) + return value, *descriptor.possible_values[value] + +def parse_register(register_name): + base = path.dirname(__file__) + + filename = path.join(base, "bits", register_name.lower() + ".txt") + l = list(parse_bits.parse_file_fields(filename)) + #return OrderedDict( + # (d.field_name, d) for d in parse_bits.aggregate(l) + #) + cls = type(register_name, (BaseRegister,), {}) + instance = cls() + descriptors = list(parse_bits.aggregate(l)) + for descriptor in descriptors: + setattr(instance, descriptor.field_name, partial(instance.get, descriptor=descriptor)) + setattr(instance, f"_{descriptor.field_name}", partial(instance.get_name, descriptor=descriptor)) + func = getattr(instance, descriptor.field_name) + for pv_value, (pv_name, _) in descriptor.possible_values.items(): + if pv_name is not None: + setattr(func, pv_name, pv_value) + assert getattr(instance, "descriptors", None) is None + instance.descriptors = descriptors + + return instance + +US_CMN_INST = parse_register("US_CMN_INST") +US_ALU_RGB_ADDR = parse_register("US_ALU_RGB_ADDR") +US_ALU_ALPHA_ADDR = parse_register("US_ALU_ALPHA_ADDR") +US_ALU_RGB_INST = parse_register("US_ALU_RGB_INST") +US_ALU_ALPHA_INST = parse_register("US_ALU_ALPHA_INST") +US_ALU_RGBA_INST = parse_register("US_ALU_RGBA_INST") +US_TEX_INST = parse_register("US_TEX_INST") +US_TEX_ADDR = parse_register("US_TEX_ADDR") +US_TEX_ADDR_DXDY = parse_register("US_TEX_ADDR_DXDY") +US_FC_INST = parse_register("US_FC_INST") +US_FC_ADDR = parse_register("US_FC_ADDR") + +def disassemble_addr_inner(register_const, address, const, rel): + assert rel == 0 + if const == register_const.TEMPORARY: + if address & (1 << 7): + value = address & 0x7f + return f"float({value})" + else: + return f"temp[{address}]" + elif const == register_const.CONSTANT: + return f"const[{address}]" + else: + assert False, const + +def disassemble_addr(register, addr, prefix): + addr0 = register.ADDR0(addr) + addr0_const = register.ADDR0_CONST(addr) + addr0_rel = register.ADDR0_REL(addr) + addr1 = register.ADDR1(addr) + addr1_const = register.ADDR1_CONST(addr) + addr1_rel = register.ADDR1_REL(addr) + addr2 = register.ADDR2(addr) + addr2_const = register.ADDR2_CONST(addr) + addr2_rel = register.ADDR2_REL(addr) + _, srcp_op, _ = register._SRCP_OP(addr) + + s0 = disassemble_addr_inner(register.ADDR0_CONST, addr0, addr0_const, addr0_rel) + s1 = disassemble_addr_inner(register.ADDR1_CONST, addr1, addr1_const, addr1_rel) + s2 = disassemble_addr_inner(register.ADDR2_CONST, addr2, addr2_const, addr2_rel) + sp = srcp_op.lower() + return [ + f"{prefix}{i} = {s}" + for i, s in [('0', s0), ('1', s1), ('2', s2), ('p', sp)] + ] + +swizzle_strs = ['r', 'g', 'b', 'a', '0', 'h', '1', '_'] +sel_strs = ['0', '1', '2', 'p'] + +def disassemble_rgb_swizzle_sel(us_alu_rgb_inst, us_alu_rgba_inst): + rgb_sel_a = US_ALU_RGB_INST.RGB_SEL_A(us_alu_rgb_inst) + red_swiz_a = US_ALU_RGB_INST.RED_SWIZ_A(us_alu_rgb_inst) + green_swiz_a = US_ALU_RGB_INST.GREEN_SWIZ_A(us_alu_rgb_inst) + blue_swiz_a = US_ALU_RGB_INST.BLUE_SWIZ_A(us_alu_rgb_inst) + rgb_mod_a = US_ALU_RGB_INST.RGB_MOD_A(us_alu_rgb_inst) + + rgb_sel_b = US_ALU_RGB_INST.RGB_SEL_B(us_alu_rgb_inst) + red_swiz_b = US_ALU_RGB_INST.RED_SWIZ_B(us_alu_rgb_inst) + green_swiz_b = US_ALU_RGB_INST.GREEN_SWIZ_B(us_alu_rgb_inst) + blue_swiz_b = US_ALU_RGB_INST.BLUE_SWIZ_B(us_alu_rgb_inst) + rgb_mod_b = US_ALU_RGB_INST.RGB_MOD_B(us_alu_rgb_inst) + + rgb_sel_c = US_ALU_RGBA_INST.RGB_SEL_C(us_alu_rgba_inst) + red_swiz_c = US_ALU_RGBA_INST.RED_SWIZ_C(us_alu_rgba_inst) + green_swiz_c = US_ALU_RGBA_INST.GREEN_SWIZ_C(us_alu_rgba_inst) + blue_swiz_c = US_ALU_RGBA_INST.BLUE_SWIZ_C(us_alu_rgba_inst) + rgb_mod_c = US_ALU_RGBA_INST.RGB_MOD_C(us_alu_rgba_inst) + + assert rgb_mod_a == 0 + assert rgb_mod_b == 0 + assert rgb_mod_c == 0 + + rgb_swiz_a = ''.join(swizzle_strs[n] for n in [red_swiz_a, green_swiz_a, blue_swiz_a]) + rgb_swiz_b = ''.join(swizzle_strs[n] for n in [red_swiz_b, green_swiz_b, blue_swiz_b]) + rgb_swiz_c = ''.join(swizzle_strs[n] for n in [red_swiz_c, green_swiz_c, blue_swiz_c]) + + rgb_swiz = [rgb_swiz_a, rgb_swiz_b, rgb_swiz_c] + rgb_sels = [sel_strs[n] for n in [rgb_sel_a, rgb_sel_b, rgb_sel_c]] + + return ", ".join(f"rgb{sel}.{swiz}" for swiz, sel in zip(rgb_swiz, rgb_sels)) + +def disassemble_a_swizzle_sel(us_alu_alpha_inst, us_alu_rgba_inst): + alpha_sel_a = US_ALU_ALPHA_INST.ALPHA_SEL_A(us_alu_alpha_inst) + alpha_swiz_a = US_ALU_ALPHA_INST.ALPHA_SWIZ_A(us_alu_alpha_inst) + alpha_mod_a = US_ALU_ALPHA_INST.ALPHA_MOD_A(us_alu_alpha_inst) + + alpha_sel_b = US_ALU_ALPHA_INST.ALPHA_SEL_B(us_alu_alpha_inst) + alpha_swiz_b = US_ALU_ALPHA_INST.ALPHA_SWIZ_B(us_alu_alpha_inst) + alpha_mod_b = US_ALU_ALPHA_INST.ALPHA_MOD_B(us_alu_alpha_inst) + + alpha_sel_c = US_ALU_RGBA_INST.ALPHA_SEL_C(us_alu_rgba_inst) + alpha_swiz_c = US_ALU_RGBA_INST.ALPHA_SWIZ_C(us_alu_rgba_inst) + alpha_mod_c = US_ALU_RGBA_INST.ALPHA_MOD_C(us_alu_rgba_inst) + + assert alpha_mod_a == 0 + assert alpha_mod_b == 0 + assert alpha_mod_c == 0 + + a_swiz = [swizzle_strs[n] for n in [alpha_swiz_a, alpha_swiz_b, alpha_swiz_c]] + a_sels = [sel_strs[n] for n in [alpha_sel_a, alpha_sel_b, alpha_sel_c]] + + return ", ".join(f"a{sel}.{swiz}" for swiz, sel in zip(a_swiz, a_sels)) + +def disassemble_alu(ix, code): + us_cmn_inst = code[ix + 0] + us_alu_rgb_addr = code[ix + 1] + us_alu_alpha_addr = code[ix + 2] + us_alu_rgb_inst = code[ix + 3] + us_alu_alpha_inst = code[ix + 4] + us_alu_rgba_inst = code[ix + 5] + + rgb_addr_strs = disassemble_addr(US_ALU_RGB_ADDR, us_alu_rgb_addr, "rgb") + a_addr_strs = disassemble_addr(US_ALU_ALPHA_ADDR, us_alu_alpha_addr, "a") + print(", ".join([*rgb_addr_strs, *a_addr_strs])) + + rgb_swizzle_sel = disassemble_rgb_swizzle_sel(us_alu_rgb_inst, us_alu_rgba_inst) + a_swizzle_sel = disassemble_a_swizzle_sel(us_alu_alpha_inst, us_alu_rgba_inst) + + #omod + #target + #alu_wmask + +def disassemble(ix, code): + value = US_CMN_INST.TYPE(code[ix + 0]) + alu_types = {US_CMN_INST.TYPE.US_INST_TYPE_OUT, US_CMN_INST.TYPE.US_INST_TYPE_ALU} + if value in alu_types: + disassemble_alu(ix, code) + else: + assert False, US_CMN_INST._TYPE(code[ix + 0]) + +def parse_hex(s): + assert s.startswith('0x') + return int(s.removeprefix('0x'), 16) + +if __name__ == "__main__": + filename = sys.argv[1] + with open(filename) as f: + buf = f.read() + code = [parse_hex(c.strip()) for c in buf.split(',') if c.strip()] + for i in range(len(code) // 6): + disassemble(i * 6, code)