Tool/software: TI C/C++ Compiler
Hello,
The GCC Compiler produces code like the following under certain circumstances:
movw r3, #:lower16:foo+24
movt r3, #:upper16:foo+24
This translates to the following (disassembly of the object file):
9cc: f240 0318 movw r3, #24
9d0: f2c0 0318 movt r3, #24
Please note, that both instructions contain the offset 24.
The final output (TI Linker ti-cgt-arm_5.2.9 and ti-cgt-arm_20.2.0.LTS) is:
017ec0: F6437388 MOVW.W R3, #16264 ; 0x3F88 -> okay (0x3F88 - 24 = 0x3F70)
017ec4: F6C00318 MOVT.W R3, #2072 ; 0x0818 -> Not okay (0x0818 - 24 = 0x0800)
So the TI Linker has added the offset 24 to foo for both instructions MOVW and MOVT which is kind of okay (more later).
However, the expected result for the MOVT is:
MOVT.W R3, #2048
The issue I think is in how the TI Linker implements the relocation R_ARM_THM_MOVT_ABS.
S + A means:
- S (when used on its own) is the address of the symbol.
- A is the addend for the relocation.
The addend is the value that is "already" in the imm16 filed of the MOVT instruction (24).
This would mean that the Linker has to calculate the following: 0x08003F70 + 24 = 0x08003F88 and take the upper 16 bits and put it in the imm16 field of the MOVT instruction ( ( ( 0x08003F70 + 24 ) & 0xFFFF0000 ) >> 16 or ( ( S + A ) & 0xFFFF0000 ) >> 16 ).
However it seems that it has calculated: ( ( 0x08003F70 & 0xFFFF0000 ) >> 16 ) + 24 or ( ( S & 0xFFFF0000 ) >> 16 ) + A
Best regards,
Christian