AVR Read-modify-write bug for avrtiny subarch
Original Reporter info from Mantis: ccrause @ccrause
-
Reporter name: Christo Crause
Original Reporter info from Mantis: ccrause @ccrause
- Reporter name: Christo Crause
Description:
When reading a variable from RAM, modifying it and writing the resulting value back to RAM, the address stored in the Z pointer could have been modified by predecrement/postincrement versions of LD. Below find an example of code that loads a value from RAM, modifies it then stores the modified value back to RAM. Note in the generated assembler that ld r21, Z+ is used to load the high byte of w, after this Z points to the next byte address. Z still points to the next byte address when the store operation is started, which then stores (for this example) the value of w with an offset of 1 relative to the linker assigned address of w.
This issue has been exposed by #37929 (closed) because the avrtiny subarch doesn't have a load with displacement instruction. This means that loading variables larger than a byte in size from RAM via the Z-pointer will currently always modify the Z-pointer.
Looking at tcg.a_op_const_ref shows that the high level code generator only loads the address of a reference once, before the read-modify-write sequence.
Steps to reproduce:
program test;
var
w: word;
procedure dummy;
begin
inc(w);
OCR0A := w;
end;
begin
end.
Additional information:
# [8] inc(w);
ldi r19,lo8(U_sPsTEST_ss_W)
ldi r18,hi8(U_sPsTEST_ss_W)
mov r30,r19
mov r31,r18
ld r21,Z+
ld r22,Z
ldi r20,1
add r21,r20
adc r22,r17
st Z+,r21
st Z,r22
Mantis conversion info:
- Mantis ID: 38142
- Build: r47541
- Version: 3.3.1
- Fixed in version: 3.3.1
- Fixed in revision: 47612 (#eb098a3d)