test: let the shim compile sources that touch the SFRs and libc

Two things kept every register-driven module out of the host harness. The
SFR keywords were unknown, so rtl837x_sfr.h did not compile at all, and once
it did, each translation unit would have defined its own copy of the
registers. They map to extern declarations now; a mock emits the storage
once by re-including the header with the keywords redefined.

The other was memset. rtl837x_common.h hides the firmware's own prototypes
under RTLP_HOST_TEST so host builds use the C library, but nothing declared
the library versions, and the modules do call them. The shim pulls in
string.h ahead of everything, where nothing can clash with it.
This commit is contained in:
d00f committed 2026-09-17 03:55:30 +02:00
1 parent 2f005d2993
commit 83491bc9e3
1 file changed
+21 -5
+21 -5
View File
@@ -12,6 +12,7 @@
#define SDCC_SHIM_H #define SDCC_SHIM_H
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
/* Memory-space qualifiers → nothing (host has one flat address space). */ /* Memory-space qualifiers → nothing (host has one flat address space). */
#define __xdata #define __xdata
@@ -22,12 +23,27 @@
/* bool, not unsigned char: SDCC's bit types normalize any assigned value /* bool, not unsigned char: SDCC's bit types normalize any assigned value
* to 0/1, which _Bool reproduces exactly. */ * to 0/1, which _Bool reproduces exactly. */
#define __bit bool #define __bit bool
#define __sbit bool
/* NOTE: the firmware ships its own 8051 memcpy/memset/strlen/strcpy/sleep with /* Special-function registers are declared in rtl837x_sfr.h as
* incompatible signatures (rtl837x_common.h). Host TUs must therefore build with * `__sfr __at(0xNN) NAME;`. With __at erased those become plain declarations,
* -fno-builtin (so gcc doesn't auto-declare the builtins) and must NOT include * so they must carry extern or every translation unit including the header
* <string.h>/<unistd.h>. Test code uses the t_* helpers in support.h instead. */ * defines its own copy. __sbit is the bit-in-an-SFR form and only appears
* there; the local bit variable keyword is __bit above. test/hw_mock.c
* undefines these four and re-includes the header once to emit the storage. */
#define __sfr extern volatile uint8_t
#define __sfr16 extern volatile uint16_t
#define __sfr32 extern volatile uint32_t
#define __sbit extern bool
/* The firmware ships its own memcpy/memset/strlen/strcpy/sleep, and
* rtl837x_common.h hides those prototypes under RTLP_HOST_TEST so host builds
* take the C library versions. Something has to declare them, and firmware
* sources do call memset and memcpy; this header is force-included ahead of
* everything, so pulling <string.h> in here puts the libc versions in scope
* before any firmware header and nothing clashes. sleep() is not in
* <string.h> and is declared on its own rather than through <unistd.h>. */
#include <string.h>
extern unsigned int sleep(unsigned int seconds);
/* Function attributes → nothing (no banking / no 8051 calling conventions). */ /* Function attributes → nothing (no banking / no 8051 calling conventions). */
#define __banked #define __banked