Electronic – NOP instruction after branch on ARMv7 Cortex M3

armassembler

I'm interested, why for Cortex M3 microcontroller (stm32f103) compiler sometimes generates a NOP instruction after branch. And why it sometimes doesn't.

For example:

0x08000496 2400      MOVS     r4,#0x00
0x08000498 4625      MOV      r5,r4
0x0800049A E006      B        0x080004AA
    64: res=res+a[i];
    65: }
0x0800049C F85A0034  LDR      r0,[r10,r4,LSL #3] // No NOP after B
0x080004A0 EB100808  ADDS     r8,r0,r8
0x080004A4 1C64      ADDS     r4,r4,#1
0x080004A6 F1450500  ADC      r5,r5,#0x00
0x080004AA 1BA0      SUBS     r0,r4,r6
0x080004AC EB750007  SBCS     r0,r5,r7
0x080004B0 DBF4      BLT      0x0800049C
    66: int64_t avg=res/x;
0x080004B2 BF00      NOP      // <------------------- NOP after BLT
    69: int v=countbits1(5);
0x080004B4 2005      MOVS     r0,#0x05
0x080004B6 F7FFFFA2  BL.W     countbits1 (0x080003FE)
0x080004BA 9001      STR      r0,[sp,#0x04]     // No NOP after BL.W
    72: unsigned int b=countLeadingZeros(5);
    73:  
0x080004BC 2005      MOVS     r0,#0x05

My initial guess was that long instruction needs word-alignment but BL.W after NOP actually doesn't have it.
If this NOP is related to pipeline somehow than why there are branches without nop's after them?

I'm confused.

UPDATE:

It turns out that branch may be not relevant at all. I tried to moving declaration of unused local variable int64_t avg – and NOP moved along with it.
So I beleive pjc50 comment is right and this NOP is there just to let debugger put a breakpoint on this line.

Best Answer

Try moving the int64_t line of C up or down a bit. The first two are clearly part of a for loop; but line 66 has generated no code at all. My guess is that the NOP is for the benefit of the debugger so that every line of C generates at least one instruction.

(Not all debuggers do this on all platforms; Visual Studio will simply move your breakpoint to the nearest line that has code associated with it.)