The following code (also attached) produces incorrect assembly
when compiled with SDCC r9575 using 'sdcc -mstm8 -c minimal.c'.
When compiled with 'sdcc -mstm8 --nogcse -c minimal.c', the code
produced is correct.
Based on a quick look at other targets, I think I'm seeing the same
problem in some (z80/z180/r2k/r3ka/gbz80/tlcs90/), but not in others
(mcs51/ds390/ds400/hc08/s08).
In the incorrect output, in testfunc(), the argument pushed to
the second call of calledfunc() is the cached value of 'j + k'. The
code should instead calculate the new value of 'j + k1' and push that.
void calledfunc(char i) { (void)i; } char condition(void) { return 1; } void testfunc(char j, char k) { char k1 = k; calledfunc(j + k); while (k1 > 0) { if (condition()) k1--; calledfunc(j + k1); } } void main(void) { testfunc(10, 5); }
The relevant part of the incorrect assembly:
000004 128 _testfunc: 129 ; minimal.c: 7: char k1 = k; 000004 7B 04 [ 1] 130 ld a, (0x04, sp) 131 ; minimal.c: 9: calledfunc(j + k); 000006 95 [ 1] 132 ld xh, a 000007 1B 03 [ 1] 133 add a, (0x03, sp) 000009 97 [ 1] 134 ld xl, a 00000A 89 [ 2] 135 pushw x 00000B 9F [ 1] 136 ld a, xl 00000C 88 [ 1] 137 push a 00000D CDr00r00 [ 4] 138 call _calledfunc 000010 84 [ 1] 139 pop a 000011 85 [ 2] 140 popw x 141 ; minimal.c: 11: while (k1 > 0) { 000012 142 00103$: 000012 9E [ 1] 143 ld a, xh 000013 4D [ 1] 144 tnz a 000014 27 15 [ 1] 145 jreq 00106$ 146 ; minimal.c: 12: if (condition()) 000016 89 [ 2] 147 pushw x 000017 CDr00r01 [ 4] 148 call _condition 00001A 85 [ 2] 149 popw x 00001B 4D [ 1] 150 tnz a 00001C 27 03 [ 1] 151 jreq 00102$ 152 ; minimal.c: 13: k1--; 00001E 1D 01 00 [ 2] 153 subw x, #256 000021 154 00102$: 155 ; minimal.c: 15: calledfunc(j + k1); 000021 89 [ 2] 156 pushw x 000022 9F [ 1] 157 ld a, xl 000023 88 [ 1] 158 push a 000024 CDr00r00 [ 4] 159 call _calledfunc 000027 84 [ 1] 160 pop a 000028 85 [ 2] 161 popw x 000029 20 E7 [ 2] 162 jra 00103$ 00002B 163 00106$: 00002B 81 [ 4] 164 ret
In lines 130 and 132, the value of 'k' is put into XH.
In lines 133 and 134, the value of 'j' is added to 'k' and put in XL.
In lines 136 and 137, XL is pushed, so the call to 'calledfunc' at line 138 receives the correct argument ('j + k').
In lines 157 through 159, XL is again pushed for the call to 'calledfunc', which is incorrect.
When compiled with '--nogcse', the second call to 'calledfunc' correctly computes and pushes the sum 'j + k1':
152 ; minimal.c: 15: calledfunc(j + k1); 000023 7B 05 [ 1] 153 ld a, (0x05, sp) 000025 1B 02 [ 1] 154 add a, (0x02, sp) 000027 88 [ 1] 155 push a 000028 CDr00r00 [ 4] 156 call _calledfunc
Thank you!
Diff:
Diff:
Fixed in [r9700]