From 78263cd24b301406f9567f3e0a4fa03488445656 Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Fri, 17 Feb 2023 23:48:32 -0500 Subject: [PATCH 01/65] Fix OptStackOps label migration case for toscmpbool, add test case --- src/cc65/coptstop.c | 2 ++ test/val/bug1989.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 test/val/bug1989.c diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 4d0151c55..8b2821dcd 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -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); diff --git a/test/val/bug1989.c b/test/val/bug1989.c new file mode 100644 index 000000000..b3e3d4c8d --- /dev/null +++ b/test/val/bug1989.c @@ -0,0 +1,40 @@ + +/* bug #1989 - OptStackOps Opt_a_toscmpbool bypassed a comparison, discovered in 544a49c */ + +#include + +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; +} From 4e411e8526df0c627c5ab0e6338853a82a51c0b2 Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Sat, 18 Feb 2023 00:13:34 -0500 Subject: [PATCH 02/65] Opt_a_tosicmp likely has a bug which will incorrectly migrate a label on a replaced op in one case. --- src/cc65/coptstop.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 8b2821dcd..ae40a55e9 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -1208,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); From 5c12659cf499343deff1d81c0c4ac235a74192c3 Mon Sep 17 00:00:00 2001 From: compyx Date: Sun, 19 Feb 2023 14:01:14 +0100 Subject: [PATCH 03/65] make avail: check for presence of binaries before creating symbolic links To avoid creating broken symlinks, first check if the binaries exists in bin/ and exit when they don't, with a message to first run `make`. --- src/Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Makefile b/src/Makefile index 8356d0001..a37fa5811 100644 --- a/src/Makefile +++ b/src/Makefile @@ -110,11 +110,21 @@ $(RM) /usr/local/bin/$(prog) endef # UNAVAIL_recipe +define AVAIL_check_prog + +@if [ ! -e ../bin/$(prog) ]; then \ + echo "failed to locate $(prog), please run make first"; \ + false; \ +fi + +endef # AVAIL_check_prog + install: $(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) ../bin/* $(DESTDIR)$(bindir) avail: + $(foreach prog,$(PROGS),$(AVAIL_check_prog)) $(foreach prog,$(PROGS),$(AVAIL_recipe)) unavail: From 2ac055383f4619cea09988aa79c2b4324c1bfb40 Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Sun, 19 Feb 2023 08:14:04 -0500 Subject: [PATCH 04/65] ld65 fix overwrite segments adding wrong padding or causing internal errors --- src/ld65/config.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/ld65/config.c b/src/ld65/config.c index c22ced1ef..c101bd1c6 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -1945,6 +1945,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. */ @@ -2081,14 +2085,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", 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 @@ -2107,13 +2116,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; } } From 4fc19a3d4c27d193297e928171f85ab361ac2ae7 Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Sun, 19 Feb 2023 08:37:07 -0500 Subject: [PATCH 05/65] ld65 overwrite segment should pad with fill value if the desired seek position is beyond the end of the file so far --- src/ld65/bin.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ld65/bin.c b/src/ld65/bin.c index bd822cc23..15b534f66 100644 --- a/src/ld65/bin.c +++ b/src/ld65/bin.c @@ -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); From 68ce335f59b9d6d69b6d348ec1e764162021bdbe Mon Sep 17 00:00:00 2001 From: compyx Date: Sun, 19 Feb 2023 19:17:45 +0100 Subject: [PATCH 06/65] Replace shell code with GNU Make conditionals and functions Use `ifeq` to provide two rules for the `avail` target: one that reports an error if any of the symlink targets are missing and one that installs the symlinks for the targets if they're all present. --- src/Makefile | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Makefile b/src/Makefile index a37fa5811..034a2230f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -110,22 +110,16 @@ $(RM) /usr/local/bin/$(prog) endef # UNAVAIL_recipe -define AVAIL_check_prog - -@if [ ! -e ../bin/$(prog) ]; then \ - echo "failed to locate $(prog), please run make first"; \ - false; \ -fi - -endef # AVAIL_check_prog - install: $(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) ../bin/* $(DESTDIR)$(bindir) avail: - $(foreach prog,$(PROGS),$(AVAIL_check_prog)) +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)) From 864eecf7c3764741855801de3228f4363b4d69fa Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Mon, 20 Feb 2023 20:08:58 -0500 Subject: [PATCH 07/65] ca16 doc for A8/A18/I8/I16: use "assume" instead of "switch" to avoid implying that a hardware state is changed. See: #1759 --- doc/ca65.sgml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 19fd3aa2a..c84c57353 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2019,7 +2019,7 @@ Here's a list of all control commands and a description, what they do: .A16