import sys from collections import defaultdict from instruction_table import untabulate_instructions_sh4 from instruction_table import untabulate_instructions_sh2 from instruction_function_name import instruction_function_name from generate import renderer from disabled_instructions import disabled_instructions def b16(n): bits = [] for i in range(16): bits.append((n >> i) & 1) return '0b' + ''.join(map(str, reversed(bits))) def format_variables(ins): s = ins.operands for i, name in enumerate(ins.variables): if 'disp' in s and name == 'd': name = 'disp' if 'imm' in s and name == 'i': name = 'imm' if 'label' in s and name == 'd': name = 'label' s = s.replace(name, "%d") return s def render_print(ins): variable_args = ", " + ", ".join(ins.variables) if ins.variables else "" operands = format_variables(ins) if operands: yield f'snprintf(operand_buf, size, "{operands}"{variable_args});' else: yield "operand_buf[0] = 0;"; yield f'*instruction_buf = "{ins.instruction}";' def render_execute(ins): function_name = instruction_function_name(ins) variable_args = ", " + ", ".join(ins.variables) if ins.variables else "" yield f"{function_name}(state, map{variable_args});" def render_mask_switch(body_func, mask, instructions): yield f"switch (code & {b16(mask)}) {{" for ins in instructions: yield f"case {b16(ins.code.code_bits)}: // {ins.instruction} {ins.operands}" yield "{" for variable in ins.variables: operand_var = ins.code.operands[variable] yield f"uint32_t {variable} = (code >> {operand_var.lsb}) & ((1 << {operand_var.length}) - 1);" yield from body_func(ins) yield f"return DECODE__DEFINED;" yield "}" yield "}" def render_mask_switches(body_func, by_mask): yield "{" for mask, instructions in by_mask.items(): instructions = sorted(instructions, key=lambda i: i.code.code_bits) yield from render_mask_switch(body_func, mask, instructions) yield "return DECODE__UNDEFINED;" yield "}" def render_decode_and_execute(by_mask): yield f"enum decode_status decode_and_execute_instruction(struct architectural_state * state, struct memory_map * map, uint16_t code)" yield from render_mask_switches(render_execute, by_mask) def render_decode_and_print(by_mask): yield f"enum decode_status decode_and_print_instruction(struct architectural_state * state, struct memory_map * map, uint16_t code, char const ** instruction_buf, char * operand_buf, uint32_t size)" yield from render_mask_switches(render_print, by_mask) def header_execute(): yield '#include "decode_execute.h"' yield '#include "impl.h"' yield "" def header_print(): yield '#include ' yield "" yield '#include "decode_print.h"' yield "" def main(): by_mask = defaultdict(list) masks = [] for ins in untabulate_instructions_sh4(): if ins.instruction in disabled_instructions: continue if ins.code.mask_bits not in masks: masks.append(ins.code.mask_bits) by_mask[ins.code.mask_bits].append(ins) render, out = renderer() render(header_execute()) render(render_decode_and_execute(by_mask)) with open(sys.argv[1], 'w') as f: f.write(out.getvalue()) render, out = renderer() render(header_print()) render(render_decode_and_print(by_mask)) with open(sys.argv[2], 'w') as f: f.write(out.getvalue()) if __name__ == "__main__": main()