I try to implement banking support, but confusing by strange linker behavior.
Code on assembler:
.dw _label
.dw (_label >> 16)
If _label on linker stage is equal to 0x1801E (-Wl-b_BANK01=0x18000) then result code will be:
1E 80 1E 80
I try to analize rel file and found that it does not contain instruction for 24 bit relocation (there should be codes in R section with four high bits set due to rel file format).
To reproduce:
$ sdcc -mez80_z80 -c aaa.c
$ sdasz80 -o bbb.rel bbb.asm
$ sdcc -mez80_z80 -Wl-b_BANK01=0x18000 aaa.rel bbb.rel
$ makebin -s 131072 aaa.ihx aaa.bin
24 bit relocation is working for stm8. I guess it could be ported to z80 and related.
Philipp
Currently I do not understand how it may work, because shifts are done in common code (asxxsrc).
Since 2019 the rules for making the banked code changed. I have adjusted the code from the original example for the current rules.
The line I used to link was like:
and the relevant code produced is:
The resulting values in binary can be recognized by noting the pattern that the codes for
ld eare1Eand, to locate them easily, after the call there are twoinc spwhich are ASCII '3' or hex33:So the current practice is that the NN of BANKNN (here,
07) is embedded in the resulting binary to be passed in E to the___sdcc_bcall_ehland the actual upper byte of the address is not passed there at all, but the mechanism for banking, as far as I see, is consistent with the SDCC manual.So the currently functioning rules and functionality should not prevent the possibility to produce banking code following the rules described in the current SDCC manual.
In an attempt to demonstrate the problem of the linker being able to use the upper byte of the 24-bit address, I've also written:
where two values in the resulting binary will be recognized by being between three
C9values:and here we see that the value for
.db (_setBit >> 16)is still00and for(_resetBit >> 16)is1E, comparing with the values from the map, it's still the lowest byte in both cases.At the moment I still haven't localized the points where the assembler and linker should cooperate to be able to resolve the upper parts of the global address directly as the
.dbvalue inside of the resulting binary file.The remaining question is, how should exactly the scenario, where the parts of the address should be resolved with a linker, look like, it the existing solution is not enough? If I understand correctly, the linker is limited by what can be passed through the format of .rel files, which is kind of standardized.
Last edit: Janko Stamenović 2025-09-03
I've also played with the last version of the upstream assembler and linker (intentionally, as our version is based on the mix of the older versions) and that version also wouldn't handle the expressions like
for the target bytes that the linker should resolve after the relocation.
What would work there are:
and
Edit: The reason
>operator is used there is that the format of.rel(relocatable objects) files doesn't allow arbitrary expressions to be calculated after the relocation. The most complex use possible is selecting bits from the relocated value, like, in this case, the byte 2 of the 3-byte address can be selected with that special asxxxx's > operator which has clear mapping to the format below.Edit2: The SDAS assemblers don't use
.msbat all, and where it is in the sources, it's commented out.Edit3: the function with
.msbrelated comments:Last edit: Janko Stamenović 2025-09-07
Ok, but why does it work for stm8 (didn't check again today, but when I did months ago, AFAIR it did work for stm8), and can we make the rab assembler behave like stm8? And maybe ez80 and tlcs90, too?
Last edit: Philipp Klaus Krause 2025-12-19
Can you give me an example for stm8 for which you know that it works (or worked) as you expected? Thanks.
Well, the test-stm8-large regression tests pass, and they use 24-bit addresses for functions. For most of the tests the top byte will be 0x00, but tests/bug-3778.c and tests/bug-3786.c should have non-zero top bytes in 24bit addresses.