On Friday, 21 July 2017 at 23:44:53 UTC, Mike wrote:
I'm getting broken binaries with -O2 and -O3. I've nailed the
culprit down to -fschedule-insns (i.e. if I add
-fno-schedule-insns to -O2 or -O3, the binary works fine).
I disassembled '-O2' and '-O2 -fno-schedule-insns' and compared
them, but they were quite different all the way through. No
only because of address locations, but also different registers
and even different opcodes. (e.g. 'str r2, [sp, #12]' vs 'strd
r1, r2, [sp, #8]')
Interestingly, I added a stategically placed `asm { "nop"; }` and
my binary was able to execute further. Comparing the disassembly
of the function I modified still showed quite a significant
difference.
Working Binary
-------------
ldr r2, [pc, #188] ; (8000c50 <hardwareInit+0x104>)
ldr r1, [pc, #188] ; (8000c54 <hardwareInit+0x108>)
ldr r3, [r2, #0]
and.w r3, r3, #780 ; 0x30c
orr.w r3, r3, #37888 ; 0x9400
movs r0, #0
str r3, [r2, #0]
strb r0, [r1, #0]
;-------------------------------------------------------
nop ; My stategically placed nop
;-------------------------------------------------------
ldr r3, [pc, #172] ; (8000c58 <hardwareInit+0x10c>)
ldr r0, [pc, #176] ; (8000c5c <hardwareInit+0x110>)
ldr r4, [pc, #176] ; (8000c60 <hardwareInit+0x114>)
ldr r2, [pc, #180] ; (8000c64 <hardwareInit+0x118>)
movs r1, #1
strb r1, [r3, #0]
ldr r3, [r0, #0]
orr.w r3, r3, #49152 ; 0xc000
str r3, [r0, #0]
strb r1, [r4, #0]
Not Working Binary
------------------
ldr r0, [pc, #184] ; (8000c4c <hardwareInit+0x100>)
ldr r1, [pc, #184] ; (8000c50 <hardwareInit+0x104>)
ldr r2, [pc, #188] ; (8000c54 <hardwareInit+0x108>)
ldr r3, [r1, #0]
ldr r4, [pc, #188] ; (8000c58 <hardwareInit+0x10c>)
movs r5, #0
strb r5, [r0, #0]
movs r0, #1
strb r0, [r2, #0]
ldr r2, [r4, #0]
ldr r5, [pc, #180] ; (8000c5c <hardwareInit+0x110>)
orr.w r2, r2, #49152 ; 0xc000
and.w r3, r3, #780 ; 0x30c
str r2, [r4, #0]
orr.w r3, r3, #37888 ; 0x9400
ldr r2, [pc, #168] ; (8000c60 <hardwareInit+0x114>)
strb r0, [r5, #0]
str r3, [r1, #0]
By "Not Working" I mean this code gets stuck in the while loop
PWR.CR.ODEN.value = true;
while(!PWR.CSR.ODRDY.value) { }
This is simply setting the "Overdrive Enable" register on the
power control peripheral of my hardware. The documentation
states:
To set or reset the ODEN bit, the HSI or HSE must be selected as
system clock.
I'm setting the HSI prior to setting ODEN, but it appears that
maybe the compiler is reordering the instructions. I still need
to investigate that further, but hopefully that provides a little
more insight.
Mike