|  | 
 
| 5.6  程序状态寄存器指令 
 ARM指令集提供了两条指令,可直接控制程序状态寄存器(PSR,Program State Register)。MRS指令用于把CPSR或SPSR的值传送到一个寄存器;MSR与之相反,把一个寄存器的内容传送到CPSR或SPSR。这两条指令结合,可用于对CPSR和SPSR进行读/写操作。
 
 交换指令如表5.5所示。
 表5.5      程序状态寄存器指令
 
 | 指    令 
 | 作    用 
 | 操    作 
 |  | MRS 
 | 把程序状态寄存器的值送到一个通用寄存器 
 | Rd=SPR 
 |  | MSR 
 | 把通用寄存器的值送到程序状态寄存器或把一个立即数送到程序状态字 
 | PSR[field]=Rm或PSR[field]=immediate 
 | 
 在指令语法中可看到一个称为fields的项,它可以是控制(C)、扩展(X)、状态(S)及标志(F)的组合。
 
 
 |   
 | 注意 
 | 程序不能通过直接修改CPSR中的T位控制直接将程序状态切换到Thumb状态,必须通过BX等指令完成程序状态的切换。 
 | 
 
 5.6.1  MRS
 
 (1)指令编码格式
 MRS指令用于将程序状态寄存器的内容传送到通用寄存器中。
 
 指令的编码格式如图5.22所示。
 
 
         图5.22  MRS指令编码格式 
 当数据被移到通用寄存器以后,就可以对数据进行处理。
 
 (2)指令的语法格式
 
 MRS{<cond>}  <Rd>,CPSR
 MRS{<cond>}  <Rd>,SPSR
 
 ① <cond>
 为指令编码中的条件域。它指示LDM(1)指令在什么条件下执行。当<cond>忽略时,指令为无条件执行(cond=AL(Alway))。
 
 ② <Rd>
 目标寄存器。当r15被用作目标寄存器时,指令执行结果不可预知。
 
 (3)指令操作的伪代码
 指令操作伪代码如下面程序段所示。
 
 If  ConditionPassed{cond}  then
 If  R==1  then
 Rd=SPSR
 ELSE
 Rd=CPSR
 
 
 | ![]() 
 | 注意 
 | ① 当操作码opcode[11∶0]≠0x000时,指令的执行结果不可预知。 ② 当操作码opcode[19∶16]≠0b1111时,指令的执行结果不可预知。
 ③ 当在用户模式下对SPSR进行操作时,指令的执行结果不可预知。
 
 | 
 
 5.6.2  MSR
 
 (1)指令编码格式
 MSR指令用于将通用寄存器中的内容或立即数传送到程序状态寄存器中。因此指令的编码格式也有两种格式。
 
 指令的源操作数为通用寄存器时编码格式如图5.23所示。
 
 
         图5.23  源操作数为通用寄存器的MSR指令编码 
 指令的源操作数为立即数时编码格式如图5.24所示。
 
 
         图5.24  源操作数为立即数的MSR指令编码 
 (2)指令的语法格式
 
 MSR{<cond>}  CPSR_<fields>,#<immediate>
 MSR{<cond>}  CPSR_<fields>,#<Rm>
 MSR{<cond>}  SPSR_<fields>,#<immediate>
 MSR{<cond>}  SPSR_<fields>,#<Rm>
 
 ① <cond>
 为指令编码中的条件域。它指示LDM(1)指令在什么条件下执行。当<cond>忽略时,指令为无条件执行(cond=AL(Alway))。
 
 ② <fields>
 设置状态寄存器中需要操作的位。状态寄存器的32位可以分为4个8位的域(field)。
 ·  bits[31∶24]为条件标志位域,用f表示。
 ·  bits[23∶16]状态位域,用s表示。
 ·  bits[15∶8]扩展位域,用x表示。
 ·  bits[7∶0]控制位域,用c表示。
 
 ③ < immediate >
 表示将要传送到状态寄存器中的立即数。
 
 (3)指令操作的伪代码
 指令操作伪代码如下面程序段所示。
 
 If  ConditionPassed{cond}  then
 If  opcode[25]==1
 Operand=8_bit_immediate  Rotate_Right {rotate_imm*2}
 Else  /*opcode[25]==0*/
 Operand=Rm
 If  R==0  then
 If  field_mask[0]==1  and  InAPrivilegedMode()  then
 CPSR[7:0]=operand[7:0]
 If  field_mask[1]==1  and  InAPrivilegedMode()  then
 CPSR[15:8]=operand[15:8]
 If  field_mask[2]==1  and  InAPrivilegedMode()  then
 CPSR[23:16]=operand[23:16]
 If  field_mask[2]==1  then
 CPSR[31:24]=operand[31:24]
 Else  /*R==1*/
 If  field_mask[0]==1  and  InAPrivilegedMode()  then
 SPSR[7:0]=operand[7:0]
 If  field_mask[1]==1  and  InAPrivilegedMode()  then
 SPSR[15:8]=operand[15:8]
 If  field_mask[2]==1  and  InAPrivilegedMode()  then
 SPSR[23:16]=operand[23:16]
 If  field_mask[2]==1  then
 SPSR[31:24]=operand[31:24]
 
 5.6.3  程序状态寄存器指令应用
 
 在ARM处理器中,只有MRS指令可以将状态寄存器CPSR或SPSR读出到通用寄存器中。指令格式如下:
 
 MRS{cond}  Rd,PSR
 
 其中,Rd为目标寄存器,Rd不允许为程序计数器PC。PSR为CPSR或SPSR。
 MRS指令举例如下。
 
 MRS  r1,CPSR ;将CPSR状态寄存器读取,保存到r1中
 MRS  r2,SPSR ;将SPSR状态寄存器读取,保存到r1中
 
 MRS指令读取CPSR,可用来判断ALU的状态标志以及IRQ/FIQ中断是否允许等;在异常处理程序中,读SPSR可指定进入异常前的处理器状态等。MRS与MSR配合使用,实现CPSR或SPSR寄存器的读-修改-写操作,可用来进行处理器模式切换,允许/禁止IRQ/FIQ中断等设置。另外,进程切换或允许异常中断嵌套时,也需要使用MRS指令读取SPSR状态值并保存起来。
 
 【例5.7】使能IRQ中断
 
 ENABLE_IRQ
 MRS    r0,CPSR
 BIC     r0,r0,#0x80
 MSR    CPSR_c,r0
 MOV    PC,LR
 
 【例5.8】禁止IRQ中断
 
 DISABLE_IRQ
 MRS   r0,CPSR
 ORR   r0,r0,#0x80
 MSR   CPSR_c,r0
 MOV   PC,LR
 
 在ARM处理器中,只有MSR指令可以直接设置状态寄存器CPSR或SPSR。指令格式如下。
 
 MSR{cond}  PSR_field,#immed_8r
 MSR{cond}  PSR_field,Rm
 
 其中,PSR是指CPSR或SPSR。<fields>设置状态寄存器中需要操作的位。状态寄存器的32位可以分为4个8位的域(field)。bits[31:24]为条件标志位域,用f表示;bits[23:16]为状态位域,用s表示;bits[15:8]为扩展位域,用x表示;bits[7:0]为控制位域,用c表示;immed_8r为要传送到状态寄存器指定域的立即数,8位;Rm为要传送到状态寄存器指定域的数据源寄存器。
 MSR指令举例如下。
 
 MSR  CPSR_c,#0xD3            ;CPSR[7:0]=0xD3,切换到管理模式
 MSR  CPSR_cxsf,r3             ;CPSR=R3
 
 只有在特权模式下才能修改状态寄存器。
 程序中不能通过MSR指令直接修改CPSR中T位控制位来实现ARM状态/Thumb状态的切换,必须使用BX指令来完成处理器状态的切换(因为BX指令属转移指令,它会打断流水线状态,实现处理器状态的切换)。MRS与MSR配合使用,实现CPSR或SPSR寄存器的读-修改-写操作,可用来进行处理器模式切换以及允许/禁止IRQ/FIQ中断等设置。
 
 【例5.9】堆栈指令初始化
 
 INITSTACK
 MOV   r0,LR               ;保存返回地址
 ;设置管理模式堆栈
 MSR   CPSR_c,#0xD3
 LDR   SP,StackSvc
 ;设置中断模式堆栈
 MSR   CPSR_c,#0xD2
 LDR   SP,StackSvc
 | 
 |