This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Inconsistency between the armv7-m document and physical board (B instruction, Thumb mode)

Hello,

    I found the arm assembler always does an extra `plus 4` when calculating the label of instruction B. (support-board: nrf52840dk, architecture; Cortex-M ), but the armv7-M document (ARM DDI 0403E.e) doesn't mention it ?  could you please give me some suggestions?

    Considering the following example:

   1) `0x01, 0xdb` (i.e. 0xdb01) corresponds to the encoding T1 of B with cond = LT and imm8=0x01

1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
--------------------------------
|1 1 0 1| cond | imm8 |
--------------------------------

   2) computing label

according to the description "
if cond == '1110' then SEE UDF;
if cond == '1111' then SEE SVC;
imm32 = SignExtend(imm8:'0', 32);
if InITBlock() then UNPREDICTABLE;

"

   we know imm32 = 0x00000002

according to the description "

Operation
if ConditionPassed() then
EncodingSpecificOperations();
BranchWritePC(PC + imm32);

"

and "

////BranchWritePC()
==========

BranchWritePC(bits(32) address)

BranchTo(address<31:1>:’0’);

"

and "

////BranchTo()
==========
BranchTo(bits(32) address)
_R[RName_PC] = address;
return;

"

   we know the label should be "pc+2", but in practise, the label is "pc+6", I tested it on my board:

```C

//

#include <stdio.h>
#include <string.h>
#include <stdint.h>

__attribute__((aligned(4))) unsigned char code[] = {
0x01, 0xdb,
0x40, 0xf2, 0x0b, 0x0b,
0xcc, 0xf8, 0x06, 0xb0,
0x32, 0xdb,
0x25, 0xfa, 0x04, 0xf5,
0x40, 0xf2, 0x2a, 0x00, 0x70, 0x47, 0x40, 0xf2, 0x3a, 0x00, 0x70, 0x47
};

/*
0x00, 0xdb,
0x40, 0xf2, 0x0b, 0x0b,
0xcc, 0xf8, 0x06, 0xb0,
0x32, 0xdb,
0x25, 0xfa, 0x04, 0xf5,

===> b always +4??? (0+4)

0x20000200 <code> blt.n 0x20000204 <code+4>
0x20000202 <code+2> movw r11, #11
0x20000206 <code+6> str.w r11, [r12, #6]
0x2000020a <code+10> blt.n 0x20000272 <impure_data+78>
0x2000020c <code+12> lsr.w r5, r5, r4

*/

/*
0x01, 0xdb
...
===> b always +4??? (2+4)

0x20000200 <code> blt.n 0x20000206 <code+6>

*/

int main(void) {
int i;

__asm volatile ("orr %[input_0], #0x1\n\t"
"blx %[input_0]\n\t"
"mov r1, r0\n\t"
: [result] "=r" (i)
: [input_0] "r" (code)
:
);
printf("get this done. returned: %d\n", i);

return 0;
}


```

  • I just found this description "Calculate the PC or Align(PC,4) value of the instruction. The PC value of an instruction is its address plus 4
    for a Thumb instruction. The Align(PC,4) value of an instruction is its PC value ANDed with 0xFFFFFFFC to
    force it to be word-aligned. (A4-104)", so maybe because Thumb adopts a different PC calculation?