Hi all,

I found today some very odd STM8 assembly code generated by SDCC. I can't figure out what it was trying to do, or why.

The C code is really simple:

uint8_t ffs_16(uint16_t value) {
    return (value ? ctz_16(value) + 1 : 0);
}

But I get this bizarre assembly code:

  000019                         90 _ffs_16:
  000019 1E 04            [ 2]   92     ldw    x, (0x04, sp)
  00001B 27 0F            [ 1]   93     jreq    00103$
  00001D 89               [ 2]   94     pushw    x
  00001E 8Ds00r00r00      [ 5]   95     callf    _ctz_16
  000022 5B 02            [ 2]   96     addw    sp, #2
  000024 4C               [ 1]   97     inc    a
  000025 88               [ 1]   98     push    a
  000026 49               [ 1]   99     rlc    a
  000027 4F               [ 1]  100     clr    a
  000028 A2 00            [ 1]  101     sbc    a, #0x00
  00002A 84               [ 1]  102     pop    a
  00002B 21                     103     .byte 0x21
  00002C                        104 00103$:
  00002C 4F               [ 1]  105     clr    a
  00002D                        106 00104$:
  00002D 87               [ 5]  108     retf

The code from 0x25-0x2A is strange and seemingly useless. It pushes what is already the correct return value (from "inc a") on to the stack, shifts off the MSb into carry, zeroes A, subtracts the carry, then throws the result away by popping back the previous value. What would have caused SDCC to emit this extraneous code?

By the way, at first the next 0x21 raw byte confused me too, but I think I see what it is doing: adding a JRF (jump false, or never jump) that treats the following "clr a" byte as the (ignored) destination, effectively skipping that instruction. Ingenious!

Code was compiled with SDCC 4.0.0 with this command line:
sdcc.exe -mstm8 --std-c99  --model-large -DPOP_COUNT_LUT_LARGE -DCTZ_LUT_LARGE -I"C:\Program Files\SDCC\include" -c utils\ctz_16.c -o obj\Library-Large\utils\ctz_16.rel

As a workaround, I changed my C code to the following, which outputs what one would expect.

uint8_t ffs_16(uint16_t value) {
    uint8_t idx = 0;
    if(value) idx = ctz_16(value) + 1;
    return idx;
}

Regards,
Basil Hussain


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

Reply via email to