From fbd8961be1df70303bcfb35e7ba7f93671f29c42 Mon Sep 17 00:00:00 2001 From: Sidney Cadot Date: Tue, 3 Dec 2024 21:21:49 +0100 Subject: [PATCH 01/15] sim65: changing memory access types to uint8_t and uint16_t. In sim65, simulator memory access to a 64 KB array is implemented via functions defined in src/sim65/memory.h and src/sim65/memory.c. In the old version, the types for both content bytes (8 bits), content words (16 bits), regular addresses (16 bits), and zero-page addresses (8 bits) were all given as bare 'unsigned'. This lead to several cases of address overrun (e.g., when an instruction wraps around from address 0xffff to 0x0000) when running the simulator against a stress test (specifically, the 65x02 test suite). To protect from this, and to more properly express the bit width of the types involved which is a good idea anyway, we start using the fixed-width types provided by 'stdint.h'. In the process, we also change the MemReadByte macro to a full function call. This may impact performance (by a small amount), but it improves memory safety, as cases where the address is accidentally expressed as a value exceeding 0xffff are handled by wrap-around (as it is in the actual hardware), rather than causing access outside of the Mem[] array where the 64 KB of simulated RAM resides. The reason for this patch is twofold. (1) It is a partial patch for issue #2539. Several issues brought to the surface by running the 65x02 testsuite are eliminated by these changes. In the discussion about this issue, it was concluded that it is a Good Idea to use the stdint-types, both for the simulated CPU registers and for the memory. This patch addresses the memory-part of that change. (2) It is a precursor patch for issue #2355. For that issue, we will implement a memory-mapped timer register. This will make handling of memory access in the simulator a bit more complex. Having proper functions with the proper types in place will help to make the timer register patch easier. --- src/sim65/memory.c | 24 ++++++++++++++++-------- src/sim65/memory.h | 21 +++++++-------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/sim65/memory.c b/src/sim65/memory.c index 68e7bb93b..b93693b91 100644 --- a/src/sim65/memory.c +++ b/src/sim65/memory.c @@ -45,8 +45,8 @@ -/* THE memory */ -unsigned char Mem[0x10000]; +/* The memory */ +uint8_t Mem[0x10000]; @@ -56,7 +56,7 @@ unsigned char Mem[0x10000]; -void MemWriteByte (unsigned Addr, unsigned char Val) +void MemWriteByte (uint16_t Addr, uint8_t Val) /* Write a byte to a memory location */ { Mem[Addr] = Val; @@ -64,7 +64,7 @@ void MemWriteByte (unsigned Addr, unsigned char Val) -void MemWriteWord (unsigned Addr, unsigned Val) +void MemWriteWord (uint16_t Addr, uint16_t Val) /* Write a word to a memory location */ { MemWriteByte (Addr, Val & 0xFF); @@ -73,22 +73,30 @@ void MemWriteWord (unsigned Addr, unsigned Val) -unsigned MemReadWord (unsigned Addr) +uint8_t MemReadByte (uint16_t Addr) +/* Read a byte from a memory location */ +{ + return Mem[Addr]; +} + + + +uint16_t MemReadWord (uint16_t Addr) /* Read a word from a memory location */ { - unsigned W = MemReadByte (Addr++); + uint8_t W = MemReadByte (Addr++); return (W | (MemReadByte (Addr) << 8)); } -unsigned MemReadZPWord (unsigned char Addr) +uint16_t MemReadZPWord (uint8_t Addr) /* Read a word from the zero page. This function differs from MemReadWord in that ** the read will always be in the zero page, even in case of an address ** overflow. */ { - unsigned W = MemReadByte (Addr++); + uint8_t W = MemReadByte (Addr++); return (W | (MemReadByte (Addr) << 8)); } diff --git a/src/sim65/memory.h b/src/sim65/memory.h index cef786aaa..b70c5bd05 100644 --- a/src/sim65/memory.h +++ b/src/sim65/memory.h @@ -36,9 +36,9 @@ #ifndef MEMORY_H #define MEMORY_H -#include "inline.h" +#include -extern unsigned char Mem[0x10000]; +extern uint8_t Mem[0x10000]; /*****************************************************************************/ /* Code */ @@ -46,26 +46,19 @@ extern unsigned char Mem[0x10000]; -void MemWriteByte (unsigned Addr, unsigned char Val); +void MemWriteByte (uint16_t Addr, uint8_t Val); /* Write a byte to a memory location */ -void MemWriteWord (unsigned Addr, unsigned Val); +void MemWriteWord (uint16_t Addr, uint16_t Val); /* Write a word to a memory location */ -#if defined(HAVE_INLINE) -INLINE unsigned char MemReadByte (unsigned Addr) +uint8_t MemReadByte (uint16_t Addr); /* Read a byte from a memory location */ -{ - return Mem[Addr]; -} -#else -#define MemReadByte(Addr) Mem[Addr] -#endif -unsigned MemReadWord (unsigned Addr); +uint16_t MemReadWord (uint16_t Addr); /* Read a word from a memory location */ -unsigned MemReadZPWord (unsigned char Addr); +uint16_t MemReadZPWord (uint8_t Addr); /* Read a word from the zero page. This function differs from MemReadWord in that ** the read will always be in the zero page, even in case of an address ** overflow. From 05b3825683e065a40710bdad068a9ba62c33d70d Mon Sep 17 00:00:00 2001 From: Sidney Cadot Date: Tue, 3 Dec 2024 23:33:57 +0100 Subject: [PATCH 02/15] sim65 : improve implementation of ROL and ROR operations Issue #2539 brings to light a number of issues in the sim65 simulator. Several issues can be traced back to undesirable side effects of the use of bare 'unsigned' types for the CPU registers in the 'CPURegs' type defined in src/sim65/6502.h. The intention is to tighten the types of the registers defined there to uint8_t and uint16_t, in accordance with the actual number of bits that those registers have in the 6502. However, it turns out that a handful of opcode implementations depend on the fact that the register types currently have more bits than the actual 6502 registers themselves for correct operation. This mostly involves operations that involve the carry bit (ROL, ROR, ADC, SBC). In preparation of fixing the CPURegs field types, we will first make sure that those opcode implementations are changed in such a way that they still work if the underlying register types are tightened to their actual bit width. This PR concerns this specific change for the ROL and ROR operations. The correct functioning of ROL and ROR after this patch has been verified by testing against the 65x02 test suite. --- src/sim65/6502.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/sim65/6502.c b/src/sim65/6502.c index cb4e579eb..48a1d560d 100644 --- a/src/sim65/6502.c +++ b/src/sim65/6502.c @@ -737,23 +737,29 @@ static unsigned HaveIRQRequest; /* ROL */ #define ROL(Val) \ - Val <<= 1; \ - if (GET_CF ()) { \ - Val |= 0x01; \ - } \ - TEST_ZF (Val); \ - TEST_SF (Val); \ - TEST_CF (Val) + do { \ + unsigned ShiftOut = (Val & 0x80); \ + Val <<= 1; \ + if (GET_CF ()) { \ + Val |= 0x01; \ + } \ + TEST_ZF (Val); \ + TEST_SF (Val); \ + SET_CF (ShiftOut); \ + } while (0) /* ROR */ #define ROR(Val) \ - if (GET_CF ()) { \ - Val |= 0x100; \ - } \ - SET_CF (Val & 0x01); \ - Val >>= 1; \ - TEST_ZF (Val); \ - TEST_SF (Val) + do { \ + unsigned ShiftOut = (Val & 0x01); \ + Val >>= 1; \ + if (GET_CF ()) { \ + Val |= 0x80; \ + } \ + TEST_ZF (Val); \ + TEST_SF (Val); \ + SET_CF (ShiftOut); \ + } while(0) /* ASL */ #define ASL(Val) \ From 3612d90c8e9faa66c09d77e6cb88e967efb54ad3 Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 9 Dec 2024 00:40:41 +0100 Subject: [PATCH 03/15] Update fire.c --- samples/cbm/fire.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/cbm/fire.c b/samples/cbm/fire.c index 40eff0707..1eae086da 100644 --- a/samples/cbm/fire.c +++ b/samples/cbm/fire.c @@ -56,7 +56,7 @@ /* Use static local variables for speed */ -#pragma static-locals (1); +#pragma static-locals (1) From be6819ca1fc1fcd93159026ef4097a3987182122 Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 9 Dec 2024 00:41:03 +0100 Subject: [PATCH 04/15] Update plasma.c --- samples/cbm/plasma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/cbm/plasma.c b/samples/cbm/plasma.c index f48d6dc77..5c0b901f7 100644 --- a/samples/cbm/plasma.c +++ b/samples/cbm/plasma.c @@ -51,7 +51,7 @@ /* Use static local variables for speed */ -#pragma static-locals (1); +#pragma static-locals (1) static const unsigned char sinustable[0x100] = { From 316ee4ad5bd862b8596002e7865b17debbfba53a Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 9 Dec 2024 00:42:28 +0100 Subject: [PATCH 05/15] Update overlay-demo.c --- samples/geos/overlay-demo.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/geos/overlay-demo.c b/samples/geos/overlay-demo.c index 73ab0e3c0..e3e92e6c2 100644 --- a/samples/geos/overlay-demo.c +++ b/samples/geos/overlay-demo.c @@ -27,7 +27,7 @@ void show(char *name) ** rather place the all the code of certain source files into the overlay by ** compiling them with --code-name OVERLAY1. */ -#pragma code-name(push, "OVERLAY1"); +#pragma code-name(push, "OVERLAY1") void foo(void) { @@ -39,27 +39,27 @@ void foo(void) show("One"); } -#pragma code-name(pop); +#pragma code-name(pop) -#pragma code-name(push, "OVERLAY2"); +#pragma code-name(push, "OVERLAY2") void bar(void) { show("Two"); } -#pragma code-name(pop); +#pragma code-name(pop) -#pragma code-name(push, "OVERLAY3"); +#pragma code-name(push, "OVERLAY3") void foobar (void) { show("Three"); } -#pragma code-name(pop); +#pragma code-name(pop) void main(int /*argc*/, char *argv[]) From 26e671710278948d23569b2bb947b222b6a9c29e Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 9 Dec 2024 00:43:05 +0100 Subject: [PATCH 06/15] Update mandelbrot.c --- samples/lynx/mandelbrot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/lynx/mandelbrot.c b/samples/lynx/mandelbrot.c index ce49fbf7a..27ac7d340 100644 --- a/samples/lynx/mandelbrot.c +++ b/samples/lynx/mandelbrot.c @@ -26,7 +26,7 @@ #define divfp(_a,_b) ((((signed long)_a)< Date: Mon, 9 Dec 2024 00:43:35 +0100 Subject: [PATCH 07/15] Update mandelbrot.c --- samples/mandelbrot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/mandelbrot.c b/samples/mandelbrot.c index 519f3d823..f4e7b83a8 100644 --- a/samples/mandelbrot.c +++ b/samples/mandelbrot.c @@ -41,7 +41,7 @@ #endif /* Use static local variables for speed */ -#pragma static-locals (1); +#pragma static-locals (1) From 5d2730f4b4aad47f2ea5152f7c71b03ef5c22895 Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 9 Dec 2024 00:44:44 +0100 Subject: [PATCH 08/15] Update multidemo.c --- samples/multidemo.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/multidemo.c b/samples/multidemo.c index 02bb6fcac..435c1b985 100644 --- a/samples/multidemo.c +++ b/samples/multidemo.c @@ -64,34 +64,34 @@ void log (char *msg) ** rather place all the code of certain source files into the overlay by ** compiling them with --code-name OVERLAY1. */ -#pragma code-name (push, "OVERLAY1"); +#pragma code-name (push, "OVERLAY1") void foo (void) { log ("Calling main from overlay 1"); } -#pragma code-name (pop); +#pragma code-name (pop) -#pragma code-name (push, "OVERLAY2"); +#pragma code-name (push, "OVERLAY2") void bar (void) { log ("Calling main from overlay 2"); } -#pragma code-name (pop); +#pragma code-name (pop) -#pragma code-name (push, "OVERLAY3"); +#pragma code-name (push, "OVERLAY3") void foobar (void) { log ("Calling main from overlay 3"); } -#pragma code-name(pop); +#pragma code-name(pop) unsigned char loademdriver (void) From 5f2c5b58ab4611f13187754ce022255722b1d6fb Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 9 Dec 2024 18:25:34 +0100 Subject: [PATCH 09/15] Update overlaydemo.c --- samples/overlaydemo.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/overlaydemo.c b/samples/overlaydemo.c index dde6b70ab..a37b06d4f 100644 --- a/samples/overlaydemo.c +++ b/samples/overlaydemo.c @@ -39,7 +39,7 @@ void log (char *msg) ** rather place all the code of certain source files into the overlay by ** compiling them with --code-name OVERLAY1. */ -#pragma code-name (push, "OVERLAY1"); +#pragma code-name (push, "OVERLAY1") void foo (void) { @@ -51,27 +51,27 @@ void foo (void) log ("Calling main from overlay 1"); } -#pragma code-name (pop); +#pragma code-name (pop) -#pragma code-name (push, "OVERLAY2"); +#pragma code-name (push, "OVERLAY2") void bar (void) { log ("Calling main from overlay 2"); } -#pragma code-name (pop); +#pragma code-name (pop) -#pragma code-name (push, "OVERLAY3"); +#pragma code-name (push, "OVERLAY3") void foobar (void) { log ("Calling main from overlay 3"); } -#pragma code-name(pop); +#pragma code-name(pop) unsigned char loadfile (char *name, void *addr, void *size) From cf470dd0dff4622f14756bac13b78bbfb2ef692f Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 9 Dec 2024 18:26:00 +0100 Subject: [PATCH 10/15] Update sieve.c --- samples/sieve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/sieve.c b/samples/sieve.c index 8d0619888..7c3b9cd75 100644 --- a/samples/sieve.c +++ b/samples/sieve.c @@ -38,7 +38,7 @@ static unsigned char Sieve[COUNT]; -#pragma static-locals(1); +#pragma static-locals(1) From d993f3a7663780d41ee4d41186dde56cee23a496 Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 9 Dec 2024 18:36:05 +0100 Subject: [PATCH 11/15] Update cc65.sgml --- doc/cc65.sgml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/cc65.sgml b/doc/cc65.sgml index d08e8418d..781e460a8 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -1370,7 +1370,7 @@ sequences of the input. Example: /* Use a space wherever an 'a' occurs in ISO-8859-1 source */ - #pragma charmap (0x61, 0x20); + #pragma charmap (0x61, 0x20) From 0f6b427170eb52cacec58ba11202b9fd009e432d Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 9 Dec 2024 18:37:02 +0100 Subject: [PATCH 12/15] Update strftime.c --- libsrc/common/strftime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/common/strftime.c b/libsrc/common/strftime.c index 38ea4850e..2f3cadc2e 100644 --- a/libsrc/common/strftime.c +++ b/libsrc/common/strftime.c @@ -40,7 +40,7 @@ /* Use static local variables for speed */ -#pragma static-locals (on); +#pragma static-locals (on) From 852b622c433f71f815f005e7e2d3e0409ca81e28 Mon Sep 17 00:00:00 2001 From: Colin Leroy-Mira Date: Tue, 3 Dec 2024 09:01:04 +0100 Subject: [PATCH 13/15] Apple2: Don't forcefully re-enable IRQ Avoid enabling IRQ after disabling them in driver code, remember previous state instead (in case user had them disabled already). --- libsrc/apple2/mou/a2.stdmou.s | 19 +++++++++++++------ libsrc/apple2/ser/a2.gs.s | 12 +++++++----- libsrc/apple2/waitvsync.s | 5 +++-- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/libsrc/apple2/mou/a2.stdmou.s b/libsrc/apple2/mou/a2.stdmou.s index c54c09d34..9b84c2f53 100644 --- a/libsrc/apple2/mou/a2.stdmou.s +++ b/libsrc/apple2/mou/a2.stdmou.s @@ -155,6 +155,7 @@ next: inc ptr1+1 ; Disable interrupts now because setting the slot number makes ; the IRQ handler (maybe called due to some non-mouse IRQ) try ; calling the firmware which isn't correctly set up yet + php sei ; Convert to and save slot number @@ -211,7 +212,7 @@ next: inc ptr1+1 common: jsr firmware ; Enable interrupts and return success - cli + plp lda #MOUSE_ERR_OK rts @@ -220,6 +221,7 @@ common: jsr firmware ; No return code required (the driver is removed from memory on return). UNINSTALL: ; Hide cursor + php sei jsr CHIDE @@ -249,7 +251,8 @@ SETBOX: ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse: ; "Disable interrupts before placing position information in the ; screen holes." -: sei +: php + sei ; Set low clamp lda (ptr1),y @@ -298,6 +301,7 @@ GETBOX: ; the screen). No return code required. MOVE: ldy slot + php sei ; Set y @@ -328,9 +332,10 @@ MOVE: ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: + php sei jsr CHIDE - cli + plp rts ; SHOW: Is called to show the mouse cursor. The mouse kernel manages a @@ -339,9 +344,10 @@ HIDE: ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: + php sei jsr CSHOW - cli + plp rts ; BUTTONS: Return the button mask in A/X. @@ -360,12 +366,13 @@ POS: ; struct pointed to by ptr1. No return code required. INFO: ldy #.sizeof(MOUSE_INFO)-1 -copy: sei +copy: php + sei : lda info,y sta (ptr1),y dey bpl :- - cli + plp rts ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl diff --git a/libsrc/apple2/ser/a2.gs.s b/libsrc/apple2/ser/a2.gs.s index e35c6156b..ea3e54cc1 100644 --- a/libsrc/apple2/ser/a2.gs.s +++ b/libsrc/apple2/ser/a2.gs.s @@ -304,8 +304,9 @@ IIgs: ldx Channel - ; Deactivate interrupts - sei + php ; Deactivate interrupts + sei ; if enabled + ldy #WR_MASTER_IRQ_RST lda #MASTER_IRQ_SHUTDOWN jsr writeSCCReg @@ -334,7 +335,7 @@ IIgs: ldx #$00 stx Opened ; Mark port as closed - cli + plp ; Reenable interrupts if needed : txa ; Promote char return value rts @@ -352,7 +353,8 @@ getClockSource: ; Must return an SER_ERR_xx code in a/x. SER_OPEN: - sei + php ; Deactivate interrupts + sei ; if enabled ; Check if the handshake setting is valid ldy #SER_PARAMS::HANDSHAKE ; Handshake @@ -497,9 +499,9 @@ BaudOK: lda #SER_ERR_OK SetupOut: + plp ; Reenable interrupts if needed ldx #$00 ; Promote char return value sty Opened - cli rts ;---------------------------------------------------------------------------- diff --git a/libsrc/apple2/waitvsync.s b/libsrc/apple2/waitvsync.s index 1697622de..486b93a53 100644 --- a/libsrc/apple2/waitvsync.s +++ b/libsrc/apple2/waitvsync.s @@ -29,7 +29,8 @@ iigs: bit RDVBLBAR rts ; Apple IIc TechNote #9, Detecting VBL -iic: sei +iic: php + sei sta IOUDISOFF lda RDVBLMSK bit ENVBL @@ -40,7 +41,7 @@ iic: sei bcs :+ ; VBL interrupts were already enabled bit DISVBL : sta IOUDISON ; IIc Tech Ref Man: The firmware normally leaves IOUDIS on. - cli + plp rts .endif ; __APPLE2ENH__ From 3933f329c23a479582808df9ff796d46914d16fa Mon Sep 17 00:00:00 2001 From: Sergio Lindo Mansilla Date: Sun, 15 Dec 2024 14:50:45 +0100 Subject: [PATCH 14/15] Improve description of namespace access in ca65 This avoid confusion with referencing global scope with the namespace token. --- doc/ca65.sgml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 2e63e0961..9c54dbb1a 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -1059,7 +1059,7 @@ The namespace token ( The only way to deny access to a scope from the outside is to declare a scope From 17e7e669c9cec299e71e0d5c408b6be4b1036f0b Mon Sep 17 00:00:00 2001 From: Sergio Lindo Mansilla Date: Sun, 15 Dec 2024 15:28:44 +0100 Subject: [PATCH 15/15] Fix typo in ca65 doc --- doc/ca65.sgml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 2e63e0961..d3905ab64 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -3897,7 +3897,7 @@ See: ,