From 9cc859ad3084d1d6625c6ec7fec7bcdc9130f210 Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Tue, 20 Oct 2026 23:37:11 +0200 Subject: [PATCH] build: carry the sdas fix for SDCC bug 4070 The 8051 assembler sign-extends every value to 24 bits, so the top byte of a __sfr32 address list like 0xa4a5a6a7 comes out as 0xff. The patch keeps 32-bit arithmetic while leaving the 24-bit T line addresses alone, so the relocations are unchanged. Proposed upstream in the bug thread. With it SFR_DATA_U32 can be used again, which saves about 240 bytes of code in REG_SET. --- README.md | 4 +- sdcc/0003-sdas-mcs51-sfr32-valmasks.patch | 130 ++++++++++++++++++++++ 2 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 sdcc/0003-sdas-mcs51-sfr32-valmasks.patch diff --git a/README.md b/README.md index d7d664d4..25c0a02d 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,9 @@ The first `make` downloads SDCC 4.6.0, applies the fixes in `sdcc/` and builds i `toolchain/`, which takes a few minutes. Later builds reuse it. The released SDCC 4.5.0 and 4.6.0 miscompile parts of this code, see [SDCC bug #4153](https://sourceforge.net/p/sdcc/bugs/4153/) and [#4154](https://sourceforge.net/p/sdcc/bugs/4154/); both fixes are in SDCC trunk since -r17039. To use an SDCC you installed yourself instead, run `make CC=sdcc ...`. +r17039. The third patch is for [#4070](https://sourceforge.net/p/sdcc/bugs/4070/), where the +assembler drops the top byte of a `__sfr32` address list; it is proposed upstream and lets +`SFR_DATA_U32` be used again. To use an SDCC you installed yourself instead, run `make CC=sdcc ...`.
If using Docker (click to expand) diff --git a/sdcc/0003-sdas-mcs51-sfr32-valmasks.patch b/sdcc/0003-sdas-mcs51-sfr32-valmasks.patch new file mode 100644 index 00000000..fa9c66ae --- /dev/null +++ b/sdcc/0003-sdas-mcs51-sfr32-valmasks.patch @@ -0,0 +1,130 @@ +https://sourceforge.net/p/sdcc/bugs/4070/ + +Index: sdas/asxxsrc/asexpr.c +=================================================================== +--- sdas/asxxsrc/asexpr.c ++++ sdas/asxxsrc/asexpr.c +@@ -863,18 +863,59 @@ + return((n & s_mask) ? (n | ~v_mask) : (n & v_mask)); + } + +-/*)Function void exprmasks(esp) ++/*)Function void exprmasks(n) + * + * int n T Line Bytes in Address + * + * The function exprmasks() configures the assembler +- * for 16, 24, or 32-Bit Data/Addresses. ++ * for 16, 24, or 32-Bit Data/Addresses. The arithmetic ++ * precision follows the address width unless a port ++ * calls valmasks() afterwards. + * + * local variables: + * none + * + * global variables: + * int a_bytes T Line Bytes in Address ++ * ++ * functions called: ++ * void valmasks() asexpr.c ++ * ++ * side effects: ++ * The address width and arithmetic precision ++ * parameters are set. ++ */ ++ ++void ++exprmasks(int n) ++{ ++ switch(n) { ++ default: ++ n = 2; ++ case 2: ++ case 3: ++ case 4: ++ break; ++ } ++ a_bytes = n; ++ valmasks(n); ++} ++ ++/*)Function void valmasks(n) ++ * ++ * int n Bytes of arithmetic precision ++ * ++ * The function valmasks() configures the 16, 24, or ++ * 32-Bit arithmetic precision independently of the ++ * T Line address width. A port whose addresses fit ++ * in 24 bits but whose symbols may hold 32-bit values ++ * (the 8051 __sfr32 address lists, for example) uses ++ * exprmasks(3) followed by valmasks(4). ++ * ++ * local variables: ++ * none ++ * ++ * global variables: + * a_uint a_mask Address mask + * a_uint s_mask Sign mask + * a_uint v_mask Value mask +@@ -885,16 +926,13 @@ + * side effects: + * The arithmetic precision parameters are set. + */ +- ++ + void +-exprmasks(int n) ++valmasks(int n) + { +- a_bytes = n; +- + #ifdef LONGINT +- switch(a_bytes) { ++ switch(n) { + default: +- a_bytes = 2; + case 2: + a_mask = (a_uint) 0x0000FFFFl; + s_mask = (a_uint) 0x00008000l; +@@ -914,9 +952,8 @@ + break; + } + #else +- switch(a_bytes) { ++ switch(n) { + default: +- a_bytes = 2; + case 2: + a_mask = (a_uint) 0x0000FFFF; + s_mask = (a_uint) 0x00008000; +Index: sdas/asxxsrc/asxxxx.h +=================================================================== +--- sdas/asxxsrc/asxxxx.h ++++ sdas/asxxsrc/asxxxx.h +@@ -1354,6 +1354,7 @@ + extern int digit(int c, int r); + extern int is_digit(int c, int r); + extern void exprmasks(int n); ++extern void valmasks(int n); + extern void expr(struct expr *esp, int n); + extern void binop(int c, struct expr *esp, struct expr *re); + extern int is_abs(struct expr *esp); +Index: sdas/as8051/i51mch.c +=================================================================== +--- sdas/as8051/i51mch.c ++++ sdas/as8051/i51mch.c +@@ -782,9 +782,12 @@ + hilo = 1; + + /* +- * Address Space ++ * Address Space: 24-bit addresses in the T lines, ++ * 32-bit arithmetic so that __sfr32 address lists ++ * like 0xa4a5a6a7 keep their most significant byte. + */ +- exprmasks(3); ++ exprmasks(3); ++ valmasks(4); + + /* + * First time only: