Coverage for MC6809/components/cpu_utils/MC6809_registers.py: 92%
67 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 some code is borrowed from:
8 XRoar emulator by Ciaran Anscomb (GPL license) more info, see README
10 :copyleft: 2013-2015 by the MC6809 team, see AUTHORS for more details.
11 :license: GNU GPL v3 or above, see LICENSE for more details.
12"""
15import logging
18log = logging.getLogger("MC6809")
21class ValueStorageBase:
22 def __init__(self, name, initial_value):
23 self.name = name
24 self.value = initial_value
26 def set(self, v):
27 self.value = v
29 def decrement(self, value=1):
30 self.set(self.value - value)
32 def increment(self, value=1):
33 self.set(self.value + value)
35 def __str__(self):
36 return f"<{self.name}:${self.value:x}>"
37 __repr__ = __str__
40class UndefinedRegister(ValueStorageBase):
41 # used in TFR and EXG
42 WIDTH = 16 # 16 Bit
43 name = "undefined!"
44 value = 0xffff
46 def __init__(self):
47 pass
49 def set(self, v):
50 log.warning("Set value to 'undefined' register!")
52 def get(self):
53 return 0xffff
56class ValueStorage8Bit(ValueStorageBase):
57 WIDTH = 8 # 8 Bit
59 def set(self, v):
60 if v > 0xff:
61 # log.info(" **** Value $%x is to big for %s (8-bit)", v, self.name)
62 v = v & 0xff
63# log.info(" ^^^^ Value %s (8-bit) wrap around to $%x", self.name, v)
64 elif v < 0:
65 # log.info(" **** %s value $%x is negative", self.name, v)
66 v = 0x100 + v
67# log.info(" **** Value %s (8-bit) wrap around to $%x", self.name, v)
68 self.value = v
70 def __str__(self):
71 return f"{self.name}={self.value:02x}"
74class ValueStorage16Bit(ValueStorageBase):
75 WIDTH = 16 # 16 Bit
77 def set(self, v):
78 if v > 0xffff:
79 # log.info(" **** Value $%x is to big for %s (16-bit)", v, self.name)
80 v = v & 0xffff
81# log.info(" ^^^^ Value %s (16-bit) wrap around to $%x", self.name, v)
82 elif v < 0:
83 # log.info(" **** %s value $%x is negative", self.name, v)
84 v = 0x10000 + v
85# log.info(" **** Value %s (16-bit) wrap around to $%x", self.name, v)
86 self.value = v
88 def __str__(self):
89 return f"{self.name}={self.value:04x}"
92class ConcatenatedAccumulator:
93 """
94 6809 has register D - 16 bit concatenated reg. (A + B)
95 """
96 WIDTH = 16 # 16 Bit
98 def __init__(self, name, a, b):
99 self.name = name
100 self._a = a
101 self._b = b
103 def set(self, value):
104 self._a.set(value >> 8)
105 self._b.set(value & 0xff)
107 @property
108 def value(self):
109 return self._a.value * 256 + self._b.value
111 def __str__(self):
112 return f"{self.name}={self.value:04x}"
115def convert_differend_width(src_reg, dst_reg):
116 """
117 e.g.:
118 8bit $cd TFR into 16bit, results in: $ffcd
119 16bit $1234 TFR into 8bit, results in: $34
121 >>> reg8 = ValueStorage8Bit(name="bar", initial_value=0xcd)
122 >>> reg16 = ValueStorage16Bit(name="foo", initial_value=0x0000)
123 >>> hex(convert_differend_width(src_reg=reg8, dst_reg=reg16))
124 '0xffcd'
126 >>> reg16 = ValueStorage16Bit(name="foo", initial_value=0x1234)
127 >>> reg8 = ValueStorage8Bit(name="bar", initial_value=0xcd)
128 >>> hex(convert_differend_width(src_reg=reg16, dst_reg=reg8))
129 '0x34'
131 TODO: verify this behaviour on real hardware
132 see: http://archive.worldofdragon.org/phpBB3/viewtopic.php?f=8&t=4886
133 """
134 src_value = src_reg.value
135 if src_reg.WIDTH == 8 and dst_reg.WIDTH == 16:
136 # e.g.: $cd -> $ffcd
137 src_value += 0xff00
138 elif src_reg.WIDTH == 16 and dst_reg.WIDTH == 8:
139 # This not not really needed, because all 8Bit register will
140 # limit the value, too.
141 # e.g.: $1234 -> $34
142 src_value = src_value & 0xff
143 return src_value
146if __name__ == "__main__":
147 import doctest
148 print(doctest.testmod())