The following code should print 0, but instead it prints 4096.
uint8 buffer ;
buffer = 0;
If, instead, I declare the buffer to be in XDATA space (
uint8 XDATA buffer ), then it does the right thing.
I tracked the problem down and it seems to be a bug in
_gptrget, which is called by
strlen. It looks like it’s not doing the right thing with pointers to PDATA (seems to overwriting the DPH register with 0?)
I’ve attached the relevant source files.
I am using SDCC 3.2.0
_gptrget.c (8.89 KB)
_strlen.c (2.28 KB)
Hello. The code for _gptrget() that you posted does not write 0 to to dph. It is actually storing the value of the register r0 into the dph register so that it can restore it later. Then it moves the value of dpl into r0 so that it can use the movx instruction to dereference the pointer. I don’t see anything obviously wrong with this.
I tried to reproduce the problem by compiling the following code:
unsigned char deref(char * x)
unsigned char foo()
__pdata unsigned char buffer;
buffer = 0;
When I compile it with the command
sdcc -c test.c --model-medium -o test.rel and look at the assembly, I don’t see any issues. If you think there is a problem and want to get it fixed, I suggest that you try to come up with some minimal and complete example code that demonstrates the problem. Alternatively, you can put your data in XDATA as you mentioned. It might also work to cast “buffer” to an XDATA pointer before passing it to strlen.
I’m referring to this part of _gptrget(). The “restoration” of dph is just zero.
mov r0,dph ; restore r0 ; 2
mov dph,#0 ; restore dph ; 2
ret ; 1
Also keep in mind that this function is declared as naked, so it’s not going to save any registers behind the scenes.
Oh, okay. PDATA pointers can only go from 0 to 255, so dph should already be zero before this function runs and restoring it to zero seems okay.
Oh, I see. I thought that dph would have to be 0xF0 since all things in PDATA would have an address of the form 0xF0XX