欢迎光临散文网 会员登陆 & 注册

ARM裸机开发篇2:ARM微处理器指令系统(二)

2021-10-25 11:17 作者:华清远见研发中心  | 我要投稿

状态操作指令

ARM指令集提供了两条指令,可直接控制程序状态寄存器(Program State Register,PSR)。MRS指令用于把CPSR或SPSR的值传送到一个寄存器;MSR与之相反,把一个寄存器的内容传送到CPSR或SPSR。这两条指令相结合,可用于对CPSR和SPSR进行读/写操作。程序状态寄存器指令如表所示。


指 令作 用操 作MRS把程序状态寄存器的值送到一个通用寄存器Rd=SPRMSR把通用寄存器的值送到程序状态寄存器或把一个立即数送到程序状态字PSR[field]=Rm或PSR[field]=immediate

在指令语法中可看到一个称为fields的项,它可以是控制(C)、扩展(X)、状态(S)及标志(F)的组合。

  1. MRS

MRS指令用于将程序状态寄存器的内容传送到通用寄存器中。

在ARM处理器中,只有MRS指令可以将状态寄存器CPSR或SPSR读出到通用寄存器中。

    1. 指令的语法格式:




    MRS{cond} Rd,PSR

    其中,Rd为目标寄存器,Rd不允许为程序计数器(PC)。PSR为CPSR或SPSR。

      1. 指令举例:




      MRS R1,CPSR ;将CPSR状态寄存器读取,保存到R1中

      MRS R2,SPSR ;将SPSR状态寄存器读取,保存到R1中

      MRS指令读取CPSR,可用来判断ALU的状态标志及IRQ/FIQ中断是否允许等;在异常处理程序中,读SPSR可指定进入异常前的处理器状态等。MRS与MSR配合使用,实现CPSR或SPSR寄存器的读—修改—写操作,可用来进行处理器模式切换,允许/禁止IRQ/FIQ中断等设置。另外,进程切换或允许异常中断嵌套时,也需要使用MRS指令读取SPSR状态值并保存起来。

      1. MSR

      在ARM处理器中,只有MSR指令可以直接设置状态寄存器CPSR或SPSR。

        1. 指令的语法格式:




        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为要传送到状态寄存器指定域的数据源寄存器。

          1. 指令举例:




          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中断等设置。

          1. 程序状态寄存器指令的应用

          【举例】 使能IRQ中断。

          ENABLE_IRQ:

          MRS R0,CPSR

          BIC R0,R0,#0x80

          MSR CPSR_c,R0

          MOV PC,LR

          【举例】 禁止IRQ中断。

          DISABLE_IRQ:

          MRS R0,CPSR

          ORR R0,R0,#0x80

          MSR CPSR_c,R0

          MOV PC,LR

          【举例】 堆栈指令初始化。

          INITSTACK:

          MOV R0,LR ;保存返回地址

          设置管理模式堆栈:

          MSR CPSR_c,#0xD3

          LDR SP,StackSvc

          设置中断模式堆栈:

          MSR CPSR_c,#0xD2

          LDR SP,StackSvc

          协处理器指令

          ARM体系结构允许通过增加协处理器来扩展指令集。最常用的协处理器是用于控制片上功能的系统协处理器。例如,控制Cache和存储管理单元的cp15寄存器。此外,还有用于浮点运算的浮点ARM协处理器,各生产商还可以根据需要开发自己的专用协处理器。

          ARM协处理器具有自己专用的寄存器组,它们的状态由控制ARM状态的指令的镜像指令来控制。程序的控制流指令由ARM处理器来处理,所有协处理器指令只能同数据处理和数据传送有关。按照RISC的Load/Store体系原则,数据的处理和传送指令是被清楚分开的,所以它们有不同的指令格式。ARM处理器支持16个协处理器,在程序执行过程中,每个协处理器忽略ARM和其他协处理器指令。当一个协处理器硬件不能执行属于它的协处理器指令时,将产生一个未定义指令异常中断,在该异常中断处理过程中,可以通过软件仿真该硬件操作。如果一个系统中不包含向量浮点运算器,则可以选择浮点运算软件包来支持向量浮点运算。

          ARM协处理器可以部分地执行一条指令,然后产生中断。如除法运算除数为0和溢出,这样可以更好地处理运行时产生(run-time-generated)的异常。但是,指令的部分执行是由协处理器完成的,此过程对ARM来说是透明的。当ARM处理器重新获得执行时,它将从产生异常的指令处开始执行。对某一个协处理器来说,并不一定用到协处理器指令中的所有的域。具体协处理器如何定义和操作完全由协处理器的制造商自己决定,因此,ARM协处理器指令中的协处理器寄存器的标识符及操作助记符也有各种不同的实现定义。程序员可以通过宏定义这些指令的语法格式。

          ARM协处理器指令可分为以下3类。

            1. 协处理器数据操作。协处理器数据操作完全是协处理器内部操作,它完成协处理器寄存器的状态改变。如浮点加运算,在浮点协处理器中两个寄存器相加,结果放在第3个寄存器中。这类指令包括CDP指令。

            2. 协处理器数据传送指令。这类指令从寄存器读取数据装入协处理器寄存器,或将协处理器寄存器的数据装入存储器。因为协处理器可以支持自己的数据类型,所以每个寄存器传送的字数与协处理器有关。ARM处理器产生存储器地址,但传送的字节由协处理器控制。这类指令包括LDC指令和STC指令。

            3. 协处理器寄存器传送指令。在某些情况下,需要ARM处理器和协处理器之间传送数据。如一个浮点运算协处理器,FIX指令从协处理器寄存器取得浮点数据,将它转换为整数,并将整数传送到ARM寄存器中。经常需要用浮点比较产生的结果来影响控制流,因此,比较结果必须传送到ARM的CPSR中。这类协处理器寄存器传送指令包括MCR和MRC。




            如表所示列出了所有协处理器处理指令。

            助 记 符操 作CDP协处理器数据操作LDC装载协处理器寄存器MCR从ARM寄存器传数据到协处理器寄存器MRC从协处理器寄存器传数据到ARM寄存器STC存储协处理器寄存器

            下面简单介绍一下比较常用的MCR及MRC命令的用法:

            1. ARM寄存器到协处理器寄存器的数据传送指令MCR

            2. 指令编码格式

            ARM寄存器到协处理器寄存器的数据传送指令MCR(Move to Coprocessor from ARM Register)将ARM寄存器<Rd> 的值传送到协处理器寄存器cp_num中。如果没有协处理器执行指定操作,将产生未定义指令异常。指令的编码格式如图所示。


            1. 指令的语法格式

            MCR{<cond>} <coproc>,<opcode_1>,<Rd>,<CRn>,<CRm> {<opcode_2>}

            ① <cond>

            为指令编码中的条件域。它指示指令在什么条件下执行。当<cond>忽略时,指令为无条件执行(cond=AL(Alway ))。

            ② <coproc>

            指定协处理器的编号,标准的协处理器的名字为p0、p1、…、p15。

            ③ <opcode_1>

            指定协处理器执行的操作码,确定哪一个协处理器指令将被执行。

            ④ <Rd>

            确定哪一个ARM寄存器的数值将被传送。如果程序计数器PC的值被传送,指令的执行结果不可预知。

            ⑤ <CRn>

            确定包含第一个操作数的协处理器寄存器。

            ⑥ <CRm>

            确定包含第二个操作数的协处理器寄存器。

            ⑦ <opcode_2>

            指定协处理器执行的操作码,确定哪一个协处理器指令将被执行。通常与<opcode_1>配合使用。

            1. 指令举例

            将ARM寄存器r7中的值传送到协处理器p14的寄存器c7中,第一操作数opcode_1=1,第二操作数opcode_2=6。

            MCR p14,1,r7,c7,c12 ,6

            1. 指令的使用

            指令的编码格式中,bits[31∶24]、bit[20]、bits[15∶8]和bit[4]为ARM体系结构定义。其他域由各生产商定义。硬件协处理器支持与否完全由生产商定义,某款ARM芯片中,是否支持协处理器或支持哪个协处理器与ARM版本无关。生产商可以选择实现部分协处理器指令或者完全不支持协处理器。


            1. 协处理器寄存器到ARM寄存器的数据传送指令MRC

            2. 指令编码格式

            协处理器寄存器到ARM寄存器的数据传送指令MRC(Move to ARM register from Coprocessor)将协处理器cp_num 的寄存器的值传送到ARM寄存器中。如果没有协处理器执行指定操作,将产生未定义指令异常。指令的编码格式如图所示。



            1. 指令的语法格式

            MRC{<cond>} <coproc>,<opcode_1>,<Rd>,<CRn>,<CRm>{,<opcode_2>}

            为指令编码中的条件域。它指示指令在什么条件下执行。当<cond>忽略时,指令为无条件执行(cond=AL(Alway ))。

            ① <coproc>

            指定协处理器的编号,标准的协处理器的名字为p0、p1、…、p15。

            ② <opcode_1>

            指定协处理器执行的操作码,确定哪一个协处理器指令将被执行。

            ③ <Rd>

            确定哪一个ARM寄存器接受协处理器传送的数值。如果程序计数器PC被用做目的寄存器,指令的执行结果不可预知 。

            ④ <CRn>

            确定包含第一个操作数的协处理器寄存器。

            ⑤ <CRm>

            确定包含第二个操作数的协处理器寄存器。

            ⑥ <opcode_2>

            指定协处理器执行的操作码,确定哪一个协处理器指令将被执行。通常与<opcode_1>配合使用。

            1. 指令举例

            协处理器源寄存器为c0和c2,目的寄存器为ARM寄存器r4,第一操作数opcode_1=5,第二操作数opcode_2=3。

            MRC p15,5,r4,c0,c2,3

            1. 指令的使用

            如果目的寄存器为程序计数器r15,则程序状态字条件标准位根据传送数据的前4bit确定,后28bit被忽略。指令的编码格式中,bits[31:24]、bit[20]、bits[15:8]和bit[4]为ARM体系结构定义。其他域由各生产商定义。

            硬件协处理器支持与否完全由生产商定义,某款ARM芯片中,是否支持协处理器或支持哪个协处理器与ARM版本无关。生产商可以选择实现部分协处理器指令或者完全不支持协处理器。

            如果协处理器必须完成一些内部工作来准备一个32位数据向ARM传送(例如,浮点FIX操作必须将浮点值转换为等效的定点值),那么这些工作必须在协处理器提交传送前进行。因此,在准备数据时经常需要协处理器握手信号处于“忙-等待”状态。ARM可以在忙-等待时间内产生中断。如果它确实得以中断,那么它将暂停握手以服务中断。当它从中断服务程序返回时,将可能重试协处理器指令,但也可能不重试。例如,中断可能导致任务切换,无论哪种情况,协处理器必须给出一致结果,因此,在握手提交阶段之前的准备工作不允许改变处理器的可见状态。

            如图所示列出了cp15的各个寄存器的目的。



            异常产生指令

            ARM指令集中提供了两条产生异常的指令,通过这两条指令可以用软件的方法实现异常。如表所示为ARM异常产生指令。

            助 记 符含 义操 作SWI软中断指令产生软中断,处理器进入管理模式BKPT断点中断指令处理器产生软件断点

            软件中断指令(Software Interrupt,SWI)用于产生软中断,从而实现从用户模式变换到管理模式,CPSR保存到管理模式的SPSR中,执行转移到SWI向量,在其他模式下也可以使用SWI指令,处理器同样切换到管理模式。

              1. 指令的语法格式。




              SWI{<cond>} <immed_24>

                1. 指令举例。




                ① 下面指令产生软中断,中断立即数为0。

                SWI 0;

                ② 产生软中断,中断立即数为0x123456。

                SWI 0x123456;

                ③ 使用SWI指令时,通常使用以下两种方法进行参数传递。

                a.指令24位的立即数指定了用户请求的类型,中断服务程序的参数通过寄存器传递。

                下面的程序产生一个中断号为12的软中断。

                MOV R0,#34 ;设置功能号为34

                SWI 12 ;产生软中断,中断号为12

                b.另一种情况,指令中的24位立即数被忽略,用户请求的服务类型由寄存器R0的值决定,参数通过其他寄存器传递。

                下面的例子通过R0传递中断号,R1传递中断的子功能号。

                MOV R0,#12 ;设置12号软中断

                MOV R1,#34 ;设置功能号为34

                SWI 0

                其他指令介绍

                1. 特殊指令介绍

                Fmxr /Fmrx指令是NEON下的扩展指令,在做浮点运算的时候,要先打开vfp,因此需要用到Fmxr指令。

                Fmxr:由arm寄存器将数据转移到协处理器中。

                Fmrx:由协处理器转移到arm寄存器中。

                如图所示为浮点异常寄存器格式。



                如表所示为FPEXC的位定义。

                位域功能描述[31]EX异常位,该位指定了有多少信息需要存储记录SIMD/VFP协处理器的状态[30]ENNEON/VFP使能位,设置EN位1则开启NEON/VFP协处理器,复位会将EN置0[29:0]保留

                FPEXC<浮点异常寄存器>,该寄存器是一个可控制SIMD及VFP的全局使能寄存器,并指定了这些扩展技术是如何记录的。

                如果要打开VFP协处理器的话,可以用以下指令:

                mov r0, #0x40000000

                fmxr fpexc, r0 @ enable NEON and VFP coprocessor

                1. CLZ 计算前导零数目

                  1. 语法格式:




                  CLZ {cond} Rd,Rm

                  其中:

                  • cond 是一个可选的条件代码。

                  • Rd是目标寄存器。

                  • Rm 是操作数寄存器。


                  1. 用法:CLZ指令对Rm中的值的前导零进行计数,并将结果返回到Rd中,如果未在源寄存器中设置任何位,则该结果值为32,如果设置了位31,则结果值为0。

                  2. 条件标记:该指令不会更改标记。

                  3. 体系结构:ARMv5 以上。

                  4. 示例如图所示。



                  1. 饱和指令介绍

                  这是用来设计饱和算法的一组指令,所谓饱和是指出现下列3种情况:

                    1. 对于有符号饱和运算,如果结果小于-2n,则返回结果将为-2n。

                    2. 对于无符号饱和运算,如果整数结果是负值,那么返回的结果将为0。

                    3. 对于结果大于2n -1的情况,则返回结果将为2n -1。




                    只要出现这情况,就称为饱和,并且饱和指令会设置Q标记,下面简单介绍一下QADD带符号加法。

                    QSUB:带符号减法。

                    QDADD:带符号加倍加法。

                    QDSUB:带符号加倍减法。

                    将结果饱和导入符号范围(-231≤x ≤231-1)内。

                      1. 语法格式:




                      op{cond} {Rd} ,Rm,Rn

                      其中:

                      • op 是QADD,QSUB,QDADD,QDSUB之一。

                      • cond 是一个可选的条件代码。

                      • Rd 是目标寄存器。

                      • Rm, Rn 是存放操作数的寄存器(注:不要将r15用做Rd,Rm或Rn)。

                        1. 用法如下:




                        • QADD指令可将Rm和Rn中的值相加。

                        • QSUB指令可从Rm中的值减去Rn中的值。

                        • QDADD/QDSUB指令涉及并行指令,因此这里不多做讨论。

                          1. 条件标记:如果发生饱和,则这些指令设置Q标记,若要读取Q标记的状态,需要使用MRS指令。

                          2. 体系结构:该指令可用于v5T-E及v6或者更高版本的体系中。

                          3. 示例如下:




                          QADD r0 ,r1,r9

                          QSUBLT r9,r0,r1

                          ARM 汇编实验

                          实验目的

                          • 掌握 ARM汇编语言的基本使用;

                          • 熟悉 eclipse 开发工具建立汇编工程和仿真;

                          实验原理

                          根据上面阐述RAM 汇编语言的使用语法和功能,编写汇编程序,实现一个简单的数据运算操作。

                          实验内容

                          汇编程序设计如下

                          .text

                          .global _start

                          _start:


                          mov r0, #0x9

                          nop

                          mov r1, #0x7


                          loop:

                          bl add_sub


                          stop:

                          b stop



                          add_sub:

                          add r2, r0, r1

                          sub r3, r0, r1


                          mul r4, r0,r1

                          mov pc, lr


                          实验步骤

                          1. 导入工程源码

                          请参考第37章的导入已有工程章节。

                          光盘实验源码路径:【资料光盘\华清远见-FS-MP1A开发资料-2020-11-06\02-程序源码\03-ARM体系结构与接口技术\Cortex-A7\h_project】

                          1. 打开“Register”显示框

                          单击window -> show view -> Register,



                          1. 单步仿真

                          配置完成之后,点击“

                          ”开始仿真,弹出Debug框。




                          单击“

                          ”单步仿真。查看仿真现象。

                          实验现象

                          1. 单击“

                          ”单步,查看Rn寄存器的变化。





                          单步运行可以看到R2、R3和R4的值变化。

                          硬件平台:华清远见FS-MP1A开发板(STM32MP157)

                          部分开发教程下载:加QQ群483143191,群文件里有。

                          部分视频课程收看:华清远见研发中心的个人空间_哔哩哔哩_Bilibili

                          淘宝购买链接:item.taobao.com/item.ht

                          手机淘宝分享码:复制本行文字打开手淘₤T4FPXn3YYJ2₤


                          ARM裸机开发篇2:ARM微处理器指令系统(二)的评论 (共 条)

                          分享到微博请遵守国家法律