- 嵌入式技术基础与实践(第5版)
- 王宜怀 许粲昊 曹国平
- 3846字
- 2020-08-28 21:07:19
2.2 指令系统
CPU的功能是从外部设备获得数据,通过加工、处理,再把处理结果送到CPU的外部世界。设计一个CPU,首先需要设计一套可以执行特定功能的操作命令,这种操作命令称为指令。CPU所能执行的各种指令的集合,称为该CPU的指令系统。表2-4所示为ARM Cortex-M指令集概况。在ARM系统中,架构(Architecture)即体系结构,主要指使用的指令集,由同一架构可以衍生出许多不同处理器型号。对ARM而言,其他芯片厂商,可由ARM提供的一种处理器型号具体生产出许多不同的MCU或应用处理器型号。ARMv7-M是一种架构型号,其中v7是指版本号,而基于该架构处理器的有Cortex-M3、Cortex-M4、Cortex-M4F等。
表2-4 ARM Cortex-M指令集概况
本节在给出指令简表与寻址方式的基础上,简要阐述ARM Cortex-M系列共有的57条基本指令功能。
2.2.1 指令简表与寻址方式
1. 指令简表
ARM Cortex-M4F不仅支持所有的Thumb和Thumb-2的全部指令,还支持浮点运算指令、DSP扩展指令等。常用的指令大体分为数据操作指令、转移指令、存储器数据传送指令和其他指令四大类,如表2-5所示。其他指令需要时请查阅《ARMv7-M参考手册》。
表2-5 常用指令简表
2. 寻址方式
指令是对数据的操作,通常把指令中所要操作的数据称为操作数,ARM Cortex-M4F处理器所需的操作数可能来自寄存器、指令代码、存储单元。而确定指令中所需操作数的各种方法称为寻址方式(Addressing Mode)。下面指令格式中的“{}”表示其中可选项。例如,LDRH Rt,[Rn{,#imm}],表示有“LDRH Rt,[Rn]”“LDRH Rt,[Rn,#imm]”两种指令格式。指令中的“[]”表示其中内容为地址,“//”表示注释。
1)立即数寻址
在立即数寻址方式中,操作数直接通过指令给出,数据包含在指令编码中,随着指令一起被编译成机器码存储于程序空间中,用“#”作为立即数的前导标识符。ARM Cortex-M4立即数范围为0x00~0xff。例如:
2)寄存器寻址
在寄存器寻址中,操作数来自于寄存器。例如:
3)直接寻址
在直接寻址方式中,操作数来自于存储单元,指令中直接给出存储单元地址。指令码中,显示给出数据的位数,有字(4字节)、半字(2字节)、单字节3种情况。例如:
4)偏移寻址及寄存器间接寻址
在偏移寻址中,操作数来自于存储单元,指令中通过寄存器及偏移量给出存储单元的地址。偏移量不超过4KB(指令编码中偏移量为12位)。偏移量为0的偏移寻址也称为寄存器间接寻址。例如:
2.2.2 数据传送类指令
数据传送类指令的功能有两种情况:一是取存储器地址空间中的数传送到寄存器中;二是将寄存器中的数传送到另一寄存器或存储器地址空间中。数据传送类基本指令有16条。
1. 取数指令
存储器中内容加载(Load)到寄存器中的指令如表2-6所示。其中,LDR、LDRH、LDRB指令分别表示加载来自存储器单元的一个字、半字和单字节(不足部分以0填充);LDRSH和LDRSB指令是指加载存储单元的半字、字节有符号数扩展成32位到指定寄存器Rt。
表2-6 取数指令
在LDM Rn{!},reglist指令中,Rn表示存储器单元起始地址的寄存器;reglist包含一个或多个寄存器,若包含多个寄存器必须以“,”分隔,外面用“{}”标识;“!”是一个可选的回写后缀,reglist列表中包含Rn寄存器时不要回写后缀,否则须带回写后缀“!”。带后缀时,在数据传送完毕之后,最后的地址将写回Rn=Rn+4×(n-1),n为reglist中寄存器的个数。Rn不能为R15,reglist可以为R0~R15的任意组合;Rn寄存器中的值必须字对齐。这些指令不影响N、Z、C、V状态标志。
2. 存数指令
寄存器中内容存储(Store)至存储器中的指令如表2-7所示。STR、STRH和STRB指令存储Rt寄存器中的字、低半字或低字节至存储器单元。存储器单元地址由Rn与Rm之和决定,Rt、Rn和Rm必须为R0~R7之一。
其中,“STM Rn!,reglist”指令将reglist列表寄存器内容以字存储至Rn寄存器中的存储单元地址。以4字节访问存储器地址单元,访问地址从Rn寄存器指定的地址值到Rn+4×(n-1),n为reglist中寄存器的个数。按寄存器编号递增顺序访问,最低编号使用最低地址空间,最高编号使用最高地址空间。对于STM指令,若reglist列表中包含了Rn寄存器,则Rn寄存器必须位于列表首位。如果列表中不包含Rn,则将位于Rn+4×n地址回写到Rn寄存器中。这些指令不影响N、Z、C、V状态标志。
表2-7 存数指令
3. 寄存器间数据传送指令
如表2-8所示,MOV指令中,Rd表示目标寄存器;imm为立即数,范围为0x00~0xff。当MOV指令中Rd为PC寄存器时,丢弃第0位;当出现跳转时,传送值的第0位清零后的值作为跳转地址。虽然MOV指令可以用作分支跳转指令,但强烈推荐使用BX或BLX指令。这些指令影响N、Z状态标志,但不影响C、V状态标志。
表2-8 寄存器间数据传送指令
4. 堆栈操作指令
堆栈(Stack)操作指令如表2-9所示。PUSH指令将寄存器值存于堆栈中,最低编号寄存器使用最低存储地址空间,最高编号寄存器使用最高存储地址空间;POP指令将值从堆栈中弹回寄存器,最低编号寄存器使用最低存储地址空间,最高编号寄存器使用最高存储地址空间。执行PUSH指令后,更新SP寄存器值SP=SP-4;执行POP指令后更新SP寄存器值SP=SP+4。若POP指令的reglist列表中包含了PC寄存器,在POP指令执行完成时跳转到该指针PC所指地址处。该值最低位通常用于更新xPSR的T位,此位必须置1,才能确保程序正常运行。
表2-9 堆栈操作指令
例如:
5. 生成与指针PC相关地址指令
如表2-10所示,ADR指令将指针PC值加上一个偏移量得到的地址写进目标寄存器中。若利用ADR指令生成的目标地址用于跳转指令BX、BLX,则必须确保该地址最后一位为1。Rd为目标寄存器,label为与指针PC相关的表达式。在该指令下,Rd必须为R0~R7,数值必须字对齐且在当前PC值的1020字节以内。此指令不影响N、Z、C、V状态标志。这条指令主要提供编译阶段使用,一般可看成一条伪指令。
表2-10 ADR指令
2.2.3 数据操作类指令
数据操作主要指算术运算、逻辑运算、移位等。
1. 算术运算类指令
(1)算术运算类指令有加、减、乘、比较等,如表2-11所示。
表2-11 算术运算类指令
(2)加、减指令对操作数的限制条件,如表2-12所示。
表2-12 ADC、ADD、RSB、SBC和SUB操作数限制条件
2. 逻辑运算类指令
逻辑运算类指令如表2-13所示。AND、EOR和ORR指令把寄存器Rn、Rm值逐位与、异或和或操作;BIC指令是将寄存器Rn的值与Rm的值的反码按位做逻辑“与”操作,结果保存到Rd。这些指令更新N、Z状态标志,不影响C、Z状态标志。
表2-13 逻辑运算类指令
Rd、Rn和Rm必须为R0~R7,其中Rd为目标寄存器,Rn为存放第一个操作数寄存器,且必须和目标寄存器Rd一致(即Rd就是Rn),Rm为存放第二个操作数寄存器。
3. 移位类指令
移位类指令如表2-14所示。ASR、LSL、LSR和ROR指令,将寄存器Rm的值由寄存器Rs或立即数imm决定移动位数,执行算术右移、逻辑左移、逻辑右移和循环右移。这些指令中,Rd、Rm、Rs必须为R0~R7。对于非立即数指令,Rd和Rm必须一致。Rd为目标寄存器,若省去Rd,表示其值与Rm寄存器一致;Rm为存放被移位数据寄存器;Rs为存放移位长度寄存器;imm为移位长度,ASR指令移位长度范围为1~32,LSL指令移位长度范围为0~31,LSR指令移位长度范围为1~32。
表2-14 移位指令
1)单向移位指令
算术右移指令ASR指令比较特别,它把要操作的字节当作有符号数,而符号位(b31)保持不变,其他位右移一位,即首先将b0位移入C中,其他位(b1~b31)右移一位,相当于操作数除以2。为了保证符号不变,ASR指令使符号位b31返回本身。逻辑右移指令LSR把32位操作数右移一位,首先将b0位移入C中,其他右移一位,0移入b31。根据结果,ASR、LSL、LSR指令对标志位N、Z有影响,最后移出位更新C标志位。
2)循环移位指令
在循环右移指令ROR中,将b0位移入b31中的同时也移入C中,其他位右移一位。根据结果,ROR指令对标志位N、Z有影响,最后移出位更新C标志位。
4. 位测试指令
位测试指令如表2-15所示。
表2-15 位测试指令
5. 数据序转指令
数据序转指令如表2-16所示,该指令用于改变数据的字节顺序。Rn为源寄存器,Rd为目标寄存器,且必须为R0~R7之一。REV指令将32位大端数据转小端存放或将32位小端数据转大端存放;REV16指令将一个32位数据划分为两个16位大端数据,将这两个16位大端数据转小端存放或将一个32位数据划分为两个16位小端数据,将这两个16位小端数据转大端存放;REVSH指令将16位带符号大端数据转为32位带符号小端数据,或者将16位带符号小端数据转为32位带符号大端数据,如图2-4所示。这些指令不影响N、Z、C、V状态标志。
图2-4 反序操作
表2-16 数据序转指令
6. 扩展类指令
扩展类指令如表2-17所示。寄存器Rm存放待扩展操作数;寄存器Rd为目标寄存器;Rm、Rd必须为R0~R7。这些指令不影响N、Z、C、V状态标志。
表2-17 扩展类指令
2.2.4 跳转控制类指令
跳转控制类指令如表2-18所示,这些指令不影响N、Z、C、V状态标志。
表2-18 跳转控制类指令
跳转控制类指令举例如下,特别注意BL用于调用子程序。
B指令所带条件众多,形成不同条件下的跳转,但只在前256字节至后254字节地址范围内跳转。B指令所带的条件如表2-19所示。
表2-19 B指令所带的条件
2.2.5 其他指令
未列入数据传输类、数据操作类、跳转控制类三大类的指令,归为其他指令,如表2-20所示。其中,spec_reg表示特殊寄存器,如APSR、IPSR、EPSR、IEPSR、IAPSR、EAPSR、PSR、MSP、PSP、PRIMASK或CONTROL。
表2-20 其他指令
表中的中断指令(禁止总中断指令“CPSIE i”,使能总中断指令“CPSID i”)为编程必用指令,实际编程时,由宏函数给出。
下面对两条休眠指令WFE与WFI做简要说明。这两条指令均只用于低功耗模式,并不产生其他操作(这一点类似于NOP指令)。休眠指令WFE执行情况由事件寄存器决定。若事件寄存器为零,只有在发生如下事件时才执行:①发生异常,且该异常未被异常屏蔽寄存器或当前优先级屏蔽;②在进入异常期间,系统控制寄存器的SEVONPEND置位;③若使能调试模式时,触发调试请求;④外围设备发出一个事件或在多重处理器系统中另一个处理器使用SVC指令。若事件寄存器为1,WFE指令清该寄存器后立刻执行。休眠指令WFI执行条件为:发生异常,或PRIMASK.PM被清0,产生的中断将会先占,或者发生触发调试请求(不论调试是否被使能)。