Coverage for MC6809/components/cpu_utils/instruction_caller.py: 92%
44 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 python
3"""
4 MC6809 - 6809 CPU emulator in Python
5 =======================================
7 :copyleft: 2013-2014 by the MC6809 team, see AUTHORS for more details.
8 :license: GNU GPL v3 or above, see LICENSE for more details.
9"""
12import inspect
14from MC6809.components.cpu6809_trace import InstructionTrace
15from MC6809.components.cpu_utils.instruction_call import PrepagedInstructions
16from MC6809.components.cpu_utils.Instruction_generator import func_name_from_op_code
17from MC6809.components.MC6809data.MC6809_data_utils import MC6809OP_DATA_DICT
20def opcode(*opcodes):
21 """A decorator for opcodes"""
22 def decorator(func):
23 setattr(func, "_is_opcode", True)
24 setattr(func, "_opcodes", opcodes)
25 return func
26 return decorator
29class OpCollection:
30 def __init__(self, cpu):
31 self.cpu = cpu
32 self.opcode_dict = {}
33 self.collect_ops()
35 def get_opcode_dict(self):
36 return self.opcode_dict
38 def collect_ops(self):
39 # Get the members not from class instance, so that's possible to
40 # exclude properties without "activate" them.
41 cls = type(self.cpu)
42 for name, cls_method in inspect.getmembers(cls):
43 if name.startswith("_") or isinstance(cls_method, property):
44 continue
46 try:
47 opcodes = getattr(cls_method, "_opcodes")
48 except AttributeError:
49 continue
51 instr_func = getattr(self.cpu, name)
52 self._add_ops(opcodes, instr_func)
54 def _add_ops(self, opcodes, instr_func):
55 # log.debug("%20s: %s" % (
56 # instr_func.__name__, ",".join(["$%x" % c for c in opcodes])
57 # ))
58 for op_code in opcodes:
59 assert op_code not in self.opcode_dict, \
60 f"Opcode ${op_code:x} ({instr_func.__name__}) defined more then one time!"
62 op_code_data = MC6809OP_DATA_DICT[op_code]
64 func_name = func_name_from_op_code(op_code)
66 if self.cpu.cfg.trace: 66 ↛ 67line 66 didn't jump to line 67, because the condition on line 66 was never true
67 InstructionClass = InstructionTrace
68 else:
69 InstructionClass = PrepagedInstructions
71 instrution_class = InstructionClass(self.cpu, instr_func)
72 try:
73 func = getattr(instrution_class, func_name)
74 except AttributeError as err:
75 raise AttributeError(f"{err} (op code: ${op_code:02x})")
77 self.opcode_dict[op_code] = (op_code_data["cycles"], func)
80if __name__ == "__main__":
81 from dragonpy.Dragon32.config import Dragon32Cfg
83 from MC6809.components.cpu6809 import CPU
84 from MC6809.components.memory import Memory
85 from MC6809.tests.test_base import BaseCPUTestCase
87 cmd_args = BaseCPUTestCase.UNITTEST_CFG_DICT
88 cfg = Dragon32Cfg(cmd_args)
89 memory = Memory(cfg)
90 cpu = CPU(memory, cfg)
92 for op_code, data in sorted(cpu.opcode_dict.items()):
93 cycles, func = data
94 if op_code > 0xff:
95 op_code = f"${op_code:04x}"
96 else:
97 op_code = f" ${op_code:02x}"
99 print(f"Op {op_code} - cycles: {cycles:2d} - func: {func.__name__}")
101 print(" --- END --- ")