Coverage for MC6809/components/mc6809_interrupt.py: 38%

50 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 

25 

26 

27class InterruptMixin: 

28 

29 # ---- Not Implemented, yet. ---- 

30 

31 @opcode( # AND condition code register, then wait for interrupt 

32 0x3c, # CWAI (immediate) 

33 ) 

34 def instruction_CWAI(self, opcode, m): 

35 """ 

36 This instruction ANDs an immediate byte with the condition code register 

37 which may clear the interrupt mask bits I and F, stacks the entire 

38 machine state on the hardware stack and then looks for an interrupt. 

39 When a non-masked interrupt occurs, no further machine state information 

40 need be saved before vectoring to the interrupt handling routine. This 

41 instruction replaced the MC6800 CLI WAI sequence, but does not place the 

42 buses in a high-impedance state. A FIRQ (fast interrupt request) may 

43 enter its interrupt handler with its entire machine state saved. The RTI 

44 (return from interrupt) instruction will automatically return the entire 

45 machine state after testing the E (entire) bit of the recovered 

46 condition code register. 

47 

48 The following immediate values will have the following results: FF = 

49 enable neither EF = enable IRQ BF = enable FIRQ AF = enable both 

50 

51 source code forms: CWAI #$XX E F H I N Z V C 

52 

53 CC bits "HNZVC": ddddd 

54 """ 

55# log.error("$%x CWAI not implemented, yet!", opcode) 

56 # Update CC bits: ddddd 

57 

58 @opcode( # Undocumented opcode! 

59 0x3e, # RESET (inherent) 

60 ) 

61 def instruction_RESET(self, opcode): 

62 """ 

63 Build the ASSIST09 vector table and setup monitor defaults, then invoke 

64 the monitor startup routine. 

65 

66 source code forms: 

67 

68 CC bits "HNZVC": ***** 

69 """ 

70 raise NotImplementedError(f"${opcode:x} RESET") 

71 # Update CC bits: ***** 

72 

73 # ---- Interrupt handling ---- 

74 

75 irq_enabled = False 

76 

77 def irq(self): 

78 if not self.irq_enabled or self.I == 1: 

79 # log.critical("$%04x *** IRQ, ignore!\t%s" % ( 

80 # self.program_counter.value, self.get_cc_info() 

81 # )) 

82 return 

83 

84 if self.E: 

85 self.push_irq_registers() 

86 else: 

87 self.push_firq_registers() 

88 

89 ea = self.memory.read_word(self.IRQ_VECTOR) 

90 # log.critical("$%04x *** IRQ, set PC to $%04x\t%s" % ( 

91 # self.program_counter.value, ea, self.get_cc_info() 

92 # )) 

93 self.program_counter.set(ea) 

94 

95 def push_irq_registers(self): 

96 """ 

97 push PC, U, Y, X, DP, B, A, CC on System stack pointer 

98 """ 

99 self.cycles += 1 

100 self.push_word(self.system_stack_pointer, self.program_counter.value) # PC 

101 self.push_word(self.system_stack_pointer, self.user_stack_pointer.value) # U 

102 self.push_word(self.system_stack_pointer, self.index_y.value) # Y 

103 self.push_word(self.system_stack_pointer, self.index_x.value) # X 

104 self.push_byte(self.system_stack_pointer, self.direct_page.value) # DP 

105 self.push_byte(self.system_stack_pointer, self.accu_b.value) # B 

106 self.push_byte(self.system_stack_pointer, self.accu_a.value) # A 

107 self.push_byte(self.system_stack_pointer, self.get_cc_value()) # CC 

108 

109 def push_firq_registers(self): 

110 """ 

111 FIRQ - Fast Interrupt Request 

112 push PC and CC on System stack pointer 

113 """ 

114 self.cycles += 1 

115 self.push_word(self.system_stack_pointer, self.program_counter.value) # PC 

116 self.push_byte(self.system_stack_pointer, self.get_cc_value()) # CC 

117 

118 @opcode( # Return from interrupt 

119 0x3b, # RTI (inherent) 

120 ) 

121 def instruction_RTI(self, opcode): 

122 """ 

123 The saved machine state is recovered from the hardware stack and control 

124 is returned to the interrupted program. If the recovered E (entire) bit 

125 is clear, it indicates that only a subset of the machine state was saved 

126 (return address and condition codes) and only that subset is recovered. 

127 

128 source code forms: RTI 

129 

130 CC bits "HNZVC": ----- 

131 """ 

132 cc = self.pull_byte(self.system_stack_pointer) # CC 

133 self.set_cc(cc) 

134 if self.E: 

135 self.accu_a.set( 

136 self.pull_byte(self.system_stack_pointer) # A 

137 ) 

138 self.accu_b.set( 

139 self.pull_byte(self.system_stack_pointer) # B 

140 ) 

141 self.direct_page.set( 

142 self.pull_byte(self.system_stack_pointer) # DP 

143 ) 

144 self.index_x.set( 

145 self.pull_word(self.system_stack_pointer) # X 

146 ) 

147 self.index_y.set( 

148 self.pull_word(self.system_stack_pointer) # Y 

149 ) 

150 self.user_stack_pointer.set( 

151 self.pull_word(self.system_stack_pointer) # U 

152 ) 

153 

154 self.program_counter.set( 

155 self.pull_word(self.system_stack_pointer) # PC 

156 ) 

157# log.critical("RTI to $%04x", self.program_counter.value) 

158 

159 @opcode( # Software interrupt (absolute indirect) 

160 0x3f, # SWI (inherent) 

161 ) 

162 def instruction_SWI(self, opcode): 

163 """ 

164 All of the processor registers are pushed onto the hardware stack (with 

165 the exception of the hardware stack pointer itself), and control is 

166 transferred through the software interrupt vector. Both the normal and 

167 fast interrupts are masked (disabled). 

168 

169 source code forms: SWI 

170 

171 CC bits "HNZVC": ----- 

172 """ 

173 raise NotImplementedError(f"${opcode:x} SWI") 

174 

175 @opcode( # Software interrupt (absolute indirect) 

176 0x103f, # SWI2 (inherent) 

177 ) 

178 def instruction_SWI2(self, opcode, ea, m): 

179 """ 

180 All of the processor registers are pushed onto the hardware stack (with 

181 the exception of the hardware stack pointer itself), and control is 

182 transferred through the software interrupt 2 vector. This interrupt is 

183 available to the end user and must not be used in packaged software. 

184 This interrupt does not mask (disable) the normal and fast interrupts. 

185 

186 source code forms: SWI2 

187 

188 CC bits "HNZVC": ----- 

189 """ 

190 raise NotImplementedError(f"${opcode:x} SWI2") 

191 

192 @opcode( # Software interrupt (absolute indirect) 

193 0x113f, # SWI3 (inherent) 

194 ) 

195 def instruction_SWI3(self, opcode, ea, m): 

196 """ 

197 All of the processor registers are pushed onto the hardware stack (with 

198 the exception of the hardware stack pointer itself), and control is 

199 transferred through the software interrupt 3 vector. This interrupt does 

200 not mask (disable) the normal and fast interrupts. 

201 

202 source code forms: SWI3 

203 

204 CC bits "HNZVC": ----- 

205 """ 

206 raise NotImplementedError(f"${opcode:x} SWI3") 

207 

208 @opcode( # Synchronize with interrupt line 

209 0x13, # SYNC (inherent) 

210 ) 

211 def instruction_SYNC(self, opcode): 

212 """ 

213 FAST SYNC WAIT FOR DATA Interrupt! LDA DISC DATA FROM DISC AND CLEAR 

214 INTERRUPT STA ,X+ PUT IN BUFFER DECB COUNT IT, DONE? BNE FAST GO AGAIN 

215 IF NOT. 

216 

217 source code forms: SYNC 

218 

219 CC bits "HNZVC": ----- 

220 """ 

221 raise NotImplementedError(f"${opcode:x} SYNC")