DESN2000: Engineering Design & Professional Practice (EE&T)
Constants, pseudo-instructions and literal pools
School of Electrical Engineering & Telecommunications Graduate School of Biomedical Engineering
Copyright By Assignmentchef assignmentchef
Biomedical Microsystems Lab
Constants
Pseudo-instructions
Loading constants
Loading addresses
Assembler & linker
2022 UNSW Sydney
ARM instructions are 32 bits long.
ARM instructions are 32 bits long
How to fit a 32-bit constant into an instruction?
How do you then fit a 32-bit constant into an instruction? MOV as example:
Let us look at the binary encoding a MOV instruction
Rn Rd shifter_operand
2022 UNSW Sydney
Bits[27:25]
Bits[24:21]
Bit [27:25] data instruction
Bits[11:0]
that is whether registers, registers with shifts or rotate or immediate values to be used as operands.
Register 3
depends on addressing mode:
type of data processing instruction
Bit [24:21] opcode (1101- mov)
Bit [0:11] has a few options depending on the addressing mode opcode (1101 for MOV)
Since our concern is loading constant, let us look at
addressing mode with immediate
Register with shift or rotate Immediate
Loading a constant, so immediate addressing mode format:
Constants between 0 and 255
d27 31 co2n
214 opco2d
7 8-bit-imme0
ignificant
byte (immediate
8-bit-imme
The least significant byte (immediate) can be any number between 0 and 255
Bits[7:0] (immediate): number between 0 ~ 255.
Bits [11:8] of the instruction specify a rotate value. Bits [11:8] of the instruction specify a rotate value.
Bits[11:8]: a rotation value, which is multiplied by 2, then used to rotate the forgoing 8-
The rotated value is multiplied by 2, then used to rotate the bit immediate via the ALU.
8-bit value to the right by that amount
The rotated value is multiplied by 2, then used to rotate the
vimme ROR(2vrot) where vimme 2 [0 : 255] vrot 2 [0 : 15]
Doesnt cover all 32-bit integers.
8-bit value to the right by that amount
8-bit-imme
Shifter ROR
Allows ARM to generate constants of the form:
2022 UNSW Sydney
Shifter ROR
Example: calculate the rotation needed to generate the value 4080. 4080 = (1111 1111 0000)2
(1111 1111)2, or 0xFF, can be rotated left by 4 bits to generate 4080. Rotating left by 4 equivalent to rotating right by 28.
So MOV R0, #4080 replaced by MOV R0, #0xFF, ROR 28. Assembler does this for you.
2022 UNSW Sydney
MVN (move negative) moves ones complement of the operand.
We can generate additional constants using MVN with the rotation scheme:
s vimme ROR(2vrot) where vimme 2 [0 : 255]
vrot 2 [0 : 15] Rotating 0xFF right by 8 bits, then taking 1s complement.
Example: loading the decimal 16777215 into R0. 16777215 = 0x00FFFFFF
also mentally inconvenient.
So MOV R0, #16777215 replaced by MVN R0, #0xFF, ROR 8.
Bottom line: MOV/MVN + rotation can only create a subset of 32-bit integers.
2022 UNSW Sydney
More problems we often do something like:
EQU 0x04000000
AREA EXAMPLE, CODE, READONLY ENTRY
MOV r0, #SRAM_BASE
All occurrences of SRM_BASE is replaced by 0x04000000
The code fails if SRAM_BASE changes to a value that cannot be generated by the byte rotation scheme.
2022 UNSW Sydney
Pseudo-instructions
Solution: pseudo-instructions.
Understood by the assembler (software) and replaced with real instructions for the
ARM processor (hardware).
Pseudo-instructions Real instructions
HW is constrained by implementation considerations / limitations. Using software to work around these limitations.
Example pseudo-instructions:
LDR
Loads any numerical constant const into register rd. Do-nothing instruction, stand-in for real instruction MOV R0, R0.
MOV R0, #0xFFFFFFFF
is replaced by real instruction MVN R0, #0.
2022 UNSW Sydney
Assembler substitution
Loading constants: LDR
On encountering LDR
1. Tries to substitute with MOV / MVN, with optional rotation.
2. If this fails, create the constant in program space, known as a literal pool, then use the LDR
Example demonstrating all 3 cases:
AREA Example, CODE ENTRY
stop B stop Func1 LDR r0, =42
LDR r1, =0x55555555 LDR r2, =0xFFFFFFFF MOV PC, lr
stop Func1
AREA Example, CODE ENTRY
MOV r0, #42
LDR r1, [PC, #4] MVN r2, #0
MOV PC, lr
DCD 0x55555555
2022 UNSW Sydney
Loading constants: LDR MOV
Case 1: the instruction LDR r0, =42 is replaced with MOV r0, #42 without needing any rotation.
AREA Example, CODE ENTRY
stop B stop Func1 LDR r0, =42
LDR r1, =0x55555555 LDR r2, =0xFFFFFFFF MOV PC, lr
stop Func1
AREA Example, CODE ENTRY
MOV r0, #42
LDR r1, [PC, #4] MVN r2, #0
MOV PC, lr
DCD 0x55555555
2022 UNSW Sydney
Loading constants: LDR literal pool
Case 2: the instruction LDR r1, =0x55555555 is replaced with LDR r1, [PC, #4]:
1. Create a literal pool (Lit_pool) at the end of the code block.
2. Load the constant by PC-offset addressing (PC + 4).
Allows any 32-bit constants to be loaded into a register.
Why 4 bytes?
AREA Example, CODE ENTRY
stop B stop Func1 LDR r0, =42
LDR r1, =0x55555555
LDR r2, =0xFFFFFFFF MOV PC, lr
stop Func1
AREA Example, CODE ENTRY
MOV r0, #42
LDR r1, [PC, #4] PC 8 (execute)
MVN r2, #0 MOV PC, lr DCD 0x55555555
PC 4 (decode) PC (fetch)
2022 UNSW Sydney
Loading constants: LDR MVN
Case 3: the instruction LDR r2, =0xFFFFFFFF is replaced with MVN r2, #0 without needing any rotation, but requires bit flipping, hence the MVN instruction.
AREA Example, CODE ENTRY
stop B stop Func1 LDR r0, =42
LDR r1, =0x55555555
LDR r2, =0xFFFFFFFF
MOV PC, lr
stop Func1
AREA Example, CODE ENTRY
MOV r0, #42
LDR r1, [PC, #4] MVN r2, #0
MOV PC, lr
DCD 0x55555555
2022 UNSW Sydney
Loading constants: LDR literal pool
The literal pool method uses pre-indexed addressing (PC + offset) to reach the 32-bit constant.
LDR
LDR
Lit_pool DCD
Limitations:
Fails if the END directive is > 4 KB from the LDR
2022 UNSW Sydney
..
..
Loading constants: LDR literal pool
Example: literal pool does not work here:
stop Func1
AREA Example, CODE ENTRY
LDR r0, =42
LDR r1, =0x55555555 LDR r2, =0xFFFFFFFF ADD r0, r0,r2
MOV PC, lr
SPACE 4200
Reserve a zeroed block of memory
LDR r1, =0x55555555 fails, because END is (~ 4 KB + 8) away, exceeding the limit of pre-indexed addressing.
What to do?
2022 UNSW Sydney
Loading constants: LTORG
Already using software (assembler) to re-write code Take it a step further!
The LTORG directive tells the assembler to build the current literal pool immediately, at where the LTORG appears.
Original code Assembler step-1 (build literal pool)
stop Func1
AREA Example, CODE ENTRY
LDR r0, =42
LDR r1, =0x55555555 LDR r2, =0xFFFFFFFF ADD r0, r0,r2
MOV PC, lr
SPACE 4200
stop Func1
AREA Example, CODE ENTRY
LDR r0, =42
LDR r1, =0x55555555 LDR r2, =0xFFFFFFFF ADD r0, r0,r2
MOV PC, lr
DCD 0x55555555 SPACE 4200
2022 UNSW Sydney
Loading constants: LTORG
Already using software (assembler) to re-write code Take it a step further!
The LTORG directive tells the assembler to build the current literal pool immediately, at where the LTORG appears.
Assembler step-2 (re-write) Assembler step-1 (build literal pool)
stop Func1
AREA Example, CODE ENTRY
Execute Fetch Decode
MOV r0, #42
LDR r1, [PC, #8] MVN r2, #0
ADD r0, r0,r2 MOV PC, lr
DCD 0x55555555 SPACE 4200
PC + 4 PC + 8
stop Func1
AREA Example, CODE ENTRY
LDR r0, =42
LDR r1, =0x55555555 LDR r2, =0xFFFFFFFF ADD r0, r0,r2
MOV PC, lr
DCD 0x55555555 SPACE 4200
2022 UNSW Sydney
Loading constants: LTORG
Be careful where you use LTORG
The assembler simply replaces it with a DCD block.
Very important that the fetch circuit never enter this block by automatic PC stepping.
Otherwise executing the constants as instructions.
BL some_func
Lit_pool DCD
ADD r0, r0, r1
Lit_pool DCD
Execute (PC 8)
Execute (PC 8)
Decode (PC 4) Fetch (PC)
ARM throws UNDEF exception: Decoder cannot recognize the instruction bit stream
2022 UNSW Sydney
.
Loading constants: LTORG
Best places for LTORG are:
1. At the end of a subroutine; or
2. After unconditional branch instructions
BL some_func
Lit_pool DCD
ADD r0, r0, r1
Lit_pool DCD
Execute (PC 8)
Execute (PC 8)
Decode (PC 4) Fetch (PC)
Lucky: ARM throws UNDEF exception, decoder cannot recognize the instruction bit stream crash. Unlucky: unintended instruction silently executed.
2022 UNSW Sydney
.
Loading constants: summary
Use LDR
Literal pools are generated at the end of each code section.
The assembler will (in this order):
1. If possible, replace with MOV or MVN.
2. Check if the constant is already in a literal pool. If so, address the existing constant.
3. Try to place the constant in the next literal pool.
4. Generate an error if the literal pool will be out of range.
You can control the literal pool location with LTORG.
LTORG usage:
Put LTORG after a subroutine or after an unconditional branch.
The LTORG must still be reachable within 4KB (PC-offset addressing limit). bottom line: modularizing your code is a good thing.
2022 UNSW Sydney
Loading addresses: ADR
The starting address of a table / list / set of coefficients is needed to access the table / list / set.
This address is stored in a register for pre-index / post-index addressing.
Pseudo-instruction ADR
Loading addresses: ADR
The assembler replaces ADR
SUB
PC Address of the instruction being fetched (8 bytes ahead of ADR).
ADR frees us from having to manually track label addresses, letting the assembler update them automatically. Much like #define in C.
2022 UNSW Sydney
Loading addresses: ADR
The assembler computes the PC-relative offset for us.
AREA adrlabel, CODE READONLY
ENTRY Start BL func stop B stop
func ADR r0, Start SUB r0, PC, #16 ADR r1, DataArea
ADD r2, r2, r3
MOV pc, lr DataArea SPACE 8000
Execute (PC-8) Decode (PC-4) Fetch (PC)
2022 UNSW Sydney
16 bytes
Loading addresses: ADR
Q: what #offset would the assembler use when substituting ADR r1, DataArea?
AREA adrlabel, CODE READONLY
ENTRY Start BL func stop B stop
func ADR r0, Start
ADR r1, DataArea ADD r1, PC, ??
ADD r2, r2, r3
MOV pc, lr DataArea SPACE 8000
Execute (PC-8) Decode (PC-4) Fetch (PC)
ADD r1, PC, #4
2022 UNSW Sydney
Loading addresses: ADR
Pseudo-instruction ADR is converted to real instruction ADD / SUB, with immediate addressing mode. Thus the offset is limited to 255 words.
ADR fails if the label is > 255 words away from the PC. The assembler raises an error.
How do we work around this limitation?
2022 UNSW Sydney
Loading addresses: ADRL
Solution: more instruction re-writing tricksJ
Assembler replaces ADRL
AREA adrlabel, CODE READONLY
Start BL func stop B stop
func ADR r0, Start ; SUB r0, PC, #16 ADR r1, DataArea ; ADD r1, PC, #4
ADRL r2, DataArea+4300 ADD r2, PC, #255
MOV pc, lr ADD r2, r2, #4045 DataArea SPACE 8000
2022 UNSW Sydney
Loading addresses: ADR & ADRL
Limitation: label used with ADR or ADRL must be in the same code section. A code section is denoted by the AREA directive.
Sections are independent, named, indivisible chunks of code or data that are manipulated by the linker, which combines AREAs into a single program.
AREA adrlabel, CODE READONLY
ENTRY Start BL func stop B stop
func ADR r0, Start ADR r1, DataArea
ADR r2, DataArea+4300
MOV pc, lr DataArea SPACE 8000
A code section
2022 UNSW Sydney
Loading addresses: LDR
The LDR instruction (previously for loading constants) can also load label addresses.
The pseudo-instruction has the form: LDR
Unlike ADR and ADRL, LDR can load addresses outside the current section. Achieved using literal pools.
2022 UNSW Sydney
Loading addresses: summary
When loading label address into a register, if the label address is:
255 words away: use ADR
> 255 words: use ADRL
Use LDR
1. referencing labels outside the current code section, or
2. you know a literal pool will be created for the current code section
Q: So complicated, why bother with these guidelines?
Minimizing the amount of code expansion from pseudo-instructions, keeping the program small. Embedded systems have limited memory.
LDR =
1 instr. + literal pool
2022 UNSW Sydney
Translating C code to executable
foo.c Complier bar.c Complier
foo.s Assembler bar.s Assembler
bar.o a.out
2022 UNSW Sydney
A program that translates symbolic machine instructions into binary representation.
Main tasks:
Reads and uses directives.
Replaces pseudo-instructions.
Produce machine code
Encodes code and data as bit-blocks from symbolic instruction & declarations
Maps labels into addresses
Creates object file (*.o files) a module.
Contains relocation information, symbol table(s) and (optionally) debugging
information.
foo.c Complier bar.c Complier
foo.s Assembler bar.s Assembler
bar.o a.out
2022 UNSW Sydney
A program that combines several object (.o) files into a binary file, executable by the hardware.
Enable separate compilation of files (modules) changes to one file do not require recompilation of other files.
Steps in linking:
1. Combine text (i.e code) segment from all .o file.
2. Combine data segment from all .o file, append to the end of the text segment.
3. Resolve label references, e.g. labels from other code sections.
foo.c Complier bar.c Complier
foo.s Assembler bar.s Assembler
bar.o a.out
2022 UNSW Sydney
directives
Labels are not visible beyond the current module (*.o file) by default.
EXPORT / GLOBAL: declares that a label can be used by the Linker to resolve labels referenced in another module.
Makes functions, constants visible to other modules.
IMPORT / EXTERN: tells the Assembler that the label is defined elsewhere and will be resolved by the Linker.
Allows externally defined functions, constants to be used.
foo.c Complier bar.c Complier
foo.s Assembler bar.s Assembler
bar.o a.out
2022 UNSW Sydney
Constants
Pseudo-instructions
Loading constants
Loading addresses
Assembler & linker
In Moodle:
Start working on Lab 5 (Due: end of your 3-hr lab)
Start doing Week 9 exercise
2022 UNSW Sydney
CS: assignmentchef QQ: 1823890830 Email: [email protected]
Reviews
There are no reviews yet.