Electronic – NOP instruction after branch on ARMv7 Cortex M3


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);
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.


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.)