I think this one is fixed by r17025 (bug #4153). The reduced test case from kimstig shows the same pattern I ran into there: the result of the 16-bit subtract lands in the same registers as the operand, but in swapped order, so mov r3,a clobbers the high byte before addc reads it. With a clean 4.6.0 and --model-medium, with or without --no-peep, I still get: mov a,r4 add a,#0xff mov r3,a addc a,#0xff mov r4,a With 4.6.0 plus only the positionRegs() change from #4153, and with trunk r17039, the same...
I think I found why exprmasks(4) breaks the relocations, and a smaller fix. The 0xFF comes from rngchk() in asexpr.c: it sign-extends every value to the width set by exprmasks(), and the 8051 port calls exprmasks(3), so 0xa4a5a6a7 becomes 0xFFA5A6A7 before >> 24 is applied. exprmasks(4) fixes that, but a_bytes also controls how many address bytes go into the T lines. The sdas 8051 single byte relocation in outrb() (asout.c, "sdas mcs51 specific") marks the entry as R_BYT3 and writes a_bytes bytes,...
The r4 overlap comes from spillThis() freeing registers that the symbol no longer owns. Traced on r17021, where the call result is iTemp29 instead of iTemp30: at ic 40 spilSomething() puts iTemp0 on the stack. As the first stack spill it calls spillLRWithPtrReg(iTemp0), which spills every range using r0/r1 that does not end before iTemp0 starts (3). That includes iTemp13 [r0 r4], range 13:16, which had already ended and given its registers back; r4 then went to iTemp3 [r3 r4], range 6:43. spillThis(iTemp13)...
The patch from #4154 is independent of this one and still applies cleanly on top of r17025, in case it helps there too. Thanks for applying this one, and to Philipp for confirming it on trunk.
A short follow-up in case it makes this easier to look at. Below is a standalone version of the test, without the regression framework. It prints PASS or FAIL through the ucsim simif interface: sdcc -mmcs51 repro-4154.c printf 'run\nquit\n' | s51 -t 8052 -I 'if=xram[0x7654]' repro-4154.ihx With plain 4.5.0 it prints FAIL in the small, large and stack-auto models, and with the patch from this ticket it prints PASS. I also tried shrinking it with cvise, but the function under test barely got smaller,...
A short follow-up in case it makes this easier to look at. Below is a standalone version of the test, without the regression framework. It prints PASS or FAIL through the ucsim simif interface: sdcc -mmcs51 repro-4153.c printf 'run\nquit\n' | s51 -t 8052 -I 'if=xram[0x7654]' repro-4153.ihx With plain 4.5.0 it prints FAIL in the small and large models, and with the patch from this ticket it prints PASS. I also tried shrinking it with cvise, but the function under test barely got smaller, so it seems...
The patch against r17011 is attached. It has the three-line change in src/mcs51/ralloc.c and the test as support/regression/tests/bug-4154.c. Without the change the test fails on info_while[2] in mcs51-small, mcs51-large and mcs51-small-stack-auto. It applies on its own and together with the patch from #4153.
mcs51: spillThis() frees registers that a dead live range no longer owns