From 2dc794e94567e8e04e1b7ccac69dd85a0754f7ec Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 28 Sep 2019 15:53:38 -0700 Subject: [PATCH 1/3] Move all PSTRs to own section, allow string dedup GNU ld can deduplicate strings, and does so for most normal char *s automatically. However, for PSTRs we were using a unique section per string *and* the section was not flagges as containing dedupable 0-terminated strings. Modify the PSTR macro to emit assembly, which lets us set the section flags required (SM) for the variables, and use inline assembly to get the asm-block defined address. Should result in smaller compiled binaries if any strings are duplicated. --- tools/sdk/ld/eagle.app.v6.common.ld.h | 3 +++ tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/sdk/ld/eagle.app.v6.common.ld.h b/tools/sdk/ld/eagle.app.v6.common.ld.h index 2f5735fff7..8bf6676f3e 100644 --- a/tools/sdk/ld/eagle.app.v6.common.ld.h +++ b/tools/sdk/ld/eagle.app.v6.common.ld.h @@ -181,6 +181,9 @@ SECTIONS *libwps.a:(.literal.* .text.*) *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom0.text.* .irom.text .irom.text.*) + /* Constant strings in flash (PSTRs) */ + *(.irom0.pstr) + /* __FUNCTION__ locals */ *(.rodata._ZZ*__FUNCTION__) *(.rodata._ZZ*__PRETTY_FUNCTION__) diff --git a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h index d74b8b000c..3e102ad1bb 100644 --- a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h +++ b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h @@ -34,7 +34,12 @@ extern "C" { // PSTR() macro modified to start on a 32-bit boundary. This adds on average // 1.5 bytes/string, but in return memcpy_P and strcpy_P will work 4~8x faster #ifndef PSTR - #define PSTR(s) (__extension__({static const char __c[] __attribute__((__aligned__(4))) PROGMEM = (s); &__c[0];})) + // Adapted from AVR-specific code at https://forum.arduino.cc/index.php?topic=194603.0 + #define PSTR(str) (__extension__({ \ + PGM_P ptr; \ + asm volatile ( ".pushsection .irom0.pstr, \"SM\", @progbits, 1 \n .align 4 \n 0: .string " __STRINGIZE(str) "\n .popsection \n" ); \ + asm volatile ( "movi %0, 0b" : "=r" (ptr) ); \ + ptr; })) #endif // Flash memory must be read using 32 bit aligned addresses else a processor From 52e4af9d3cb7c16e5a21443be6de00fb9f23d24b Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 28 Sep 2019 16:49:30 -0700 Subject: [PATCH 2/3] Give each PSTR its own segment --- tools/sdk/ld/eagle.app.v6.common.ld.h | 2 +- tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/sdk/ld/eagle.app.v6.common.ld.h b/tools/sdk/ld/eagle.app.v6.common.ld.h index 8bf6676f3e..383154e491 100644 --- a/tools/sdk/ld/eagle.app.v6.common.ld.h +++ b/tools/sdk/ld/eagle.app.v6.common.ld.h @@ -182,7 +182,7 @@ SECTIONS *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom0.text.* .irom.text .irom.text.*) /* Constant strings in flash (PSTRs) */ - *(.irom0.pstr) + *(.irom0.pstr.*) /* __FUNCTION__ locals */ *(.rodata._ZZ*__FUNCTION__) diff --git a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h index 3e102ad1bb..02c1065f90 100644 --- a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h +++ b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h @@ -23,6 +23,7 @@ extern "C" { // Ref: https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html // Place each progmem object into its own named section, avoiding conflicts #define PROGMEM __attribute__((section( "\".irom.text." __FILE__ "." __STRINGIZE(__LINE__) "." __STRINGIZE(__COUNTER__) "\""))) + #define PROGMEM_PSTR "\".irom0.pstr." __FILE__ "." __STRINGIZE(__LINE__) "." __STRINGIZE(__COUNTER__) "\"" #endif #ifndef PGM_P #define PGM_P const char * @@ -37,7 +38,7 @@ extern "C" { // Adapted from AVR-specific code at https://forum.arduino.cc/index.php?topic=194603.0 #define PSTR(str) (__extension__({ \ PGM_P ptr; \ - asm volatile ( ".pushsection .irom0.pstr, \"SM\", @progbits, 1 \n .align 4 \n 0: .string " __STRINGIZE(str) "\n .popsection \n" ); \ + asm volatile ( ".pushsection " PROGMEM_PSTR ", \"SM\", @progbits, 1 \n .align 4 \n 0: .string " __STRINGIZE(str) "\n .popsection \n" ); \ asm volatile ( "movi %0, 0b" : "=r" (ptr) ); \ ptr; })) #endif From 0728f1d2618c4e3891e9ddae5559244f1cf89555 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 28 Sep 2019 16:56:55 -0700 Subject: [PATCH 3/3] Allow disposing of unused strings before merging Add the "a" section flag to allow the linker to throw away unneeded strings. Without this flag, the linker will not discard unreferenced strings and ROMs will increase in size, possibly dramatically. --- tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h index 02c1065f90..20512bed4c 100644 --- a/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h +++ b/tools/sdk/libc/xtensa-lx106-elf/include/sys/pgmspace.h @@ -38,7 +38,7 @@ extern "C" { // Adapted from AVR-specific code at https://forum.arduino.cc/index.php?topic=194603.0 #define PSTR(str) (__extension__({ \ PGM_P ptr; \ - asm volatile ( ".pushsection " PROGMEM_PSTR ", \"SM\", @progbits, 1 \n .align 4 \n 0: .string " __STRINGIZE(str) "\n .popsection \n" ); \ + asm volatile ( ".pushsection " PROGMEM_PSTR ", \"aSM\", @progbits, 1 \n .align 4 \n 0: .string " __STRINGIZE(str) "\n .popsection \n" ); \ asm volatile ( "movi %0, 0b" : "=r" (ptr) ); \ ptr; })) #endif