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