From 4d7a2e28c788a3a031e500f9637e9b31043c5649 Mon Sep 17 00:00:00 2001 From: d00f Date: Thu, 13 Aug 2026 12:16:02 +0200 Subject: [PATCH] stp: keep the designated bridge recording out of internal RAM The report on the PR is that it will not link for KP_9000_6XHML_X2, with "?ASlink-Error-Could not get N consecutive bytes in internal RAM for area OSEG" five times over. It builds here on sdcc 4.2.0 and 4.5.0 for that same machine and the same commit, so something in the toolchain differs, but the pressure it is complaining about is mine and it costs little to give back. stp_in() is __banked, so its temporaries get exclusive DSEG instead of overlaying with anything else. Recording the designated bridge put four more live values across a memcpy in the middle of it and the register allocator answered with five spill locations. The module went from 5 bytes of DSEG to 12, and from 17 sloc references to 49. Moving that block into a __reentrant helper puts its temporaries on the stack instead. The module now claims no DSEG at all, 5 bytes better than before the recording was added, and the image sits at 95 bytes of DSEG against 101 on main. It costs 170 bytes of BANK2, where there is room. --- rtl837x_stp.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/rtl837x_stp.c b/rtl837x_stp.c index e4af019..3386b2e 100644 --- a/rtl837x_stp.c +++ b/rtl837x_stp.c @@ -141,6 +141,22 @@ struct stp_pkt_in { #define STP_O ((__xdata struct stp_pkt *)&uip_buf[RTL_FRAME_DESC_SIZE]) #define STP_I ((__xdata struct stp_pkt_in *)&uip_buf[0]) +/* __reentrant so the temporaries land on the stack: stp_in() is __banked and + * its locals get exclusive internal RAM, which is what runs out first here. */ +static void stp_record_designated(uint8_t port) __reentrant +{ + stp_dbridge[port].prio = STP_I->bridge.prio; + stp_dbridge[port].ext = STP_I->bridge.ext; + memcpy(stp_dbridge[port].mac, STP_I->bridge.mac, 6); + stp_dpid[port] = ((uint16_t)STP_I->port_prio << 8) | STP_I->port_id; + stp_cost_scratch = STP_I->root_path_cost; + stp_dcost[port] = ((stp_cost_scratch & 0xff) << 24) + | ((stp_cost_scratch & 0xff00) << 8) + | ((stp_cost_scratch >> 8) & 0xff00) + | (stp_cost_scratch >> 24); +} + + signed char cmpMAC(__xdata uint8_t *m1, __xdata uint8_t *m2) __reentrant { for (uint8_t i = 0; i < 6; i++) { @@ -452,15 +468,7 @@ void stp_in(void) __banked return; } - stp_dbridge[port].prio = STP_I->bridge.prio; - stp_dbridge[port].ext = STP_I->bridge.ext; - memcpy(stp_dbridge[port].mac, STP_I->bridge.mac, 6); - stp_dpid[port] = ((uint16_t)STP_I->port_prio << 8) | STP_I->port_id; - stp_cost_scratch = STP_I->root_path_cost; - stp_dcost[port] = ((stp_cost_scratch & 0xff) << 24) - | ((stp_cost_scratch & 0xff00) << 8) - | ((stp_cost_scratch >> 8) & 0xff00) - | (stp_cost_scratch >> 24); + stp_record_designated(port); /* Better root than the one we know? */ if (STP_I->root.prio < root_bridge.prio