sh-dis/generate_bits.py
Zack Buhman ea3c389944 add non-FPU/UBC/MMU/cache SH4 instructions
Previously, ast transformations were performed informally as ad-hoc
modifications to the generated C source code. In this commit, the
same transformations are performed by rewriting the ast prior to code
generation time.

The most significant new transformer is transform_assignment_list.
This transforms assignments such as:

  a, b, c = f(b, c, d)

To:

  a = f(&b, &c, d)

The former syntax is used frequently in the manual's description of
FPU-related instructions.
2024-04-22 21:34:43 +08:00

80 lines
2.6 KiB
Python

sr_bits = (
("T" , 0 , 1), # true/false condition
("S" , 1 , 1), # saturation
("IMASK", 4 , 4), # interrupt mask level, 4 bits
("Q" , 8 , 1), # state for divide step
("M" , 9 , 1), # state for divide step
("FD" , 15, 1), # FPU disable
("BL" , 28, 1), # Exception/interrupt block bit
("RB" , 29, 1), # General register bank specifier in privileged mode
("MD" , 30, 1), # Processor mode
)
fpscr_bits = (
("RM" , 0, 2), # Rounding mode
("FLAG_INEXACT" , 2, 1),
("FLAG_UNDERFLOW" , 3, 1),
("FLAG_OVERFLOW" , 4, 1),
("FLAG_DIVISION_BY_ZERO" , 5, 1),
("FLAG_INVALID_OPERATION" , 6, 1),
("ENABLE_INEXACT" , 7, 1),
("ENABLE_UNDERFLOW" , 8, 1),
("ENABLE_OVERFLOW" , 9, 1),
("ENABLE_DIVISION_BY_ZERO", 10, 1),
("ENABLE_INVALID" , 11, 1),
("CAUSE_INEXACT" , 12, 1),
("CAUSE_UNDERFLOW" , 13, 1),
("CAUSE_OVERFLOW" , 14, 1),
("CAUSE_DIVISION_BY_ZERO" , 15, 1),
("CAUSE_INVALID" , 16, 1),
("CAUSE_FPU_ERROR" , 17, 1),
("DN" , 18, 1), # Denormalization mode
("PR" , 19, 1), # Precision mode
("SZ" , 20, 1), # Transfer size mode
("FR" , 21, 1), # Floating-point register bank
)
def generate_bitfield(bits, start=0, end=31):
res = 0
current = start
for name, index, length in bits:
if index != current:
size = index - current
yield f"_res{res}", size
res += 1
yield name, length
current = index + length
end_len = end + 1
if current != end_len:
yield f"_res{res}", end_len - current
def generate_bitfield_little(bits):
return generate_bitfield(bits)
def generate_bitfield_big(bits):
return reversed(list(generate_bitfield(bits)))
def generate(struct_name, bits):
yield ""
yield f"struct {struct_name} {{"
yield "#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__"
for name, size in generate_bitfield_little(bits):
yield f" uint32_t {name.lower()} : {size};"
yield "#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__"
for name, size in generate_bitfield_big(bits):
yield f" uint32_t {name.lower()} : {size};"
yield "#else"
yield '# error "unsupported endianness"'
yield "#endif"
yield "};"
yield ""
if __name__ == "__main__":
print("#pragma once")
print()
print("#include <stdint.h>")
print()
print('\n'.join(generate("sr_bits", sr_bits)))
print('\n'.join(generate("fpscr_bits", fpscr_bits)))