On 23/06/2021 10:37, BERTRAND Joël wrote: > In bad.S, self->handler(self->app, LDL_MAC_DEV_NONCE_UPDATED, &arg) gives : > a340: 68 01 movw r12, r16 > a342: ff e4 ldi r31, 0x4F ; 79 > a344: cf 1a sub r12, r31 > a346: fe ef ldi r31, 0xFE ; 254 > a348: df 0a sbc r13, r31 > a34a: e3 50 subi r30, 0x03 ; 3 > a34c: ff 4f sbci r31, 0xFF ; 255 > a34e: 01 90 ld r0, Z+ > a350: f0 81 ld r31, Z > a352: e0 2d mov r30, r0 > a354: ae 01 movw r20, r28 > a356: 4f 5a subi r20, 0xAF ; 175 > a358: 5f 4f sbci r21, 0xFF ; 255 > a35a: 65 e0 ldi r22, 0x05 ; 5 > a35c: 70 e0 ldi r23, 0x00 ; 0 > a35e: d6 01 movw r26, r12 > a360: 8d 91 ld r24, X+ > a362: 9c 91 ld r25, X > a364: 09 95 icall > > I have rebuilt a second firmware that works as expected with: > > if (self->handler == NULL) for(;;); > self->handler(self->app, LDL_MAC_DEV_NONCE_UPDATED, &arg); > > Asmb output contains : > > if (self->handler == NULL) for(;;); > a33c: e3 50 subi r30, 0x03 ; 3 > a33e: ff 4f sbci r31, 0xFF ; 255 > a340: 01 90 ld r0, Z+ > a342: f0 81 ld r31, Z > a344: e0 2d mov r30, r0 > a346: 30 97 sbiw r30, 0x00 ; 0 > a348: 09 f4 brne .+2 ; 0xa34c > a34a: 4a c0 rjmp .+148 ; 0xa3e0 > self->handler(self->app, LDL_MAC_DEV_NONCE_UPDATED, &arg); > a34c: 68 01 movw r12, r16 > a34e: 2f e4 ldi r18, 0x4F ; 79 > a350: c2 1a sub r12, r18 > a352: 2e ef ldi r18, 0xFE ; 254 > a354: d2 0a sbc r13, r18 > a356: ae 01 movw r20, r28 > a358: 4f 5a subi r20, 0xAF ; 175 > a35a: 5f 4f sbci r21, 0xFF ; 255 > a35c: 65 e0 ldi r22, 0x05 ; 5 > a35e: 70 e0 ldi r23, 0x00 ; 0 > a360: d6 01 movw r26, r12 > a362: 8d 91 ld r24, X+ > a364: 9c 91 ld r25, X > a366: 09 95 icall > > I'm not a AVR ASMB specialist, but I don't understand why > self->handler(self->app, LDL_MAC_DEV_NONCE_UPDATED, &arg) produces a > different code (with of course the same compilation options) when it was > preceded by if (self->handler == NULL) for(;;); >
I haven't looked at any of the rest of your code. But here I think the differences are just that after the NULL check, the compiler knows that self->handler is already in Z, and this can be re-used later in the indirect call. So the registers used for getting the other parameters, and perhaps the order they are collected, can change accordingly. Optimisations and register allocation algorithms can often make the assembly appear significantly differently when in fact the changes are typically cosmetic.