当前位置:首页 > 嵌入式 > 嵌入式教程
[导读]多寄存器Load/Store内存访问指令也叫批量加载/存储指令,它可以实现在一组寄存器和一块连续的内存单元之间传送数据。LDM用于加载多个寄存器,STM用于存储多个寄存器。多寄存器Load/Store内存访问指令允许一条指令传送16个寄存器的任何子集或所有寄存器。

5.4 多寄存器Load/Store内存访问指令

多寄存器Load/Store内存访问指令也叫批量加载/存储指令,它可以实现在一组寄存器和一块连续的内存单元之间传送数据。LDM用于加载多个寄存器,STM用于存储多个寄存器。多寄存器Load/Store内存访问指令允许一条指令传送16个寄存器的任何子集或所有寄存器。

多寄存器Load/Store内存访问指令主要用于现场保护、数据复制和参数传递等。

注意

多寄存器Load/Store内存访问指令会增加中断延时,因为ARM通常不会打断正在执行的指令去响应中断,而必须等到指令执行完。也就是说,如果一个中断在多寄存器Load/Store内存访问指令执行期间产生,那么处理器在多寄存器Load/Store内存访问指令执行完后才对中断响应。

表5.2总结了多寄存器Load/Store内存访问指令

表5.2 多寄存器Load/Store内存访问指令

指 令

作 用

操 作

LDM

装载多个寄存器

{Rd}*N←mem32[start address+4*N]

STM

保存多个寄存器

{Rd}*N→mem32[start address+4*N]

5.4.1 多寄存器内存字数据传送指令1.LDM(1)指令

(1)指令编码格式

LDM(1)指令将数据从连续的内存单元中读取到指令中指定的寄存器列表中的各寄存器中。

当PC包含在LDM指令的寄存器列表中时,指令从内存中读取的字数据将被作为目标地址值,指令执行后程序将从目标地址处开始执行,从而实现了指令的跳转。

指令的编码格式如图5.15所示。

图5.15 LDM(1)指令编码格式

(2)指令的语法格式

LDM{<cond>}<addressing_mode> <Rn>{!}, <registers>

① <cond>

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

② <address_mode>

指令的寻址方式。确定编码格式中的P、U和W位。

③ <Rn>

确定寻址模式所使用的基址寄存器。

如果r15作为指令的基址寄存器,指令的执行结果不可预知。

④ !

设置指令编码格式中的W位。它使指令执行后将操作数的内存地址写入基址寄存器<Rn>中;如果!被忽略,W位为0,指令执行完后,不修改基址寄存器的值。

注意

如果基址寄存器包含在指令列表中,当指令执行完后,基址寄存器的值是新加载进的特定内存地址的值。也就是说,即使指令没有出现在指令列表中,基址寄存器的值也可能被修改。

⑤ <registers>

被加载的寄存器列表。不同的寄存器之间用“,”隔开。完整的寄存器列表包含在“{}”中。编号低的寄存器对应于内存中低地址单元,编号高的寄存器对应于内存中高地址单元。

注意

无论寄存器在寄存器列表“{}”中如何排列,都将遵循上述规则。

寄存器r0~r15分别对应于指令编码中bit[0]~bit[15]位。如果Ri存在于寄存器列表中,则相应的位等于1,否则为0。

(3)指令操作的伪代码

指令操作伪代码如下面程序段所示。

If ConditionPass{cond} then

Address=start_address

For i=0 to 14

If register_list[i]==1 then

Ri=Memory[address,4]

Address=address+4

If register_list[15]==1 then

Value = Memory[address,4]

If(architecture version 5 or above) then

Pc= value AND 0xfffffffe

T bit=value[0]

Else

Pc= value AND 0xfffffffc

Address=address+4

Assert end_address=address+4

2.STM(1)指令

(1)指令编码格式

STM(1)指令将指令中寄存器列表中的各寄存器数值写入到连续的内存单元中。主要用于块数据的写入、数据栈操作以及进入子程序时保存相关寄存器的操作。

指令编码格式如图5.16所示。

图5.16 STM(1)指令编码格式

(2)指令的语法格式

STM{<cond>}<addressing_mode> <Rn>{!}, <registers>

① <cond>

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

② <address_mode>

指令的寻址方式。确定编码格式中的P、U和W位。

③ <Rn>

确定寻址模式所使用的基址寄存器。

如果r15作为指令的基址寄存器,指令的执行结果不可预知。

④ !

设置指令编码格式中的W位。它使指令执行后将操作数的内存地址写入基址寄存器<Rn>中;如果!被忽略,W位为0,指令执行完后,不修改基址寄存器的值。

⑤ <registers>

被加载的寄存器列表。不同的寄存器之间用“,”隔开。完整的寄存器列表包含在“{}”中。编号低的寄存器对应于内存中低地址单元,编号高的寄存器对应于内存中高地址单元。

寄存器r0~r15分别对应于指令编码中bit[0]~bit[15]位。如果Ri存在于寄存器列表中,则相应的位等于1,否则为0。

(3)指令操作的伪代码

指令操作伪代码如下面程序段所示。

If ConditionPassed{cond} then

Address=Start_address

For i=0 to 15

If register_list[i]==1

Memory[address,4]=Ri

Address=address+4

Assert end_address==address-4

5.4.2 用户模式多寄存器内存字数据传送指令1.LDM(2)指令

(1)指令编码格式

LDM(2)指令将数据从连续的内存单元中读取到指令中指定的寄存器列表中的各寄存器中。

注意

与LDM(1)指令不同,PC不能包含在寄存器列表中。

指令的编码格式如图5.17所示。

图5.17 LDM(2)指令编码格式

(2)指令的语法格式

LDM{<cond>}<addressing_mode> <Rn>, <registers_without_pc>ˆˆ

① <cond>

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

② <address_mode>

指令的寻址方式。确定编码格式中的P位和U位。此指令中W位指定为0。

③ <Rn>

确定寻址模式所使用的基址寄存器。

如果r15作为指令的基址寄存器,指令的执行结果不可预知。

④ <registers_without_pc>ˆ

被加载的寄存器列表。不同的寄存器之间用“,”隔开。完整的寄存器列表包含在“{}”中。此寄存器列表中不能包含PC寄存器。

如果PC包含在寄存器列表中,指令的执行结果不可预知。

其他细节可参考LDM(1)指令。

(3)指令操作的伪代码

指令操作伪代码如下面程序段所示。

If ConditionPassed{cond} then

Address=start_address

For i=0 to 14

If register_list[i]==1

Ri_usr=Memory[address,4]

Address=address+4

Assert end_address == address-4

2.STM(2)指令

(1)指令编码格式

STM(2)指令将指令中寄存器列表中的各寄存器数值写入到连续的内存单元中。主要用于块数据的写入、数据栈操作以及进入子程序时保存相关寄存器等操作。

指令编码格式如图5.18所示。

图5.18 STM(2)指令编码格式

(2)指令的语法格式

STM{<cond>}<addressing_mode> <Rn>, <registers >ˆ

① <cond>

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

② <address_mode>

指令的寻址方式。确定编码格式中的P位和U位。此指令中W位指定为0。

③ <Rn>

确定寻址模式所使用的基址寄存器。

如果r15作为指令的基址寄存器,指令的执行结果不可预知。

④ <registers >ˆ

寄存器列表。只能使用用户模式下的寄存器。

(3)指令操作的伪代码

指令操作伪代码如下面程序段所示。

If ConditionPassed{cond} then

Address=start_address

For i=0 to 15

If register_list[i] == 1

Memory[address,4]=Ri_usr

Address = address +4

Assert end_address == address-4

5.4.3 带状态寄存器的多寄存器内存字数据装载指令(LDM(3))

(1)指令编码格式

LDM(3)指令将数据从连续的内存单元中读取数据到寄存器列表中的各寄存器中。它同时将当前处理器模式对应的SPSR寄存器的内容复制到CPSR寄存器中。

当PC包含在LDM指令的寄存器列表中时,指令从内存中读取的数据将被作为目标地址值,指令执行后程序将从目标地址处开始执行,从而实现了指令的跳转。

在ARM v5及以上的版本和T系列的ARM v4版本中,SPSR寄存器的T位将复制到CPSR寄存器的T位,该位决定目标地址处的程序状态。在以前的版本中程序继续执行在ARM状态。

指令的编码格式如图5.19所示。

图5.19 LDM(3)指令编码格式

(2)指令的语法格式

LDM{<cond>}<addressing_mode> <Rn>{!}, <registers_and_pc>ˆ

① <cond>

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

② <address_mode>

指令的寻址方式。确定编码格式中的P、U和W位。

③ <Rn>

确定寻址模式所使用的基址寄存器。

如果r15作为指令的基址寄存器,指令的执行结果不可预知。

④ !

设置指令编码格式中的W位。它使指令执行后将操作数的内存地址写入基址寄存器<Rn>中;如果!被忽略,W位为0,指令执行完后,不修改基址寄存器的值。

注意

如果基址寄存器包含在指令列表中,当指令执行完后,基址寄存器的值是新加载进的特定内存地址的值。也就是说,即使指令没有出现在指令列表中,基址寄存器的值也可能被修改。

⑤ <registers_and_pc>ˆ

寄存器列表。

注意

在本格式的指令中寄存器列表中必须包含PC寄存器。

被加载的寄存器列表。不同的寄存器之间用“,”隔开。完整的寄存器列表包含在“{}”中。编号低的寄存器对应于内存中的低地址单元,编号高的寄存器对应于内存中的高地址单元。

寄存器r0~r15分别对应于指令编码中bit[0]~bit[15]位。如果Ri存在于寄存器列表中,则相应的位等于1,否则为0。

该指令执行时将当前处理器模式下的SPSR值复制到CPSR中。指令的其他参数可参见LDM(1)指令格式。

(3)指令操作的伪代码

指令操作伪代码如下面程序段所示。

If ConditionPass{<cond>} then

Address=start_address

For i=0 to 14

If register_list[i]==1 then

Ri=Memory[address,4]

Address=address+4

CPSR=SPSR

Value=memory[address,4]

If {architecture version 4T, 5 or above} and {T bit ==1} then

Else

Pc=value AND oxfffffffc

Address=address + 4

Assert end_address=address-4

5.4.4 数据传送指令应用

LDM/STM批量加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDM为加载多个寄存器,STM为存储多个寄存器。允许一条指令传送16个寄存器的任何子集或所有寄存器。指令格式如下:

LDM{cond}<模式> Rn{!},regist{ˆ}

STM{cond}<模式> Rn{!},regist{ˆ}

LDM/STM的主要用途有现场保护、数据复制和参数传递等。其模式有8种,如下所示。

前面4种用于数据块的传输,后面4种是堆栈操作。

(1)IA:每次传送后地址加4。

(2)IB:每次传送前地址加4。

(3)DA:每次传送后地址减4。

(4)DB:每次传送前地址减4。

(5)FD:满递减堆栈。

(6)ED:空递增堆栈。

(7)FA:满递增堆栈。

(8)EA:空递增堆栈。

其中,寄存器Rn为基址寄存器,装有传送数据的初始地址,Rn不允许为R15;后缀“!”表示最后的地址写回到Rn中;寄存器列表reglist可包含多于一个寄存器或寄存器范围,使用“,”分开,如{R1,R2,R6~R9},寄存器排列由小到大排列;“ˆ”后缀不允许在用户模式下,只能在系统模式下使用。若在LDM指令用寄存器列表中包含有PC时使用,那么除了正常的多寄存器传送外,将SPSR拷贝到CPSR中,这可用于异常处理返回;使用“ˆ”后缀进行数据传送且寄存器列表不包含PC时,加载/存储的是用户模式寄存器,而不是当前模式寄存器。

注意

地址对齐问题,在这些指令中,忽略地址位[1:0]。

批量加载/存储指令举例如下。

LDMIA r0!,{r3~r9} ;加载r0指向的地址上的多字数据,保存到r3~r9中,r0值更新

STMIA r1!,{r3~r9} ;将r3~r9的数据存储到r1指向的地址上,r1值更新

STMFD SP!,{r0~r7,LR} ;现场保存,将r0~r7、LR入栈

LDMFD SP!,{r0~r7,PC}ˆ ;恢复现场,异常处理返回

在进行数据复制时,先设置好源数据指针,然后使用块拷贝寻址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB进行读取和存储。而进行堆栈操作时,则要先设置堆栈指针,一般使用SP然后使用堆栈寻址指令STMFD/LDMFD、STMED/LDMED、STMEA/LDMEA实现堆栈操作。

多寄存器传送指令如例5.3所示。其中r1为指令执行前的基址寄存器,r1’则为指令执行后的基址寄存器。

【例5.3】多寄存器传送指令示意。

(1)STMIA r1,{r5~r7}

(2)STMIB r1!,{r5~r7}

(3)STMDA r1!,{r5~r7}

(4)STMDB r1!,{r5~r7}

数据是存储在基址寄存器的地址之上还是之下,地址是存储第一个值之前还是之后、增加还是减少,如表5.3所示。

表5.3 多寄存器Load/Store内存访问指令映射

向 上 生 长

向 下 生 长

增加

之前

STMIB

LDMIB

STMFA

LDMED

之后

STMIA

LDMIA

STMEA

LDMFD

增加

之前

LDMDB

STMDB

LDMEA

STMFD

之后

LDMDA

STMDA

LDMFA

STMED

【例5.4】使用LDM/STM进行数据复制。

LDR r0,=SrcData ;设置源数据地址

LDR r1,=DstData ;设置目标地址

LDMIA r0,{r2~r9} ;加载8字数据到寄存器r2~r9

STMIA r1,{r2~r9} ;存储寄存器r2~r9到目标地址

【例5.5】使用LDM/STM进行现场寄存器保护,常在子程序或异常处理使用。

SENDBYTE

STMFD SP!,{r0~r7,LR} ;寄存器压栈保护

…….

BL DELAY ;调用DELAY子程序

…….

LDMFD SP!,{r0~r7,PC} ;恢复寄存器,并返回

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

据《日经新闻》报道,软银旗下英国芯片制造商Arm计划到2025年销售AI芯片。该公司专门成立一个AI芯片部门,并将在2025年春季之前制造出原型产品,并于秋季开始大规模生产。

关键字: 软银 AGI ARM AI芯片

业内消息,近日日本软件银行集团(SoftBank Group)旗下安谋国际科技公司(Arm)计划研发人工智能(AI)芯片,先成立一个AI芯片部门,目标是明年春季建立AI芯片原型产品,然后将量产工作交由代工厂制造,预估20...

关键字: ARM AI芯片

双核心,出色安全性功能、内部堆栈DRAM、丰富的外围

关键字: 微处理器 DRAM 工业物联网

Arm CPU正在从根本上推动AI变革,并造福地球。Arm架构是未来AI计算的基石。​

关键字: ARM AI

近日,Arm推出了Arm® Ethos™-U85神经网络处理器(NPU)和Arm Corstone™-320物联网参考设计平台,旨在满足海量的数据处理和大规模计算,加速推进边缘AI的发展进程。

关键字: ARM

为了赶超云计算市场上的竞争对手,谷歌正试图通过定制的Arm服务器芯片降低云计算服务成本。

关键字: 谷歌 ARM 定制芯片

嵌入式开发作为一个融合了计算机软硬件和系统工程的综合性领域,其成功与否往往取决于三个核心要素的有效整合与协调。这三个要素分别是:硬件平台的选择与设计、软件开发及其优化、以及系统级的设计与集成。深入理解并熟练掌握这三个方面...

关键字: 嵌入式开发 ARM

随着汽车软件数量爆发式的增长,整个行业都需要重新思考汽车产品的开发流程。为此,Arm推出了丰富的硬件IP、新的系统IP,以及全新的汽车计算与计算子系统产品路线图,旨在为各种汽车应用实现性能、功能安全、可扩展等方面的支持。

关键字: ARM 汽车电子

知名移动芯片设计公司ARM最近迈出重要一步,它正式推出汽车芯片设计。ARM推出的芯片设计方案名叫Neoverse,随同芯片一起推出的还有面向汽车制造商、汽车供应商的新系统。

关键字: ARM 汽车芯片 芯片

双核心 Arm Cortex-A35、图形加速、高速连接能力,及内建硬件安全功能

关键字: 微处理器 电动车充电站 智能家居
关闭
关闭