On 24/07/2019 21:41, Michael Kwasnicki wrote:
So the inputs to inline assembly are by value and not by reference, as I
thought. Right?
Correct. The inputs are used to initialise the registers.
The correlation between my named registers and those C variables was
pure coincidence.
No, it is pure optimisation, not coincidence. And of course you don't
necessarily get registers for variables in C - certainly not for const
values.
And by making the named registers both - input and output - it creates a
reference to the original C variable.
Yes, roughly.
The big question here is why you are using assembly at all. Why not
just write in C?
void test2(void) {
uint8_t size = 42;
const uint8_t start = _BV(WGM02) | _BV(CS00);
const uint8_t stop = 0x00;
TCCR0A = _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
OCR0A = 9; // TOP
const uint8_t zero = 1; // 0 < i <= TOP
const uint8_t one = 7; // 0 < i <= TOP
OCR0B = one;
TCCR0B = start;
while (size--) {
for (uint8_t bits = 0; bits < 8; bits++) {
OCR0B = one;
}
OCR0B = zero;
}
TCCR0B = stop;
}
It is simpler, easier to understand, much easier to get right, and gives
code that is marginally smaller and faster than your hand-written
assembly. (It is even better with -O2, which is the optimisation level
I recommend as usually giving smaller and faster code than -Os.)
mvh.,
David
Regards,
Michael K.
Am 24.07.2019 um 19:17 schrieb Joseph C. Sible <josephcsi...@gmail.com
<mailto:josephcsi...@gmail.com>>:
Since you intend to modify the inputs, you need to declare them as
outputs as well (with the + constraint). If you don't do this, GCC is
allowed to assume you don't write to them, and can share any that have
the same values.
Joseph C. Sible
On Wed, Jul 24, 2019, 13:04 Michael Kwasnicki <avr-...@kwasi-ich.de
<mailto:avr-...@kwasi-ich.de>> wrote:
Hello dear list members,
I am new to this list because I need someone to discuss a
potential compiler bug.
I try to mix inline assembly in C code. In the assembly I use
passed in variables which are named:
_https://godbolt.org/z/w8wuJy_
_
_
The register mapping is:
[rZero] -> R20
[rOne] -> R21
[rStart] -> R18
[rStop] -> R19
[rSize] -> R22
[bits] -> R19
If I look at the output assembly I can see the compiler did some
optimisation.
R19 is shared between [bits] and [rStop].
In this case this is okay as the bit count reaches zero at the end
and thus [bits] and [rStop] have the same value then.
But when I change the initial value of `bitcount` in C to 7 all
hell breaks loose.
https://godbolt.org/z/F7rrB_
The register mapping is:
[rZero] -> R20
[rOne] -> R18
[rStart] -> R19
[rStop] -> R21
[rSize] -> R22
[bits] -> R18
This time the compiler optimisation corrupted the program.
R18 is shared between [rOne] and [bits]. [rOne] was supposed to be
a constant that is cached in a register. But [bits] gets decremented.
Thus the value passed to OCR0B varies and is not constant any more
changing the logic of the inline assembly.
I am not experienced with inline assembly so I might have missed
something but my general expectation for assembly is that if I
name things differently, they are different things (registers in
this case).
The issue does not show up with -O0 but anything above.
Locally I am running avr-gcc (GCC) 9.1.0. Not sure what the exact
version at godbolt is.
Cheers,
Michael
_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org <mailto:AVR-GCC-list@nongnu.org>
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list
_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list
_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list