The following code (also attached) produces incorrect assembly when compiled with SDCC r9514 using 'sdcc -mstm8 -c minimal.c'. v[2] should be set to (v[0] & 0x7f), but is incorrectly always set to zero.
typedef unsigned char uint8_t;
extern uint8_t v[3];
void
main(void)
{
uint8_t aa;
uint8_t bb;
aa = v[0];
bb = aa & 0x80;
aa &= 0x7F;
v[1] = bb;
v[2] = aa;
}
The relevant part of the resulting assembly:
000000 112 _main:
000000 52 02 [ 2] 113 sub sp, #2
114 ; minimal.c: 16: aa = v[0];
000002 AEr00r00 [ 2] 115 ldw x, #_v+0
000005 1F 01 [ 2] 116 ldw (0x01, sp), x
000007 1E 01 [ 2] 117 ldw x, (0x01, sp)
000009 F6 [ 1] 118 ld a, (x)
119 ; minimal.c: 18: bb = aa & 0x80;
00000A A4 80 [ 1] 120 and a, #0x80
00000C 90 97 [ 1] 121 ld yl, a
122 ; minimal.c: 19: aa &= 0x7F;
00000E A4 7F [ 1] 123 and a, #0x7f
124 ; minimal.c: 21: v[1] = bb;
000010 1E 01 [ 2] 125 ldw x, (0x01, sp)
000012 5C [ 2] 126 incw x
000013 88 [ 1] 127 push a
000014 90 9F [ 1] 128 ld a, yl
000016 F7 [ 1] 129 ld (x), a
000017 84 [ 1] 130 pop a
131 ; minimal.c: 22: v[2] = aa;
000018 1E 01 [ 2] 132 ldw x, (0x01, sp)
00001A 5C [ 2] 133 incw x
00001B 5C [ 2] 134 incw x
00001C F7 [ 1] 135 ld (x), a
00001D 5B 02 [ 2] 136 addw sp, #2
00001F 81 [ 4] 137 ret
The problem can be seen in lines 120-123. The contents of v[0], having been previously loaded into the 'a' register, are ANDed with 0x80, then saved in 'yl' for later saving to v[1]. So after line 121, both 'a' and 'yl' contain the value of variable bb. Register 'a' is then ANDed with 0x7f on line 123, but it should be the value of variable aa which is ANDed with 0x7f, NOT variable bb. As a result, the value eventually stored in v[2] is wrong.
I examined the assembly produced from this code for other targets (mcs51/z80/z180/r2k/r3ka/gbz80/tlcs90/ds390/ds400/hc08/s08), and only saw this problem with the stm8 target.
The value of variable aa containing in the register A is pushed to the stack on line 127, and the poped back to A on line 130.
So when saving to v[2], the register A is right holding the value of variable aa.
After line 121 a should be reloaded from (x) and it isn't. Reopening.
Fixed in revision #9516.
Thanks, Ben!