Merge branch 'master' into ca65_jmp_abs_wrap_error

This commit is contained in:
bbbradsmith
2023-08-19 14:07:52 -04:00
71 changed files with 1781 additions and 216 deletions

View File

@@ -496,7 +496,7 @@ static ExprNode* FuncIsMnemonic (void)
/* Skip the name */
NextTok ();
return GenLiteralExpr (Instr > 0);
return GenLiteralExpr (Instr >= 0);
}

View File

@@ -118,7 +118,6 @@ void SetFeature (feature_t Feature, unsigned char On)
case FEAT_C_COMMENTS: CComments = On; break;
case FEAT_FORCE_RANGE: ForceRange = On; break;
case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= On; break;
case FEAT_ADDRSIZE: AddrSize = On; break;
case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = On; break;
case FEAT_STRING_ESCAPES: StringEscapes = On; break;
case FEAT_LONG_JSR_JMP_RTS: LongJsrJmpRts = On; break;

View File

@@ -85,5 +85,4 @@ unsigned char OrgPerSeg = 0; /* Make .org local to current seg */
unsigned char CComments = 0; /* Allow C like comments */
unsigned char ForceRange = 0; /* Force values into expected range */
unsigned char UnderlineInNumbers = 0; /* Allow underlines in numbers */
unsigned char AddrSize = 0; /* Allow .ADDRSIZE function */
unsigned char BracketAsIndirect = 0; /* Use '[]' not '()' for indirection */

View File

@@ -87,7 +87,6 @@ extern unsigned char OrgPerSeg; /* Make .org local to current seg */
extern unsigned char CComments; /* Allow C like comments */
extern unsigned char ForceRange; /* Force values into expected range */
extern unsigned char UnderlineInNumbers; /* Allow underlines in numbers */
extern unsigned char AddrSize; /* Allow .ADDRSIZE function */
extern unsigned char BracketAsIndirect; /* Use '[]' not '()' for indirection */

View File

@@ -1043,6 +1043,11 @@ static void DoFeature (void)
ErrorSkip ("Invalid feature: '%m%p'", &CurTok.SVal);
return;
}
if (Feature == FEAT_ADDRSIZE) {
Warning (1, "Deprecated feature: '.feature addrsize'. Pseudo function .addrsize is always available.");
}
NextTok ();
/* Optional +/- or ON/OFF */

View File

@@ -748,24 +748,7 @@ static token_t FindDotKeyword (void)
R = bsearch (&K, DotKeywords, sizeof (DotKeywords) / sizeof (DotKeywords [0]),
sizeof (DotKeywords [0]), CmpDotKeyword);
if (R != 0) {
/* By default, disable any somewhat experiemental DotKeyword. */
switch (R->Tok) {
case TOK_ADDRSIZE:
/* Disallow .ADDRSIZE function by default */
if (AddrSize == 0) {
return TOK_NONE;
}
break;
default:
break;
}
return R->Tok;
} else {
return TOK_NONE;
}

View File

@@ -79,6 +79,7 @@ IntStack WarnUnusedLabel = INTSTACK(1); /* - unused labels */
IntStack WarnUnusedParam = INTSTACK(1); /* - unused parameters */
IntStack WarnUnusedVar = INTSTACK(1); /* - unused variables */
IntStack WarnUnusedFunc = INTSTACK(1); /* - unused functions */
IntStack WarnConstOverflow = INTSTACK(0); /* - overflow conversion of numerical constants */
/* Map the name of a warning to the intstack that holds its state */
typedef struct WarnMapEntry WarnMapEntry;
@@ -102,6 +103,7 @@ static WarnMapEntry WarnMap[] = {
{ &WarnUnusedLabel, "unused-label" },
{ &WarnUnusedParam, "unused-param" },
{ &WarnUnusedVar, "unused-var" },
{ &WarnConstOverflow, "const-overflow" },
};
Collection DiagnosticStrBufs;

View File

@@ -76,6 +76,7 @@ extern IntStack WarnUnusedLabel; /* - unused labels */
extern IntStack WarnUnusedParam; /* - unused parameters */
extern IntStack WarnUnusedVar; /* - unused variables */
extern IntStack WarnUnusedFunc; /* - unused functions */
extern IntStack WarnConstOverflow; /* - overflow conversion of numerical constants */
/* Forward */
struct StrBuf;

View File

@@ -39,6 +39,8 @@
#include <errno.h>
#include <ctype.h>
#include <math.h>
#include <inttypes.h>
#include <limits.h>
/* common */
#include "chartype.h"
@@ -151,6 +153,11 @@ static const struct Keyword {
#define IT_ULONG 0x08
/* Internal type for numeric constant scanning.
** Size must be explicit for cross-platform uniformity.
*/
typedef uint32_t scan_t;
/*****************************************************************************/
/* code */
@@ -521,7 +528,8 @@ static void NumericConst (void)
int IsFloat;
char C;
unsigned DigitVal;
unsigned long IVal; /* Value */
scan_t IVal; /* Scanned value. */
int Overflow;
/* Get the pp-number first, then parse on it */
CopyPPNumber (&Src);
@@ -575,6 +583,7 @@ static void NumericConst (void)
/* Since we now know the correct base, convert the input into a number */
SB_SetIndex (&Src, Index);
IVal = 0;
Overflow = 0;
while ((C = SB_Peek (&Src)) != '\0' && (Base <= 10 ? IsDigit (C) : IsXDigit (C))) {
DigitVal = HexVal (C);
if (DigitVal >= Base) {
@@ -582,9 +591,17 @@ static void NumericConst (void)
SB_Clear (&Src);
break;
}
IVal = (IVal * Base) + DigitVal;
/* Test result of adding digit for overflow. */
if (((scan_t)(IVal * Base + DigitVal) / Base) != IVal) {
Overflow = 1;
}
IVal = IVal * Base + DigitVal;
SB_Skip (&Src);
}
if (Overflow) {
Error ("Numerical constant \"%s\" too large for internal %d-bit representation",
SB_GetConstBuf (&Src), (int)(sizeof(IVal)*CHAR_BIT));
}
/* Distinguish between integer and floating point constants */
if (!IsFloat) {

View File

@@ -793,6 +793,8 @@ static int HandleSymRedefinition (SymEntry* Sym, const Type* T, unsigned Flags)
*/
Error ("Redeclaration of enumerator constant '%s'", Sym->Name);
Sym = 0;
} else if (Flags & SC_STRUCTFIELD) {
Error ("Duplicate member '%s'", Sym->Name);
}
}
}
@@ -1338,15 +1340,14 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
Name);
Entry = 0;
} else if ((Flags & SC_ESUTYPEMASK) != SC_TYPEDEF) {
/* If a static declaration follows a non-static declaration, then
** diagnose the conflict. It will warn and compile an extern
** declaration if both declarations are global, otherwise give an
** error.
/* If a static declaration follows a non-static declaration, then the result is undefined.
** Most compilers choose to either give an error at compile time,
** or remove the extern property for a link time error if used.
*/
if (SymTab == SymTab0 &&
(Flags & SC_EXTERN) == 0 &&
(Entry->Flags & SC_EXTERN) != 0) {
Warning ("Static declaration of '%s' follows non-static declaration", Name);
Error ("Static declaration of '%s' follows non-static declaration", Name);
} else if ((Flags & SC_EXTERN) != 0 &&
(Entry->Owner == SymTab0 || (Entry->Flags & SC_DEF) != 0) &&
(Entry->Flags & SC_EXTERN) == 0) {
@@ -1358,8 +1359,12 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
*/
if (Entry->Owner == SymTab0) {
if ((Flags & SC_STORAGE) == 0) {
/* Linkage must be unchanged */
/* Linkage must be unchanged.
** The C standard specifies that a later extern declaration will be ignored,
** and will use the previous linkage instead. Giving a warning for this case.
*/
Flags &= ~SC_EXTERN;
Warning ("Extern declaration of '%s' follows static declaration, extern ignored", Name);
} else {
Error ("Non-static declaration of '%s' follows static declaration", Name);
}

View File

@@ -55,7 +55,7 @@
static void DoConversion (ExprDesc* Expr, const Type* NewType)
static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
/* Emit code to convert the given expression to a new type. */
{
const Type* OldType;
@@ -128,6 +128,7 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType)
** internally already represented by a long.
*/
if (NewBits <= OldBits) {
long OldVal = Expr->IVal;
/* Cut the value to the new size */
Expr->IVal &= (0xFFFFFFFFUL >> (32 - NewBits));
@@ -139,6 +140,10 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType)
Expr->IVal |= shl_l (~0UL, NewBits);
}
}
if ((OldVal != Expr->IVal) && IS_Get (&WarnConstOverflow) && !Explicit) {
Warning ("Implicit conversion of constant overflows %d-bit destination", NewBits);
}
}
/* Do the integer constant <-> absolute address conversion if necessary */
@@ -283,7 +288,7 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType)
/* Both types must be complete */
if (!IsIncompleteESUType (NewType) && !IsIncompleteESUType (Expr->Type)) {
/* Do the actual conversion */
DoConversion (Expr, NewType);
DoConversion (Expr, NewType, 0);
} else {
/* We should have already generated error elsewhere so that we
** could just silently fail here to avoid excess errors, but to
@@ -330,7 +335,7 @@ void TypeCast (ExprDesc* Expr)
ReplaceType (Expr, NewType);
} else if (IsCastType (Expr->Type)) {
/* Convert the value. The result has always the new type */
DoConversion (Expr, NewType);
DoConversion (Expr, NewType, 1);
} else {
TypeCompatibilityDiagnostic (NewType, Expr->Type, 1,
"Cast to incompatible type '%s' from '%s'");

View File

@@ -850,14 +850,25 @@ static char *filterInput (FILE *F, char *tbl)
/* loads file into buffer filtering it out */
int a, prevchar = -1, i = 0, bracket = 0, quote = 1;
for (;;) {
a = getc(F);
if ((a == '\n') || (a == '\015')) a = ' ';
if (a == ',' && quote) a = ' ';
if (a == '\042') quote =! quote;
a = getc(F);
while (1) {
if (i >= BLOODY_BIG_BUFFER) {
AbEnd ("File too large for internal parsing buffer (%d bytes)",BLOODY_BIG_BUFFER);
}
if (((a == '\n') || (a == '\015')) ||
(a == ',' && quote)) {
a = ' ';
}
if (a == '\042') {
quote =! quote;
}
if (quote) {
if ((a == '{') || (a == '(')) bracket++;
if ((a == '}') || (a == ')')) bracket--;
if ((a == '{') || (a == '(')) {
bracket++;
}
if ((a == '}') || (a == ')')) {
bracket--;
}
}
if (a == EOF) {
tbl[i] = '\0';
@@ -873,13 +884,18 @@ static char *filterInput (FILE *F, char *tbl)
if (a == ';' && quote) {
do {
a = getc (F);
} while (a != '\n');
fseek (F, -1, SEEK_CUR);
} while (a != '\n' && a != EOF);
/* Don't discard this newline/EOF, continue to next loop.
** A previous implementation used fseek(F,-1,SEEK_CUR),
** which is invalid for text mode files, and was unreliable across platforms.
*/
continue;
} else {
tbl[i++] = a;
prevchar = a;
}
}
a = getc(F);
}
if (bracket != 0) AbEnd ("There are unclosed brackets!");

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

@@ -49,12 +49,17 @@
#define SIM65_ERROR 0x7F
/* Does not use EXIT_FAILURE because it may overlap with test results. */
#define SIM65_ERROR -1
/* An error result for errors that are not part of the simulated test.
** Note that set simulated test can only return 8-bit errors 0-255.
*/
#define SIM65_ERROR_TIMEOUT 0x7E
#define SIM65_ERROR_TIMEOUT -2
/* An error result for max CPU instructions exceeded. */
extern int PrintCycles;
/* flag to print cycles at program termination */
/*****************************************************************************/
@@ -75,6 +80,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

@@ -60,8 +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;
/* 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[] = {
@@ -72,7 +78,6 @@ static const unsigned char HeaderSignature[] = {
static const unsigned char HeaderVersion = 2;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
@@ -139,7 +144,7 @@ static void OptQuitXIns (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* quit after MaxCycles cycles */
{
MaxCycles = strtoul(Arg, NULL, 0);
MaxCycles = strtoull(Arg, NULL, 0);
}
static unsigned char ReadProgramFile (void)
@@ -184,6 +189,7 @@ static unsigned char ReadProgramFile (void)
}
/* Get load address */
Val2 = 0; /* suppress uninitialized variable warning */
if (((Val = fgetc(F)) == EOF) ||
((Val2 = fgetc(F)) == EOF)) {
Error ("'%s': Header missing load address", ProgramFile);
@@ -236,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");
@@ -298,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 reached.");
}
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); /* Error code in range 0-255. */
}
@@ -242,7 +238,15 @@ static void PVClose (CPURegs* Regs)
Print (stderr, 2, "PVClose ($%04X)\n", FD);
RetVal = close (FD);
if (FD != 0xFFFF) {
RetVal = close (FD);
} else {
/* test/val/constexpr.c "abuses" close, expecting close(-1) to return -1.
** This behaviour is not the same on all target platforms.
** MSVC's close treats it as a fatal error instead and terminates.
*/
RetVal = 0xFFFF;
}
SetAX (Regs, RetVal);
}