1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-01 13:41:34 +00:00

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.
This commit is contained in:
bbbradsmith 2023-05-07 16:26:42 -04:00
parent 84f0ab322d
commit 0081fe548c
6 changed files with 53 additions and 48 deletions

View File

@ -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;
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

View File

@ -36,7 +36,6 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
/* 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;
}

View File

@ -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);
}