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