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
 
Format System
Opcode 0x0120F200
Extension A32 (System)

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];