I placed a table in the first file of my project:
EXPORT TaskBranchTable ... TaskBranchTable DCD Main DCD Task1 DCD Task2 DCD Task3
I wroted next code in another file of this project:
IMPORT TaskBranchTable ... ADR R1, TaskBranchTable LDR R0, [R1] BX R0
Keil shows me error: "A1898E: Target cannot be relocated. No suitable relocation exists for this instruction"? How to write a program so that the error did not occur? Which Directive to use correctly?
Of course you can write in the following form and the error will disappear:
IMPORT TaskBranchTable ... LDR R1, =TaskBranchTable LDR R0, [R1] BX R0
But "LDR R0, =label" pseudo instruction writes a 1 in the least significant bit.
IMPORT TaskBranchTable LDR R1, _TaskBranchTable ; will go to ldr r1, [pc+x] form LDR R0, [R1] BX R0 _TaskBranchTable DCD TaskBranchTable ; 32-bit relocatable
Thank you! It works! And why such a restriction on the use of the instruction "ADR"? Why can't I export address any label from an external file?
That's the problem with using pseudo-instructions, ADR is trying to use PC relative addressing (ADD/SUB, single instruction, limited immediate values), and this seriously limits scope. LDR= might work, but in most cases would have to use the literal pool to create something that the linker could relocate. I find it's easier to explicitly tell the assembler what I really want it to generate, using real instructions, then there's no ambiguity for it to make the wrong opcode/coding choices on my behalf. There's also trade-offs with respect to whether the assembler can contain things within a single file where self-relative references can be folded, or if the linker has to fix things up, which can itself be limited by the choices the assembler made earlier.
I think they try to avoid compound instructions, as it might make for unstable code sizes between passes, as code generated varies to account for scope and near/far forms.
infocenter.arm.com/.../index.jsp