It should be possible to just ship the header files with SDCC (this already happens for some MCS-51 derivatives and some HC08 devices).
The HC08 headers are actually quite interesting. They use bitfield structs to declare individual bits in the I/O ports. I tried to do the same for the PDK14, but got mixed results, see code below.
"PORTA4" is defined as bit4 on PA.
PORTA4^=1 creates functional, but very inefficient code. (11 instructions instead of 3)
PORTA4=1/PORTA4|=1/PORTA4&=~1 creates broken code and SDCC exits with an assembler error.
struct __pdk_bits
{
unsigned int bit0:1;
unsigned int bit1:1;
unsigned int bit2:1;
unsigned int bit3:1;
unsigned int bit4:1;
unsigned int bit5:1;
unsigned int bit6:1;
unsigned int bit7:1;
};
#define PORTA4 ((struct __pdk_bits *)(&pa))->bit4
#define LEDPIN PA4
unsigned char _sdcc_external_startup(void)
{
clkmd = CLKMD_IHRC_DIV2|CLKMD_ENABLE_IHRC; // 8 Mhz main clock
return 0; // perform normal initialization
}
void main(void)
{
pac |= _BV(LEDPIN); // Use this exact syntax to infer set0/set1
for (;;) {
// pa ^= _BV(LEDPIN); // Toggle LED
PORTA4 ^=1; // works, but creates 11 instructions
delay_ms(500);
PORTA4 = 1; // creates broken assembler code
}
}
; blinky.c: 38: PORTA4 ^=1; // works, but creates 11 instructions
mov a, _pa+0
swap a
and a, #0x01
xor a, #0x01
clear p
sr a
mov a, _pa+0
and a, #0xef
t0sn f, c
or a, #0x10
mov _pa+0, a
; blinky.c: 39: delay_ms(500);
mov a, #0xf4
mov _delay_ms_PARM_1+0, a
mov a, #0x01
mov _delay_ms_PARM_1+1, a
call _delay_ms
; blinky.c: 40: PORTA4 = 1; // creates broken assembler code
mov a, #0x10
or _pa+0, a
goto 00102$