| Immediate Range Limits in VIXL |
| ============================== |
| |
| VIXL's macro assembler tries to increase the range of branches and literal loads |
| automatically for you, but applications must still be aware of these extended |
| limits, and stay within them, in order to ensure valid code is generated. |
| |
| In debug builds, assertions prevent exceeding these limits at run time. In |
| release builds, for performance reasons, the application is responsible for |
| staying within the limits. |
| |
| You should decide what corrections should be applied in your application if it |
| exceeds these limits. |
| |
| Terms |
| ----- |
| |
| **Bind** assigning an address to a label such that the instructions that refer |
| to the label can be assigned PC-relative offsets. |
| |
| **Forward** a forward branch or load literal will refer to a location that will |
| be bound later in code generation, ie. at a higher address. |
| |
| **Backward** a backward branch or load literal refers to a location that has |
| already been bound earlier in code generation, ie. at a lower address. |
| |
| **Instruction range** the range of values that can be encoded in the instruction |
| to be generated. Outside the instruction range, additional instructions may be |
| generated to increase the range, branching further than would be possible in |
| one instruction, for example. |
| |
| **Veneer** a sequence of additional instructions produced to increase the |
| instruction range. |
| |
| **Adjusted PC** the PC including its architecturally-defined offset. In AArch32 |
| T32, this is the current PC plus four bytes. In AArch64, there is no adjustment; |
| Adjusted PC is equal to PC. |
| |
| AArch64 |
| ------- |
| |
| ### Branches |
| |
| All instructions and targets must be aligned to the instruction size, four |
| bytes. |
| |
| #### Unconditional immediate branches (`B`) |
| |
| * Unconditional immediate branches have an instruction range of -134,217,728 to |
| +134,217,724 bytes from the current PC. |
| * No veneers are applied to unconditional immediate branches to extend their |
| instruction range. |
| * Callers can use the function `IsValidImmPCOffset(UncondBranchType, offset)` to |
| check `offset` (in units of instruction) is within the instruction range. |
| |
| #### Conditional branches (`B.cond`) and compare-and-branch (`CBZ`, `CBNZ`) |
| |
| * Conditional branch and compare-and-branch instructions have the same |
| instruction range. |
| * The instruction range is -1,048,576 to +1,048,574 bytes from the current PC. |
| * Veneers are applied to extend the range to -134,217,724 to +135,266,298 bytes |
| from the current PC. |
| * Unconditional branch range minus one instruction backwards. |
| * Unconditional branch range plus conditional branch range forwards. |
| * Callers can use the functions `IsValidImmPCOffset(CondBranchType, offset)` and |
| `IsValidImmPCOffset(CompareBranchType, offset)` to check `offset` (in units of |
| instruction) is within the instruction range. |
| |
| #### Test-and-branch (`TBZ`, `TBNZ`) |
| |
| * Test-and-branch instructions have an instruction range of -32,768 to 32,764 |
| bytes from the current PC. |
| * Veneers are applied to extend the range to -134,217,728 to +135,299,062 bytes |
| from the current PC. |
| * Unconditional branch range minus one instruction backwards. |
| * Unconditional branch range plus test-and-branch range forwards. |
| * Callers can use the function `IsValidImmPCOffset(TestBranchType, offset)` to |
| check `offset` (in units of instruction) is within the instruction range. |
| |
| ### Literals |
| |
| #### Compute PC-relative address (`ADR`) |
| |
| * Compute PC-relative address instructions have an instruction range of |
| -1,048,576 to +1,048,575 bytes from the current PC. |
| * No veneers are applied to extend the instruction range. |
| * Callers can use `IsInt21(offset)` to check `offset` (in bytes) is within the |
| instruction range. |
| |
| #### Load from PC-relative address (`LDR`) |
| |
| * Load from PC-relative address instructions have an instruction range of |
| -1,048,576 to +1,048,572 bytes from the current PC. The offset must be four-byte |
| aligned. |
| * Automatically-placed literals (eg. those created by `Ldr(reg, literal_value)`) |
| will be emitted into code such that they are in range of the instructions that |
| refer to them. |
| * Veneers are not applied to manually-placed literals, ie. those created by |
| `Literal<T> x(value)` and emitted by `place()`. |
| * Callers can use `IsInt19(offset)` to check `offset` (in units of instruction) |
| is within the instruction range. |
| |
| AArch32 |
| ------- |
| |
| Limits stated in this section relate to the T32 instruction encodings only. |
| |
| ### Branches |
| |
| #### Unconditional immediate branches (`B`) |
| |
| * Unconditional immediate branches have an instruction range of -16,777,216 to |
| +16,777,214 bytes from the current adjusted PC. |
| * Veneers are applied to forward branches to extend them to an unlimited range. |
| * No veneers are applied to backward branches. |
| |
| #### Conditional immediate branches (`B`) |
| |
| * Conditional immediate branches have an instruction range of -1,048,576 to |
| +1,048,574 bytes from the current adjusted PC. |
| * Veneers are applied to forward branches to extend them to an unlimited range. |
| * Veneers are applied to backward branches to extend the range to that of |
| unconditional immediate branches, -16,777,216 bytes from the current adjusted |
| PC. |
| |
| #### Compare and branch (`CBZ`, `CBNZ`) |
| |
| * Compare and branch has an instruction range of 0 to +126 bytes from the |
| current adjusted PC. |
| * Veneers are applied to forward branches to extend them to an unlimited range. |
| * Veneers are applied to backward branches to extend the range to that of |
| unconditional immediate branches, -16,777,216 bytes from the current adjusted |
| PC. |
| |
| ### Literals |
| |
| #### Compute/load PC-relative address (`ADR`, `LDR`) |
| |
| * Compute and load PC-relative address instructions have the same instruction |
| range. |
| * The instruction range is -4,095 to +4,095 bytes from the current adjusted PC. |
| The PC is aligned down to a four-byte boundary before the offset is added. |
| * Automatically-placed literals (ie. those created by `Literal<T> x(value)`) |
| will be emitted into code such that they are in range of the instructions that |
| refer to them. |
| * Veneers are not applied to manually-placed literals, ie. those created by |
| `Literal<T> x(value, RawLiteral::kManuallyPlaced)` and emitted by `Place()`. |
| |