Custom linker memory map howto

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Custom linker memory map howto

Post by jorgegv »

Hi guys,

When compiling my engine for 128K mode, I need some data to be placed in addresses below 0xC000. This was not a problem until now that I have quite a lot of code: since the standard memory layout is CODE-DATA-BSS (from bottom to top of memory), CODE size has pushed the DATA+BSS sections into the higher end of the memory, putting some data above 0xC000.

Searching for a solution, I saw this link which states:
You don't have to use the library-supplied crts nor do the crts have to be as sophisticated as the above. You may prefer to have something very simple or something with a different memory map. If the compile line contains "-startup=-1" a local file "crt.asm" will be taken as the crt. The crt must set up the environment and call _main at minimum. If no memory map is set up, the output will be a single binary blob with CODE, DATA, BSS items mixed in the order the linker encounters them.
...which I found quite convenient: my CRT could be really something like "LD SP,XXXX; DI; CALL _main", and then I can manage my data to be in low memory by carefully specifying the list of object files for my program, putting first the data that needs to be in low memory, then the rest of the code. My memory layout would just be the object file order as found by the linker.

So far I have created the mentioned crt.asm.m4 (crt.asm alone did not work) and changed my compilation line (-startup=-1), but I have got some weird errors about some missing symbols that I believe my program does not use:

Code: Select all

[jorgegv@endor rage1]$ cat crt.asm.m4 
	extern	_main

start:
	di
	ld	sp,0x8181
	call	_main
	jp	start
[jorgegv@endor rage1]$ make -fMakefile-48 main.bin
Bulding main.bin....
zcc +zx -vn -SO3 --c-code-in-asm --list -s -m -compiler=sdcc -clib=sdcc_iy --max-allocs-per-node200000 -pragma-include zpragma-48.inc -Iengine/include -Ibuild/generated    engine/lowmem/bswitch.o engine/lowmem/asmdata.o engine/src/btile.o engine/src/bullet.o engine/src/codeset.o engine/src/collision.o engine/src/controller.o engine/src/dataset.o engine/src/debug.o engine/src/enemy.o engine/src/flow.o engine/src/game_loop.o engine/src/game_state.o engine/src/hero.o engine/src/hotzone.o engine/src/interrupts.o engine/src/inventory.o engine/src/main.o engine/src/map.o engine/src/memory.o engine/src/screen.o engine/src/sp1engine.o engine/src/sprite.o build/game_src/game_functions.o build/game_src/user_functions.o build/generated/game_data.o engine/src/beeper.o -startup=-1 -o main.bin
Error at file 'alloc/malloc/z80/asm_heap_init.asm' line 49: symbol 'mtx_plain' not defined
Error at file 'threads/mutex/z80/asm_mtx_init.asm' line 57: symbol 'thrd_success' not defined
Error at file 'threads/mutex/z80/asm_mtx_init.asm' line 62: symbol 'thrd_error' not defined
Errors in source file /home/jorgegv/src/spectrum/z88dk/lib/config//../..//libsrc/_DEVELOPMENT/target/zx/zx_crt.asm.m4:
Error at file 'alloc/malloc/z80/asm_heap_init.asm' line 49: symbol 'mtx_plain' not defined
Error at file 'threads/mutex/z80/asm_mtx_init.asm' line 57: symbol 'thrd_success' not defined
Error at file 'threads/mutex/z80/asm_mtx_init.asm' line 62: symbol 'thrd_error' not defined
make: *** [Makefile.common:111: main.bin] Error 1
It seems that the configuration is not as easy as the docs indicate and the library uses some other CRT...

Do you have any recommendations about this approach? Or should I dive into the wonders of low level CRT configuration? is there a good reference about CRT + memory map configuration?

Thanks in advance
J.
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Custom linker memory map howto

Post by jorgegv »

OK, I have digged some more, and I found the following solution:
  • Define the #pragma __MMAP to the value -1. This makes the compilation use a user-supplied memory map, which must be named mmap.inc and placed in the current directory.
  • Copy the file fromz88dk/libsrc/_DEVELOPMENT/target/crt_memory_model_z80.inc mmap.inc into mmap.inc
  • Edit mmap.inc and move the data_compilerand bss_compiler section specifications from their places to the start of the memory map, just below section code_crt_common directive
  • My regular compilation line si kept as-is, with -startup=31
With this done, all my program data now is placed at the start of the memory map.

I presume I can move all the other bss_*, data_* and rodata_* sections also to the beginning of the memory map, for the sake of completeness.

Any opinions?
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Custom linker memory map howto

Post by jorgegv »

Finally, regarding my custom CRT mentioned at the beginning of the thread, I found that I was already doing something quite similar for the memory bank binaries (which are self-contained):
  • Use the -nostartup ZCC option, so that NO startup code is used to generate the binary
  • Put the custom crt.asm as the first file to be compiled by the linker when creating the final binary
With this setup, I get exactly the layout I needed. But I have also found that the custom mmap.inc method explained above is a better solution.

Thanks to all for being my developer Teddy Bears / Rubber Ducks =D

Have a nice week.
J.
andydansby
Member
Posts: 51
Joined: Fri May 27, 2016 8:58 pm

Re: Custom linker memory map howto

Post by andydansby »

I did briefly touch on this @ https://zxspectrumcoding.wordpress.com/ ... -lesson-4/. This is of course SCCZ80. The mmap is a pretty powerful tool.
Post Reply