Merge branch 'master' into ca65_jmp_abs_wrap_error

This commit is contained in:
Brad Smith
2023-05-03 21:12:37 -04:00
committed by GitHub
149 changed files with 1649 additions and 519 deletions

View File

@@ -115,7 +115,11 @@ install:
$(INSTALL) ../bin/* $(DESTDIR)$(bindir)
avail:
ifneq ($(patsubst %,../bin/%,$(PROGS)),$(wildcard $(patsubst %,../bin/%,$(PROGS))))
$(error executables are missing, please run make first)
else
$(foreach prog,$(PROGS),$(AVAIL_recipe))
endif
unavail:
$(foreach prog,$(PROGS),$(UNAVAIL_recipe))

View File

@@ -43,6 +43,10 @@
/*****************************************************************************/
/* EffAddr Flags */
#define EFFADDR_OVERRIDE_ZP 0x00000001UL
/* GetEA result struct */
typedef struct EffAddr EffAddr;
@@ -51,6 +55,7 @@ struct EffAddr {
unsigned long AddrModeSet; /* Possible addressing modes */
struct ExprNode* Expr; /* Expression if any (NULL otherwise) */
unsigned Reg; /* Register number in sweet16 mode */
unsigned long Flags; /* Other properties */
/* The following fields are used inside instr.c */
unsigned AddrMode; /* Actual addressing mode used */

View File

@@ -72,11 +72,13 @@ void GetEA (EffAddr* A)
/* Clear the output struct */
A->AddrModeSet = 0;
A->Expr = 0;
A->Flags = 0;
/* Handle an addressing size override */
switch (CurTok.Tok) {
case TOK_OVERRIDE_ZP:
Restrictions = AM65_DIR | AM65_DIR_X | AM65_DIR_Y;
A->Flags |= EFFADDR_OVERRIDE_ZP;
NextTok ();
break;

View File

@@ -66,6 +66,7 @@ static const char* const FeatureKeys[FEAT_COUNT] = {
"addrsize",
"bracket_as_indirect",
"string_escapes",
"long_jsr_jmp_rts",
};
@@ -97,37 +98,30 @@ feature_t FindFeature (const StrBuf* Key)
feature_t SetFeature (const StrBuf* Key)
/* Find the feature and set the corresponding flag if the feature is known.
** In any case, return the feature found. An invalid Key will return
** FEAT_UNKNOWN.
void SetFeature (feature_t Feature, unsigned char On)
/* Set the corresponding feature flag if Feature is valid.
*/
{
/* Map the string to an enum value */
feature_t Feature = FindFeature (Key);
/* Set the flags */
switch (Feature) {
case FEAT_DOLLAR_IS_PC: DollarIsPC = 1; break;
case FEAT_LABELS_WITHOUT_COLONS: NoColonLabels = 1; break;
case FEAT_LOOSE_STRING_TERM: LooseStringTerm = 1; break;
case FEAT_LOOSE_CHAR_TERM: LooseCharTerm = 1; break;
case FEAT_AT_IN_IDENTIFIERS: AtInIdents = 1; break;
case FEAT_DOLLAR_IN_IDENTIFIERS: DollarInIdents = 1; break;
case FEAT_LEADING_DOT_IN_IDENTIFIERS: LeadingDotInIdents= 1; break;
case FEAT_ORG_PER_SEG: OrgPerSeg = 1; break;
case FEAT_PC_ASSIGNMENT: PCAssignment = 1; break;
case FEAT_MISSING_CHAR_TERM: MissingCharTerm = 1; break;
case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = 1; break;
case FEAT_C_COMMENTS: CComments = 1; break;
case FEAT_FORCE_RANGE: ForceRange = 1; break;
case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= 1; break;
case FEAT_ADDRSIZE: AddrSize = 1; break;
case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = 1; break;
case FEAT_STRING_ESCAPES: StringEscapes = 1; break;
default: /* Keep gcc silent */ break;
case FEAT_DOLLAR_IS_PC: DollarIsPC = On; break;
case FEAT_LABELS_WITHOUT_COLONS: NoColonLabels = On; break;
case FEAT_LOOSE_STRING_TERM: LooseStringTerm = On; break;
case FEAT_LOOSE_CHAR_TERM: LooseCharTerm = On; break;
case FEAT_AT_IN_IDENTIFIERS: AtInIdents = On; break;
case FEAT_DOLLAR_IN_IDENTIFIERS: DollarInIdents = On; break;
case FEAT_LEADING_DOT_IN_IDENTIFIERS: LeadingDotInIdents= On; break;
case FEAT_ORG_PER_SEG: OrgPerSeg = On; break;
case FEAT_PC_ASSIGNMENT: PCAssignment = On; break;
case FEAT_MISSING_CHAR_TERM: MissingCharTerm = On; break;
case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = On; break;
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;
default: break;
}
/* Return the value found */
return Feature;
}

View File

@@ -68,6 +68,7 @@ typedef enum {
FEAT_ADDRSIZE,
FEAT_BRACKET_AS_INDIRECT,
FEAT_STRING_ESCAPES,
FEAT_LONG_JSR_JMP_RTS,
/* Special value: Number of features available */
FEAT_COUNT
@@ -86,10 +87,8 @@ feature_t FindFeature (const StrBuf* Key);
** feature is invalid, return FEAT_UNKNOWN.
*/
feature_t SetFeature (const StrBuf* Key);
/* Find the feature and set the corresponding flag if the feature is known.
** In any case, return the feature found. An invalid Key will return
** FEAT_UNKNOWN.
void SetFeature (feature_t Feature, unsigned char On);
/* Set the corresponding feature flag if Feature is valid.
*/

View File

@@ -67,6 +67,7 @@ unsigned char LineCont = 0; /* Allow line continuation */
unsigned char LargeAlignment = 0; /* Don't warn about large alignments */
unsigned char RelaxChecks = 0; /* Relax a few assembler checks */
unsigned char StringEscapes = 0; /* Allow C-style escapes in strings */
unsigned char LongJsrJmpRts = 0; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */
unsigned char WarningsAsErrors = 0; /* Error if any warnings */
/* Emulation features */

View File

@@ -69,6 +69,7 @@ extern unsigned char LineCont; /* Allow line continuation */
extern unsigned char LargeAlignment; /* Don't warn about large alignments */
extern unsigned char RelaxChecks; /* Relax a few assembler checks */
extern unsigned char StringEscapes; /* Allow C-style escapes in strings */
extern unsigned char LongJsrJmpRts; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */
extern unsigned char WarningsAsErrors; /* Error if any warnings */
/* Emulation features */

View File

@@ -75,7 +75,7 @@ void FinishIncludePaths (void)
AddSubSearchPathFromEnv (IncSearchPath, "CC65_HOME", "asminc");
/* Add some compiled-in search paths if defined at compile time. */
#if defined(CA65_INC) && !defined(_WIN32)
#if defined(CA65_INC) && !defined(_WIN32) && !defined(_AMIGA)
AddSearchPath (IncSearchPath, CA65_INC);
#endif

View File

@@ -120,9 +120,21 @@ static void PutJMP (const InsDesc* Ins);
** to check for this case and is otherwise identical to PutAll.
*/
static void PutJMP816 (const InsDesc* Ins);
/* Handle the JMP instruction for the 816.
** Allowing the long_jsr_jmp_rts feature to permit a long JMP.
** Note that JMP [abs] and JML [abs] are always both permitted for instruction $DC,
** because the [] notation for long indirection makes the generated instruction unambiguous.
*/
static void PutJSR816 (const InsDesc* Ins);
/* Handle the JSR instruction for the 816.
** Allowing the long_jsr_jmp_rts feature to permit a long JSR.
*/
static void PutRTS (const InsDesc* Ins attribute ((unused)));
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
** the enclosing scope is FAR.
** the enclosing scope is FAR, but only if the long_jsr_jmp_rts feature applies.
*/
static void PutAll (const InsDesc* Ins);
@@ -169,7 +181,7 @@ static const struct {
{ "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRK", 0x0000001, 0x00, 0, PutAll },
{ "BRK", 0x0800005, 0x00, 6, PutAll },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
{ "CLC", 0x0000001, 0x18, 0, PutAll },
@@ -240,7 +252,7 @@ static const struct {
{ "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRK", 0x0000001, 0x00, 0, PutAll },
{ "BRK", 0x0800005, 0x00, 6, PutAll },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
{ "CLC", 0x0000001, 0x18, 0, PutAll },
@@ -330,7 +342,7 @@ static const struct {
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRA", 0x0020000, 0x12, 0, PutPCRel8 }, /* DTV */
{ "BRK", 0x0000001, 0x00, 0, PutAll },
{ "BRK", 0x0800005, 0x00, 6, PutAll },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
{ "CLC", 0x0000001, 0x18, 0, PutAll },
@@ -406,7 +418,7 @@ static const struct {
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
{ "BRK", 0x0000001, 0x00, 0, PutAll },
{ "BRK", 0x0800005, 0x00, 6, PutAll },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
{ "CLC", 0x0000001, 0x18, 0, PutAll },
@@ -498,7 +510,7 @@ static const struct {
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
{ "BRK", 0x0000001, 0x00, 0, PutAll },
{ "BRK", 0x0800005, 0x00, 6, PutAll },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
{ "CLC", 0x0000001, 0x18, 0, PutAll },
@@ -610,7 +622,7 @@ static const struct {
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
{ "BRK", 0x0000001, 0x00, 0, PutAll },
{ "BRK", 0x0800005, 0x00, 6, PutAll },
{ "BSR", 0x0040000, 0x63, 0, PutPCRel4510 },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
@@ -735,7 +747,7 @@ static const struct {
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
{ "BRK", 0x0000005, 0x00, 6, PutAll },
{ "BRK", 0x0800005, 0x00, 6, PutAll },
{ "BRL", 0x0040000, 0x82, 0, PutPCRel16 },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
@@ -744,7 +756,7 @@ static const struct {
{ "CLI", 0x0000001, 0x58, 0, PutAll },
{ "CLV", 0x0000001, 0xb8, 0, PutAll },
{ "CMP", 0x0b8f6fc, 0xc0, 0, PutAll },
{ "COP", 0x0000004, 0x02, 6, PutAll },
{ "COP", 0x0800005, 0x02, 6, PutAll },
{ "CPA", 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */
{ "CPX", 0x0c0000c, 0xe0, 1, PutAll },
{ "CPY", 0x0c0000c, 0xc0, 1, PutAll },
@@ -758,9 +770,9 @@ static const struct {
{ "INX", 0x0000001, 0xe8, 0, PutAll },
{ "INY", 0x0000001, 0xc8, 0, PutAll },
{ "JML", 0x4000010, 0x5c, 1, PutAll },
{ "JMP", 0x4010818, 0x4c, 6, PutAll },
{ "JMP", 0x4010818, 0x4c, 6, PutJMP816 },
{ "JSL", 0x0000010, 0x20, 7, PutAll },
{ "JSR", 0x0010018, 0x20, 7, PutAll },
{ "JSR", 0x0010018, 0x20, 7, PutJSR816 },
{ "LDA", 0x0b8f6fc, 0xa0, 0, PutAll },
{ "LDX", 0x0c0030c, 0xa2, 1, PutAll },
{ "LDY", 0x0c0006c, 0xa0, 1, PutAll },
@@ -821,7 +833,7 @@ static const struct {
{ "TYA", 0x0000001, 0x98, 0, PutAll },
{ "TYX", 0x0000001, 0xbb, 0, PutAll },
{ "WAI", 0x0000001, 0xcb, 0, PutAll },
{ "WDM", 0x0000004, 0x42, 6, PutAll },
{ "WDM", 0x0800004, 0x42, 6, PutAll },
{ "XBA", 0x0000001, 0xeb, 0, PutAll },
{ "XCE", 0x0000001, 0xfb, 0, PutAll }
}
@@ -897,7 +909,7 @@ static const struct {
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
{ "BRK", 0x0000001, 0x00, 0, PutAll },
{ "BRK", 0x0800005, 0x00, 6, PutAll },
{ "BSR", 0x0020000, 0x44, 0, PutPCRel8 },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
@@ -1257,7 +1269,8 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A)
ExprNode* Left = A->Expr->Left;
if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) &&
Left->Op == EXPR_SYMBOL &&
GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) {
GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP &&
!(A->Flags & EFFADDR_OVERRIDE_ZP)) {
/* Output a warning */
Warning (1, "Suspicious address expression");
@@ -1605,7 +1618,7 @@ static void PutJMP (const InsDesc* Ins)
if (EvalEA (Ins, &A)) {
/* Check for indirect addressing */
if (A.AddrModeBit & AM65_ABS_IND && CPU < CPU_65SC02) {
if ((A.AddrModeBit & AM65_ABS_IND) && (CPU < CPU_65SC02)) {
/* Compare the low byte of the expression to 0xFF to check for
** a page cross. Be sure to use a copy of the expression otherwise
@@ -1628,12 +1641,46 @@ static void PutJMP (const InsDesc* Ins)
static void PutRTS (const InsDesc* Ins attribute ((unused)))
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
** the enclosing scope is FAR.
static void PutJMP816 (const InsDesc* Ins)
/* Handle the JMP instruction for the 816.
** Allowing the long_jsr_jmp_rts feature to permit a long JMP.
** Note that JMP [abs] and JML [abs] are always both permitted for instruction $DC,
** because the [] notation for long indirection makes the generated instruction unambiguous.
*/
{
if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
if (LongJsrJmpRts) {
PutJMP (Ins);
} else {
InsDesc InsAbs = *Ins;
InsAbs.AddrMode &= ~(AM65_ABS_LONG);
PutJMP (&InsAbs);
}
}
static void PutJSR816 (const InsDesc* Ins)
/* Handle the JSR instruction for the 816.
** Allowing the long_jsr_jmp_rts feature to permit a long JSR.
*/
{
if (LongJsrJmpRts) {
PutAll (Ins);
} else {
InsDesc InsAbs = *Ins;
InsAbs.AddrMode &= ~(AM65_ABS_LONG);
PutJMP (&InsAbs);
}
}
static void PutRTS (const InsDesc* Ins attribute ((unused)))
/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
** the enclosing scope is FAR, but only if the long_jsr_jmp_rts feature applies.
*/
{
if (LongJsrJmpRts && SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
Emit0 (0x6B); /* RTL */
} else {
Emit0 (0x60); /* RTS */

View File

@@ -390,7 +390,20 @@ void MacDef (unsigned Style)
{
Macro* M;
TokNode* N;
FilePos Pos;
int HaveParams;
int LastTokWasSep;
/* For classic macros, remember if we are at the beginning of the line.
** If the macro name and parameters pass our checks then we will be on a
** new line, so set it now
*/
LastTokWasSep = 1;
/* Save the position of the start of the macro definition to allow
** using Perror to display the error if .endmacro isn't found
*/
Pos = CurTok.Pos;
/* We expect a macro name here */
if (CurTok.Tok != TOK_IDENT) {
@@ -491,14 +504,16 @@ void MacDef (unsigned Style)
while (1) {
/* Check for end of macro */
if (Style == MAC_STYLE_CLASSIC) {
/* In classic macros, only .endmacro is allowed */
if (CurTok.Tok == TOK_ENDMACRO) {
/* In classic macros, if .endmacro is not at the start of the line
** it will be added to the macro definition instead of closing it.
*/
if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) {
/* Done */
break;
}
/* May not have end of file in a macro definition */
if (CurTok.Tok == TOK_EOF) {
Error ("'.ENDMACRO' expected");
PError (&Pos, "'.ENDMACRO' expected for macro '%m%p'", &M->Name);
goto Done;
}
} else {
@@ -573,6 +588,11 @@ void MacDef (unsigned Style)
}
++M->TokCount;
/* Save if last token was a separator to know if .endmacro is at
** the start of a line
*/
LastTokWasSep = TokIsSep(CurTok.Tok);
/* Read the next token */
NextTok ();
}

View File

@@ -489,12 +489,15 @@ static void OptDebugInfo (const char* Opt attribute ((unused)),
static void OptFeature (const char* Opt attribute ((unused)), const char* Arg)
/* Set an emulation feature */
{
/* Make a string buffer from Arg */
StrBuf Feature;
/* Make a string buffer from Arg and use it to find the feature. */
StrBuf StrFeature;
feature_t Feature = FindFeature (SB_InitFromString (&StrFeature, Arg));
/* Set the feature, check for errors */
if (SetFeature (SB_InitFromString (&Feature, Arg)) == FEAT_UNKNOWN) {
/* Enable the feature, check for errors */
if (Feature == FEAT_UNKNOWN) {
AbEnd ("Illegal emulation feature: '%s'", Arg);
} else {
SetFeature (Feature, 1);
}
}
@@ -855,7 +858,12 @@ static void OneLine (void)
/* The line has switched the segment */
Size = 0;
}
DefSizeOfSymbol (Sym, Size);
/* Suppress .size Symbol if this Symbol already has a multiply-defined error,
** as it will only create its own additional unnecessary error.
*/
if ((Sym->Flags & SF_MULTDEF) == 0) {
DefSizeOfSymbol (Sym, Size);
}
}
/* Line separator must come here */

View File

@@ -1023,7 +1023,10 @@ static void DoFatal (void)
static void DoFeature (void)
/* Switch the Feature option */
{
/* Allow a list of comma separated keywords */
feature_t Feature;
unsigned char On;
/* Allow a list of comma separated feature keywords with optional +/- or ON/OFF */
while (1) {
/* We expect an identifier */
@@ -1034,18 +1037,24 @@ static void DoFeature (void)
/* Make the string attribute lower case */
LocaseSVal ();
/* Set the feature and check for errors */
if (SetFeature (&CurTok.SVal) == FEAT_UNKNOWN) {
Feature = FindFeature(&CurTok.SVal);
if (Feature == FEAT_UNKNOWN) {
/* Not found */
ErrorSkip ("Invalid feature: '%m%p'", &CurTok.SVal);
return;
} else {
/* Skip the keyword */
NextTok ();
}
NextTok ();
/* Optional +/- or ON/OFF */
On = 1;
if (CurTok.Tok != TOK_COMMA && !TokIsSep (CurTok.Tok)) {
SetBoolOption(&On);
}
/* Allow more than one keyword */
/* Apply feature setting. */
SetFeature (Feature, On);
/* Allow more than one feature separated by commas. */
if (CurTok.Tok == TOK_COMMA) {
NextTok ();
} else {

View File

@@ -112,6 +112,7 @@ struct CharSource {
CharSource* Next; /* Linked list of char sources */
token_t Tok; /* Last token */
int C; /* Last character */
int SkipN; /* For '\r\n' line endings, skip '\n\ if next */
const CharSourceFunctions* Func; /* Pointer to function table */
union {
InputFile File; /* File data */
@@ -325,6 +326,7 @@ static void UseCharSource (CharSource* S)
Source = S;
/* Read the first character from the new file */
S->SkipN = 0;
S->Func->NextChar (S);
/* Setup the next token so it will be skipped on the next call to
@@ -386,6 +388,11 @@ static void IFNextChar (CharSource* S)
while (1) {
int N = fgetc (S->V.File.F);
if (N == '\n' && S->SkipN) {
N = fgetc (S->V.File.F);
}
S->SkipN = 0;
if (N == EOF) {
/* End of file. Accept files without a newline at the end */
if (SB_NotEmpty (&S->V.File.Line)) {
@@ -401,9 +408,12 @@ static void IFNextChar (CharSource* S)
/* Check for end of line */
} else if (N == '\n') {
/* End of line */
break;
} else if (N == '\r') {
/* End of line, skip '\n' if it's the next character */
S->SkipN = 1;
break;
/* Collect other stuff */
} else {

View File

@@ -306,7 +306,7 @@ void SegAlign (unsigned long Alignment, int FillVal)
ActiveSeg->Align = CombinedAlignment;
/* Output a warning for larger alignments if not suppressed */
if (CombinedAlignment >= LARGE_ALIGNMENT && !LargeAlignment) {
if (CombinedAlignment >= LARGE_ALIGNMENT && CombinedAlignment > ActiveSeg->Align && CombinedAlignment > Alignment && !LargeAlignment) {
Warning (0, "Combined alignment is suspiciously large (%lu)",
CombinedAlignment);
}

View File

@@ -570,7 +570,18 @@ void SymCheck (void)
/* Check for open scopes */
if (CurrentScope->Parent != 0) {
Error ("Local scope was not closed");
if (CurrentScope->Label) {
/* proc has a label indicating the line it was opened. */
LIError (&CurrentScope->Label->DefLines,
"Local proc '%s' was not closed",
GetString (CurrentScope->Name));
} else {
/* scope has no label to track a line number, uses end-of-document line instead.
** Anonymous scopes will reveal their internal automatic name.
*/
Error ("Local scope '%s' was not closed",
GetString (CurrentScope->Name));
}
}
/* First pass: Walk through all symbols, checking for undefined's and

View File

@@ -1153,6 +1153,8 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
/* Save lhs into zeropage */
AddStoreLhsA (D);
/* AddStoreLhsA may have moved the OpIndex, recalculate insertion point to prevent label migration. */
D->IP = D->OpIndex + 1;
/* cmp */
X = NewCodeEntry (OP65_CMP, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI);
@@ -1206,6 +1208,8 @@ static unsigned Opt_a_tosicmp (StackOpData* D)
/* RHS src is not directly comparable */
X = NewCodeEntry (OP65_STA, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI);
InsertEntry (D, X, D->Rhs.A.ChgIndex + 1);
/* RHS insertion may have moved the OpIndex, recalculate insertion point to prevent label migration. */
D->IP = D->OpIndex + 1;
/* Cmp with stored RHS */
X = NewCodeEntry (OP65_CMP, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI);

View File

@@ -803,7 +803,6 @@ const Type* GetStructReplacementType (const Type* SType)
switch (SizeOf (SType)) {
case 1: NewType = type_uchar; break;
case 2: NewType = type_uint; break;
case 3: /* FALLTHROUGH */
case 4: NewType = type_ulong; break;
default: NewType = SType; break;
}

View File

@@ -3090,9 +3090,10 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef)
Expr->Type = Expr2.Type;
} else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer addition */
flags = typeadjust (Expr, &Expr2, 0);
/* Load rhs into the primary */
LoadExpr (CF_NONE, &Expr2);
/* Adjust rhs primary if needed */
flags = typeadjust (Expr, &Expr2, 0);
} else {
/* OOPS */
AddDone = -1;

View File

@@ -601,7 +601,7 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
** We don't currently support this case.
*/
if (RType == Param->Type) {
Error ("Passing '%s' of this size by value is not supported", GetFullTypeName (Param->Type));
Error ("Passing '%s' of this size (%d) by value is not supported", GetFullTypeName (Param->Type), SizeOf (RType));
}
}

View File

@@ -76,7 +76,7 @@ void FinishIncludePaths (void)
AddSubSearchPathFromEnv (SysIncSearchPath, "CC65_HOME", "include");
/* Add some compiled-in search paths if defined at compile time. */
#if defined(CC65_INC) && !defined(_WIN32)
#if defined(CC65_INC) && !defined(_WIN32) && !defined(_AMIGA)
AddSearchPath (SysIncSearchPath, CC65_INC);
#endif

View File

@@ -1216,7 +1216,7 @@ static void OptPrintTargetPath (const char* Opt attribute ((unused)),
SearchPaths* TargetPaths = NewSearchPath ();
AddSubSearchPathFromEnv (TargetPaths, "CC65_HOME", "target");
#if defined(CL65_TGT) && !defined(_WIN32)
#if defined(CL65_TGT) && !defined(_WIN32) && !defined(_AMIGA)
AddSearchPath (TargetPaths, CL65_TGT);
#endif
AddSubSearchPathFromBin (TargetPaths, "target");

View File

@@ -193,8 +193,16 @@ static void BinWriteMem (BinDesc* D, MemoryArea* M)
NewAddr += M->Start;
}
if (DoWrite || (M->Flags & MF_FILL) != 0) {
/* Seek in "overwrite" segments */
if (S->Flags & SF_OVERWRITE) {
/* Seek in "overwrite" segments. Fill if the seek position has not been reached yet. */
unsigned long FileLength;
unsigned long SeekTarget = NewAddr - M->Start + M->FileOffs;
fseek (D->F, 0, SEEK_END);
FileLength = ftell (D->F);
if (SeekTarget > FileLength) {
WriteMult (D->F, M->FillVal, SeekTarget - FileLength);
PrintNumVal ("SF_OVERWRITE", SeekTarget - FileLength);
}
fseek (D->F, NewAddr - M->Start + M->FileOffs, SEEK_SET);
} else {
WriteMult (D->F, M->FillVal, NewAddr-Addr);

View File

@@ -1950,6 +1950,10 @@ unsigned CfgProcess (void)
/* Remember the start address before handling this segment */
unsigned long StartAddr = Addr;
/* For computing FillLevel */
unsigned long FillLevel;
unsigned long FillAdded = 0;
/* Take note of "overwrite" segments and make sure there are no
** other segment types following them in current memory region.
*/
@@ -2039,14 +2043,14 @@ unsigned CfgProcess (void)
++Overflows;
if (S->Flags & SF_OFFSET) {
CfgWarning (GetSourcePos (S->LI),
"Segment '%s' offset is too small in '%s' by %lu byte%c",
"Segment '%s' offset is too small in '%s' by %lu byte%s",
GetString (S->Name), GetString (M->Name),
Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's');
Addr - NewAddr, (Addr - NewAddr == 1) ? "" : "s");
} else {
CfgWarning (GetSourcePos (S->LI),
"Segment '%s' start address is too low in '%s' by %lu byte%c",
"Segment '%s' start address is too low in '%s' by %lu byte%s",
GetString (S->Name), GetString (M->Name),
Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's');
Addr - NewAddr, (Addr - NewAddr == 1) ? "" : "s");
}
} else {
Addr = NewAddr;
@@ -2086,14 +2090,19 @@ unsigned CfgProcess (void)
/* Increment the fill level of the memory area; and, check for an
** overflow.
*/
M->FillLevel = Addr + S->Seg->Size - M->Start;
if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) {
FillLevel = Addr + S->Seg->Size - M->Start;
if (FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) {
++Overflows;
M->Flags |= MF_OVERFLOW;
CfgWarning (GetSourcePos (M->LI),
"Segment '%s' overflows memory area '%s' by %lu byte%c",
"Segment '%s' overflows memory area '%s' by %lu byte%s",
GetString (S->Name), GetString (M->Name),
M->FillLevel - M->Size, (M->FillLevel - M->Size == 1) ? ' ' : 's');
FillLevel - M->Size, (FillLevel - M->Size == 1) ? "" : "s");
}
if (FillLevel > M->FillLevel) {
/* Regular segments increase FillLevel. Overwrite segments may increase but not decrease FillLevel. */
FillAdded = FillLevel - M->FillLevel;
M->FillLevel = FillLevel;
}
/* If requested, define symbols for the start and size of the
@@ -2112,13 +2121,14 @@ unsigned CfgProcess (void)
Addr += S->Seg->Size;
/* If this segment will go out to the file, or its place
** in the file will be filled, then increase the file size,
** unless it's an OVERWRITE segment.
** in the file will be filled, then increase the file size.
** An OVERWRITE segment will only increase the size if it overlapped some of the fill area.
*/
if (S->Load == M &&
((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0) &&
(S->Flags & SF_OVERWRITE) == 0) {
M->F->Size += Addr - StartAddr;
((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0)) {
M->F->Size += (!(S->Flags & SF_OVERWRITE)) ?
(Addr - StartAddr) :
FillAdded;
}
}

View File

@@ -88,13 +88,13 @@ void InitSearchPaths (void)
AddSubSearchPathFromEnv (CfgDefaultPath, "CC65_HOME", "cfg");
/* Add some compiled-in search paths if defined at compile time. */
#if defined(LD65_LIB) && !defined(_WIN32)
#if defined(LD65_LIB) && !defined(_WIN32) && !defined(_AMIGA)
AddSearchPath (LibDefaultPath, LD65_LIB);
#endif
#if defined(LD65_OBJ) && !defined(_WIN32)
#if defined(LD65_OBJ) && !defined(_WIN32) && !defined(_AMIGA)
AddSearchPath (ObjDefaultPath, LD65_OBJ);
#endif
#if defined(LD65_CFG) && !defined(_WIN32)
#if defined(LD65_CFG) && !defined(_WIN32) && !defined(_AMIGA)
AddSearchPath (CfgDefaultPath, LD65_CFG);
#endif

View File

@@ -230,7 +230,7 @@ Section* ReadSection (FILE* F, ObjData* O)
"%lu. Last module requiring alignment was '%s'.",
GetString (Name), Alignment, MAX_ALIGNMENT,
GetObjFileName (O));
} else if (Alignment >= LARGE_ALIGNMENT && !LargeAlignment) {
} else if (Alignment >= LARGE_ALIGNMENT && Alignment > S->Alignment && Alignment > Sec->Alignment && !LargeAlignment) {
Warning ("Combined alignment for segment '%s' is suspiciously "
"large (%lu). Last module requiring alignment was '%s'.",
GetString (Name), Alignment, GetObjFileName (O));

View File

@@ -312,7 +312,7 @@ static void AssembleByte(unsigned bits, char val)
static unsigned char AnalyseNextChunks(signed *newlen, signed len, char data[32], char ColorBits)
{
char longest = 1;
char prev = 255;
unsigned char prev = 255;
char count = 0;
char index = 0;
char lindex = 0;