1 /*
2    Copyright (C) 1998-2003 T. Scott Dattalo
3 
4 This file is part of the libgpsim library of gpsim
5 
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10 
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 Lesser General Public License for more details.
15 
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, see
18 <http://www.gnu.org/licenses/lgpl-2.1.html>.
19 */
20 
21 #ifndef SRC_PROCESSOR_H_
22 #define SRC_PROCESSOR_H_
23 #include <glib.h>
24 
25 #include <cstdio>
26 #include <vector>
27 #include <list>
28 #include <map>
29 #include <string>
30 
31 #include "breakpoints.h"
32 #include "gpsim_classes.h"
33 #include "gpsim_object.h"
34 #include "modules.h"
35 #include "trace.h"
36 #include "pic-instructions.h"
37 #include "registers.h"
38 #include "gpsim_time.h"
39 #include "gpsim_interface.h"
40 #include "trigger.h"
41 #include "value.h"
42 
43 class CPU_Freq;
44 class ClockPhase;
45 class FileContext;
46 class Processor;
47 class ProcessorConstructor;
48 class ProcessorConstructorList;
49 class ProgramMemoryCollection;
50 class Stimulus_Node;
51 class TraceType;
52 class XrefObject;
53 class phaseCaptureInterrupt;
54 class phaseExecute1Cycle;
55 class phaseExecute2ndHalf;
56 class phaseIdle;
57 
58 //---------------------------------------------------------
59 /// MemoryAccess - A base class designed to support
60 /// access to memory. For the PIC, this class is extended by
61 /// the ProgramMemoryAccess and RegisterMemoryAccess classes.
62 
63 class MemoryAccess :  public TriggerObject, public gpsimObject
64 {
65 public:
66     explicit MemoryAccess(Processor *new_cpu);
67     ~MemoryAccess();
68 
69     virtual Processor *get_cpu();
70 
71     std::list<Register *> SpecialRegisters;
72 
73 protected:
74     Processor *cpu;             /// The processor to which this object belongs
75 };
76 
77 
78 //---------------------------------------------------------
79 /// The ProgramMemoryAccess class is the interface used
80 /// by objects other than the simulator to manipulate the
81 /// pic's program memory. For example, the breakpoint class
82 /// modifies program memory when break points are set or
83 /// cleared. The modification goes through here.
84 
85 class ProgramMemoryAccess :  public MemoryAccess
86 {
87 public:
88     /// Symbolic debugging
89     enum HLL_MODES
90     {
91         ASM_MODE,      // Source came from plain old .asm files
92         HLL_MODE       // Source came from a high level language like C or JAL.
93     };
94 
95     explicit ProgramMemoryAccess(Processor *new_cpu);
96     ~ProgramMemoryAccess();
97 
98     virtual void putToAddress(unsigned int addr, instruction *new_instruction);
99     virtual void putToIndex(unsigned int uIndex, instruction *new_instruction);
100     instruction *getFromAddress(unsigned int addr);
101     instruction *getFromIndex(unsigned int uIndex);
102     instruction *get_base_instruction(unsigned int addr);
103     unsigned int get_opcode(unsigned int addr);
104     unsigned int get_rom(unsigned int addr);
105     void put_rom(unsigned int addr, unsigned int value);
106     char *get_opcode_name(unsigned int addr, char *buffer, unsigned int size);
107     virtual unsigned int get_PC();
108     virtual void set_PC(unsigned int);
109     virtual Program_Counter *GetProgramCounter();
110 
111     void remove(unsigned int address, instruction *bp_instruction);
112 
113     void put_opcode(unsigned int addr, unsigned int new_opcode);
114     // When a pic is replacing one of it's own instructions, this routine
115     // is called.
116     void put_opcode_start(unsigned int addr, unsigned int new_opcode);
117 
118     // Assign a cross reference object to an instruction
119     void assign_xref(unsigned int address, XrefObject * cross_reference);
120 
121     virtual void callback();
122     void init(Processor *);
123     // Helper functions for querying the program memory
124 
125     // hasValid_opcode -- returns true if the opcode at the address is valid
126     bool hasValid_opcode_at_address(unsigned int address);
127     bool hasValid_opcode_at_index(unsigned int uIndex);
128 
129     // step - step one of more instructions
130     virtual void step(unsigned int steps, bool refresh = true);
131     virtual void step_over(bool refresh = true);
132 
133     virtual void run(bool refresh = true);
134     virtual void stop();
135     virtual void finish();
136 
137     // isModified -- returns true if the program at the address has been modified
138     // (this is only valid for those processor capable of writing to their own
139     // program memory)
140     bool isModified(unsigned int address);
141 
142 
143     // Given a file and a line in that file, find the instrucion in the
144     // processor's memory that's closest to it.
145     virtual int  find_closest_address_to_line(int file_id, int src_line);
146     virtual int  find_address_from_line(FileContext *fc, int src_line);
147     //virtual int  find_closest_address_to_hll_line(int file_id, int src_line);
148 
149     // Given an address to an instruction, find the source line that
150     // created it:
151 
152     int get_src_line(unsigned int address);
153 
154     // Return the file ID of the source program responsible for the opcode at address.
155     int get_file_id(unsigned int address);
156 
157     // A couple of functions for manipulating  breakpoints
158     virtual unsigned int  set_break_at_address(unsigned int address);
159     virtual unsigned int  set_notify_at_address(unsigned int address,
160             TriggerObject *cb);
161     virtual unsigned int  set_profile_start_at_address(unsigned int address,
162             TriggerObject *cb);
163     virtual unsigned int  set_profile_stop_at_address(unsigned int address,
164             TriggerObject *cb);
165     virtual int clear_break_at_address(unsigned int address,
166                                        enum instruction::INSTRUCTION_TYPES type);
167     virtual int clear_break_at_address(unsigned int address,
168                                        instruction * pInstruction);
169     virtual int clear_notify_at_address(unsigned int address);
170     virtual int clear_profile_start_at_address(unsigned int address);
171     virtual int clear_profile_stop_at_address(unsigned int address);
172     virtual int address_has_break(unsigned int address,
173                                   enum instruction::INSTRUCTION_TYPES type = instruction::BREAKPOINT_INSTRUCTION);
174     virtual int address_has_notify(unsigned int address);
175     virtual int address_has_profile_start(unsigned int address);
176     virtual int address_has_profile_stop(unsigned int address);
177     virtual instruction *find_instruction(unsigned int address,
178                                           enum instruction::INSTRUCTION_TYPES type);
179     virtual void toggle_break_at_address(unsigned int address);
180     virtual void set_break_at_line(unsigned int file_id, unsigned int src_line);
181     virtual void clear_break_at_line(unsigned int file_id,
182                                      unsigned int src_line);
183     virtual void toggle_break_at_line(unsigned int file_id,
184                                       unsigned int src_line);
185 
186     void set_hll_mode(unsigned int);
get_hll_mode()187     enum HLL_MODES get_hll_mode()
188     {
189         return hll_mode;
190     }
isHLLmode()191     bool isHLLmode()
192     {
193         return get_hll_mode() == HLL_MODE;
194     }
195 
196 private:
197     ProgramMemoryCollection *m_pRomCollection;
198     unsigned int _address;
199     unsigned int _opcode;
200     unsigned int _state;
201 
202     enum HLL_MODES hll_mode;
203 
204     // breakpoint instruction pointer. This is used by get_base_instruction().
205     // If an instruction has a breakpoint set on it, then get_base_instruction
206     // will return a pointer to the instruction and will initialize bpi to
207     // the breakpoint instruction that has replaced the one in the processor's
208     // program memory.
209     Breakpoint_Instruction *bpi;
210 };
211 
212 
213 //---------------------------------------------------------
214 /// The RegisterMemoryAccess class is the interface used
215 /// by objects other than the simulator to manipulate the
216 /// cpu's register memory.
217 
218 class RegisterMemoryAccess : public MemoryAccess
219 {
220 public:
221     explicit RegisterMemoryAccess(Processor *pCpu);
222     virtual ~RegisterMemoryAccess();
223 
224     virtual Register *get_register(unsigned int address);
get_size()225     unsigned int get_size()
226     {
227         return nRegisters;
228     }
229     void set_Registers(Register **_registers, int _nRegisters);
230 
231     // The insertRegister and removeRegister methods are used primarily
232     // to set and clear breakpoints.
233     bool insertRegister(unsigned int address, Register *);
234     bool removeRegister(unsigned int address, Register *);
235     bool hasBreak(unsigned int address);
236     void reset(RESET_TYPE r);
237 
238     Register &operator [](unsigned int address);
239 
240 private:
241     unsigned int nRegisters;
242     bool initialized;
243     Register **registers;       // Pointer to the array of registers.
244 };
245 
246 
247 //------------------------------------------------------------------------
248 //
249 /// FileContext - Maintain state information about files.
250 /// The state of each source file for a processor is recorded in the
251 /// FileContext class. Clients can query information like the name
252 /// of the source file or the line number responsible for generating
253 /// a specific instruction.
254 
255 class FileContext
256 {
257 private:
258     std::string name_str;         // File name
259     FILE *fptr = nullptr;         // File ptr when the file is opened
260     std::vector<int> line_seek;   // A vector of file offsets to the start of lines
261     std::vector<int> pm_address;  // A vector of program memory addresses for lines
262     unsigned int m_uiMaxLine = 0; // number of lines in the file
263 
264     friend class FileContextList;
265 
266 protected:
267     bool m_bIsList = false;          // True if this is a list file.
268     bool m_bIsHLL = false;           // True if this is a HLL file.
269 
setListId(bool b)270     void setListId(bool b)
271     {
272         m_bIsList = b;
273     }
setHLLId(bool b)274     void setHLLId(bool b)
275     {
276         m_bIsHLL = b;
277     }
278 
279 public:
280     explicit FileContext(std::string &new_name);
281     explicit FileContext(const char *new_name);
282     ~FileContext();
283 
284     void ReadSource();
285     char *ReadLine(unsigned int line_number, char *buf, unsigned int nBytes);
286     char *gets(char *buf, unsigned int nBytes);
287     void rewind();
288     void open(const char *mode);
289     void close();
IsOpen()290     bool IsOpen()
291     {
292         return fptr != nullptr;
293     }
IsList()294     bool IsList()
295     {
296         return m_bIsList;
297     }
IsHLL()298     bool IsHLL()
299     {
300         return m_bIsHLL;
301     }
302 
303     /// get_address - given a line number, return the program memory address
304     int get_address(unsigned int line);
305     /// put_address - associate a line number with a program memory address.
306     void put_address(unsigned int line, unsigned int address);
307 
name()308     std::string &name()
309     {
310         return name_str;
311     }
312     unsigned int max_line();
313 };
314 
315 
316 //------------------------------------------------------------------------
317 //
318 // FileContextList - a vector of FileContext objects.
319 //
320 //
321 class FileContextList : private std::vector<FileContext>
322 {
323 public:
324 #ifndef _MSC_VER
325     typedef std::vector<FileContext> _Myt;
326 #endif
327 
328     FileContextList();
329     ~FileContextList();
330 
331     int Add(std::string& new_name, bool hll = false);
332     int Add(const char *new_name, bool hll = false);
333 
334     int Find(std::string &fname);
335 
336     FileContext *operator [](int file_number);
337 
338     void list_id(int new_list_id);
list_id()339     int list_id()
340     {
341         return list_file_id;
342     }
343 
nsrc_files()344     int nsrc_files()
345     {
346         return (int) size();
347     }
348 
349     char *ReadLine(int file_id, int line_number, char *buf, int nBytes);
350     char *gets(int file_id, char *buf, int nBytes);
351     void rewind(int file_id);
352     void SetSourcePath(const char *pPath);
353 
354 private:
355     std::string sSourcePath;
356     int lastFile;
357     int list_file_id;
358 };
359 
360 
361 class CPU_Vdd : public Float
362 {
363 public:
364     CPU_Vdd(Processor * _cpu, double freq); //const char *_name, double newValue, const char *desc);
365 
366     virtual void set(double d);
367 
368 private:
369     Processor * cpu;
370 };
371 
372 
373 //------------------------------------------------------------------------
374 //
375 /// Processor - a generic base class for processors supported by gpsim
376 
377 class Processor : public Module
378 {
379 public:
380     typedef bool (*LPFNISPROGRAMFILE)(const char *, FILE *);
381 
382     /// Load the source code for this processor. The pProcessorName
383     /// is an optional name that a user can assign to the processor.
384     virtual bool LoadProgramFile(const char *hex_file,
385                                  FILE *pFile,
386                                  const char *pProcessorName) = 0;
387     /// The source files for this processor.
388     FileContextList files;
389 
390     /// Oscillator cycles for 1 instruction
391     unsigned int clocks_per_inst;
392 
393     /// Supply voltage
394     // double Vdd;
395 
396     /// Stimulus nodes for CVREF and V06REF
397     Stimulus_Node         *CVREF = nullptr;
398     Stimulus_Node         *V06REF = nullptr;
399 
400     /// Processor capabilities
401     unsigned long m_Capabilities;
402     enum
403     {
404         eSTACK                  = 0x00000001,
405         eWATCHDOGTIMER          = 0x00000002,
406         eBREAKONSTACKOVER       = 0x00000004,
407         eBREAKONSTACKUNDER      = 0x00000009,
408         eBREAKONWATCHDOGTIMER   = 0x00000010,
409     };
410     unsigned long GetCapabilities();
411 
412     /// Processor RAM
413 
414     Register **registers;
415     RegisterCollection *m_UiAccessOfRegisters = nullptr; // should this be in rma class?
416 
417     /// Currently selected RAM bank
418     Register **register_bank = nullptr;
419 
420     /// Program memory - where instructions are stored.
421 
422     instruction **program_memory = nullptr;
423 
424     /// Program memory interface
425     ProgramMemoryAccess  *pma;
426     virtual ProgramMemoryAccess * createProgramMemoryAccess(Processor *processor);
427     virtual void                  destroyProgramMemoryAccess(ProgramMemoryAccess *pma);
ConstructInvalidInstruction(Processor * processor,unsigned int address,unsigned int new_opcode)428     virtual instruction *         ConstructInvalidInstruction(Processor *processor,
429             unsigned int address, unsigned int new_opcode)
430     {
431         return new invalid_instruction(processor, address, new_opcode);
432     }
433     /// register memory interface
434     RegisterMemoryAccess rma;
435 
436     /// eeprom memory interface (if present).
437     RegisterMemoryAccess ema;
438     unsigned int m_uPageMask;
439     unsigned int m_uAddrMask;
440 
441     /// Program Counter
442     Program_Counter *pc;
443 
444     /// Context debugging is a way of debugging the processor while it is
445     /// in different states. For example, when the interrupt flag is set
446     /// (for those processors that support interrupts), the processor is
447     /// in a different 'state' then when the interrupt flag is cleared.
448 
449     std::list<ProgramMemoryAccess *> pma_context;
450 
451     /// Tracing
452     /// The readTT and writeTT are TraceType objects for tracing
453     /// register reads and writes.
454     /// The mTrace map is a collection of special trace types that
455     /// share the same trace function code. For example, interrupts
456     /// and resets are special trace events that don't warrant thier
457     /// own trace function code.
458     TraceType *readTT, *writeTT;
459     std::map <unsigned int, TraceType *> mTrace;
460 
461     // Processor's 'bad_instruction' object
462     invalid_instruction bad_instruction;
463 
464     // --- TSD removed 01JAN07 These don't appear to be used anywhere
465     //virtual void set(const char *cP,int len=0);
466     //virtual void get(char *, int len);
467 
468     //
469     // Creation and manipulation of registers
470     //
471 
472     void create_invalid_registers();
473     void delete_invalid_registers();
474     void add_file_registers(unsigned int start_address,
475                             unsigned int end_address,
476                             unsigned int alias_offset);
477     void delete_file_registers(unsigned int start_address,
478                                unsigned int end_address, bool bRemoveWithoutDelete = false);
479     void alias_file_registers(unsigned int start_address,
480                               unsigned int end_address,
481                               unsigned int alias_offset);
map_rm_address2index(int address)482     virtual int  map_rm_address2index(int address) { return address; }
map_rm_index2address(int index)483     virtual int  map_rm_index2address(int index) { return index; }
484     virtual void init_register_memory(unsigned int memory_size);
485     virtual unsigned int register_memory_size() const = 0;
CalcJumpAbsoluteAddress(unsigned int,unsigned int uDestAddr)486     virtual unsigned int CalcJumpAbsoluteAddress(unsigned int /* uInstAddr */,
487             unsigned int uDestAddr)
488     {
489         return uDestAddr;
490     }
CalcCallAbsoluteAddress(unsigned int,unsigned int uDestAddr)491     virtual unsigned int CalcCallAbsoluteAddress(unsigned int /* uInstAddr */,
492             unsigned int uDestAddr)
493     {
494         return uDestAddr;
495     }
496 
497     //
498     // Creation and manipulation of Program Memory
499     //
500 
501     virtual void init_program_memory(unsigned int memory_size);
502     virtual void init_program_memory(unsigned int address, unsigned int value);
503     virtual void erase_program_memory(unsigned int address);
504     virtual void init_program_memory_at_index(unsigned int address,
505             unsigned int value);
506     virtual void init_program_memory_at_index(unsigned int address,
507             const unsigned char *, int nBytes);
program_memory_size()508     virtual unsigned int program_memory_size() const
509     {
510         return 0;
511     }
program_address_limit()512     virtual unsigned int program_address_limit() const
513     {
514         return map_pm_index2address(program_memory_size());
515     }
516     virtual unsigned int get_program_memory_at_address(unsigned int address);
517     void build_program_memory(unsigned int *memory,
518                               unsigned int minaddr,
519                               unsigned int maxaddr);
520 
map_pm_address2index(int address)521     virtual int  map_pm_address2index(int address) const
522     {
523         return address;
524     }
map_pm_index2address(int index)525     virtual int  map_pm_index2address(int index) const
526     {
527         return index;
528     }
529     virtual void set_out_of_range_pm(unsigned int address, unsigned int value);
530     guint64 cycles_used(unsigned int address);
IsAddressInRange(unsigned int address)531     virtual bool IsAddressInRange(unsigned int address)
532     {
533         return address < program_address_limit();
534     }
535 
536     // opcode_size - number of bytes for an opcode.
opcode_size()537     virtual int opcode_size() { return 2; }
538 
539     //
540     // Symbolic debugging
541     //
542     // First the source files:
543 
544     void attach_src_line(unsigned int address,
545                          unsigned int file_id,
546                          unsigned int sline,
547                          unsigned int lst_line);
548     void read_src_files();
549 
550 
551     virtual void dump_registers();
552     virtual instruction * disasm(unsigned int address, unsigned int inst) = 0;
553 
get_intedgx(int x)554     virtual bool get_intedgx(int x) {fprintf(stderr, "Unexpected call to get_intedgx\n"); return true;}
555 
556     //virtual void initializeAttributes();
557 
558     //
559     // Processor State
560     //
561     // copy the entire processor state to a file
562     virtual void save_state(FILE *);
563     // take an internal snap shot of the current state.
564     virtual void save_state();
565 
566     // restore the processor state
567     virtual void load_state(FILE *);
568 
569     //
570     // Execution control
571     //
572 
573     virtual void run(bool refresh = true) = 0;
574     virtual void run_to_address(unsigned int destination);
575     virtual void finish() = 0;
576 
sleep()577     virtual void sleep() {}
exit_sleep()578     virtual void exit_sleep()
579     {
580         fputs("RRR exit_sleep\n", stderr);
581     }
582     virtual void step(unsigned int steps, bool refresh = true) = 0;
583     virtual void step_over(bool refresh = true);
584     virtual void step_one(bool refresh = true) = 0;
585     virtual void step_cycle() = 0;
586     virtual void interrupt() = 0 ;
587 
588     // Simulation modes
589 
590     /// setWarnMode - when true, gpsim will issue warnings whenever
591     /// something suspicious is occuring.
592     virtual void setWarnMode(bool);
getWarnMode()593     virtual bool getWarnMode()
594     {
595         return bWarnMode;
596     }
597 
598     /// setSafeMode - when true, gpsim will model the 'official'
599     /// behavior of the chip. When false, the simulator behaves the same
600     /// as the hardware.
601     virtual void setSafeMode(bool);
getSafeMode()602     virtual bool getSafeMode()
603     {
604         return bSafeMode;
605     }
606 
607     /// setUnknownMode - when true, gpsim will implement three-state logic
608     /// for data. When false, unkown data are treated as zeros.
609     virtual void setUnknownMode(bool);
getUnknownMode()610     virtual bool getUnknownMode()
611     {
612         return bUnknownMode;
613     }
614 
615     /// setBreakOnReset - when true, gpsim will implement three-state logic
616     /// for data. When false, unkown data are treated as zeros.
617     virtual void setBreakOnReset(bool);
getBreakOnReset()618     virtual bool getBreakOnReset()
619     {
620         return bBreakOnReset;
621     }
622 
getBreakOnInvalidRegisterRead()623     bool getBreakOnInvalidRegisterRead()
624     {
625         return *m_pbBreakOnInvalidRegisterRead;
626     }
getBreakOnInvalidRegisterWrite()627     bool getBreakOnInvalidRegisterWrite()
628     {
629         return *m_pbBreakOnInvalidRegisterWrite;
630     }
631 
632     ///
633     /// Notification of breakpoint set
NotifyBreakpointSet(Breakpoints::BreakStatus &,TriggerObject *)634     virtual void NotifyBreakpointSet(Breakpoints::BreakStatus & /* bs */, TriggerObject * /* bpo */) { }
NotifyBreakpointCleared(Breakpoints::BreakStatus &,TriggerObject *)635     virtual void NotifyBreakpointCleared(Breakpoints::BreakStatus & /* bs */, TriggerObject * /* bpo */) { }
636 
637     // Tracing control
638 
639     virtual void trace_dump(int type, int amount);
640     virtual int trace_dump1(int type, char *buffer, int bufsize);
641     virtual RegisterValue getWriteTT(unsigned int addr);
642     virtual RegisterValue getReadTT(unsigned int addr);
643 
644     //
645     // Processor Clock control
646     //
647 
648     void set_frequency(double f);
649     void set_frequency_rc(double f);
650     void set_RCfreq_active(bool);
651     virtual double get_frequency();
652 
set_ClockCycles_per_Instruction(unsigned int cpi)653     void set_ClockCycles_per_Instruction(unsigned int cpi)
654     {
655         clocks_per_inst = cpi;
656     }
get_ClockCycles_per_Instruction()657     unsigned int get_ClockCycles_per_Instruction()
658     {
659         return clocks_per_inst;
660     }
661 
662     void update_cps();
663 
664     virtual double get_OSCperiod();
665 
get_InstPeriod()666     virtual double get_InstPeriod()
667     {
668         return get_OSCperiod() * get_ClockCycles_per_Instruction();
669     }
670 
671     virtual void disassemble(signed int start_address,
672                              signed int end_address);
673     virtual void list(unsigned int file_id,
674                       unsigned int pcval,
675                       int start_line,
676                       int end_line);
677 
678     // Configuration control
679 
set_config_word(unsigned int,unsigned int)680     virtual bool set_config_word(unsigned int /* address */, unsigned int /* cfg_word */)
681     {
682         return false; // fixme - make this a pure virtual function...
683     }
684     virtual unsigned int get_config_word(unsigned int address) = 0;
config_word_address()685     virtual unsigned int config_word_address()
686     {
687         return 0;
688     }
get_config_index(unsigned int)689     virtual int get_config_index(unsigned int /* address */)
690     {
691         return -1;
692     }
693 
694     //
695     // Processor reset
696     //
697 
698     virtual void reset(RESET_TYPE r) = 0;
699 
get_Vdd()700     virtual double get_Vdd()
701     {
702         return m_vdd->getVal();
703     }
set_Vdd(double v)704     virtual void set_Vdd(double v)
705     {
706         m_vdd->set(v);
707     }
708     virtual void update_vdd();
709 
710     //
711     // Debugging - used to view the state of the processor (or whatever).
712     //
713 
714     virtual void Debug();
715 
716     //
717     // FIXME -- create -- a way of constructing a processor (why not use constructors?)
718     //
719 
720     virtual void create();
721     static Processor *construct();
722     ProcessorConstructor  *m_pConstructorObject;
723 
724     Processor(const char *_name = nullptr, const char *desc = nullptr);
725     virtual ~Processor();
726 
727     CPU_Vdd   *m_vdd;
728     phaseExecute1Cycle	*mExecute1Cycle = nullptr;
729     ClockPhase 		*mCurrentPhase = nullptr;
730     phaseExecute2ndHalf 	*mExecute2ndHalf = nullptr;     // misnomer - should be 2-cycle
731     phaseCaptureInterrupt	*mCaptureInterrupt = nullptr;
732     phaseIdle 		*mIdle = nullptr;
733 
734 private:
735     CPU_Freq *mFrequency;
736     unsigned int  m_ProgramMemoryAllocationSize;
737 
738     // Simulation modes
739     bool bSafeMode;
740     bool bWarnMode;
741     bool bUnknownMode;
742     bool bBreakOnReset;
743     Boolean *m_pbBreakOnInvalidRegisterRead;
744     Boolean *m_pbBreakOnInvalidRegisterWrite;
745     Boolean *m_pWarnMode;
746     Boolean *m_pSafeMode;
747     Boolean *m_pUnknownMode;
748     Boolean *m_pBreakOnReset;
749 };
750 
751 
752 //-------------------------------------------------------------------
753 //
754 // ProcessorConstructor -- a class to handle all of gpsim's supported
755 // processors
756 //
757 // gpsim supports dozens of processors. All of these processors are
758 // grouped together in the ProcessConstructor class. Within the class
759 // is a static STL list<> object that holds an instance of a
760 // ProcessorConstructor for each gpsim supported processor. Whenever
761 // the user selects a processor to simulate, the find() member
762 // function will search through the list and find the one that matches
763 // the user supplied ASCII string.
764 //
765 // Why have this class?
766 // The idea behind this class is that a ProcessorConstructor object
767 // can be instantiated for each processor and that instantiation will
768 // place the object into list of processors. Prior to gpsim-0.21, a
769 // giant array held the list of all available processors. However,
770 // there were two problems with this: it was painful to look at and
771 // it precluded processors that were defined outside of the gpsim
772 // core library.
773 
774 class ProcessorConstructor
775 {
776 public:
777     typedef Processor * (*tCpuContructor)(const char *_name);
778 
779 protected:
780     // A pointer to a function that when called will construct a processor
781     tCpuContructor cpu_constructor;
782 
783 public:
784     virtual Processor * ConstructProcessor(const char *opt_name = nullptr);
785 
786     // The processor name (plus upto three aliases).
787 #define nProcessorNames 4
788     const char *names[nProcessorNames];
789 
790     //------------------------------------------------------------
791     // contructor --
792     //
793     ProcessorConstructor(
794         tCpuContructor    _cpu_constructor,
795         const char *name1,
796         const char *name2,
797         const char *name3 = nullptr,
798         const char *name4 = nullptr);
799 
~ProcessorConstructor()800     virtual ~ProcessorConstructor()
801     {
802     }
803 
804     static ProcessorConstructorList * processor_list;
805     static ProcessorConstructorList * GetList();
806 };
807 
808 
809 // THE list of all of gpsim's processors:
810 class ProcessorConstructorList : public std::list <ProcessorConstructor *>
811 {
812 public:
ProcessorConstructorList()813     ProcessorConstructorList() {}
814 
815     static ProcessorConstructor * findByType(const char *type);
816     static std::string DisplayString();
817     static ProcessorConstructorList *GetList();
818 
819 private:
820     static ProcessorConstructorList *processor_list;
821 };
822 
823 
824 //----------------------------------------------------------
825 // Global definitions:
826 
827 #if defined(IN_MODULE) && defined(_WIN32)
828 // we are in a module: don't access active_cpu object directly!
829 LIBGPSIM_EXPORT Processor * get_active_cpu();
830 #else
831 // we are in gpsim: use of get_active_cpu() and set_active_cpu() is recommended,
832 // even if active_cpu object can be accessed directly.
833 extern Processor *active_cpu;
834 
get_active_cpu()835 inline Processor *get_active_cpu()
836 {
837     return active_cpu;
838 }
839 
set_active_cpu(Processor * act_cpu)840 inline void set_active_cpu(Processor *act_cpu)
841 {
842     active_cpu = act_cpu;
843 }
844 #endif
845 
846 
847 #endif
848