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

1#!/usr/bin/env python 

2 

3""" 

4 MC6809 - 6809 CPU emulator in Python 

5 ======================================= 

6 

7 6809 is Big-Endian 

8 

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/ 

13 

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. 

16 

17 Based on: 

18 * ApplyPy by James Tauber (MIT license) 

19 * XRoar emulator by Ciaran Anscomb (GPL license) 

20 more info, see README 

21""" 

22 

23 

24import logging 

25 

26from MC6809.utils.humanize import cc_value2txt 

27 

28 

29log = logging.getLogger("MC6809") 

30 

31 

32class ConditionCodeRegister: 

33 """ 

34 Imitate the normal register API 

35 """ 

36 name = "CC" 

37 WIDTH = 8 # 8 Bit 

38 

39 def __init__(self, cpu): 

40 self.get_cc_value = cpu.get_cc_value 

41 self.set_cc = cpu.set_cc 

42 

43 @property 

44 def value(self): 

45 return self.get_cc_value() 

46 

47 def set(self, status): 

48 return self.set_cc(status) 

49 

50 

51class CPUConditionCodeRegisterMixin: 

52 """ CC - 8 bit condition code register bits """ 

53 

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) 

64 

65 self.cc_register = ConditionCodeRegister(self) 

66 

67 #### 

68 

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 

78 

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 ) 

83 

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()) 

90 

91 #### 

92 

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") 

101 

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") 

111 

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") 

120 

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") 

129 

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") 

138 

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") 

147 

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") 

156 

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") 

165 

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") 

174 

175 #### 

176 

177 def clear_NZ(self): 

178 # log.debug("\tclear_NZ()") 

179 self.N = 0 

180 self.Z = 0 

181 

182 def clear_NZC(self): 

183 # log.debug("\tclear_NZC()") 

184 self.N = 0 

185 self.Z = 0 

186 self.C = 0 

187 

188 def clear_NZV(self): 

189 # log.debug("\tclear_NZV()") 

190 self.N = 0 

191 self.Z = 0 

192 self.V = 0 

193 

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 

200 

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 

208 

209 #### 

210 

211 def update_NZ_8(self, r): 

212 self.set_N8(r) 

213 self.set_Z8(r) 

214 

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 

221 

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 

227 

228 def update_NZ_16(self, r): 

229 self.set_N16(r) 

230 self.set_Z16(r) 

231 

232 def update_NZ0_8(self, r): 

233 self.set_N8(r) 

234 self.set_Z8(r) 

235 self.V = 0 

236 

237 def update_NZ0_16(self, r): 

238 self.set_N16(r) 

239 self.set_Z16(r) 

240 self.V = 0 

241 

242 def update_NZC_8(self, r): 

243 self.set_N8(r) 

244 self.set_Z8(r) 

245 self.set_C8(r) 

246 

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) 

252 

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) 

258 

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)