1
0
mirror of https://github.com/cc65/cc65.git synced 2024-11-18 15:05:14 +00:00

Merge branch 'master' into ca65_long_jsr_jmp_rts

This commit is contained in:
Bob Andrews 2023-02-24 19:25:32 +01:00 committed by GitHub
commit 12fc59351e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 262 additions and 60 deletions

View File

@ -125,6 +125,7 @@ Long options:
--target sys Set the target system
--verbose Increase verbosity
--version Print the assembler version
--warnings-as-errors Treat warnings as errors
---------------------------------------------------------------------------
</verb></tscreen>
@ -359,6 +360,13 @@ Here is a description of all the command line options:
warning level is 1, and it would probably be silly to set it to
something lower.
<label id="option--warnings-as-errors">
<tag><tt>--warnings-as-errors</tt></tag>
An error will be generated if any warnings were produced.
</descrip>
<p>
@ -2019,7 +2027,7 @@ Here's a list of all control commands and a description, what they do:
<sect1><tt>.A16</tt><label id=".A16"><p>
Valid only in 65816 mode. Switch the accumulator to 16 bit.
Valid only in 65816 mode. Assume the accumulator is 16 bit.
Note: This command will not emit any code, it will tell the assembler to
create 16 bit operands for immediate accumulator addressing mode.
@ -2029,7 +2037,7 @@ Here's a list of all control commands and a description, what they do:
<sect1><tt>.A8</tt><label id=".A8"><p>
Valid only in 65816 mode. Switch the accumulator to 8 bit.
Valid only in 65816 mode. Assume the accumulator is 8 bit.
Note: This command will not emit any code, it will tell the assembler to
create 8 bit operands for immediate accu addressing mode.
@ -2112,15 +2120,15 @@ Here's a list of all control commands and a description, what they do:
</verb></tscreen>
the assembler will force a segment alignment to the least common multiple of
15, 18 and 251 - which is 22590. To protect the user against errors, the
assembler will issue a warning when the combined alignment exceeds 256. The
command line option <tt><ref id="option--large-alignment"
name="--large-alignment"></tt> will disable this warning.
15, 18 and 251 - which is 22590. To protect the user against errors, when the
combined alignment is larger than the explicitly requested alignments,
the assembler will issue a warning if it also exceeds 256. The command line
option <tt><ref id="option--large-alignment" name="--large-alignment"></tt>
will disable this warning.
Please note that with alignments that are a power of two (which were the
only alignments possible in older versions of the assembler), the problem is
less severe, because the least common multiple of powers to the same base is
always the larger one.
Please note that with only alignments that are a power of two, a warning will
never occur, because the least common multiple of powers to the same base is
always simply the larger one.
@ -3053,7 +3061,7 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH
<sect1><tt>.I16</tt><label id=".I16"><p>
Valid only in 65816 mode. Switch the index registers to 16 bit.
Valid only in 65816 mode. Assume the index registers are 16 bit.
Note: This command will not emit any code, it will tell the assembler to
create 16 bit operands for immediate operands.
@ -3064,7 +3072,7 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH
<sect1><tt>.I8</tt><label id=".I8"><p>
Valid only in 65816 mode. Switch the index registers to 8 bit.
Valid only in 65816 mode. Assume the index registers are 8 bit.
Note: This command will not emit any code, it will tell the assembler to
create 8 bit operands for immediate operands.

View File

@ -6,7 +6,8 @@
<abstract>
Internal details of cc65 code generation,
such as calling assembly functions from C.
such as the expected linker configuration,
and calling assembly functions from C.
</abstract>
<!-- Table of contents -->
@ -16,6 +17,76 @@ such as calling assembly functions from C.
<sect>Linker configuration<p>
The C libraries and code generation depend directly on a suitable linker configuration.
There are premade configuration files in the <tt/cfg&sol;/ directory, normally chosen by the
linker's selected target. These can be used as a template for customization.
The C libraries depend on several special segments to be defined in your linker configuration.
Generated code will also use some of them by default.
Some platform libraries have additional special segments.
Memory areas are free to be defined in a way that is appropriate to each platform,
and the segments they contain are used as a layer of semantics and abstraction,
to allow much of the reorganization to be done with the linker config,
rather than requiring platform-specific code source changes.
<sect1><tt/ZEROPAGE/ segment<p>
Used by the C library and generated code for efficient internal and temporary state storage,
also called "pseudo-registers".
<sect1><tt/STARTUP/ segment<p>
Used by each platform instance of the C library in <tt/crt0.s/ to contain the entry point
of the program.
The startup module will export <tt/__STARTUP__ : absolute = 1/ to force the linker to
always include <tt/crt0.s/ from the library.
<sect1><tt/CODE/ segment<p>
The default segment for generated code, and most C library code will be located here.
Use <tt/#pragma code-name/ to redirect generated code to another segment.
<sect1><tt/BSS/ segment<p>
Used for uninitialized variables.
Originally an acronym for "Block Started by Symbol", but the meaning of this is now obscure.
Use <tt/#pragma bss-name/ to redirect uninitialized variables to another segment.
<sect1><tt/DATA/ segment<p>
Used for initialized variables.
On some platforms, this may be initialized as part of the program loading process,
but on others it may have a separate <tt/LOAD/ and <tt/RUN/ address,
allowing <tt/copydata/ to copy the initialization from the loaded location
into their run destination in RAM.
Use <tt/#pragma data-name/ to redirect initialized variables to another segment.
<sect1><tt/RODATA/ segment<p>
Used for read-only (constant) data.
Use <tt/#pragma rodata-name/ to redirect constant data to another segment.
<sect1><tt/FEATURES/ table<p>
This currently defines table locations for the <tt/CONDES/
constructor, destructor, and interruptor features.
Some platform libraries use these.
The constructors will be called with <tt/initlib/ at startup,
and the destructors with <tt/donelib/ at program exit.
Interruptors are called with <tt/callirq/.
<sect>Calling assembly functions from C<p>
<sect1>Calling conventions<p>

View File

@ -59,7 +59,7 @@
Contains hints on creating the most effective code with cc65.
<tag><htmlurl url="cc65-intern.html" name="cc65-intern.html"></tag>
Describes internal details of cc65, such as calling conventions.
Describes internal details of cc65: linker configuration, calling conventions, etc.
<tag><htmlurl url="using-make.html" name="using-make.html"></tag>
Build programs, using the GNU Make utility.

View File

@ -90,6 +90,7 @@ Long options:
--start-group Start a library group
--target sys Set the target system
--version Print the linker version
--warnings-as-errors Treat warnings as errors
---------------------------------------------------------------------------
</verb></tscreen>
@ -330,6 +331,13 @@ Here is a description of all of the command-line options:
directory, in the list of directories specified using <tt/--obj-path/, in
directories given by environment variables, and in a built-in default directory.
<label id="option--warnings-as-errors">
<tag><tt>--warnings-as-errors</tt></tag>
An error will be generated if any warnings were produced.
</descrip>

View File

@ -68,6 +68,7 @@ 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 */
unsigned char DollarIsPC = 0; /* Allow the $ symbol as current PC */

View File

@ -70,6 +70,7 @@ 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 */
extern unsigned char DollarIsPC; /* Allow the $ symbol as current PC */

View File

@ -656,6 +656,15 @@ static void OptVersion (const char* Opt attribute ((unused)),
static void OptWarningsAsErrors (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Generate an error if any warnings occur */
{
WarningsAsErrors = 1;
}
static void DoPCAssign (void)
/* Start absolute code */
{
@ -919,27 +928,28 @@ int main (int argc, char* argv [])
{
/* Program long options */
static const LongOpt OptTab[] = {
{ "--auto-import", 0, OptAutoImport },
{ "--bin-include-dir", 1, OptBinIncludeDir },
{ "--cpu", 1, OptCPU },
{ "--create-dep", 1, OptCreateDep },
{ "--create-full-dep", 1, OptCreateFullDep },
{ "--debug", 0, OptDebug },
{ "--debug-info", 0, OptDebugInfo },
{ "--feature", 1, OptFeature },
{ "--help", 0, OptHelp },
{ "--ignore-case", 0, OptIgnoreCase },
{ "--include-dir", 1, OptIncludeDir },
{ "--large-alignment", 0, OptLargeAlignment },
{ "--list-bytes", 1, OptListBytes },
{ "--listing", 1, OptListing },
{ "--memory-model", 1, OptMemoryModel },
{ "--pagelength", 1, OptPageLength },
{ "--relax-checks", 0, OptRelaxChecks },
{ "--smart", 0, OptSmart },
{ "--target", 1, OptTarget },
{ "--verbose", 0, OptVerbose },
{ "--version", 0, OptVersion },
{ "--auto-import", 0, OptAutoImport },
{ "--bin-include-dir", 1, OptBinIncludeDir },
{ "--cpu", 1, OptCPU },
{ "--create-dep", 1, OptCreateDep },
{ "--create-full-dep", 1, OptCreateFullDep },
{ "--debug", 0, OptDebug },
{ "--debug-info", 0, OptDebugInfo },
{ "--feature", 1, OptFeature },
{ "--help", 0, OptHelp },
{ "--ignore-case", 0, OptIgnoreCase },
{ "--include-dir", 1, OptIncludeDir },
{ "--large-alignment", 0, OptLargeAlignment },
{ "--list-bytes", 1, OptListBytes },
{ "--listing", 1, OptListing },
{ "--memory-model", 1, OptMemoryModel },
{ "--pagelength", 1, OptPageLength },
{ "--relax-checks", 0, OptRelaxChecks },
{ "--smart", 0, OptSmart },
{ "--target", 1, OptTarget },
{ "--verbose", 0, OptVerbose },
{ "--version", 0, OptVersion },
{ "--warnings-as-errors", 0, OptWarningsAsErrors },
};
/* Name of the global name space */
@ -1144,6 +1154,10 @@ int main (int argc, char* argv [])
SegDump ();
}
if (WarningCount > 0 && WarningsAsErrors) {
Error("Warnings as errors");
}
/* If we didn't have an errors, finish off the line infos */
DoneLineInfo ();

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

@ -46,6 +46,17 @@
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Statistics */
unsigned WarningCount = 0;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
@ -66,6 +77,9 @@ void Warning (const char* Format, ...)
fprintf (stderr, "%s: Warning: %s\n", ProgName, SB_GetConstBuf (&S));
SB_Done (&S);
/* Count warnings */
++WarningCount;
}

View File

@ -43,6 +43,17 @@
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Statistics */
extern unsigned WarningCount;
/*****************************************************************************/
/* Code */
/*****************************************************************************/

View File

@ -43,19 +43,20 @@
const char* OutputName = "a.out"; /* Name of output file */
unsigned OutputNameUsed = 0; /* Output name was used by %O */
const char* OutputName = "a.out"; /* Name of output file */
unsigned OutputNameUsed = 0; /* Output name was used by %O */
unsigned ModuleId = 0; /* Id for o65 module */
unsigned ModuleId = 0; /* Id for o65 module */
/* Start address */
unsigned char HaveStartAddr = 0; /* Start address not given */
unsigned long StartAddr = 0x200; /* Start address */
unsigned char HaveStartAddr = 0; /* Start address not given */
unsigned long StartAddr = 0x200; /* Start address */
unsigned char VerboseMap = 0; /* Verbose map file */
unsigned char AllowMultDef = 0; /* Allow multiple definitions */
unsigned char LargeAlignment = 0; /* Don't warn about large alignments */
unsigned char VerboseMap = 0; /* Verbose map file */
unsigned char AllowMultDef = 0; /* Allow multiple definitions */
unsigned char LargeAlignment = 0; /* Don't warn about large alignments */
unsigned char WarningsAsErrors = 0; /* Error if any warnings */
const char* MapFileName = 0; /* Name of the map file */
const char* LabelFileName = 0; /* Name of the label file */
const char* DbgFileName = 0; /* Name of the debug file */
const char* MapFileName = 0; /* Name of the map file */
const char* LabelFileName = 0; /* Name of the label file */
const char* DbgFileName = 0; /* Name of the debug file */

View File

@ -44,21 +44,22 @@
extern const char* OutputName; /* Name of output file */
extern unsigned OutputNameUsed; /* Output name was used by %O */
extern const char* OutputName; /* Name of output file */
extern unsigned OutputNameUsed; /* Output name was used by %O */
extern unsigned ModuleId; /* Id for o65 module */
extern unsigned ModuleId; /* Id for o65 module */
extern unsigned char HaveStartAddr; /* True if start address was given */
extern unsigned long StartAddr; /* Start address */
extern unsigned char HaveStartAddr; /* True if start address was given */
extern unsigned long StartAddr; /* Start address */
extern unsigned char VerboseMap; /* Verbose map file */
extern unsigned char AllowMultDef; /* Allow multiple definitions */
extern unsigned char LargeAlignment; /* Don't warn about large alignments */
extern unsigned char VerboseMap; /* Verbose map file */
extern unsigned char AllowMultDef; /* Allow multiple definitions */
extern unsigned char LargeAlignment; /* Don't warn about large alignments */
extern unsigned char WarningsAsErrors; /* Error if any warnings */
extern const char* MapFileName; /* Name of the map file */
extern const char* LabelFileName; /* Name of the label file */
extern const char* DbgFileName; /* Name of the debug file */
extern const char* MapFileName; /* Name of the map file */
extern const char* LabelFileName; /* Name of the label file */
extern const char* DbgFileName; /* Name of the debug file */

View File

@ -559,6 +559,15 @@ static void OptVersion (const char* Opt attribute ((unused)),
static void OptWarningsAsErrors (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Generate an error if any warnings occur */
{
WarningsAsErrors = 1;
}
static void OptMultDef (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Set flag to allow multiple definitions of a global symbol */
@ -637,6 +646,7 @@ static void ParseCommandLine(void)
{ "--start-group", 0, CmdlOptStartGroup },
{ "--target", 1, CmdlOptTarget },
{ "--version", 0, OptVersion },
{ "--warnings-as-errors", 0, OptWarningsAsErrors },
};
unsigned I;
@ -845,6 +855,10 @@ int main (int argc, char* argv [])
(MemoryAreaOverflows > 1) ? 's' : ' ');
}
if (WarningCount > 0 && WarningsAsErrors) {
Error("Warnings as errors");
}
/* Create the output file */
CfgWriteTarget ();

View File

@ -95,6 +95,9 @@ void CfgWarning (const FilePos* Pos, const char* Format, ...)
Warning ("%s:%u: %s",
GetString (Pos->Name), Pos->Line, SB_GetConstBuf (&Buf));
SB_Done (&Buf);
/* Count warnings */
++WarningCount;
}

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

40
test/val/bug1989.c Normal file
View File

@ -0,0 +1,40 @@
/* bug #1989 - OptStackOps Opt_a_toscmpbool bypassed a comparison, discovered in 544a49c */
#include <stdlib.h>
unsigned char i,r,j;
void fail() // for the r=0 case, the == comparison was getting jumped over by OptStackOps
{
if ((i & 0x1f) == (r ? 0 : 16)) j -=8;
}
void pass()
{
if ((i & 0x1f) == (unsigned char)(r ? 0 : 16)) j -= 8;
}
void test(unsigned char ti, unsigned char tr, unsigned char tj)
{
unsigned char rj;
i = ti;
r = tr;
j = tj;
pass();
rj = j;
i = ti;
r = tr;
j = tj;
fail();
if (j != rj) exit(1);
}
int main(void)
{
test( 1,0,33);
test( 0,0,33);
test( 1,1,33);
test(16,1,33);
return 0;
}