/* Copyright (C) 1998 T. Scott Dattalo This file is part of gpsim. gpsim is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. gpsim 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 General Public License for more details. You should have received a copy of the GNU General Public License along with gpsim; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __BREAKPOINTS_H__ #define __BREAKPOINTS_H__ #include #include #include #include #include "trigger.h" #include "pic-instructions.h" #include "registers.h" #include "exports.h" #include "gpsim_object.h" // defines ObjectBreakTypes using namespace std; extern Integer *verbosity; // in ../src/init.cc class InvalidRegister; class TriggerGroup : public TriggerAction { public: protected: list triggerList; virtual ~TriggerGroup(){} }; #define MAX_BREAKPOINTS 0x400 #define BREAKPOINT_MASK (MAX_BREAKPOINTS-1) class Breakpoint_Instruction : public AliasedInstruction , public TriggerObject { public: unsigned int address; virtual bool set_break(); virtual Processor* get_cpu(); virtual void print(); virtual int printTraced(Trace *pTrace, unsigned int tbi, char *pBuf, int szBuf); virtual void clear(); virtual char const * bpName() { return "Execution"; } Breakpoint_Instruction(Processor *new_cpu, unsigned int new_address, unsigned int bp); virtual enum INSTRUCTION_TYPES isa() {return BREAKPOINT_INSTRUCTION;}; virtual void execute(); virtual bool isBase() { return false;} virtual bool eval_Expression(); }; class Notify_Instruction : public Breakpoint_Instruction { TriggerObject *callback; public: Notify_Instruction(Processor *cpu, unsigned int address, unsigned int bp, TriggerObject *cb); virtual enum INSTRUCTION_TYPES isa() {return NOTIFY_INSTRUCTION;}; virtual void execute(); virtual char const * bpName() { return "Notify Execution"; } }; class Profile_Start_Instruction : public Notify_Instruction { public: Profile_Start_Instruction(Processor *cpu, unsigned int address, unsigned int bp, TriggerObject *cb); virtual enum INSTRUCTION_TYPES isa() {return PROFILE_START_INSTRUCTION;}; virtual char const * bpName() { return "Profile Start"; } }; class Profile_Stop_Instruction : public Notify_Instruction { public: Profile_Stop_Instruction(Processor *cpu, unsigned int address, unsigned int bp, TriggerObject *cb); virtual enum INSTRUCTION_TYPES isa() {return PROFILE_STOP_INSTRUCTION;}; virtual char const * bpName() { return "Profile Stop"; } }; // // Assertions // // Assertions are like breakpoints except that they're conditional. // For example, a user may wish to verify that the proper register // bank is selected while a variable is accessed. // class RegisterAssertion : public Breakpoint_Instruction { public: unsigned int regAddress; unsigned int regMask; unsigned int regValue; bool bPostAssertion; // True if assertion is checked after instruction simulates. typedef bool (*PFNISASSERTIONCONDITION)(unsigned int uRegValue, unsigned int uRegMask, unsigned int uRegTestValue); PFNISASSERTIONCONDITION m_pfnIsAssertionBreak; enum { eRAEquals, eRANotEquals, eRAGreaterThen, eRALessThen, eRAGreaterThenEquals, eRALessThenEquals, }; static bool IsAssertionEqualsBreakCondition(unsigned int uRegValue, unsigned int uRegMask, unsigned int uRegTestValue); static bool IsAssertionNotEqualsBreakCondition(unsigned int uRegValue, unsigned int uRegMask, unsigned int uRegTestValue); static bool IsAssertionGreaterThenBreakCondition(unsigned int uRegValue, unsigned int uRegMask, unsigned int uRegTestValue); static bool IsAssertionLessThenBreakCondition(unsigned int uRegValue, unsigned int uRegMask, unsigned int uRegTestValue); static bool IsAssertionGreaterThenEqualsBreakCondition(unsigned int uRegValue, unsigned int uRegMask, unsigned int uRegTestValue); static bool IsAssertionLessThenEqualsBreakCondition(unsigned int uRegValue, unsigned int uRegMask, unsigned int uRegTestValue); RegisterAssertion(Processor *new_cpu, unsigned int instAddress, unsigned int bp, unsigned int _regAddress, unsigned int _regMask, unsigned int _regValue, bool bPostAssertion=false ); RegisterAssertion(Processor *new_cpu, unsigned int instAddress, unsigned int bp, unsigned int _regAddress, unsigned int _regMask, unsigned int _operator, unsigned int _regValue, bool bPostAssertion=false ); virtual void execute(); virtual void print(); virtual int printTraced(Trace *pTrace, unsigned int tbi, char *pBuf, int szBuf); virtual char const * bpName() { return "Register Assertion"; } }; class Breakpoints; #if defined(IN_MODULE) && defined(_WIN32) // we are in a module: don't access the Breakpoints object directly! LIBGPSIM_EXPORT Breakpoints & get_bp(); #else // we are in gpsim: use of get_bp() is recommended, // even if the bp object can be accessed directly. extern Breakpoints bp; inline Breakpoints &get_bp() { return bp; } #endif class Breakpoints { public: enum BREAKPOINT_TYPES { BREAK_DUMP_ALL = 0, BREAK_CLEAR = 0, BREAK_ON_EXECUTION = 1<<24, BREAK_ON_REG_READ = 2<<24, BREAK_ON_REG_WRITE = 3<<24, BREAK_ON_REG_READ_VALUE = 4<<24, BREAK_ON_REG_WRITE_VALUE = 5<<24, BREAK_ON_INVALID_FR = 6<<24, BREAK_ON_CYCLE = 7<<24, BREAK_ON_WDT_TIMEOUT = 8<<24, BREAK_ON_STK_OVERFLOW = 9<<24, BREAK_ON_STK_UNDERFLOW = 10<<24, NOTIFY_ON_EXECUTION = 11<<24, PROFILE_START_NOTIFY_ON_EXECUTION = 12<<24, PROFILE_STOP_NOTIFY_ON_EXECUTION = 13<<24, NOTIFY_ON_REG_READ = 14<<24, NOTIFY_ON_REG_WRITE = 15<<24, NOTIFY_ON_REG_READ_VALUE = 16<<24, NOTIFY_ON_REG_WRITE_VALUE = 17<<24, BREAK_ON_ASSERTION = 18<<24, BREAK_MASK = 0xff<<24 }; #define GLOBAL_CLEAR 0 #define GLOBAL_STOP_RUNNING (1<<0) #define GLOBAL_INTERRUPT (1<<1) #define GLOBAL_SLEEP (1<<2) #define GLOBAL_PM_WRITE (1<<3) #define GLOBAL_SOCKET (1<<4) struct BreakStatus { BREAKPOINT_TYPES type; Processor *cpu; unsigned int arg1; unsigned int arg2; TriggerObject *bpo; } break_status[MAX_BREAKPOINTS]; int m_iMaxAllocated; class iterator { public: iterator(int index) : iIndex(index) { } int iIndex; iterator & operator++(int) { iIndex++; return *this; } BreakStatus * operator*() { return &get_bp().break_status[iIndex]; } bool operator!=(iterator &it) { return iIndex != it.iIndex; } }; iterator begin() { return iterator(0); } iterator end() { return iterator(m_iMaxAllocated); } BreakStatus *get(int index) { return (index>=0 && index