When the operand field of a LDR instruction uses a label to reference a memory location, it is implemented as a “PC-relative” reference, as in:
LDR R0,x // ‘PC-Relative’ addressing
This assumes that the data is stored in what ARM calls a “literal pool” located a short distance from the instruction. The assembler calculates this distance and embeds it as a constant within the representation of the instruction. When the instruction executes, the constant is added to the current value of the program counter (PC) to determine the address of the operand.
However, the use of PC-relative addressing with the STR instruction was deprecated in the Thumb-2 instruction set introduced as part of the ARMv7-M architecture.
STR R0,x // Rejected by the assembler as ‘deprecated’
Instead, STR references to labelled data require a two-instruction sequence:
ADR R1,x // R1 = address of x STR R0,[R1] // R0 stored at address provided by R1
One might reasonably assume (although incorrectly) that PC-relative addressing is a special case of “Immediate Offset” addressing in which the address is the sum of a register (the PC in this case) and a constant, as in:
LDR R0,[PC,constant] // Immediate Offset addressing
For example, the T3 encoding of a “Load Immediate” instruction specifies the register (Rn) and constant (imm12) in bitfields of 4 and 12 bits each, so it would seem that PC-relative addressing would simply insert the register code of the PC (R15 = 1111) into the Rn bitfield of the instruction:
LDR Rt,[Rn,imm12] // ‘Immediate mode’ addressing
However, the constant (imm12) is unsigned, so this would limit PC-relative references to only “forward” references. Instead, setting Rn to 1111 is a special case that causes the execution of the instruction to interpret bit 7 (the ‘U’ bit) of the encoding differently. When U=1, the address is computed as PC + imm12, but when U=0, it is computed as PC – imm12. This instruction, known as “LDR Literal”, can then make both forward and backward references to literal pool data.
Unfortunately, although there is an “STR Immediate”, specifying Rn = 1111 causes the instruction to be undefined. I.e., there is no “STR Literal” instruction. Why?