SoC
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
  • Arm Cortex M3
  • Contact
Reading: Accessing the ARM Application Program Status Register
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 the ARM Application Program Status Register

Andrew Irwin
Last updated: September 28, 2023 12:46 pm
Andrew Irwin 13 Min Read
Share
SHARE

The Application Program Status Register (APSR) is one of the key registers in the ARM Cortex series of processors. It contains important status and control information related to the execution state of an application program. Directly accessing the APSR can provide valuable insights into the current state of the processor and allow modifying certain control bits to influence application behavior. This article will provide a comprehensive guide on how to access the APSR register on ARM Cortex devices.

Contents
Overview of the APSR RegisterReading the APSR ValueUsing LDR InstructionsUsing MRS InstructionsWriting to the APSR RegisterPreserving APSR Flag SettingsUse Cases for Direct APSR AccessConditional Code ExecutionDisabling InterruptsSaturation ArithmeticDebuggingAPSR Usage GuidelinesDifferences Between Cortex-M and Cortex-AInteractions with EXC_RETURNAccessing APSR in Thumb vs ARM ModeInteraction with Execution PriorityAccessing APSR in Privileged vs Unprivileged CodeUsing APSR SafelyConclusion

Overview of the APSR Register

The APSR is a 32-bit read/write register which contains the current state of the condition flags, the interrupt disable bit, and the Q flag for saturation arithmetic. It is accessible in all modes – user, FIQ, IRQ, supervisor, abort, undefined and system. The register can be broken down into the following bit fields:

  • Bits 31-28: Negative/Less than/Zero/Overflow flags
  • Bit 27: Q flag for saturation arithmetic
  • Bit 9: Interrupt disable bit
  • Bits 8-0: Reserved

The N, Z, C, and V bits (bits 31 to 28) hold the state of the condition flags which are used for conditional execution in ARM code. These get updated automatically based on the results of data processing instructions. The Q flag (bit 27) indicates saturation on overflow during signed arithmetic. The I bit (bit 9) can be used to disable IRQ interrupts when set to 1. The remaining bits are unused and reserved for future expansion.

Reading the APSR Value

There are two ways to read the current value in the APSR register – directly accessing the register using LDR instructions or transferring a copy of it to a general purpose register using MRS instructions.

Using LDR Instructions

Any word aligned LDR instruction can directly access the APSR as it is memory mapped to the coprocessor space. For example: LDR R0, =CPSR @ Load APSR into R0 LDR R1, [CPSR] @ Load APSR into R1

Here the CPSR label points to the memory address of the APSR register. So the LDR instruction loads the value from that memory location into the destination register R0 or R1. This allows you to read the APSR in a single instruction.

Using MRS Instructions

The Move to Register from Special register (MRS) instruction can be used to transfer a copy of the APSR contents to a general purpose register. The syntax for MRS is: MRS Rd, APSR

For example: MRS R2, APSR @ Copy APSR to R2

The MRS instruction copies the value in APSR to register R2. While MRS requires 2 instructions – one to do the transfer and one to use the transferred contents, it has the benefit of not directly accessing memory. The LDR method reads the actual APSR location whereas MRS just gets a snapshot copy of it.

Writing to the APSR Register

Updates to the APSR register are possible using the MSR (Move to Special Register) instruction. Using MSR you can directly modify the N, Z, C, V flags to values of your choosing. However, writing to the APSR does come with some caveats:

  • You can only modify the condition flags (bits 31 to 28)
  • Modifying the flags does not actually update processor state
  • Changing I bit state using MSR is deprecated

Let’s look at some examples of using MSR to write to APSR: MSR APSR_nzcvq, R5 @ Set flags using R5 MSR APSR_nzcvq, #0xF0000000 @ Set flags directly

Here APSR_nzcvq specifies that we want to modify only the condition flags portion of APSR. In the first example, the value in R5 is used to update the flags. In the 2nd example, an immediate value sets the flags to known values.

Important: Though MSR allows you to directly configure the flags, this won’t actually update the processor state. The flags will be overwritten by the next instruction that does a comparison or arithmetic operation. To preserve custom flag settings, you have to prevent any updating of flags in subsequent instructions.

Preserving APSR Flag Settings

As noted earlier, directly modifying the APSR condition flags using MSR does not actually update ARM processor state. So how do you keep the custom flag settings from getting overwritten? One method is to avoid flag-setting instructions immediately after MSR. For example: MSR APSR_nzcvq, R5 @ Set custom flags AND R2, R3, #1 @ Bitwise AND – does not affect flags LSL R1, R2, #3 @ Logical shift – does not affect flags

The AND and LSL instructions here do not update flags, so the changes made by MSR are preserved. An easier method is to make use of the IT instruction which can conditionally disable flag updates: MSR APSR_nzcvq, R5 @ Set custom flags IT NE @ Next 2 instructions do not update flags AND R2, R3, #1 LSL R1, R2, #3

The IT NE instruction disables flag updates for the next two instructions inside the IT block. This causes the AND and LSL to not modify flags, preserving our custom APSR values.

Use Cases for Direct APSR Access

Why would you want to directly access and modify the APSR contents? Here are some example use cases:

Conditional Code Execution

By setting the condition flags in APSR, you can force conditional code to execute on the opposite condition. For example: MSR APSR_nzcvq, #0xF0000000 @ Set N,C,V flags = 1 BEQ label @ Will branch now

Even though the BEQ checks for Z=1, we force it to branch by setting N,C,V = 1 via MSR.

Disabling Interrupts

Setting the I bit in APSR will disable IRQ interrupts. This can be done via: MRS R1, APSR @ Read APSR ORR R1, #0x200 @ Set I bit MSR APSR_nzcvq, R1 @ Write back

However, as noted earlier, directly changing the I bit via MSR is deprecated on Cortex-M devices. The recommended method is to use the PRIMASK register instead for interrupts.

Saturation Arithmetic

The Q flag in APSR can be checked after arithmetic to determine if saturation happened. This is useful when doing fixed point math. SMLAWB R1, R2, R3, R4 @ Signed multiply accumulate MRS R5, APSR @ Check Q flag TST R5, #0x08000000 BEQ no_saturation @ Branch if no saturation

Debugging

Accessing APSR during debugging can help view the current processor state. The flags provide an indication of previous comparison results. Examining APSR when a crash occurs gives insight into the cause.

APSR Usage Guidelines

While APSR provides useful status and control functionality, direct access should be used carefully. Keep the following guidelines in mind:

  • Avoid direct APSR access in interrupt handlers
  • Minimize read-modify-write sequences to APSR
  • Use MRS/MSR for readability even if LDR is faster
  • Ensure MSR of flags is followed by non flag-setting instructions
  • Preference PRIMASK over I bit for interrupt disable
  • Check Q flag for saturation arithmetic if required

Differences Between Cortex-M and Cortex-A

The Cortex-M and Cortex-A series of ARM processors have some differences when accessing APSR:

  • Cortex-M – APSR always accessible in handler mode
  • Cortex-A – APSR access limited to specific modes
  • Cortex-M – MSR to I bit deprecated, use PRIMASK instead
  • Cortex-A – Can disable IRQ via MSR to I bit
  • Cortex-M – LDR of APSR does an actual memory read
  • Cortex-A – LDR of APSR just returns the current value

So code that accesses APSR directly may need to be adjusted when porting between the two architecture families.

Interactions with EXC_RETURN

The EXC_RETURN register holds info about the stack frame when exception handlers are invoked. The lowest 4 bits of EXC_RETURN mirror the condition flags: EXC_RETURN[3:0] = APSR[31:28]

This means when modifying APSR flags, the lower 4 bits of EXC_RETURN also get updated. The reverse applies too – changing the low nybble of EXC_RETURN results in the flags being updated.

Accessing APSR in Thumb vs ARM Mode

In Thumb mode, the APSR is accessible via the special register number 0x400F. In ARM mode, it uses the specific register name CPSR instead. For example: Thumb mode: MRS R1, APSR MSR APSR_nzcvq, R2 ARM Mode: MRS R1, CPSR MSR CPSR_f, R2

So code accessing APSR directly needs to be aware of the instruction set state.

Interaction with Execution Priority

The ARM architecture has finely grained control over execution priority using registers like BASEPRI, FAULTMASK and PRIMASK. These work together with APSR’s I bit to allow priority-based preemption of exceptions and interrupts. Setting BASEPRI prevents low priority exceptions from interrupting the current execution context. FAULTMASK prevents faults from escalating to hard faults in certain cases. PRIMASK disables all exceptions below a certain priority level. These registers work with the I bit to provide flexible prioritized interruption control.

Accessing APSR in Privileged vs Unprivileged Code

The APSR can be accessed freely in privileged code without restrictions. But in unprivileged user mode, there are some limitations imposed by the architecture:

  • MRS can only transfer APSR_nzcvq (just the condition flags)
  • MSR can only write to APSR_nzcvq
  • Direct LDR/STR access to APSR is prohibited

So unprivileged code cannot read/write the full APSR value or the interrupt disable bit. This prevents user applications from arbitrarily modifying the processor state.

Using APSR Safely

Directly accessing APSR can be useful but also dangerous if done carelessly. Some tips for using APSR safely:

  • Avoid APSR manipulation in interrupt handlers
  • Keep read-modify-write of APSR to a minimum
  • Do not overwrite I bit, use PRIMASK register instead
  • Ensure exception return behavior is understood if changing flags
  • Prevent conditional execution from straying far on false condition
  • Restrict APSR access in unprivileged code as per architecture

With careful usage, the APSR can provide helpful insight into processor execution state and greater control over program flow.

Conclusion

The Application Program Status Register in ARM Cortex processors packs useful status and control bits related to the current execution context. Understanding how to properly read, modify and utilize the APSR can help developers optimize program behavior. This guide covered the key methods for accessing APSR – using LDR for direct reads, MRS/MSR for transfers and the intricacies around changing the condition flags and interrupt disable bits. With the power of APSR access comes great responsibility, so adhere to the architectural guidelines and use it judiciously. Refer to this article whenever you need deeper insight or more control around your Cortex-M application via the APSR.

Newsletter Form (#3)

More ARM insights right in your inbox

 


Share This Article
Facebook Twitter Email Copy Link Print
Previous Article What are the the Application Program Status Register (APSR) in Arm Cortex-M
Next Article Processor Modes and Mode Control in the ARM CPSR
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

What is watchdog in PLC?

A watchdog timer (sometimes called a watchdog or just watchdog)…

9 Min Read

cortex-m33 vs m4

The Cortex-M33 and Cortex-M4 are both ARM processor cores designed…

6 Min Read

How generic are Cortex-M0+ MCUs?

Cortex-M0+ microcontrollers (MCUs) from ARM offer a good balance of…

6 Min Read

What is the reset vector address of ARM Cortex-M0?

The reset vector address of ARM Cortex-M0 is 0x00000000. This…

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

Sign in to your account