Below is the test program.
#include <stdio.h>
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef struct HuffTableT
{
uint16 mMinCode[16];
uint16 mMaxCode[16];
uint8 mValPtr[16];
} HuffTable;
static HuffTable gHuffTab0;
static uint8 gBits[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
static void huffCreate(const uint8* pBits, HuffTable* pHuffTable)
{
uint8 i = 0;
uint8 j = 0;
uint16 code = 0;
for ( ; ; )
{
uint8 num = pBits[i];
if (!num)
{
pHuffTable->mMinCode[i] = 0x0000;
pHuffTable->mMaxCode[i] = 0xFFFF;
pHuffTable->mValPtr[i] = 0;
}
else
{
pHuffTable->mMinCode[i] = code;
pHuffTable->mMaxCode[i] = code + num - 1;
pHuffTable->mValPtr[i] = j;
j = (uint8)(j + num);
code = (uint16)(code + num);
}
code <<= 1;
i++;
if (i > 15)
break;
}
}
int main(void) {
int i;
huffCreate(gBits, &gHuffTab0);
for (i = 0; i < 16; i++) {
printf("%04x %04x %02x\n",
gHuffTab0.mMinCode[i],
gHuffTab0.mMaxCode[i],
gHuffTab0.mValPtr[i]);
}
return 0;
}
It uses some of the following source:
https://github.com/richgel999/picojpeg/blob/master/picojpeg.c
Compiled with SDCC 4.5.0.
With -mz80 option gives correct output.
0000 ffff 00
0000 0000 00
0002 0003 01
0008 000a 03
0016 0019 06
0034 0038 0a
0072 0077 0f
00f0 00f6 15
01ee 01f5 1c
03ec 03f4 24
07ea 07f3 2d
0fe8 0ff2 37
1fe6 1ff1 42
3fe4 3ff0 4e
7fe2 7fef 5b
ffe0 ffee 69
But with -mr800 option it looks like this:
0000 ffff 00
0000 0000 ee
0002 0000 ff
0008 0000 03
0016 0000 06
0034 0000 0a
0072 0000 0f
00f0 0000 15
01ee 0000 1c
03ec 0000 24
07ea 0000 2d
0fe8 0000 37
1fe6 0000 42
3fe4 0000 4e
7fe2 0000 5b
ffe0 0000 69
The assembly for calculating mMaxCode is different as follows:
Z80:
;t.c:36: pHuffTable->mMaxCode[i] = code + num - 1;
ld a, -15 (ix)
add a, -5 (ix)
ld -6 (ix), a
ld a, -14 (ix)
adc a, #0x00
ld -5 (ix), a
ld l, -7 (ix)
ld h, #0x00
add hl, bc
ld c, l
ld b, h
dec bc
push hl
ld l, -6 (ix)
ld h, -5 (ix)
ld (hl), c
inc hl
ld (hl), b
pop hl
R800:
;t.c:36: pHuffTable->mMaxCode[i] = code + num - 1;
pop de
pop hl
push hl
push de
ld d, #0x00
add hl, de
ld a, c
ld e, -3 (ix)
ld d, -2 (ix)
ld b, #0x00
add a, e
ld e, a
ld a, b
adc a, d
ld d, a
ld a, e
add a, #0xff
ld b, a
ld a, d
adc a, #0xff
ld (hl), b
inc hl
ld (hl), a
I can reproduce the issue using current sdcc, both from trunk and the rabbit branch.
Interestingly, the ez80 port is not affected, despite its register allocation cost function being quite similar to r800.
Fixed in [r15630].
Related
Commit: [r15630]