libsidplayfp  2.0.2
mos6510.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2019 Leandro Nini <drfiemost@users.sourceforge.net>
5  * Copyright 2007-2010 Antti Lankila
6  * Copyright 2000 Simon White
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef MOS6510_H
24 #define MOS6510_H
25 
26 #include <stdint.h>
27 #include <cstdio>
28 
29 #include "flags.h"
30 #include "EventCallback.h"
31 #include "EventScheduler.h"
32 
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36 
37 class EventContext;
38 
39 namespace libsidplayfp
40 {
41 
42 #ifdef DEBUG
43 class MOS6510;
44 
45 namespace MOS6510Debug
46 {
47  void DumpState(event_clock_t time, MOS6510 &cpu);
48 }
49 #endif
50 
51 /*
52  * Define this to get correct emulation of SHA/SHX/SHY/SHS instructions
53  * (see VICE CPU tests).
54  * This will slow down the emulation a bit with no real benefit
55  * for SID playing so we keep it disabled.
56  */
57 #ifdef VICE_TESTSUITE
58 # define CORRECT_SH_INSTRUCTIONS
59 #endif
60 
61 
71 class MOS6510
72 {
73 #ifdef DEBUG
74  friend void MOS6510Debug::DumpState(event_clock_t time, MOS6510 &cpu);
75 #endif
76 
77 public:
78  class haltInstruction {};
79 
80 private:
86  static const int MAX = 65536;
87 
89  static const uint8_t SP_PAGE = 0x01;
90 
91 public:
93  static const int SR_INTERRUPT = 2;
94 
95 private:
96  struct ProcessorCycle
97  {
98  void (MOS6510::*func)();
99  bool nosteal;
100  ProcessorCycle() :
101  func(0),
102  nosteal(false) {}
103  };
104 
105 private:
107  EventScheduler &eventScheduler;
108 
110  int cycleCount;
111 
113  int interruptCycle;
114 
116  bool irqAssertedOnPin;
117 
119  bool nmiFlag;
120 
122  bool rstFlag;
123 
125  bool rdy;
126 
128  bool adl_carry;
129 
130  bool d1x1;
131 
132 #ifdef CORRECT_SH_INSTRUCTIONS
133  bool rdyOnThrowAwayRead;
135 #endif
136 
138  Flags flags;
139 
140  // Data regarding current instruction
141  uint_least16_t Register_ProgramCounter;
142  uint_least16_t Cycle_EffectiveAddress;
143  uint_least16_t Cycle_Pointer;
144 
145  uint8_t Cycle_Data;
146  uint8_t Register_StackPointer;
147  uint8_t Register_Accumulator;
148  uint8_t Register_X;
149  uint8_t Register_Y;
150 
151 #ifdef DEBUG
152  // Debug info
153  int_least32_t instrStartPC;
154  uint_least16_t instrOperand;
155 
156  FILE *m_fdbg;
157 
158  bool dodump;
159 #endif
160 
162  struct ProcessorCycle instrTable[0x101 << 3];
163 
164 private:
166  EventCallback<MOS6510> m_nosteal;
167 
169  EventCallback<MOS6510> m_steal;
170 
171  void eventWithoutSteals();
172  void eventWithSteals();
173 
174  inline void Initialise();
175 
176  // Declare Interrupt Routines
177  inline void IRQLoRequest();
178  inline void IRQHiRequest();
179  inline void interruptsAndNextOpcode();
180  inline void calculateInterruptTriggerCycle();
181 
182  // Declare Instruction Routines
183  inline void fetchNextOpcode();
184  inline void throwAwayFetch();
185  inline void throwAwayRead();
186  inline void FetchDataByte();
187  inline void FetchLowAddr();
188  inline void FetchLowAddrX();
189  inline void FetchLowAddrY();
190  inline void FetchHighAddr();
191  inline void FetchHighAddrX();
192  inline void FetchHighAddrX2();
193  inline void FetchHighAddrY();
194  inline void FetchHighAddrY2();
195  inline void FetchLowEffAddr();
196  inline void FetchHighEffAddr();
197  inline void FetchHighEffAddrY();
198  inline void FetchHighEffAddrY2();
199  inline void FetchLowPointer();
200  inline void FetchLowPointerX();
201  inline void FetchHighPointer();
202  inline void FetchEffAddrDataByte();
203  inline void PutEffAddrDataByte();
204  inline void PushLowPC();
205  inline void PushHighPC();
206  inline void PushSR();
207  inline void PopLowPC();
208  inline void PopHighPC();
209  inline void PopSR();
210  inline void brkPushLowPC();
211  inline void WasteCycle();
212 
213  inline void Push(uint8_t data);
214  inline uint8_t Pop();
215  inline void compare(uint8_t data);
216 
217  // Delcare Instruction Operation Routines
218  inline void adc_instr();
219  inline void alr_instr();
220  inline void anc_instr();
221  inline void and_instr();
222  inline void ane_instr();
223  inline void arr_instr();
224  inline void asl_instr();
225  inline void asla_instr();
226  inline void aso_instr();
227  inline void axa_instr();
228  inline void axs_instr();
229  inline void bcc_instr();
230  inline void bcs_instr();
231  inline void beq_instr();
232  inline void bit_instr();
233  inline void bmi_instr();
234  inline void bne_instr();
235  inline void branch_instr(bool condition);
236  inline void fix_branch();
237  inline void bpl_instr();
238  inline void bvc_instr();
239  inline void bvs_instr();
240  inline void clc_instr();
241  inline void cld_instr();
242  inline void cli_instr();
243  inline void clv_instr();
244  inline void cmp_instr();
245  inline void cpx_instr();
246  inline void cpy_instr();
247  inline void dcm_instr();
248  inline void dec_instr();
249  inline void dex_instr();
250  inline void dey_instr();
251  inline void eor_instr();
252  inline void inc_instr();
253  inline void ins_instr();
254  inline void inx_instr();
255  inline void iny_instr();
256  inline void jmp_instr();
257  inline void las_instr();
258  inline void lax_instr();
259  inline void lda_instr();
260  inline void ldx_instr();
261  inline void ldy_instr();
262  inline void lse_instr();
263  inline void lsr_instr();
264  inline void lsra_instr();
265  inline void oal_instr();
266  inline void ora_instr();
267  inline void pha_instr();
268  inline void pla_instr();
269  inline void rla_instr();
270  inline void rol_instr();
271  inline void rola_instr();
272  inline void ror_instr();
273  inline void rora_instr();
274  inline void rra_instr();
275  inline void rti_instr();
276  inline void rts_instr();
277  inline void sbx_instr();
278  inline void say_instr();
279  inline void sbc_instr();
280  inline void sec_instr();
281  inline void sed_instr();
282  inline void sei_instr();
283  inline void shs_instr();
284  inline void sta_instr();
285  inline void stx_instr();
286  inline void sty_instr();
287  inline void tax_instr();
288  inline void tay_instr();
289  inline void tsx_instr();
290  inline void txa_instr();
291  inline void txs_instr();
292  inline void tya_instr();
293  inline void xas_instr();
294  inline void sh_instr(uint8_t offset);
295 
299  void invalidOpcode();
300 
301  // Declare Arithmetic Operations
302  inline void doADC();
303  inline void doSBC();
304 
305  inline bool checkInterrupts() const { return rstFlag || nmiFlag || (irqAssertedOnPin && !flags.getI()); }
306 
307  inline void buildInstructionTable();
308 
309 protected:
310  MOS6510(EventScheduler &scheduler);
311  ~MOS6510() {}
312 
319  virtual uint8_t cpuRead(uint_least16_t addr) =0;
320 
327  virtual void cpuWrite(uint_least16_t addr, uint8_t data) =0;
328 
329 public:
330  void reset();
331 
332  static const char *credits();
333 
334  void debug(bool enable, FILE *out);
335  void setRDY(bool newRDY);
336 
337  // Non-standard functions
338  void triggerRST();
339  void triggerNMI();
340  void triggerIRQ();
341  void clearIRQ();
342 };
343 
344 }
345 
346 #endif // MOS6510_H
libsidplayfp::MOS6510::MOS6510
MOS6510(EventScheduler &scheduler)
Definition: mos6510.cpp:1443
libsidplayfp::MOS6510::triggerRST
void triggerRST()
Definition: mos6510.cpp:150
libsidplayfp::MOS6510::cpuWrite
virtual void cpuWrite(uint_least16_t addr, uint8_t data)=0
libsidplayfp::EventScheduler
Definition: EventScheduler.h:62
libsidplayfp::MOS6510::triggerNMI
void triggerNMI()
Definition: mos6510.cpp:164
libsidplayfp::MOS6510::credits
static const char * credits()
Definition: mos6510.cpp:2162
libsidplayfp::MOS6510
Definition: mos6510.h:72
libsidplayfp::MOS6510::clearIRQ
void clearIRQ()
Definition: mos6510.cpp:196
libsidplayfp::MOS6510::reset
void reset()
Definition: mos6510.cpp:2143
libsidplayfp::MOS6510::setRDY
void setRDY(bool newRDY)
Definition: mos6510.cpp:102
libsidplayfp::MOS6510::SR_INTERRUPT
static const int SR_INTERRUPT
Status register interrupt bit.
Definition: mos6510.h:93
libsidplayfp::MOS6510::haltInstruction
Definition: mos6510.h:78
libsidplayfp::MOS6510::triggerIRQ
void triggerIRQ()
Definition: mos6510.cpp:180
libsidplayfp::MOS6510::cpuRead
virtual uint8_t cpuRead(uint_least16_t addr)=0
libsidplayfp::EventCallback
Definition: EventCallback.h:36
libsidplayfp::Flags
Definition: flags.h:35