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