Coverage for MC6809/components/mc6809_cc_register.py: 100%
127 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 6809 is Big-Endian
9 Links:
10 http://dragondata.worldofdragon.org/Publications/inside-dragon.htm
11 http://www.burgins.com/m6809.html
12 http://koti.mbnet.fi/~atjs/mc6809/
14 :copyleft: 2013-2015 by the MC6809 team, see AUTHORS for more details.
15 :license: GNU GPL v3 or above, see LICENSE for more details.
17 Based on:
18 * ApplyPy by James Tauber (MIT license)
19 * XRoar emulator by Ciaran Anscomb (GPL license)
20 more info, see README
21"""
24import logging
26from MC6809.utils.humanize import cc_value2txt
29log = logging.getLogger("MC6809")
32class ConditionCodeRegister:
33 """
34 Imitate the normal register API
35 """
36 name = "CC"
37 WIDTH = 8 # 8 Bit
39 def __init__(self, cpu):
40 self.get_cc_value = cpu.get_cc_value
41 self.set_cc = cpu.set_cc
43 @property
44 def value(self):
45 return self.get_cc_value()
47 def set(self, status):
48 return self.set_cc(status)
51class CPUConditionCodeRegisterMixin:
52 """ CC - 8 bit condition code register bits """
54 def __init__(self, *args, **kwargs):
55 super().__init__(*args, **kwargs)
56 self.E = 0 # E - 0x80 - bit 7 - Entire register state stacked
57 self.F = 0 # F - 0x40 - bit 6 - FIRQ interrupt masked
58 self.H = 0 # H - 0x20 - bit 5 - Half-Carry
59 self.I = 0 # I - 0x10 - bit 4 - IRQ interrupt masked
60 self.N = 0 # N - 0x08 - bit 3 - Negative result (twos complement)
61 self.Z = 0 # Z - 0x04 - bit 2 - Zero result
62 self.V = 0 # V - 0x02 - bit 1 - Overflow
63 self.C = 0 # C - 0x01 - bit 0 - Carry (or borrow)
65 self.cc_register = ConditionCodeRegister(self)
67 ####
69 def get_cc_value(self):
70 return self.C | \
71 self.V << 1 | \
72 self.Z << 2 | \
73 self.N << 3 | \
74 self.I << 4 | \
75 self.H << 5 | \
76 self.F << 6 | \
77 self.E << 7
79 def set_cc(self, status):
80 self.E, self.F, self.H, self.I, self.N, self.Z, self.V, self.C = (
81 0 if status & x == 0 else 1 for x in (128, 64, 32, 16, 8, 4, 2, 1)
82 )
84 def get_cc_info(self):
85 """
86 return cc flags as text representation, like: 'E.H....C'
87 used in trace mode and unittests
88 """
89 return cc_value2txt(self.get_cc_value())
91 ####
93 def set_H(self, a, b, r):
94 if not self.H and (a ^ b ^ r) & 0x10:
95 self.H = 1
96# log.debug("\tset_H(): set half-carry flag to %i: ($%02x ^ $%02x ^ $%02x) & 0x10 = $%02x",
97# self.H, a, b, r, r2
98# )
99# else:
100# log.debug("\rset_H(): leave old value 1")
102 def set_Z8(self, r):
103 if self.Z == 0:
104 r2 = r & 0xff
105 self.Z = 1 if r2 == 0 else 0
106# log.debug("\tset_Z8(): set zero flag to %i: $%02x & 0xff = $%02x",
107# self.Z, r, r2
108# )
109# else:
110# log.debug("\tset_Z8(): leave old value 1")
112 def set_Z16(self, r):
113 if not self.Z and not r & 0xffff:
114 self.Z = 1
115# log.debug("\tset_Z16(): set zero flag to %i: $%04x & 0xffff = $%04x",
116# self.Z, r, r2
117# )
118# else:
119# log.debug("\tset_Z16(): leave old value 1")
121 def set_N8(self, r):
122 if not self.N and r & 0x80:
123 self.N = 1
124# log.debug("\tset_N8(): set negative flag to %i: ($%02x & 0x80) = $%02x",
125# self.N, r, r2
126# )
127# else:
128# log.debug("\tset_N8(): leave old value 1")
130 def set_N16(self, r):
131 if not self.N and r & 0x8000:
132 self.N = 1
133# log.debug("\tset_N16(): set negative flag to %i: ($%04x & 0x8000) = $%04x",
134# self.N, r, r2
135# )
136# else:
137# log.debug("\tset_N16(): leave old value 1")
139 def set_C8(self, r):
140 if not self.C and r & 0x100:
141 self.C = 1
142# log.debug("\tset_C8(): carry flag to %i: ($%02x & 0x100) = $%02x",
143# self.C, r, r2
144# )
145# else:
146# log.debug("\tset_C8(): leave old value 1")
148 def set_C16(self, r):
149 if not self.C and r & 0x10000:
150 self.C = 1
151# log.debug("\tset_C16(): carry flag to %i: ($%04x & 0x10000) = $%04x",
152# self.C, r, r2
153# )
154# else:
155# log.debug("\tset_C16(): leave old value 1")
157 def set_V8(self, a, b, r):
158 if not self.V and (a ^ b ^ r ^ (r >> 1)) & 0x80:
159 self.V = 1
160# log.debug("\tset_V8(): overflow flag to %i: (($%02x ^ $%02x ^ $%02x ^ ($%02x >> 1)) & 0x80) = $%02x",
161# self.V, a, b, r, r, r2
162# )
163# else:
164# log.debug("\tset_V8(): leave old value 1")
166 def set_V16(self, a, b, r):
167 if not self.V and (a ^ b ^ r ^ (r >> 1)) & 0x8000:
168 self.V = 1
169# log.debug("\tset_V16(): overflow flag to %i: (($%04x ^ $%04x ^ $%04x ^ ($%04x >> 1)) & 0x8000) = $%04x",
170# self.V, a, b, r, r, r2
171# )
172# else:
173# log.debug("\tset_V16(): leave old value 1")
175 ####
177 def clear_NZ(self):
178 # log.debug("\tclear_NZ()")
179 self.N = 0
180 self.Z = 0
182 def clear_NZC(self):
183 # log.debug("\tclear_NZC()")
184 self.N = 0
185 self.Z = 0
186 self.C = 0
188 def clear_NZV(self):
189 # log.debug("\tclear_NZV()")
190 self.N = 0
191 self.Z = 0
192 self.V = 0
194 def clear_NZVC(self):
195 # log.debug("\tclear_NZVC()")
196 self.N = 0
197 self.Z = 0
198 self.V = 0
199 self.C = 0
201 def clear_HNZVC(self):
202 # log.debug("\tclear_HNZVC()")
203 self.H = 0
204 self.N = 0
205 self.Z = 0
206 self.V = 0
207 self.C = 0
209 ####
211 def update_NZ_8(self, r):
212 self.set_N8(r)
213 self.set_Z8(r)
215 def update_0100(self):
216 """ CC bits "HNZVC": -0100 """
217 self.N = 0
218 self.Z = 1
219 self.V = 0
220 self.C = 0
222 def update_NZ01_8(self, r):
223 self.set_N8(r)
224 self.set_Z8(r)
225 self.V = 0
226 self.C = 1
228 def update_NZ_16(self, r):
229 self.set_N16(r)
230 self.set_Z16(r)
232 def update_NZ0_8(self, r):
233 self.set_N8(r)
234 self.set_Z8(r)
235 self.V = 0
237 def update_NZ0_16(self, r):
238 self.set_N16(r)
239 self.set_Z16(r)
240 self.V = 0
242 def update_NZC_8(self, r):
243 self.set_N8(r)
244 self.set_Z8(r)
245 self.set_C8(r)
247 def update_NZVC_8(self, a, b, r):
248 self.set_N8(r)
249 self.set_Z8(r)
250 self.set_V8(a, b, r)
251 self.set_C8(r)
253 def update_NZVC_16(self, a, b, r):
254 self.set_N16(r)
255 self.set_Z16(r)
256 self.set_V16(a, b, r)
257 self.set_C16(r)
259 def update_HNZVC_8(self, a, b, r):
260 self.set_H(a, b, r)
261 self.set_N8(r)
262 self.set_Z8(r)
263 self.set_V8(a, b, r)
264 self.set_C8(r)