SoC
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
  • Arm Cortex M3
  • Contact
Reading: Accessing Constants and Immediate Values in ARM Instructions (Cortex M)
SUBSCRIBE
SoCSoC
Font ResizerAa
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Search
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Have an existing account? Sign In
Follow US
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
© S-O-C.ORG, All Rights Reserved.
Arm

Accessing Constants and Immediate Values in ARM Instructions (Cortex M)

Elijah Erickson
Last updated: October 5, 2023 9:38 am
Elijah Erickson 7 Min Read
Share
SHARE

ARM Cortex M processors provide several ways to access constant and immediate values directly within instructions. This allows efficient access to data without having to load values from memory. The main methods are: 1) Immediate values encoded directly in instruction opcodes, 2) PC-relative addressing to access constants in literal pools, 3) Load multiple registers using stacked PC-relative literals.

Contents
1. Immediate Values Encoded in InstructionsAdvantagesDisadvantages2. PC-Relative Addressing Into Literal PoolsAdvantagesDisadvantages3. Load Multiple Registers Using Stacked PC-Relative LiteralsAdvantagesDisadvantagesAccessing String ConstantsLoad Addresses Into Inline ConstantsPosition Independence and ADRLoad 32-bit Values EfficientlyUse MOVW/MOVT for Large Inline ConstantsSummaryExample Code SnippetsConclusion

1. Immediate Values Encoded in Instructions

Many ARM instructions allow small immediate values to be directly encoded within the instruction opcode. For example: ADD R1, R2, #10 ; Add immediate value 10 to R2 and store in R1 SUB R3, R4, #100 ; Subtract 100 from R4 and store in R3

Here the immediate values 10 and 100 are directly stored within the encoded instruction. The allowed range of immediate values depends on the particular instruction. Typical ranges are 8-bit (0-255) or 12-bit (0-4095) unsigned integers. Signed integers are also supported in various ranges such as 8-bit (-128 to 127) or 5-bit (-16 to 15). Bitwise logic instructions support wider immediate values with bit masks.

Advantages

  • Faster and smaller code vs loading from memory
  • Allow simple constants for math, addresses, bit masks, etc

Disadvantages

  • Limited range – can’t store 32-bit constants
  • Constant takes space in instruction stream

2. PC-Relative Addressing Into Literal Pools

To access larger constants and addresses, ARM Cortex M processors provide PC-relative addressing into literal pools located in the instruction stream. This allows 32-bit values to be accessed using a pc-relative load instruction like LDR. LDR R1, =0x12345678 ; Load R1 from literal pool with 32-bit value LDR R2, =AddressVal ; Load R2 with address from literal pool

The literal pools are placed by the assembler/linker in the instruction stream alongside the code. The processor calculates the address as the PC value plus a byte offset encoded in the LDR instruction. This allows position-independent code access to constants.

Advantages

  • 32-bit values supported
  • Position independent code
  • Constants don’t take space in instructions

Disadvantages

  • Requires literal pool lookup
  • Range limited to 1MB from PC value

3. Load Multiple Registers Using Stacked PC-Relative Literals

The LDM instruction can load multiple registers using stacked PC-relative literals. For example: LDM R0, {R1-R5} ; Load R1-R5 from stacked literals

R0 is used as a dummy base register. The values for R1-R5 are loaded from a table of PC-relative literals assembled into the instruction stream. This provides an efficient way to initialize multiple registers to constants.

Advantages

  • Initialize multiple registers
  • Position independent code
  • Save instruction space vs individual LDRs

Disadvantages

  • Fixed at load time, can’t index
  • Requires literal pool lookup

Accessing String Constants

String constants can be accessed using PC-relative loads one character at a time. For example: LDR R0, =MyString ; R0 loaded with address of string LDRB R1, [R0,#0] ; Load byte 0 of string into R1 LDRB R2, [R0,#1] ; Load byte 1 of string into R2

R0 is first loaded with the address of the string constant. Then LDRB instructions are used to load individual bytes into registers. This allows efficient access to string constants without requiring the string data to be copied into RAM.

Load Addresses Into Inline Constants

The LDR instruction can be used to load an address into a register and add an immediate offset to compute an inline constant. For example: LDR R1, =0x20000000 LDR R2, [R1, #16] ; Loads 0x200000010 into R2

Here R1 is loaded with base address 0x20000000. Then LDR uses that base and adds an offset of 16 to compute address 0x200000010. This is useful for accessing constants spread out at fixed offsets from a base.

Position Independence and ADR

When loading addresses using PC-relative literals, positioning independence must be considered. If code is relocated, literal pool addresses may change. The ADR assembler directive can be used to ensure position independence: ADR R0, MyData ; R0 loaded with PC-relative offset LDR R1, [R0,#0] ; Load using offset in R0

ADR computes the PC-relative offset to MyData and stores it in R0. This offset will remain constant if code moves. LDR uses offset indirection to access the data.

Load 32-bit Values Efficiently

For 32-bit values, use LDR over LDRB to avoid stalling the pipeline. LDR loads the full 32-bits efficiently in one instruction vs four LDRB instructions.

Use MOVW/MOVT for Large Inline Constants

For very large inline constants, the MOVW and MOVT instructions can embed a 32-bit value directly in the instruction stream spread across two instructions. For example: MOVW R1, #0x1234 MOVT R1, #0x5678 ; R1 loaded with 0x12345678

This avoids the need for a PC-relative literal pool lookup.

Summary

  • Use immediate values for small 8-12 bit constants
  • Use PC-relative literals for 32-bit values and addresses
  • LDM initializes multiple registers efficiently
  • Access string constants directly from literal pool
  • Use ADR for position independence
  • Prefer LDR over LDRB for 32-bit values
  • MOVW/MOVT embed large 32-bit constants

By utilizing these techniques, ARM Cortex M code can access constants and immediate values directly and efficiently without requiring runtime lookups. This improves performance and reduces memory usage.

Example Code Snippets

Here are some example code snippets demonstrating constant access methods: // Small immediate value ADD R1, R2, #100 // 32-bit value loaded via PC-relative LDR LDR R1, =0x10000000 // String constant LDR R0, =MyString LDRB R1, [R0,#0] // ADR for position independence ADR R0, MyData LDR R1, [R0,#0] // MOV/MOVT large embedded constant MOVW R1, #0x1234 MOVT R1, #0x5678 // Load multiple registers via literal stack LDM R0, {R1-R5} // Compute inline constant via load offset LDR R1, =0x20000000 LDR R2, [R1,#16]

Conclusion

ARM Cortex M provides flexible options for embedding and accessing constants and immediate values directly within code. By understanding the range, performance and position independence of each method, developers can optimize code for size, speed and simplicity. Proper utilization of these techniques is key to enabling efficient firmware on ARM Cortex M cores.

Newsletter Form (#3)

More ARM insights right in your inbox

 


Share This Article
Facebook Twitter Email Copy Link Print
Previous Article Instruction and Data Caches in ARM Cortex-M (Explained)
Next Article Code vs Data Memory Partitioning in Microcontrollers
Leave a comment Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

2k Followers Like
3k Followers Follow
10.1k Followers Pin
- Sponsored-
Ad image

You Might Also Like

Basepri Example

The BASEPRI register is one of the system control registers…

10 Min Read

Relocate the Vector Table in Cortex-M0

The vector table is a key component in Cortex-M0 microcontrollers…

9 Min Read

Reset Vector Configuration for External Flash with Cortex-M1

When using an external flash memory with a Cortex-M1 microcontroller,…

9 Min Read

Alignment Requirements for Data Types on ARM Cortex M3

When working with the ARM Cortex M3 processor, properly aligning…

6 Min Read
SoCSoC
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
Welcome Back!

Sign in to your account