When building the below code, the dataseg option is not respected when the the global variable is initialised with a value.
I was expecting that when the ram bank is set, all global variables will be in that bank, independent of whether it is initialised or not. If the current behaviour is correct, perhaps a warning would be appropriate. The reason for the bank difference was unclear to me without some investigation.
/// GPL 2.0 or later
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
uint8_t test1 = 0;
uint8_t test2;
void do_something() {
test1 = 3;
test2 = 4;
}
void main() {
do_something();
printf( "%04X %04X", &test1, &test2 );
}
#ifdef __SDCC
__sfr __at 0xff sif;
int putchar( int c ) {
sif = 'p';
sif = c;
return c;
}
#endif
sdcc -c --constseg ROMBANK --codeseg ROMBANK --dataseg RAMBANK -mz80 --fverbose-asm ./ram_bank.c -o ram_bank.rel && sdcc -Wl-b_RAMBANK=0xC000 -Wl-b_ROMBANK=0x0000 -mz80 --fverbose-asm ./ram_bank.rel -o ram_bank.ihx && ucsim_z80 -I if=outputs[0xff] ram_bank.ihx
Simulation started, PC=0x000000
8000 C000
Looking at the map, the test1 variable is at 8000 not at c000 as expected:
...
_INITIALIZED 00008000 00000001 = 1. bytes (REL,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
00008000 _test1 ram_bank
...
_RAMBANK 0000C000 00000001 = 1. bytes (REL,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
0000C000 _test2 ram_bank
If I remove the initialiser for test1
...
uint8_t test1; // no initialiser
uint8_t test2;
void do_something() {
...
The variables are now in the same bank:
r
Simulation started, PC=0x000000
C000 C001
_RAMBANK 0000C000 00000002 = 2. bytes (REL,CON)
Value Global Global Defined In Module
----- -------------------------------- ------------------------
0000C000 _test1 ram_bank
0000C001 _test2 ram_bank
$ sdcc -v
SDCC : z80/sm83/ez80/z80n/mos6502/mos65c02 4.6.2 #16695 (Linux)