From 0081fe548ce3908dee2624a322d89af8d06ed4bb Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Sun, 7 May 2023 16:26:42 -0400 Subject: [PATCH] sim64 universal 64-bit cycle count support: MaxCycleCount is accounted by countdown, eliminating the 1-instruction-overhead issue, and removing the need to compare against a growing TotalCycles. Makes main.c responsible for counting total cycles, instead of 6502.c, so the size of MaxCycleCount etc. is fully determined in one location. Makes error.c responsible for PrintCycles instead of paravirt.c, so that it can be treated globally instead of Return value of main() should be SIM65_ERROR because it is unreachable by design. --- src/sim65/6502.c | 18 ------------------ src/sim65/6502.h | 6 ------ src/sim65/error.c | 25 +++++++++++++++++++++++++ src/sim65/error.h | 6 ++++++ src/sim65/main.c | 40 +++++++++++++++++++++------------------- src/sim65/paravirt.c | 6 +----- 6 files changed, 53 insertions(+), 48 deletions(-) diff --git a/src/sim65/6502.c b/src/sim65/6502.c index 6c23b0dfc..9d2c93da8 100644 --- a/src/sim65/6502.c +++ b/src/sim65/6502.c @@ -64,18 +64,12 @@ static CPURegs Regs; /* Cycles for the current insn */ static unsigned Cycles; -/* Total number of CPU cycles exec'd */ -static unsigned long TotalCycles; - /* NMI request active */ static unsigned HaveNMIRequest; /* IRQ request active */ static unsigned HaveIRQRequest; -/* flag to print cycles at program termination */ -int PrintCycles; - /*****************************************************************************/ /* Helper functions and macros */ @@ -3277,18 +3271,6 @@ unsigned ExecuteInsn (void) Handlers[CPU][OPC] (); } - /* Count cycles */ - TotalCycles += Cycles; - /* Return the number of clock cycles needed by this insn */ return Cycles; } - - - -unsigned long GetCycles (void) -/* Return the total number of cycles executed */ -{ - /* Return the total number of cycles */ - return TotalCycles; -} diff --git a/src/sim65/6502.h b/src/sim65/6502.h index f8e894567..39b995793 100644 --- a/src/sim65/6502.h +++ b/src/sim65/6502.h @@ -96,12 +96,6 @@ unsigned ExecuteInsn (void); ** executed instruction. */ -unsigned long GetCycles (void); -/* Return the total number of clock cycles executed */ - -extern int PrintCycles; -/* flag to print cycles at program termination */ - /* End of 6502.h */ diff --git a/src/sim65/error.c b/src/sim65/error.c index 441b07d2a..fc24ca006 100644 --- a/src/sim65/error.c +++ b/src/sim65/error.c @@ -41,6 +41,20 @@ +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* flag to print cycles at program termination */ +int PrintCycles = 0; + +/* cycles are counted by main.c */ +extern unsigned long long TotalCycles; + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -99,3 +113,14 @@ void Internal (const char* Format, ...) va_end (ap); exit (SIM65_ERROR); } + + + +void SimExit (int Code) +/* Exit the simulation with an exit code */ +{ + if (PrintCycles) { + fprintf (stdout, "%llu cycles\n", TotalCycles); + } + exit (Code); +} diff --git a/src/sim65/error.h b/src/sim65/error.h index ea54fa048..a016881c6 100644 --- a/src/sim65/error.h +++ b/src/sim65/error.h @@ -55,6 +55,9 @@ #define SIM65_ERROR_TIMEOUT 0x7E /* An error result for max CPU instructions exceeded. */ +extern int PrintCycles; +/* flag to print cycles at program termination */ + /*****************************************************************************/ @@ -75,6 +78,9 @@ void ErrorCode (int Code, const char* Format, ...) attribute((noreturn, format(p void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an internal error message and die */ +void SimExit (int Code); +/* Exit the simulation with an exit code */ + /* End of error.h */ diff --git a/src/sim65/main.c b/src/sim65/main.c index d92d52ef6..f5ace1909 100644 --- a/src/sim65/main.c +++ b/src/sim65/main.c @@ -36,7 +36,6 @@ #include #include #include -#include /* common */ #include "abend.h" @@ -61,14 +60,14 @@ /* Name of program file */ const char* ProgramFile; -/* exit simulator after MaxCycles Cycles */ -unsigned long MaxCycles; +/* count of total cycles executed */ +unsigned long long TotalCycles = 0; -/* maximum number of cycles that can be tested, -** requires overhead for longest possible instruction, -** which should be 7, using 16 for safety. -*/ -#define MAXCYCLES_LIMIT (ULONG_MAX-16) +/* exit simulator after MaxCycles Cccles */ +unsigned long long MaxCycles = 0; + +/* countdown from MaxCycles */ +unsigned long long RemainCycles; /* Header signature 'sim65' */ static const unsigned char HeaderSignature[] = { @@ -145,11 +144,7 @@ static void OptQuitXIns (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* quit after MaxCycles cycles */ { - MaxCycles = strtoul(Arg, NULL, 0); - /* Guard against overflow. */ - if (MaxCycles >= MAXCYCLES_LIMIT) { - Error("'-x parameter out of range. Max: %lu",MAXCYCLES_LIMIT); - } + MaxCycles = strtoull(Arg, NULL, 0); } static unsigned char ReadProgramFile (void) @@ -247,6 +242,7 @@ int main (int argc, char* argv[]) unsigned I; unsigned char SPAddr; + unsigned int Cycles; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "sim65"); @@ -309,18 +305,24 @@ int main (int argc, char* argv[]) MemInit (); SPAddr = ReadProgramFile (); - ParaVirtInit (I, SPAddr); Reset (); + RemainCycles = MaxCycles; while (1) { - ExecuteInsn (); - if (MaxCycles && (GetCycles () >= MaxCycles)) { - ErrorCode (SIM65_ERROR_TIMEOUT, "Maximum number of cycles reached."); + Cycles = ExecuteInsn (); + TotalCycles += Cycles; + if (MaxCycles) { + if (Cycles > RemainCycles) { + ErrorCode (SIM65_ERROR_TIMEOUT, "Maximum number of cycles (%llu) reached.", MaxCycles); + } + RemainCycles -= Cycles; } } - /* Return an apropriate exit code */ - return EXIT_SUCCESS; + /* Unreachable. sim65 program must exit through paravirtual PVExit + ** or timeout from MaxCycles producing an error. + */ + return SIM65_ERROR; } diff --git a/src/sim65/paravirt.c b/src/sim65/paravirt.c index 0b16f89e9..af162acfa 100644 --- a/src/sim65/paravirt.c +++ b/src/sim65/paravirt.c @@ -124,11 +124,7 @@ static unsigned PopParam (unsigned char Incr) static void PVExit (CPURegs* Regs) { Print (stderr, 1, "PVExit ($%02X)\n", Regs->AC); - if (PrintCycles) { - Print (stdout, 0, "%lu cycles\n", GetCycles ()); - } - - exit (Regs->AC); + SimExit (Regs->AC); }