# ARMv4T Assembly Pseudo-Instructions
**Shortened and programmer-friendly instructions translated into real instructions for the processer by the assembler.**
*Pseudo-instructions* streamlines the programming process around the limitations imposed by the hardware.
## No operation
```armasm
NOP{cond}
```
- `cond` - [[ARMv4T Assembly#Conditional execution|condition]] for execution.
The `NOP` or *no operation* instruction causes the processor to *do nothing*. It is typically used for timing purposes or forced memory alignment. The assembler translates it into:
```armasm
MOV{cond} r0, r0
```
## Loading constants
```armasm
LDR{cond} <Rd> =<constant>
```
- `cond` - [[ARMv4T Assembly#Conditional execution|condition]] for execution.
- `Rd` - the *destination* register.
- `constant` - a *32-bit* number.
32-bit constants can be loaded into registers with the inclusion of `=` along with an `LDR` instruction.
As data processing instructions can only take immediate operands of a [[ARM Instruction Encoding#Immediate|subset of 32-bit numbers]], this pseudo-instruction allows *all* 32-bit numbers to be *easily available* as valid operands by placing them in available registers.
The assembler handles this pseudo-instruction in two ways.
### MOV/MVN and rotation
If the requested constant is representable by an *8-bit number* and an *even number of [[Bit Shift#Rotate|rotations]]* between 0 and 30, such as valid [[ARM Instruction Encoding#Immediate|data processing immediate operands]], then the assembler will use the `MOV` instruction with an optional rotation.
If the requested constant is representable by the *complement* of the above *rotation method*, then the assembler will use the `MVN` instruction.
>[!8-bit representable number and an even number of rotations]-
> The number $4080_{10}$ is equal to $1111\;1111\;0000_{2}$.
>
> It can be represented by $1111\;1111_{2}=\text{FF}_{16}$ *rotated left* by 4 bits. A left rotation by $n$ bits is equivalent to a right rotation by $32-n$ bits.
>
> The result will be a 32-bit number with *8 leading zeros*, followed by $1111\;1111\;0000$.
>
> Thus, `LDR r0, =4080` is replaced by `MOV r0, #0xFF, ROR 28`.
>[!Number representable as the complement of a rotated 8-bit number]-
> The number $16777215_{10}$ is equal to $1111\;1111\;1111\;1111\;1111\;1111_{2}$.
>
> It can be represented by $1111\;1111_{2}=\text{FF}_{16}$ *rotated right* by 8 bits and then complemented.
>
> The right rotation will create a 32-bit number with $1111\;1111$ as its leading bits followed by *24 trailing zeros*. The complement of this will be the number required.
>
> Thus, `LDR r0, =16777215` is replaced by `MVN r0, #0xFF, ROR 8`.
### Literal pool
If the requested constant is *not a valid operand* for the `MOV` and `MVN` instructions, then the constant must be stored in a space in the program *after the code* known as a *literal pool*.
The assembly translates the pseudo-instruction to load the constant from memory through *PC-offset addressing*.
>[!Number stored in literal pool]-
>```armasm
>func LDR r1, =0x55555555
> LDR r2, =0xFFFFFFFF
> MOV PC, lr
>
> END
>```
>The above code block is translated to the one below. Note that creation of the literal pool through the use of the [[ARMv4T Assembly#DCD|DCD]] directive and the translation of the lines `LDR r1, =0x55555555` and `LDR r2, =0xFFFFFFFF`.
>
>```armasm
>func LDR r1, [PC, #8]
> MVN r2, #0
> MOV PC, lr
>
> END
>
> literalPool DCD 0x55555555
>```
#### LTORG
Literal pools are accessed by [[ARM Instruction Encoding#Pre-indexed addressing|pre-indexed addressing]] which is limited by an [[ARM Instruction Encoding#Immediate offset|offset]] that is *12-bits* long. In long programs the *default* literal pool may be unreachable.
The `LTORG` directive can be used to build the current literal pool *immediately* at the location of the directive. The assembler replaces the `LTORG` line with the correct `DCD` block.
>[!Untranslated and translated example]-
> ```armasm
> func LDR r1, =0x55555555
> LDR r2, =0xFFFFFFFF
> ADD r0, r0, r2
> MOV PC, lr
> LTORG
> ```
>
> ```armasm
> func LDR r1, =0x55555555
> LDR r2, =0xFFFFFFFF
> ADD r0, r0, r2
> MOV PC, lr
> literalPool DCD 0x55555555
> ```
`LTORG` must be placed where the program will not *automatically enter* by PC stepping. To ensure this `LTORG` directives must be placed either:
- At the end of a *subroutine*; i.e. preceded by `MOV PC lr`.
- After *unconditional branch* instructions.
## Loading addresses
The addresses of labels can be loaded into registers using two methods, depending on the location of the label. These pseudo-instructions removes the requirement of manually tracking label addresses.
### ADR
If the label is *within* the *current section* of code and within *255 words* from the PC, then the address of the label can be loaded with:
```armasm
ADR{cond} <Rd> <label>
```
The assembler automatically calculates the *number of bytes offset* between the label and the PC and translates the instruction into:
```armasm
ADD <Rd>, PC, #<offset>
SUB <Rd>, PC, #<offset>
```
The limitation of range is caused by the 8-bit [[ARM Instruction Encoding#Immediate|immediate operand size]].
>[!Untranslated and translated example]-
> In the following code the two `ADR` lines are translated.
>```armasm
> start BL func
> stop B stop
>
> func ADR r0, start
> ADR r1, data
> ADD r2, r2, r3
> MOV PC, lr
> data SPACE 8000
> END
>```
>
>```armasm
> start BL func
> stop B stop
>
> func SUB r0, PC, #16
> ADD r1, PC, #4
> ADD r2, r2, r3
> MOV PC, lr
> data SPACE 8000
> END
>```
### ADRL
If the label is *within* the *current section* of code but not within *255 words* from the PC, then the address of the label can be loaded with:
```armasm
ADR{cond}L <Rd> <label>
```
`ADRL` behaves like `ADR` except it is translated into *two* `ADD` or `SUB` instructions.
### LDR
If the label is *outside* the *current section* of the code or further than 255 words from the PC, then the address of the label can be loaded with:
```armasm
LDR{cond} <Rd>, =<label>
```