The attached file a.c is compiled with this command and output:
$ sdcc -mpic16 -ppic18f4550 a.c
message: using default linker script "/usr/share/gputils/lkr/18f4550.lkr"
to produce the file a.asm. Here's the problem: the variable "foo_impl" is stored in ROM (due to its const qualifier), while the variable "foos" is stored in RAM (due the variable itself *not* actually being const qualified). The implementation of call_fptr() unfortunately first does a multiply and some adds to point FSR0 at foos[idx], then loads two bytes from that location and uses those two bytes to reload FSR0! This is wrong: since the referent of the pointer stored in foos[idx] is in ROM, one needs to instead read three bytes from foos[idx] and load them into TBLPTR and then use TBLRD.
Splitting up the code into two statements, the first loading foos[idx] into a local variable fooptr of type [const foo_t *] and the second going through that pointer to get to fooptr(), works correctly as it then uses the generic pointer functions as it seems the compiler no longer "knows" what fooptr is pointing at.
$ sdcc -v
SDCC : mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08 2.8.0 #5117 (Feb 21 2010) (UNIX)
Log in to post a comment.