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.
80 lines
2.6 KiB
Python
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)))
|