I have encountered a situation where SDCC is generating bad STM8 code. For some reason, in a certain scenario it is not rewinding the stack pointer after returning from a function call. That is, before the function call, it pushes arguments to the stack as normal, but afterwards it is NOT following up with a "addw sp, #N" instruction.

The following example program demonstrates the issue. There may be a simpler test case, but this is what I was able to narrow down to a minimal example from the actual code where I discovered the problem.

// Compile with: sdcc -S -mstm8 main.c
#include <stddef.h>

typedef struct {
    unsigned long m;
    unsigned long n;
} some_t;

static const struct {
    unsigned long a;
    unsigned long b;
    unsigned long c;
    unsigned long d;
} blah[] = {
    { 2483400797, 742211619, 3, 256765940 },
};

void foo(unsigned long x, unsigned long y, some_t *z) {
    (void)x;
    (void)y;
    (void)z;
}

unsigned long bar(unsigned long x, unsigned long y) {
    (void)x;
    (void)y;
    return 0UL;
}

void main(void) {
    unsigned long t;
    some_t r;

    for(size_t i = 0; i < (sizeof(blah) / sizeof(blah[0])); i++) {
        t = bar(blah[i].a, blah[i].b);
    }

    for(size_t i = 0; i < (sizeof(blah) / sizeof(blah[0])); i++) {
        foo(blah[i].a, blah[i].b, &r);
    }

    while(1);
}

When one inspects the generated assembly code, you can see that where it calls bar(), it generates the following:

    pushw    y
    ldw    x, (0x0f, sp)
    pushw    x
    ldw    x, (0x0f, sp)
    pushw    x
    ldw    x, (0x17, sp)
    pushw    x
    ldw    x, (0x17, sp)
    pushw    x
    call    _bar
    addw    sp, #8   ; <-- SP rewind
    popw    y

But when it later calls foo(), it generates the following:

    pushw    x
    ldw    x, (0x0d, sp)
    pushw    x
    ldw    x, (0x0d, sp)
    pushw    x
    pushw    y
    ldw    x, (0x15, sp)
    pushw    x
    call    _foo
    ldw    x, (0x11, sp)   ; <-- no SP rewind!

As you can see, it does not follow the "call" instruction with anything to rewind the stack pointer and clean up the arguments it previously pushed! Therefore, execution here goes haywire, because unexpected values are encountered for stack-held variables (in my original code, 'i' became bogus and the for loop exited early).

This bug is worrying me, as I have been attempting to mitigate by rearranging my code in all sorts of ways, yet I cannot convince SDCC to emit the proper stack clean-up code for the affected function call. Anyone have any advice?

Regards,
Basil Hussain

P.S. SDCC version:

SDCC : mcs51/z80/z180/r2k/r2ka/r3ka/sm83/tlcs90/ez80_z80/z80n/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8/pdk13/pdk14/pdk15/mos6502 4.2.0 #13081 (MINGW64)


_______________________________________________
Sdcc-user mailing list
Sdcc-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sdcc-user

Reply via email to