msr
Move to Special Register (Banked)
MSR <banked_reg>, <Rn>
Writes to a banked register from a general-purpose register.
Details
Writes the value of a general-purpose register to a banked system register. This instruction is available only in privileged modes (not User mode) and performs a mode-aware write to the specified banked register. No condition flags are affected by this instruction.
Pseudocode Operation
BankedReg[sysm] ← Rn
Example
MSR banked_reg, r1
Encoding
Binary Layout
cond
00010
R
1
0
M1
1111
0
0
1
M
0000
Rn
Operands
-
banked_reg
Banked -
Rn
First source / base general-purpose register
Reference (Arm AArch32 ISA)
Instruction Forms
| Encoding | Instruction | ISA | Bit pattern | ||
|---|---|---|---|---|---|
| 0x0120F200 | MSR{<c>}{<q>} <banked_reg>, <Rn> | A32 | cond | 00010 | R | 1 | 0 | M1 | 1111 | 0 | 0 | 1 | M | 0000 | Rn | ||
| 0xF3808020 | MSR{<c>}{<q>} <banked_reg>, <Rn> | T32 | 11110011100 | R | Rn | 10 | 0 | 0 | M1 | 0 | 0 | 1 | M | 0 | 0 | 0 | 0 | ||
| 0x0320F000 | MSR{<c>}{<q>} <spec_reg>, #<imm> | A32 | cond | 00110 | R | 10 | mask | 1 | 1 | 1 | 1 | imm12 | ||
| 0x0120F000 | MSR{<c>}{<q>} <spec_reg>, <Rn> | A32 | cond | 00010 | R | 1 | 0 | mask | 1111 | 0 | 0 | 0 | 0 | 0000 | Rn | ||
| 0xF3808000 | MSR{<c>}{<q>} <spec_reg>, <Rn> | T32 | 11110011100 | R | Rn | 10 | 0 | 0 | mask | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Description
Move to Banked or Special register from general-purpose register moves the value of a general-purpose register to the Banked general-purpose register or Saved Program Status Registers (SPSRs) of the specified mode, or to ELR_hyp.
MSR (Banked register) is unpredictable if executed in User mode.
When EL3 is using AArch64, if an MSR (Banked register) instruction that is executed in a Secure EL1 mode would access SPSR_mon, SP_mon, or LR_mon, it is trapped to EL3.
The effect of using an MSR (Banked register) instruction with a register argument that is not valid for the current mode is unpredictable. For more information see Usage restrictions on the Banked register transfer instructions.
Operation
if ConditionPassed() then
EncodingSpecificOperations();
if PSTATE.EL == EL0 then
UNPREDICTABLE;
else
mode = PSTATE.M;
if write_spsr then
SPSRaccessValid(SYSm, mode); // Check for UNPREDICTABLE cases
case SYSm of
when '01110' SPSR_fiq<31:0> = R[n];
when '10000' SPSR_irq<31:0> = R[n];
when '10010' SPSR_svc<31:0> = R[n];
when '10100' SPSR_abt<31:0> = R[n];
when '10110' SPSR_und<31:0> = R[n];
when '11100'
if !ELUsingAArch32(EL3) then AArch64.MonitorModeTrap();
SPSR_mon<31:0> = R[n];
when '11110' SPSR_hyp<31:0> = R[n];
else
integer m;
BankedRegisterAccessValid(SYSm, mode); // Check for UNPREDICTABLE cases
case SYSm of
when '00xxx' // Access the User mode registers
m = UInt(SYSm<2:0>) + 8;
Rmode[m,M32_User] = R[n];
when '01xxx' // Access the FIQ mode registers
m = UInt(SYSm<2:0>) + 8;
Rmode[m,M32_FIQ] = R[n];
when '1000x' // Access the IRQ mode registers
m = 14 - UInt(SYSm<0>); // LR when SYSm<0> == 0, otherwise SP
Rmode[m,M32_IRQ] = R[n];
when '1001x' // Access the Supervisor mode registers
m = 14 - UInt(SYSm<0>); // LR when SYSm<0> == 0, otherwise SP
Rmode[m,M32_Svc] = R[n];
when '1010x' // Access the Abort mode registers
m = 14 - UInt(SYSm<0>); // LR when SYSm<0> == 0, otherwise SP
Rmode[m,M32_Abort] = R[n];
when '1011x' // Access the Undefined mode registers
m = 14 - UInt(SYSm<0>); // LR when SYSm<0> == 0, otherwise SP
Rmode[m,M32_Undef] = R[n];
when '1110x' // Access Monitor registers
if !ELUsingAArch32(EL3) then AArch64.MonitorModeTrap();
m = 14 - UInt(SYSm<0>); // LR when SYSm<0> == 0, otherwise SP
Rmode[m,M32_Monitor] = R[n];
when '11110' // Access ELR_hyp register
ELR_hyp = R[n];
when '11111' // Access SP_hyp register
Rmode[13,M32_Hyp] = R[n];