Coverage for MC6809/components/cpu_utils/Instruction_generator.py: 28%
99 statements
« prev ^ index » next coverage.py v7.2.1, created at 2023-03-06 19:50 +0100
« prev ^ index » next coverage.py v7.2.1, created at 2023-03-06 19:50 +0100
1#!/usr/bin/env python3
3"""
4 MC6809 - 6809 CPU emulator in Python
5 =======================================
7 :copyleft: 2013-2015 by the MC6809 team, see AUTHORS for more details.
8 :license: GNU GPL v3 or above, see LICENSE for more details.
9"""
12import os
13import sys
15from MC6809.components.MC6809data.MC6809_data_utils import MC6809OP_DATA_DICT
16from MC6809.components.MC6809data.MC6809_op_data import (
17 BYTE,
18 OP_DATA,
19 REG_A,
20 REG_B,
21 REG_CC,
22 REG_D,
23 REG_DP,
24 REG_PC,
25 REG_S,
26 REG_U,
27 REG_X,
28 REG_Y,
29 WORD,
30)
33SPECIAL_FUNC_NAME = "special"
35REGISTER_DICT = {
36 REG_X: "index_x",
37 REG_Y: "index_y",
39 REG_U: "user_stack_pointer",
40 REG_S: "system_stack_pointer",
42 REG_PC: "program_counter",
44 REG_A: "accu_a",
45 REG_B: "accu_b",
46 REG_D: "accu_d",
48 REG_DP: "direct_page",
49 REG_CC: "cc_register",
51 # undefined_reg.name:"undefined_reg", # for TFR", EXG
52}
55if __doc__: 55 ↛ 58line 55 didn't jump to line 58, because the condition on line 55 was never false
56 DOC = __doc__.rsplit("=", 1)[1]
57else:
58 DOC = "" # e.g.: run with --OO
60INIT_CODE = f'''
61""\"
62 This file was generated with: "{os.path.basename(__file__)}"
63 Please don't change it directly ;)
64 {DOC}
65""\"
68from MC6809.components.cpu_utils.instruction_base import InstructionBase
70class PrepagedInstructions(InstructionBase):
71 def __init__(self, *args, **kwargs):
72 super(PrepagedInstructions, self).__init__(*args, **kwargs)
74 self.write_byte = self.cpu.memory.write_byte
75 self.write_word = self.cpu.memory.write_word
77'''
80def build_func_name(addr_mode, ea, register, read, write):
81 # print(addr_mode, ea, register, read, write
83 if addr_mode is None:
84 return SPECIAL_FUNC_NAME
86 func_name = addr_mode.lower()
88 if ea:
89 func_name += "_ea"
90 if register:
91 func_name += f"_{register}"
92 if read:
93 func_name += f"_read{read}"
94 if write:
95 func_name += f"_write{write}"
97# print(func_name
98 return func_name
101def func_name_from_op_code(op_code):
102 op_code_data = MC6809OP_DATA_DICT[op_code]
103 addr_mode = op_code_data["addr_mode"]
104 ea = op_code_data["needs_ea"]
105 register = op_code_data["register"]
106 read = op_code_data["read_from_memory"]
107 write = op_code_data["write_to_memory"]
108 return build_func_name(addr_mode, ea, register, read, write)
111def generate_code(f):
112 addr_modes = set()
113 registers = set()
114 variants = set()
115 for instr_data in list(OP_DATA.values()):
116 for mnemonic, mnemonic_data in list(instr_data["mnemonic"].items()):
117 read_from_memory = mnemonic_data["read_from_memory"]
118 write_to_memory = mnemonic_data["write_to_memory"]
119 needs_ea = mnemonic_data["needs_ea"]
120 register = mnemonic_data["register"]
121 for op_code, op_data in list(mnemonic_data["ops"].items()):
122 addr_mode = op_data["addr_mode"]
123# print(hex(op_code),
125 if addr_mode is None:
126 # special function (RESET/ PAGE1,2) defined in InstructionBase
127 print("address mode is None:", mnemonic, op_data)
128 continue
130 addr_mode = addr_mode.lower()
132 variant = (addr_mode, needs_ea, register, read_from_memory, write_to_memory)
133 # print(variant)
134 variants.add(variant)
136 if needs_ea and read_from_memory:
137 addr_modes.add(f"get_ea_m_{addr_mode}")
138 elif needs_ea:
139 addr_modes.add(f"get_ea_{addr_mode}")
140 elif read_from_memory:
141 addr_modes.add(f"get_m_{addr_mode}")
143 if register is not None:
144 registers.add(register)
146# if (addr_mode and needs_ea and register and read_from_memory and write_to_memory) is None:
148 variants = list(variants)
149 variants.sort(key=lambda x: "".join(f"{i}" for i in x))
151 # for no, data in enumerate(variants):
152 # print(no, data)
153 # print("+++++++++++++")
155 for line in INIT_CODE.splitlines():
156 f.write(f"{line}\n")
158 for register in sorted(REGISTER_DICT[register] for register in registers):
159 f.write(
160 " self.{r}=self.cpu.{r}\n".format(
161 r=register,
162 )
163 )
164 f.write("\n")
166 for addr_mode in sorted(addr_modes):
167 f.write(
168 " self.{a}=self.cpu.{a}\n".format(a=addr_mode)
169 )
170 f.write("\n")
172 for addr_mode, needs_ea, register, read_from_memory, write_to_memory in variants:
173 func_name = build_func_name(addr_mode, needs_ea, register, read_from_memory, write_to_memory)
175 f.write(f" def {func_name}(self, opcode):\n")
177 code = []
179 if needs_ea and read_from_memory:
180 code.append(f"ea, m = self.cpu.get_ea_m_{addr_mode}()")
182 if write_to_memory:
183 code.append("ea, value = self.instr_func(")
184 else:
185 code.append("self.instr_func(")
186 code.append(" opcode=opcode,")
188 if needs_ea and read_from_memory:
189 code.append(" ea=ea,")
190 code.append(" m=m,")
191 elif needs_ea:
192 code.append(f" ea=self.get_ea_{addr_mode}(),")
193 elif read_from_memory:
194 code.append(f" m=self.get_m_{addr_mode}(),")
196 if register:
197 code.append(
198 f" register=self.{REGISTER_DICT[register]},"
199 )
201 code.append(")")
203 if write_to_memory == BYTE:
204 code.append("self.write_byte(ea, value)")
205 elif write_to_memory == WORD:
206 code.append("self.write_word(ea, value)")
208 for line in code:
209 f.write(f" {line}\n")
211 f.write("\n")
214def generate(filename):
215 with open(filename, "w") as f:
216 # generate_code(sys.stdout)
217 generate_code(f)
218 sys.stderr.write(f"New {filename!r} generated.\n")
221if __name__ == "__main__":
222 # print("LDA immediate:", func_name_from_op_code(0x96))
224 generate("instruction_call.py")