I have this (bad) code:
#include <stdio.h>
unsigned short FadeColor(unsigned short color, unsigned char step)
{
signed short c1 = (color & 0x07) - step;
signed short c2 = ((color & 0x070)>>4) - step;
if (c1<0) c1=0;
if (c2<0) c2=0;
return c1 + (c2<<4);
}
void main()
{
unsigned short color = FadeColor(0x077, 4);
printf("color %02x\n", color);
}
__sfr __at 0xff sif;
int putchar(int c) {
sif = 'p';
sif = c;
return c;
}
I'm using sdcc --version
SDCC : mcs51/z80/z180/r2k/r2ka/r3ka/r4k/r5k/r6k/sm83/tlcs90/ez80/z80n/r800/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8/pdk13/pdk14/pdk15/mos6502/mos65c02/f8/f8l TD- 4.5.24 #16523 (MINGW64)
Running it with:
sdcc -mz80 --no-peep --opt-code-size --max-allocs-per-node 50000 ./bug.c -o ./bug.ihx && ucsim_z80 -I if=outputs[0xff] ./bug.ihx
I expect it to print: color 33
But instead I get this: color 03
This incorrect code has been generated:
;./bug.c:6: signed short c2 = ((color & 0x070)>>4) - step;
ld a, l
and a, #0x70
ld h, #0x00
ld a, #0x04
00123$:
srl h
rr a
dec a
jp nz, 00123$
sub a, e
ld l, a
sbc a, a
ld h, a
After and a, #0x70 the result should be loaded back to L, right shift HL and load L back into A before sub a, e. If I lower the --max-allocs-per-node to 10000 it does exactly that. It also works correctly on SDCC 4.5.0 with --max-allocs-per-node set to 50000 (and even with higher settings) .
I can reproduce the issue using SDCC from current trunk on my Debian GNU/Linux testing on amd64 system.
Last edit: Philipp Klaus Krause 2026-05-16
Fixed in [r16532].
Related
Commit: [r16532]