1 //============================================================================
2 //
3 // MM     MM  6666  555555  0000   2222
4 // MMMM MMMM 66  66 55     00  00 22  22
5 // MM MMM MM 66     55     00  00     22
6 // MM  M  MM 66666  55555  00  00  22222  --  "A 6502 Microprocessor Emulator"
7 // MM     MM 66  66     55 00  00 22
8 // MM     MM 66  66 55  55 00  00 22
9 // MM     MM  6666   5555   0000  222222
10 //
11 // Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
12 // and the Stella Team
13 //
14 // See the file "License.txt" for information on usage and redistribution of
15 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 //============================================================================
17 
18 #ifndef M6502_HXX
19 #define M6502_HXX
20 
21 #include <functional>
22 
23 class Settings;
24 class System;
25 class DispatchResult;
26 
27 #ifdef DEBUGGER_SUPPORT
28   class Debugger;
29   class CpuDebug;
30 
31   #include "Expression.hxx"
32   #include "TrapArray.hxx"
33   #include "BreakpointMap.hxx"
34 #endif
35 
36 #include "bspf.hxx"
37 #include "Device.hxx"
38 #include "Serializable.hxx"
39 
40 /**
41   The 6502 is an 8-bit microprocessor that has a 64K addressing space.
42   This class provides a high compatibility 6502 microprocessor emulator.
43 
44   The memory accesses and cycle counts it generates are valid at the
45   sub-instruction level and "false" reads are generated (such as the ones
46   produced by the Indirect,X addressing when it crosses a page boundary).
47   This provides provides better compatibility for hardware that has side
48   effects and for games which are very time sensitive.
49 
50   @author  Bradford W. Mott
51 */
52 class M6502 : public Serializable
53 {
54   // The 6502 and Cart debugger classes are friends who need special access
55   friend class CartDebug;
56   friend class CpuDebug;
57 
58   public:
59 
60     using onHaltCallback = std::function<void()>;
61 
62   public:
63     /**
64       Create a new 6502 microprocessor.
65     */
66     explicit M6502(const Settings& settings);
67     ~M6502() override = default;
68 
69   public:
70     /**
71       Install the processor in the specified system.  Invoked by the
72       system when the processor is attached to it.
73 
74       @param system The system the processor should install itself in
75     */
76     void install(System& system);
77 
78     /**
79       Reset the processor to its power-on state.  This method should not
80       be invoked until the entire 6502 system is constructed and installed
81       since it involves reading the reset vector from memory.
82     */
83     void reset();
84 
85     /**
86       Request a maskable interrupt
87     */
irq()88     void irq() { myExecutionStatus |= MaskableInterruptBit; }
89 
90     /**
91       Request a non-maskable interrupt
92     */
nmi()93     void nmi() { myExecutionStatus |= NonmaskableInterruptBit; }
94 
95     /**
96       Set the callback for handling a halt condition
97     */
setOnHaltCallback(const onHaltCallback & callback)98     void setOnHaltCallback(const onHaltCallback& callback) {
99       myOnHaltCallback = callback;
100     }
101 
102     /**
103       RDY pulled low --- halt on next read.
104     */
105     void requestHalt();
106 
107     /**
108       Pull RDY high again before the callback was triggered.
109     */
clearHaltRequest()110     void clearHaltRequest() { myHaltRequested = false; }
111 
112     /**
113       Execute instructions until the specified number of instructions
114       is executed, someone stops execution, or an error occurs.  Answers
115       true iff execution stops normally.
116 
117       @param cycles Indicates the number of cycles to execute. Not that the actual
118                     granularity of the CPU is instructions, so this is only accurate up to
119                     a couple of cycles
120       @param result A DispatchResult object that will transport the result
121     */
122     void execute(uInt64 cycles, DispatchResult& result);
123 
124     bool execute(uInt64 cycles);
125 
126     /**
127       Tell the processor to stop executing instructions.  Invoking this
128       method while the processor is executing instructions will stop
129       execution as soon as possible.
130     */
stop()131     void stop() { myExecutionStatus |= StopExecutionBit; }
132 
133     /**
134       Answer true iff a fatal error has occured from which the processor
135       cannot recover (i.e. illegal instruction, etc.)
136 
137       @return true iff a fatal error has occured
138     */
fatalError() const139     bool fatalError() const { return myExecutionStatus & FatalErrorBit; }
140 
141     /**
142       Get the 16-bit value of the Program Counter register.
143 
144       @return The program counter register
145     */
146     // uInt16 getPC() const { return PC; }
147 
148     /**
149       Check the type of the last peek().
150 
151       @return true, if the last peek() was a ghost read.
152     */
lastWasGhostPeek() const153     bool lastWasGhostPeek() const { return myFlags == 0; } // DISASM_NONE
154 
155     /**
156       Return the last address that was part of a read/peek.
157 
158       @return The address of the last read
159     */
lastReadAddress() const160     uInt16 lastReadAddress() const { return myLastPeekAddress; }
161 
162     /**
163       Return the last address that was part of a write/poke.
164 
165       @return The address of the last write
166     */
lastWriteAddress() const167     uInt16 lastWriteAddress() const { return myLastPokeAddress; }
168 
169     /**
170       Return the last (non-mirrored) address that was part of a read/peek.
171 
172       @return The address of the last read
173     */
lastReadBaseAddress() const174     uInt16 lastReadBaseAddress() const { return myLastPeekBaseAddress; }
175 
176     /**
177       Return the last (non-mirrored) address that was part of a write/poke.
178 
179       @return The address of the last write
180     */
lastWriteBaseAddress() const181     uInt16 lastWriteBaseAddress() const { return myLastPokeBaseAddress; }
182 
183     /**
184       Return the source of the address that was used for a write/poke.
185       Note that this isn't the same as the address that is poked, but
186       is instead the address of the *data* that is poked (if any).
187 
188       @return The address of the data used in the last poke, else 0
189     */
lastDataAddressForPoke() const190     uInt16 lastDataAddressForPoke() const { return myDataAddressForPoke; }
191 
192     /**
193       Return the last data address used as part of a peek operation for
194       the S/A/X/Y registers.  Note that if an address wasn't used (as in
195       immediate mode), then the address is -1.
196 
197       @return The address of the data used in the last peek, else -1
198     */
lastSrcAddressS() const199     Int32 lastSrcAddressS() const { return myLastSrcAddressS; }
lastSrcAddressA() const200     Int32 lastSrcAddressA() const { return myLastSrcAddressA; }
lastSrcAddressX() const201     Int32 lastSrcAddressX() const { return myLastSrcAddressX; }
lastSrcAddressY() const202     Int32 lastSrcAddressY() const { return myLastSrcAddressY; }
203 
204     /**
205       Get the number of memory accesses to distinct memory locations
206 
207       @return The number of memory accesses to distinct memory locations
208     */
distinctAccesses() const209     uInt32 distinctAccesses() const { return myNumberOfDistinctAccesses; }
210 
211     /**
212       Saves the current state of this device to the given Serializer.
213 
214       @param out The serializer device to save to.
215       @return The result of the save.  True on success, false on failure.
216     */
217     bool save(Serializer& out) const override;
218 
219     /**
220       Loads the current state of this device from the given Serializer.
221 
222       @param in The Serializer device to load from.
223       @return The result of the load.  True on success, false on failure.
224     */
225     bool load(Serializer& in) override;
226 
227 #ifdef DEBUGGER_SUPPORT
228   public:
229     // Attach the specified debugger.
230     void attach(Debugger& debugger);
231 
readTraps()232     TrapArray& readTraps() { return myReadTraps; }
writeTraps()233     TrapArray& writeTraps() { return myWriteTraps; }
234 
breakPoints()235     BreakpointMap& breakPoints() { return myBreakPoints; }
236 
237     // methods for 'breakif' handling
238     uInt32 addCondBreak(Expression* e, const string& name, bool oneShot = false);
239     bool delCondBreak(uInt32 idx);
240     void clearCondBreaks();
241     const StringList& getCondBreakNames() const;
242 
243     // methods for 'savestateif' handling
244     uInt32 addCondSaveState(Expression* e, const string& name);
245     bool delCondSaveState(uInt32 idx);
246     void clearCondSaveStates();
247     const StringList& getCondSaveStateNames() const;
248 
249     // methods for 'trapif' handling
250     uInt32 addCondTrap(Expression* e, const string& name);
251     bool delCondTrap(uInt32 brk);
252     void clearCondTraps();
253     const StringList& getCondTrapNames() const;
254 
setGhostReadsTrap(bool enable)255     void setGhostReadsTrap(bool enable) { myGhostReadsTrap = enable; }
setReadFromWritePortBreak(bool enable)256     void setReadFromWritePortBreak(bool enable) { myReadFromWritePortBreak = enable; }
setWriteToReadPortBreak(bool enable)257     void setWriteToReadPortBreak(bool enable) { myWriteToReadPortBreak = enable; }
setLogBreaks(bool enable)258     void setLogBreaks(bool enable) { myLogBreaks = enable; }
getLogBreaks()259     bool getLogBreaks() { return myLogBreaks; }
260 #endif  // DEBUGGER_SUPPORT
261 
262   private:
263     /**
264       Get the byte at the specified address and update the cycle count.
265       Addresses marked as code are hints to the debugger/disassembler to
266       conclusively determine code sections, even if the disassembler cannot
267       find them itself.
268 
269       @param address  The address from which the value should be loaded
270       @param flags    Indicates that this address has the given flags
271                       for type of access (CODE, DATA, GFX, etc)
272 
273       @return The byte at the specified address
274     */
275     uInt8 peek(uInt16 address, Device::AccessFlags flags);
276 
277     /**
278       Change the byte at the specified address to the given value and
279       update the cycle count.
280 
281       @param address  The address where the value should be stored
282       @param value    The value to be stored at the address
283     */
284     void poke(uInt16 address, uInt8 value, Device::AccessFlags flags = Device::NONE);
285 
286     /**
287       Get the 8-bit value of the Processor Status register.
288 
289       @return The processor status register
290     */
PS() const291     uInt8 PS() const {
292       uInt8 ps = 0x20;
293 
294       if(N)     ps |= 0x80;
295       if(V)     ps |= 0x40;
296       if(B)     ps |= 0x10;
297       if(D)     ps |= 0x08;
298       if(I)     ps |= 0x04;
299       if(!notZ) ps |= 0x02;
300       if(C)     ps |= 0x01;
301 
302       return ps;
303     }
304 
305     /**
306       Change the Processor Status register to correspond to the given value.
307 
308       @param ps The value to set the processor status register to
309     */
PS(uInt8 ps)310     void PS(uInt8 ps) {
311       N = ps & 0x80;
312       V = ps & 0x40;
313       B = true;        // B = ps & 0x10;  The 6507's B flag always true
314       D = ps & 0x08;
315       I = ps & 0x04;
316       notZ = !(ps & 0x02);
317       C = ps & 0x01;
318     }
319 
320     /**
321       Called after an interrupt has be requested using irq() or nmi()
322     */
323     void interruptHandler();
324 
325     /**
326       Check whether halt was requested (RDY low) and notify
327     */
328     void handleHalt();
329 
330     /**
331       This is the actual dispatch function that does the grunt work. M6502::execute
332       wraps it and makes sure that any pending halt is processed before returning.
333     */
334     void _execute(uInt64 cycles, DispatchResult& result);
335 
336 #ifdef DEBUGGER_SUPPORT
337     /**
338       Check whether we are required to update hardware (TIA + RIOT) in lockstep
339       with the CPU and update the flag accordingly.
340     */
341     void updateStepStateByInstruction();
342 #endif  // DEBUGGER_SUPPORT
343 
344   private:
345     /**
346       Bit fields used to indicate that certain conditions need to be
347       handled such as stopping execution, fatal errors, maskable interrupts
348       and non-maskable interrupts (in myExecutionStatus)
349     */
350     static constexpr uInt8
351       StopExecutionBit        = 0x01,
352       FatalErrorBit           = 0x02,
353       MaskableInterruptBit    = 0x04,
354       NonmaskableInterruptBit = 0x08
355     ;
356     uInt8 myExecutionStatus{0};
357 
358     /// Pointer to the system the processor is installed in or the null pointer
359     System* mySystem{nullptr};
360 
361     /// Reference to the settings
362     const Settings& mySettings;
363 
364     uInt8 A{0};    // Accumulator
365     uInt8 X{0};    // X index register
366     uInt8 Y{0};    // Y index register
367     uInt8 SP{0};   // Stack Pointer
368     uInt8 IR{0};   // Instruction register
369     uInt16 PC{0};  // Program Counter
370 
371     bool N{false};     // N flag for processor status register
372     bool V{false};     // V flag for processor status register
373     bool B{false};     // B flag for processor status register
374     bool D{false};     // D flag for processor status register
375     bool I{false};     // I flag for processor status register
376     bool notZ{false};  // Z flag complement for processor status register
377     bool C{false};     // C flag for processor status register
378 
379     uInt8 icycles{0}; // cycles of last instruction
380 
381     /// Indicates the numer of distinct memory accesses
382     uInt32 myNumberOfDistinctAccesses{0};
383 
384     /// Indicates the last address which was accessed
385     uInt16 myLastAddress{0};
386 
387     /// Last cycle that triggered a breakpoint
388     uInt64 myLastBreakCycle{ULLONG_MAX};
389 
390     /// Indicates the last address which was accessed specifically
391     /// by a peek or poke command
392     uInt16 myLastPeekAddress{0}, myLastPokeAddress{0};
393     /// Indicates the last base (= non-mirrored) address which was
394     /// accessed specifically by a peek or poke command
395     uInt16 myLastPeekBaseAddress{0}, myLastPokeBaseAddress{0};
396     // Indicates the type of the last access
397     uInt16 myFlags{0};
398 
399     /// Indicates the last address used to access data by a peek command
400     /// for the CPU registers (S/A/X/Y)
401     Int32 myLastSrcAddressS{-1}, myLastSrcAddressA{-1},
402           myLastSrcAddressX{-1}, myLastSrcAddressY{-1};
403 
404     /// Indicates the data address used by the last command that performed
405     /// a poke (currently, the last address used by STx)
406     /// If an address wasn't used (ie, as in immediate mode), the address
407     /// is set to zero
408     uInt16 myDataAddressForPoke{0};
409 
410     /// Indicates the number of system cycles per processor cycle
411     static constexpr uInt32 SYSTEM_CYCLES_PER_CPU = 1;
412 
413     /// Called when the processor enters halt state
414     onHaltCallback myOnHaltCallback{nullptr};
415 
416     /// Indicates whether RDY was pulled low
417     bool myHaltRequested{false};
418 
419 #ifdef DEBUGGER_SUPPORT
evalCondBreaks()420     Int32 evalCondBreaks() {
421       for(Int32 i = Int32(myCondBreaks.size()) - 1; i >= 0; --i)
422         if(myCondBreaks[i]->evaluate())
423           return i;
424 
425       return -1; // no break hit
426     }
427 
evalCondSaveStates()428     Int32 evalCondSaveStates()
429     {
430       for(Int32 i = Int32(myCondSaveStates.size()) - 1; i >= 0; --i)
431         if(myCondSaveStates[i]->evaluate())
432           return i;
433 
434       return -1; // no save state point hit
435     }
436 
evalCondTraps()437     Int32 evalCondTraps()
438     {
439       for(Int32 i = Int32(myTrapConds.size()) - 1; i >= 0; --i)
440         if(myTrapConds[i]->evaluate())
441           return i;
442 
443       return -1; // no trapif hit
444     }
445 
446     /// Pointer to the debugger for this processor or the null pointer
447     Debugger* myDebugger{nullptr};
448 
449     // Addresses for which the specified action should occur
450     TrapArray myReadTraps, myWriteTraps;
451 
452     // Did we just now hit a trap?
453     bool myJustHitReadTrapFlag{false};
454     bool myJustHitWriteTrapFlag{false};
455     struct HitTrapInfo {
456       string message;
457       int address{0};
458     };
459     HitTrapInfo myHitTrapInfo;
460 
461     BreakpointMap myBreakPoints;
462     vector<unique_ptr<Expression>> myCondBreaks;
463     StringList myCondBreakNames;
464     vector<unique_ptr<Expression>> myCondSaveStates;
465     StringList myCondSaveStateNames;
466     vector<unique_ptr<Expression>> myTrapConds;
467     StringList myTrapCondNames;
468 #endif  // DEBUGGER_SUPPORT
469 
470     bool myGhostReadsTrap{false};          // trap on ghost reads
471     bool myReadFromWritePortBreak{false};  // trap on reads from write ports
472     bool myWriteToReadPortBreak{false};    // trap on writes to read ports
473     bool myStepStateByInstruction{false};
474     bool myLogBreaks{false};               // log breaks/taps and continue emulation
475 
476   private:
477     // Following constructors and assignment operators not supported
478     M6502() = delete;
479     M6502(const M6502&) = delete;
480     M6502(M6502&&) = delete;
481     M6502& operator=(const M6502&) = delete;
482     M6502& operator=(M6502&&) = delete;
483 };
484 
485 #endif
486