diff --git a/regs/.gitignore b/regs/.gitignore new file mode 100644 index 0000000..ac7dc36 --- /dev/null +++ b/regs/.gitignore @@ -0,0 +1,3 @@ +pvs_dst.py +pvs_src.py +pvs_dst_bits.py \ No newline at end of file diff --git a/regs/build.sh b/regs/build.sh new file mode 100644 index 0000000..7031397 --- /dev/null +++ b/regs/build.sh @@ -0,0 +1,5 @@ +set -eux + +python parse_pvs.py PVS_DST pvs_opcode_and_destination_operand.txt > pvs_dst.py +python parse_pvs.py PVS_SRC pvs_source_operand.txt > pvs_src.py +python parse_pvs_bits.py regs/pvs_opcode_and_destination_operand_bits.txt > pvs_dst_bits.py diff --git a/regs/parse_pvs.py b/regs/parse_pvs.py new file mode 100644 index 0000000..ebe4bda --- /dev/null +++ b/regs/parse_pvs.py @@ -0,0 +1,85 @@ +import sys +from typing import Union +import re +from dataclasses import dataclass +from pprint import pprint + +def split_line_fields(line): + fields = [0, 22, 30] + a = line[fields[0]:fields[1]] + b = line[fields[1]:fields[2]] + c = line[fields[2]:] + return a, b, c + +def parse_file_fields(filename): + with open(filename) as f: + lines = f.read().split('\n') + first, *rest = lines + a, b, c = split_line_fields(first) + assert a.rstrip() == 'Field Name', a + assert b.rstrip() == 'Bits', b + assert c.rstrip() == 'Description', c + + for line in rest: + if not line.strip(): + continue + a, b, c = split_line_fields(line) + yield a.strip(), b.strip(), c.strip() + +def parse_bits(s): + if ':' in s: + a, b = s.split(':') + h = int(a, 10) + l = int(b, 10) + assert h > l + return h, l + else: + b = int(s, 10) + return b + +def parse_file_fields2(filename): + for line in parse_file_fields(filename): + field_name, bits, description = line + bits = parse_bits(bits) + if not field_name.startswith(prefix + '_'): + assert field_name.startswith("SPARE_") + continue + field_name = field_name.removeprefix(prefix + '_') + yield field_name, bits, description + +def out(level, *args): + sys.stdout.write(" " * level + " ".join(args) + '\n') + +def mask_from_bits(bits): + if type(bits) is tuple: + high, low = bits + assert high > low, (high, low) + else: + high = bits + low = bits + length = (high - low) + 1 + return (1 << length) - 1 + +def low_from_bits(bits): + if type(bits) is tuple: + return bits[1] + else: + return bits + +def generate_python(prefix, fields): + #out(0, f"class {prefix}:") + fields = list(fields) + for field_name, bits, description in fields: + #out(1, f"@staticmethod") + out(0, f"def {field_name}(n):") + out(1, f"return (n >> {low_from_bits(bits)}) & {mask_from_bits(bits)}") + out(0, "") + + out(0, "table = [") + for field_name, bits, description in fields: + out(1, f'("{field_name}", {field_name}),') + out(0, "]") + +prefix = sys.argv[1] +filename = sys.argv[2] +generate_python(prefix, parse_file_fields2(filename)) diff --git a/regs/parse_pvs_bits.py b/regs/parse_pvs_bits.py new file mode 100644 index 0000000..92ac93a --- /dev/null +++ b/regs/parse_pvs_bits.py @@ -0,0 +1,30 @@ +import sys + +with open(sys.argv[1]) as f: + lines = f.read().strip().split('\n') + + + +ix = 0 + +def next_ix(): + global ix + while not lines[ix].strip(): + ix += 1 + return ix + +while ix < len(lines): + name = lines[next_ix()] + assert name.strip().endswith(":") + name = name.strip().removesuffix(":") + ix += 1 + + print(f"{name} = {{") + while ix < len(lines) and not lines[next_ix()].strip().endswith(":"): + key, value = lines[next_ix()].split("=") + if key.startswith("PVS_DST_REG_"): + key = key.removeprefix("PVS_DST_REG_") + print(f' {value.strip()}: "{key.strip()}",') + ix += 1 + print("}") + print() diff --git a/regs/pvs_disassemble.py b/regs/pvs_disassemble.py new file mode 100644 index 0000000..846699e --- /dev/null +++ b/regs/pvs_disassemble.py @@ -0,0 +1,55 @@ +import pvs_src +import pvs_dst +import pvs_dst_bits +from pprint import pprint + +code = [ + 0xf00203, + 0xd10001, + 0x1248001, + 0x1248001 +] + +def out(level, *args): + sys.stdout.write(" " * level + " ".join(args)) + +def parse_code(code): + + ix = 0 + + pvs_dst_maxlen = max(len(k) for k, _ in pvs_dst.table) + print(pvs_dst_maxlen) + + while ix < len(code): + print(f"ix: {ix // 4}") + dst_op = code[ix + 0] + src_op0 = code[ix + 1] + src_op1 = code[ix + 2] + src_op2 = code[ix + 3] + print(f" dst: {dst_op:08x}") + for name, parse in pvs_dst.table: + namepad = name.ljust(pvs_dst_maxlen + 1) + value = parse(dst_op) + if name == "OPCODE": + if pvs_dst.MATH_INST(dst_op): + print(" ", namepad, pvs_dst_bits.MATH_OPCODE[value]) + else: + print(" ", namepad, pvs_dst_bits.VECTOR_OPCODE[value]) + elif name == "REG_TYPE": + print(" ", namepad, pvs_dst_bits.PVS_DST_REG[value]) + else: + print(" ", namepad, value) + + print(f" src0: {src_op0:08x}") + for name, parse in pvs_src.table: + print(" ", name, parse(src_op0)) + print(f" src1: {src_op1:08x}") + for name, parse in pvs_src.table: + print(" ", name, parse(src_op1)) + print(f" src2: {src_op2:08x}") + for name, parse in pvs_src.table: + print(" ", name, parse(src_op2)) + + ix += 4 + +parse_code(code) diff --git a/regs/pvs_dual_math_instruction.txt b/regs/pvs_dual_math_instruction.txt index f0b0188..f876d92 100644 --- a/regs/pvs_dual_math_instruction.txt +++ b/regs/pvs_dual_math_instruction.txt @@ -2,10 +2,7 @@ Field Name Bit(s) Description PVS_SRC_REG_TYPE 1:0 Defines the Memory Select (Register Type) for the Source Operand. See Below. PVS_DST_OPCODE_MSB 2 Math Opcode MSB for Dual Math Inst. PVS_SRC_ABS_XYZW 3 If set, Take absolute value of both components of Dual Math input vector. -PVS_SRC_ADDR_MODE_0 4 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE as follows: - 0 = Absolute addressing - 1 = Relative addressing using A0 register - 2 = Relative addressing using I0 register (loop index) +PVS_SRC_ADDR_MODE_0 4 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE PVS_SRC_OFFSET 12:5 Vector Offset into selected memory (Register Type) PVS_SRC_SWIZZLE_X 15:13 X-Component Swizzle Select. See Below PVS_SRC_SWIZZLE_Y 18:16 Y-Component Swizzle Select. See Below @@ -15,7 +12,4 @@ PVS_SRC_MODIFIER_X 25 If set, Negate X Component of input vector. PVS_SRC_MODIFIER_Y 26 If set, Negate Y Component of input vector. PVS_DST_WE_SEL 28:27 Encoded Write Enable for Dual Math Op Inst (0 = X, 1 = Y, 2 = Z, 3 = W) PVS_SRC_ADDR_SEL 30:29 When PVS_SRC_ADDR_MODE is set, this selects which component of the 4-component address register to use. -PVS_SRC_ADDR_MODE_1 31 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE as follows: - 0 = Absolute addressing - 1 = Relative addressing using A0 register - 2 = Relative addressing using I0 register (loop index) +PVS_SRC_ADDR_MODE_1 31 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE diff --git a/regs/pvs_opcode_and_destination_operand.txt b/regs/pvs_opcode_and_destination_operand.txt index 5554ad4..bdd6612 100644 --- a/regs/pvs_opcode_and_destination_operand.txt +++ b/regs/pvs_opcode_and_destination_operand.txt @@ -1,18 +1,18 @@ -Field Name Bits Description -PVS_DST_OPCODE 5:0 Selects the Operation which is to be performed. -PVS_DST_MATH_INST 6 Specifies a Math Engine Operation -PVS_DST_MACRO_INST 7 Specifies a Macro Operation -PVS_DST_REG_TYPE 11:8 Defines the Memory Select (Register Type) for the Dest Operand. -PVS_DST_ADDR_MODE_1 12 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE -PVS_DST_OFFSET 20 Vector Offset into the Selected Memory -PVS_DST_WE_X 21 Write Enable for X Component -PVS_DST_WE_Y 22 Write Enable for Y Component -PVS_DST_WE_Z 23 Write Enable for Z Component -PVS_DST_WE_W 24 Write Enable for W Component -PVS_DST_VE_SAT 19:13 Vector engine operation is saturate clamped between 0 and 1 (all components) -PVS_DST_ME_SAT 25 Math engine operation is saturate clamped between 0 and 1 (all components) -PVS_DST_PRED_ENABLE 26 Operation is predicated – Operation writes if predicate bit matches predicate sense. -PVS_DST_PRED_SENSE 27 Operation predication sense – If set, operation writes if predicate bit is set. If reset, operation writes if predicate bit is reset. -PVS_DST_DUAL_MATH_OP 28 Set to describe a dual-math op. -PVS_DST_ADDR_SEL 30:29 When PVS_DST_ADDR_MODE is set, this selects which component of the 4-component address register to use. -PVS_DST_ADDR_MODE_0 31 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE +Field Name Bits Description +PVS_DST_OPCODE 5:0 Selects the Operation which is to be performed. +PVS_DST_MATH_INST 6 Specifies a Math Engine Operation +PVS_DST_MACRO_INST 7 Specifies a Macro Operation +PVS_DST_REG_TYPE 11:8 Defines the Memory Select (Register Type) for the Dest Operand. +PVS_DST_ADDR_MODE_1 12 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE +PVS_DST_OFFSET 19:13 Vector Offset into the Selected Memory +PVS_DST_WE_X 20 Write Enable for X Component +PVS_DST_WE_Y 21 Write Enable for Y Component +PVS_DST_WE_Z 22 Write Enable for Z Component +PVS_DST_WE_W 23 Write Enable for W Component +PVS_DST_VE_SAT 24 Vector engine operation is saturate clamped between 0 and 1 (all components) +PVS_DST_ME_SAT 25 Math engine operation is saturate clamped between 0 and 1 (all components) +PVS_DST_PRED_ENABLE 26 Operation is predicated – Operation writes if predicate bit matches predicate sense. +PVS_DST_PRED_SENSE 27 Operation predication sense – If set, operation writes if predicate bit is set. If reset, operation writes if predicate bit is reset. +PVS_DST_DUAL_MATH_OP 28 Set to describe a dual-math op. +PVS_DST_ADDR_SEL 30:29 When PVS_DST_ADDR_MODE is set, this selects which component of the 4-component address register to use. +PVS_DST_ADDR_MODE_0 31 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE diff --git a/regs/pvs_opcode_and_destination_operand_bits.txt b/regs/pvs_opcode_and_destination_operand_bits.txt index 695afd7..57eae2a 100644 --- a/regs/pvs_opcode_and_destination_operand_bits.txt +++ b/regs/pvs_opcode_and_destination_operand_bits.txt @@ -58,3 +58,14 @@ ME_PRED_SET_CLR = 25 ME_PRED_SET_INV = 26 ME_PRED_SET_POP = 27 ME_PRED_SET_RESTORE = 28 +PVS_DST_REG: +PVS_DST_REG_TEMPORARY = 0 +PVS_DST_REG_A0 = 1 +PVS_DST_REG_OUT = 2 +PVS_DST_REG_OUT_REPL_X = 3 +PVS_DST_REG_ALT_TEMPORARY = 4 +PVS_DST_REG_INPUT = 5 +ADDR_MODE: +ABSOLUTE = 0 +RELATIVE_A0 = 1 +RELATIVE_I0 = 2 diff --git a/regs/pvs_source_operand.txt b/regs/pvs_source_operand.txt index 973639b..382c8f8 100644 --- a/regs/pvs_source_operand.txt +++ b/regs/pvs_source_operand.txt @@ -1,16 +1,16 @@ -Field Name Bit(s) Description -PVS_SRC_REG_TYPE 1:0 Defines the Memory Select (Register Type) for the Source Operand. See Below. -SPARE_0 2 -PVS_SRC_ABS_XYZW 3 If set, Take absolute value of all 4 components of input vector. -PVS_SRC_ADDR_MODE_0 4 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE -PVS_SRC_OFFSET 12:5 Vector Offset into selected memory (Register Type) -PVS_SRC_SWIZZLE_X 15:13 X-Component Swizzle Select. See Below -PVS_SRC_SWIZZLE_Y 18:16 Y-Component Swizzle Select. See Below -PVS_SRC_SWIZZLE_Z 21:19 Z-Component Swizzle Select. See Below -PVS_SRC_SWIZZLE_W 24:22 W-Component Swizzle Select. See Below -PVS_SRC_MODIFIER_X 25 If set, Negate X Component of input vector. -PVS_SRC_MODIFIER_Y 26 If set, Negate Y Component of input vector. -PVS_SRC_MODIFIER_Z 27 If set, Negate Z Component of input vector. -PVS_SRC_MODIFIER_W 28 If set, Negate W Component of input vector. -PVS_SRC_ADDR_SEL 30:29 When PVS_SRC_ADDR_MODE is set, this selects which component of the 4-component address register to use. -PVS_SRC_ADDR_MODE_1 31 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE +Field Name Bits Description +PVS_SRC_REG_TYPE 1:0 Defines the Memory Select (Register Type) for the Source Operand. See Below. +SPARE_0 2 +PVS_SRC_ABS_XYZW 3 If set, Take absolute value of all 4 components of input vector. +PVS_SRC_ADDR_MODE_0 4 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE +PVS_SRC_OFFSET 12:5 Vector Offset into selected memory (Register Type) +PVS_SRC_SWIZZLE_X 15:13 X-Component Swizzle Select. See Below +PVS_SRC_SWIZZLE_Y 18:16 Y-Component Swizzle Select. See Below +PVS_SRC_SWIZZLE_Z 21:19 Z-Component Swizzle Select. See Below +PVS_SRC_SWIZZLE_W 24:22 W-Component Swizzle Select. See Below +PVS_SRC_MODIFIER_X 25 If set, Negate X Component of input vector. +PVS_SRC_MODIFIER_Y 26 If set, Negate Y Component of input vector. +PVS_SRC_MODIFIER_Z 27 If set, Negate Z Component of input vector. +PVS_SRC_MODIFIER_W 28 If set, Negate W Component of input vector. +PVS_SRC_ADDR_SEL 30:29 When PVS_SRC_ADDR_MODE is set, this selects which component of the 4-component address register to use. +PVS_SRC_ADDR_MODE_1 31 Combine ADDR_MODE_1 (msb) with ADDR_MODE_0 (lsb) to form 2-bit ADDR_MODE