Coverage for MC6809/components/mc6809_ops_logic.py: 96%

110 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 

24from MC6809.components.cpu_utils.instruction_caller import opcode 

25from MC6809.utils.bits import get_bit 

26 

27 

28class OpsLogicalMixin: 

29 # ---- Logical Operations ---- 

30 

31 @opcode( # AND memory with accumulator 

32 0x84, 0x94, 0xa4, 0xb4, # ANDA (immediate, direct, indexed, extended) 

33 0xc4, 0xd4, 0xe4, 0xf4, # ANDB (immediate, direct, indexed, extended) 

34 ) 

35 def instruction_AND(self, opcode, m, register): 

36 """ 

37 Performs the logical AND operation between the contents of an 

38 accumulator and the contents of memory location M and the result is 

39 stored in the accumulator. 

40 

41 source code forms: ANDA P; ANDB P 

42 

43 CC bits "HNZVC": -aa0- 

44 """ 

45 a = register.value 

46 r = a & m 

47 register.set(r) 

48 self.clear_NZV() 

49 self.update_NZ_8(r) 

50# log.debug("\tAND %s: %i & %i = %i", 

51# register.name, a, m, r 

52# ) 

53 

54 @opcode( # Exclusive OR memory with accumulator 

55 0x88, 0x98, 0xa8, 0xb8, # EORA (immediate, direct, indexed, extended) 

56 0xc8, 0xd8, 0xe8, 0xf8, # EORB (immediate, direct, indexed, extended) 

57 ) 

58 def instruction_EOR(self, opcode, m, register): 

59 """ 

60 The contents of memory location M is exclusive ORed into an 8-bit 

61 register. 

62 

63 source code forms: EORA P; EORB P 

64 

65 CC bits "HNZVC": -aa0- 

66 """ 

67 a = register.value 

68 r = a ^ m 

69 register.set(r) 

70 self.clear_NZV() 

71 self.update_NZ_8(r) 

72# log.debug("\tEOR %s: %i ^ %i = %i", 

73# register.name, a, m, r 

74# ) 

75 

76 @opcode( # OR memory with accumulator 

77 0x8a, 0x9a, 0xaa, 0xba, # ORA (immediate, direct, indexed, extended) 

78 0xca, 0xda, 0xea, 0xfa, # ORB (immediate, direct, indexed, extended) 

79 ) 

80 def instruction_OR(self, opcode, m, register): 

81 """ 

82 Performs an inclusive OR operation between the contents of accumulator A 

83 or B and the contents of memory location M and the result is stored in 

84 accumulator A or B. 

85 

86 source code forms: ORA P; ORB P 

87 

88 CC bits "HNZVC": -aa0- 

89 """ 

90 a = register.value 

91 r = a | m 

92 register.set(r) 

93 self.clear_NZV() 

94 self.update_NZ_8(r) 

95# log.debug("$%04x OR %s: %02x | %02x = %02x", 

96# self.program_counter, register.name, a, m, r 

97# ) 

98 

99 # ---- CC manipulation ---- 

100 

101 @opcode( # AND condition code register 

102 0x1c, # ANDCC (immediate) 

103 ) 

104 def instruction_ANDCC(self, opcode, m, register): 

105 """ 

106 Performs a logical AND between the condition code register and the 

107 immediate byte specified in the instruction and places the result in the 

108 condition code register. 

109 

110 source code forms: ANDCC #xx 

111 

112 CC bits "HNZVC": ddddd 

113 """ 

114 assert register == self.cc_register 

115 

116 old_cc = self.get_cc_value() 

117 new_cc = old_cc & m 

118 self.set_cc(new_cc) 

119# log.debug("\tANDCC: $%x AND $%x = $%x | set CC to %s", 

120# old_cc, m, new_cc, self.get_cc_info() 

121# ) 

122 

123 @opcode( # OR condition code register 

124 0x1a, # ORCC (immediate) 

125 ) 

126 def instruction_ORCC(self, opcode, m, register): 

127 """ 

128 Performs an inclusive OR operation between the contents of the condition 

129 code registers and the immediate value, and the result is placed in the 

130 condition code register. This instruction may be used to set interrupt 

131 masks (disable interrupts) or any other bit(s). 

132 

133 source code forms: ORCC #XX 

134 

135 CC bits "HNZVC": ddddd 

136 """ 

137 assert register == self.cc_register 

138 

139 old_cc = self.get_cc_value() 

140 new_cc = old_cc | m 

141 self.set_cc(new_cc) 

142# log.debug("\tORCC: $%x OR $%x = $%x | set CC to %s", 

143# old_cc, m, new_cc, self.get_cc_info() 

144# ) 

145 

146 # ---- Logical shift: LSL, LSR ---- 

147 

148 def LSL(self, a): 

149 """ 

150 Shifts all bits of accumulator A or B or memory location M one place to 

151 the left. Bit zero is loaded with a zero. Bit seven of accumulator A or 

152 B or memory location M is shifted into the C (carry) bit. 

153 

154 This is a duplicate assembly-language mnemonic for the single machine 

155 instruction ASL. 

156 

157 source code forms: LSL Q; LSLA; LSLB 

158 

159 CC bits "HNZVC": naaas 

160 """ 

161 r = a << 1 

162 self.clear_NZVC() 

163 self.update_NZVC_8(a, a, r) 

164 return r 

165 

166 @opcode(0x8, 0x68, 0x78) # LSL/ASL (direct, indexed, extended) 

167 def instruction_LSL_memory(self, opcode, ea, m): 

168 """ 

169 Logical shift left memory location / Arithmetic shift of memory left 

170 """ 

171 r = self.LSL(m) 

172# log.debug("$%x LSL memory value $%x << 1 = $%x and write it to $%x \t| %s" % ( 

173# self.program_counter, 

174# m, r, ea, 

175# self.cfg.mem_info.get_shortest(ea) 

176# )) 

177 return ea, r & 0xff 

178 

179 @opcode(0x48, 0x58) # LSLA/ASLA / LSLB/ASLB (inherent) 

180 def instruction_LSL_register(self, opcode, register): 

181 """ 

182 Logical shift left accumulator / Arithmetic shift of accumulator 

183 """ 

184 a = register.value 

185 r = self.LSL(a) 

186# log.debug("$%x LSL %s value $%x << 1 = $%x" % ( 

187# self.program_counter, 

188# register.name, a, r 

189# )) 

190 register.set(r) 

191 

192 def LSR(self, a): 

193 """ 

194 Performs a logical shift right on the register. Shifts a zero into bit 

195 seven and bit zero into the C (carry) bit. 

196 

197 source code forms: LSR Q; LSRA; LSRB 

198 

199 CC bits "HNZVC": -0a-s 

200 """ 

201 r = a >> 1 

202 self.clear_NZC() 

203 self.C = get_bit(a, bit=0) # same as: self.C |= (a & 1) 

204 self.set_Z8(r) 

205 return r 

206 

207 @opcode(0x4, 0x64, 0x74) # LSR (direct, indexed, extended) 

208 def instruction_LSR_memory(self, opcode, ea, m): 

209 """ Logical shift right memory location """ 

210 r = self.LSR(m) 

211# log.debug("$%x LSR memory value $%x >> 1 = $%x and write it to $%x \t| %s" % ( 

212# self.program_counter, 

213# m, r, ea, 

214# self.cfg.mem_info.get_shortest(ea) 

215# )) 

216 return ea, r & 0xff 

217 

218 @opcode(0x44, 0x54) # LSRA / LSRB (inherent) 

219 def instruction_LSR_register(self, opcode, register): 

220 """ Logical shift right accumulator """ 

221 a = register.value 

222 r = self.LSR(a) 

223# log.debug("$%x LSR %s value $%x >> 1 = $%x" % ( 

224# self.program_counter, 

225# register.name, a, r 

226# )) 

227 register.set(r) 

228 

229 def ASR(self, a): 

230 """ 

231 ASR (Arithmetic Shift Right) alias LSR (Logical Shift Right) 

232 

233 Shifts all bits of the register one place to the right. Bit seven is held 

234 constant. Bit zero is shifted into the C (carry) bit. 

235 

236 source code forms: ASR Q; ASRA; ASRB 

237 

238 CC bits "HNZVC": uaa-s 

239 """ 

240 r = (a >> 1) | (a & 0x80) 

241 self.clear_NZC() 

242 self.C = get_bit(a, bit=0) # same as: self.C |= (a & 1) 

243 self.update_NZ_8(r) 

244 return r 

245 

246 @opcode(0x7, 0x67, 0x77) # ASR (direct, indexed, extended) 

247 def instruction_ASR_memory(self, opcode, ea, m): 

248 """ Arithmetic shift memory right """ 

249 r = self.ASR(m) 

250# log.debug("$%x ASR memory value $%x >> 1 | Carry = $%x and write it to $%x \t| %s" % ( 

251# self.program_counter, 

252# m, r, ea, 

253# self.cfg.mem_info.get_shortest(ea) 

254# )) 

255 return ea, r & 0xff 

256 

257 @opcode(0x47, 0x57) # ASRA/ASRB (inherent) 

258 def instruction_ASR_register(self, opcode, register): 

259 """ Arithmetic shift accumulator right """ 

260 a = register.value 

261 r = self.ASR(a) 

262# log.debug("$%x ASR %s value $%x >> 1 | Carry = $%x" % ( 

263# self.program_counter, 

264# register.name, a, r 

265# )) 

266 register.set(r) 

267 

268 # ---- Rotate: ROL, ROR ---- 

269 

270 def ROL(self, a): 

271 """ 

272 Rotates all bits of the register one place left through the C (carry) 

273 bit. This is a 9-bit rotation. 

274 

275 source code forms: ROL Q; ROLA; ROLB 

276 

277 CC bits "HNZVC": -aaas 

278 """ 

279 r = (a << 1) | self.C 

280 self.clear_NZVC() 

281 self.update_NZVC_8(a, a, r) 

282 return r 

283 

284 @opcode(0x9, 0x69, 0x79) # ROL (direct, indexed, extended) 

285 def instruction_ROL_memory(self, opcode, ea, m): 

286 """ Rotate memory left """ 

287 r = self.ROL(m) 

288# log.debug("$%x ROL memory value $%x << 1 | Carry = $%x and write it to $%x \t| %s" % ( 

289# self.program_counter, 

290# m, r, ea, 

291# self.cfg.mem_info.get_shortest(ea) 

292# )) 

293 return ea, r & 0xff 

294 

295 @opcode(0x49, 0x59) # ROLA / ROLB (inherent) 

296 def instruction_ROL_register(self, opcode, register): 

297 """ Rotate accumulator left """ 

298 a = register.value 

299 r = self.ROL(a) 

300# log.debug("$%x ROL %s value $%x << 1 | Carry = $%x" % ( 

301# self.program_counter, 

302# register.name, a, r 

303# )) 

304 register.set(r) 

305 

306 def ROR(self, a): 

307 """ 

308 Rotates all bits of the register one place right through the C (carry) 

309 bit. This is a 9-bit rotation. 

310 

311 moved the carry flag into bit 8 

312 moved bit 7 into carry flag 

313 

314 source code forms: ROR Q; RORA; RORB 

315 

316 CC bits "HNZVC": -aa-s 

317 """ 

318 r = (a >> 1) | (self.C << 7) 

319 self.clear_NZ() 

320 self.update_NZ_8(r) 

321 self.C = get_bit(a, bit=0) # same as: self.C = (a & 1) 

322 return r 

323 

324 @opcode(0x6, 0x66, 0x76) # ROR (direct, indexed, extended) 

325 def instruction_ROR_memory(self, opcode, ea, m): 

326 """ Rotate memory right """ 

327 r = self.ROR(m) 

328# log.debug("$%x ROR memory value $%x >> 1 | Carry = $%x and write it to $%x \t| %s" % ( 

329# self.program_counter, 

330# m, r, ea, 

331# self.cfg.mem_info.get_shortest(ea) 

332# )) 

333 return ea, r & 0xff 

334 

335 @opcode(0x46, 0x56) # RORA/RORB (inherent) 

336 def instruction_ROR_register(self, opcode, register): 

337 """ Rotate accumulator right """ 

338 a = register.value 

339 r = self.ROR(a) 

340# log.debug("$%x ROR %s value $%x >> 1 | Carry = $%x" % ( 

341# self.program_counter, 

342# register.name, a, r 

343# )) 

344 register.set(r)