目标寄存器和存储器的区别器

3638人阅读
MMX状态置空:将FP特征字置空(全1),使后续浮点指令可以使用浮点寄存器,其他MMX指令自动置FP为全0.本指令应在所有MMX例程结束和调用可含有FP指令的例程时使用,以清除MMX状态.
MOVD mm,r/m32MOVD r/m32,mm
转移32位数据:将32位数据从整型寄存器/内存移到MMX寄存器,和反向移动.MOVD不能在MMX寄存器之间,内存之间及整型寄存器之间移动数据.目标操作数为MMX寄存器时,32位源操作数写入目标寄存器的低32位.目标寄存器&0扩展&为64位.源操作数为MMX寄存器时,该寄存器的低32位被写入目标操作数.
MOVQ mm,r/m64MOVQ r.m64,mm
转移64位数据:将64位数据从整型寄存器/内存移到MMX寄存器,和反向移动.目标操作数和源操作数可为MMX寄存器,64位内存操作数.但MOVQ不能在内存和内存之间进行数据转移.
PACKSSWB mm,mm/m64PACKSSDW mm,mm/m64
有符号饱和方式数据成组:将MMX寄存器和MMX寄存器/内存单元中的有符号字组变成MMX寄存器的有符号字节组.和将MMX寄存器和MMX寄存器/内存单元中的有符号双字组变成MMX寄存器的有符号字组.(注1)
PACKUSWB mm,mm/m64
无符号饱和方式数据成组将MMX寄存器和MMX寄存器/内存单元中的有符号字组变成MMX寄存器的无符号字节组.(注1)
PADDB mm,mm/m64PADDW mm,mm/m64PADDD mm,mm/m64
环绕方式数据组相加:按环绕方式将MMX寄存器/内存单元中的字节组(字组,双字组)相加到MMX寄存器中(注1)
PADDSB mm,mm/m64PADDSW mm,mm/m64
饱和方式有符号数据组相加:按饱和方式将MMX寄存器/内存单元中的有符号字节组(字组)相加到MMX寄存器中的有符号字节组(字组)数据.(注1)
PADDUSB mm,mm/m64PADDUSW mm,mm/m64
饱和方式无符号数据组相加:按饱和方式将MMX寄存器/内存单元中的无符号字节组(字组)相加到MMX寄存器中的无符号字节组(字组)数据.(注1)
PAND mm,mm/m64
逐位逻辑与:将MMX寄存器/内存单元中的64位数据进行与操作,结果存于MMX寄存器中.
PANDN mm,mm/m64
逐位逻辑与非:将MMX寄存器中的64位值取反,再将取反后的MMX寄存器与MMX寄存器/内存单元中的64位数据进行与操作,结果存于MMX寄存器中.
PCMPEQB mm,mm/m64PCMPEQW mm,mm/m64PCMPEQD mm,mm/m64
成组数据的相等比较:将MMX寄存器与MMX寄存器/内存单元中的字节组(字组,双字组)数据进行相等比较.该指令将目标操作数和源操作数的相应数据元素进行比较,相等则目标寄存器的对应数据元素被置为全1,否则置为全0.eg:PCMPEQE mm,mm/m64
PCMPGTB mm,mm/m64PCMPGTW mm,mm/m64PCMPGTD mm,mm/m64
成组数据的相等比较:将MMX寄存器与MMX寄存器/内存单元中的字节组(字组,双字组)数据进行大于比较.该指令将目标操作数和源操作数的相应数据元素进行比较,大于则目标寄存器的对应数据元素被置为全1,否则置为全0.(参考上一条)
PMADDWD mm,mm/m64
数据组(字组)的乘加:将MMX寄存器与MMX寄存器/内存单元中的字组数据相乘,然后将32位结果逐对相加并作为双字存于MMX寄存器中.eg:PMADDWD mm,mm/m64
/_____+____/
/______+_____/
PMULHW mm,mm/m64
成组数据(字组)的乘后取高位:将MMX寄存器与MMX寄存器/内存单元中的有符号字组数据相乘,然后将结果的高16位存入MMX寄存器.eg:PMULHW mm,mm/m64
High Order
High Order
High Order
High Order
PMULLW mm,mm/m64
成组数据(字组)的乘后取低位:将MMX寄存器与MMX寄存器/内存单元中的有符号字组数据相乘,然后将结果的低16位存入MMX寄存器.(参考上一条)
POR mm,mm/m64
逐位逻辑或:将MMX寄存器/内存单元中的64位数据进行或操作,结果存于MMX寄存器中.
PSLLW mm,mm/m64PSLLD mm,mm/m64PSLLQ mm,mm/m64PSLLW mm,imm8PSLLD mm,imm8PSLLQ mm,imm8
成组数据的逻辑左移:将MMX寄存器中的字(双字,四字)数据按MMX寄存器/内存单元指定的个数左移,低位移入0.将MMX寄存器中的字(双字,四字)数据按8位立即数指定的个数左移,低位移入0.
PSRAW mm,mm/m64PSRAD mm,mm/m64PSRAW mm,imm8PSRAD mm,imm8
成组数据的算术右移:将MMX寄存器中的字(双字)数据按MMX寄存器/内存单元指定的个数右移,移动中保持符号位.将MMX寄存器中的字(双字)数据按8位立即数指定的个数右移,移动中保持符号位.
PSRLW mm,mm/m64PSRLD mm,mm/m64PSRLQ mm,mm/m64PSRLW mm,imm8PSRLD mm,imm8PSRLQ mm,imm8
成组数据的逻辑右移:将MMX寄存器中的字(双字)数据按MMX寄存器/内存单元指定的个数右移,移出位用0填充.将MMX寄存器中的字(双字)数据按8位立即数指定的个数右移,移出位用0填充.
PSUBB mm,mm/m64PSUBW mm,mm/m64PSUBD mm,mm/m64
环绕方式成组数据相减:从MMX寄存器中按字节(字,双字)减去MMX寄存器/内存单元中的字节(字,双字)组.(注1)
PSUBSB mm,mm/m64PSUBSW mm,mm/m64
饱和方式有符号成组数据相减:从MMX寄存器中的有符号成组字节(字)组数据减去MMX寄存器/内存单元中的有符号字节(字)组数据.(注1)
PSUBUSB mm,mm/m64PSUBUSW mm,mm/m64
饱和方式有符号成组数据相减:从MMX寄存器中的无符号成组字节(字)组数据减去MMX寄存器/内存单元中的无符号字节(字)组数据.(注1)
PUNPCKHBW mm,mm/m64PUNPCKHWD mm,mm/m64PUNPCKHDQ mm,mm/m64
高位成组数据分解:此指令交替取出源操作数和目标操作数的数据元素的高半部分,写入目标操作数中,数据元素的低半部分被忽略.eg:PUNPCKHBW mm,mm/m64
PUNPCKLBW mm,mm/m64PUNPCKLWD mm,mm/m64PUNPCKLDQ mm,mm/m64
低位成组数据分解:此指令交替取出源操作数和目标操作数的数据元素的低半部分,写入目标操作数中,数据元素的高半部分被忽略.(参考上一条)
PXOR mm,mm/m64
逐位逻辑异或:将MMX寄存器/内存单元中的64位数据进行异或操作,结果存于MMX寄存器中.
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:125869次
积分:1992
积分:1992
排名:第8451名
原创:61篇
转载:55篇
评论:48条
(1)(2)(2)(1)(1)(1)(1)(2)(2)(2)(1)(4)(1)(1)(4)(1)(1)(4)(9)(8)(2)(4)(3)(5)(8)(11)(7)(2)(6)(1)(11)(4)(2)(1)数据传送指令之:MOV指令
> 数据传送指令之:MOV指令
数据传送指令之:MOV指令
5.1 1.指令编码格式是最简单的指令,执行的结果就是把一个数N送到目标寄存器Rd,其中N可以是寄存器,也可以是立即数。本文引用地址:多用于设置初始值或者在寄存器间传送数据。指令的编码格式如图5.1所示。图5.1 MOV指令编码格式MOV指令将移位码(shifter_operand)表示的数据传送到目的寄存器Rd,并根据操作的结果更新CPSR中相应的条件标志位。2.指令的语法格式MOV{cond&}{S} Rd&,shifter_operand&① cond&为指令编码中的条件域。它指示MOV指令在什么条件下执行。当cond&忽略时,指令为无条件执行(cond=AL(Alway))。② S(bit[20])如果S=1,MOV指令更新CPSR中条件标志位的值;如果S=0,MOV指令不更新CPSR中条件标志位的值。当更新状态寄存器CPSR中的条件标志位时,有两种情况。& 如果指令中的目标寄存器Rd&不是为r15,指令根据传送的数值设置CPSR中的N位和Z位(如果数据在传送前需要移位,则根据移位后的数值设置),并根据移位器的进位值设置CPSR的C位。标志位V和其他位不受影响。& 如果指令中的目标寄存器Rd&为r15,则当前处理器模式对应的SPSR的值复制到CPSR寄存器中,对于用户模式和系统模式,由于没有相应的SPSR,指令执行的结果不可预知。③ Rd&确定目标寄存器。④ shifter_operand&确定操作数,为目标寄存器传送数据。3.指令操作的伪代码指令操作的伪代码如下面程序段所示。If ConditionPassed{cond} then Rd=shifter_operand If S==1 and Rd==r15 then CPSR=SPSR Else if S==1 then N Flag = Rd[31] Z Flag = If Rd==0 then 1 else 0 C Flag = shifter_carry_out V Flag = unaggected4.指令举例【例5.1】MOV指令MOV指令把一个数N送到目标寄存器Rd,其中N可以是立即数,也可以是寄存器。 MOV R0, R0 ; R0 = R0... NOP 指令 MOV R0, R0, LSL#3 ; R0 = R0 * 8如果r15是目的寄存器,将修改程序计数器或标志。这用于返回到调用代码,方法是把连接寄存器的内容传送到r15。 MOV PC, R14 ; 退出到调用者 MOVS PC, R14 ; 退出到调用者并恢复标志位5.指令的使用MOV指令主要完成以下功能。& 将数据从一个寄存器传送到另一个寄存器。& 将一个常数值传送到寄存器中。& 实现无算术和逻辑运算的单纯移位操作,操作数乘2n可以用左移n位来实现。& 当PC寄存器(r15)用作目的寄存器时,可以实现程序跳转。如&MOV PC,LR&,所以这种跳转可以实现子程序调用以及从子程序返回,代替指令&B,BL&。注意在体系结构v4和v5以上的版本,必须使用BX指令代替MOV PC,LR指令,因为BX指令可以自动实现和Thumb的切换。&当PC寄存器作为目标寄存器且指令中S位被设置时,指令在执行跳转操作的同时,将当前处理器模式的SPSR寄存器内容复制到CPSR中。这种指令&MOVS PC LR&可以实现从某些异常中断中返回。
分享给小伙伴们:
我来说两句……
微信公众账号他们在开发过程中不需要了解目标硬件上内存映射和寄存器的情况
使用图形化的开发环境―LabView开发嵌入式系统
传统设计模式所应对的挑战
嵌入式系统正在渗入现代社会的各个方面,广泛地应用于航空航天、通信设备、消费电子、工业控制、汽车、船舶等领域,据统计,在美国平均每个中产阶级家庭要使用40~50个嵌入式系统。巨大的市场需求推动了嵌入式系统向更高的水平发展。设计师们一方面采用性能更强大的嵌入式处理器如32位、64位RISC芯片取代传统的8位、16位微处理器;另一方面嵌入式系统也由单处理器单操作系统的传统结构向混合型Multi-core系统发展,通过采用多个处理器和OS提高系统并行度来提高系统运行效能,并且设计师们往往同时采用MPU、DSP和FPGA等多种可编程器件来增强处理能力,满足应用功能的升级。
嵌入式系统复杂性的不断增加给设计师们带来了很大的挑战,代码长度呈指数级增加,根据十年前的估计,嵌入式系统的平均代码量为10万行,到2001 年实际已经超过了100万,而现在估计为500万。第三方独立市场预测机构EMF在对900多名嵌入式系统开发人员进行调研后指出,超过50%的嵌入式设计比预期时间晚上市,而平均延迟高达4个月;在已发布的产品中,有近30%的设计未达到预期的功能和指标。
由此可见,随着嵌入式系统复杂性的不断增加,软件工程的重要性毋庸置疑,而大部分的嵌入式系统开发人员都缺乏这方面的专业训练。与此同时,随着嵌入式系统的广泛应用,越来越多领域的专家比如机器人设计师、控制工程师、测试工程师需要使用嵌入式来构建他们的系统,他们既缺乏嵌入式系统的专业知识,也不一定经过软件工程的专业训练。因此,无论是嵌入式系统本身的发展,还是开发人员的专业限制,都需要一种新的设计模式和解决问题的途径来应对目前的挑战。
嵌入式系统开发工具的发展趋势
随着嵌入式系统的快速发展和复杂性的不断增加,基于文本的编程方式所面临的挑战愈发严峻,这种编程模式在将来不可能彻底解决问题。加州大学伯克利分校嵌入式研究专家Edward Lee博士指出,现有的嵌入式系统的开发手段如基于文本编程和面向对象的工具都难以用来构建嵌入式实时系统,因为面向对象很难直观地表达时间和平行性 (parallelism),而时间和平行性或并行(concurrency)在现在的嵌入式系统中是必不可少的。面向角色(actor- oriented)的图形化方法是更适合嵌入式软件设计的工具。
应对嵌入式系统所面临的挑战,工程师们已经有了一些解决的方向,比如采用实时多任务编程技术和交叉开发工具技术来控制功能复杂性、简化应用程序设计、保障软件质量和缩短开发周期。但是现有的嵌入式系统开发工具非常多,全世界嵌入式处理器的品种总量已经超过1000种,流行体系结构有30多个系列,在其上运行的操作系统环境也非常多样化,包括VxWorks、QNX、Linux、 Nuclears、WinCE等等。不仅各种操作系统有各自的开发工具,在同一系统下开发的不同阶段也有不同的开发工具。如在用户的目标板开发初期,需要硬件仿真器来调试硬件系统和基本的驱动程序,在调试应用程序阶段可以使用交互式的开发环境进行软件调试,在测试阶段需要一些专门的测试工具软件进行功能和性能的测试等等。最合理的解决方案是向基于平台的工具转移,它能够更好地表达整个系统,减少与特定硬件以及操作系统的相关性,使更多的软件设计和算法容易理解并被重复使用;而从基于文本的工具向图形化工具的转移则可以直观地表达系统,图形化系统设计(Graphical System Design)的理念就是源于这两大趋势。通过简化嵌入式编程的复杂性,降低了对工程师在嵌入式设计流程中各个步骤的要求;同时提供了从设计、原型到部署,从软件调试、功能测试到生产检测的统一环境,使得工程师们可以更快速地进行重复设计。
在嵌入式系统中实现图形化已经成为大势所趋,现在市场上的工具都在向图形化的方向转变,但往往仅限于基于嵌入式操作系统的图形界面开发;而且由于它们是针对特定硬件或操作系统的工具,与硬件和操作系统平台有很大的相关性,这不足以彻底解决行业将要面临的挑战的。现在市场需要的是一种完全的图形化编程语言,提供足够的灵活性和功能,以满足更广泛应用的需求。因此,图形化系统设计的关键因素是图形化编程。
对于时间和平行性的支持
20年来,科学家和工程师一直在使用Labview为他们的设计实验室、验证实验室和生产现场构建数据采集和仪器控制解决方案,并在这些应用领域成为业界的事实标准。其核心在于,LabVIEW图形化编程语言使没有太多软件背景的技术专家能够快速搭建高级测量和控制系统。和传统的文本编程相比,LabVIEW天生是一种并行结构的编程语言,而时间和并行性在现在的嵌入式系统中是必不可少的。比如,LabVIEW在已有的定时循环结构上新加了硬件定时功能,它是一种表示时间和并行的语义,可以设置操作系统优先级、延时、循环速率等等,如图1所示。如果我们将图1所示的两个并行任务的执行目标扩展到嵌入式对象,比如FPGA或微处理器,就可以发现通过编程环境的一致性和可升级性,LabVIEW 能够容易地实现和管理嵌入式系统的并行性。回想在文章前面所提到的向多处理器转移的趋势,现在我们可以憧憬使用可扩展的直观图形化编程来开发应用,并将处理过程分配到不同的处理器上。
图1 LabView对两个并行任务的编程
支持多种算法设计
谈到嵌入式系统设计,人们所指的其实包括两部分工作:算法设计和固件设计。对于嵌入式系统设计来说,另一个关键要求是软件平台必须能够兼顾实时嵌入式设计中常见的多种算法设计,即计算模型。这些计算模型符合系统设计师们筹划系统时的方式,从而降低从&系统要求&转换到&软件设计&的复杂性。近年来 LabVIEW已经包含了多种计算模型以更好地满足不同专业背景的嵌入式系统开发者的需求。LabVIEW现在可以通过连续时间仿真、状态图、图形化数据流模型和基于文本的数学语言mathscript等多种方式来表达各种算法,同时它提供了很多交互式的工具用来帮助数字滤波器、控制模型、通信系统的设计以及数字信号处理算法的开发,从而在这些顶层应用中进一步简化设计师的工作。
快速构建原型&沟通虚拟世界与物理世界的桥梁
人力资源师
(责任编辑:sunning)
------分隔线----------------------------
报名咨询方式
咨询报名咨询报名MSN:
花少学好,留学涌动实惠潮...
出国留学首选稀缺专业---...
雅思考试考场规则你知道多少---...
米娜昨日在福师大举行的座谈会上发言海都网―海峡都市报讯(海都网记者 李薇 文/图) “...
欧美同学会北京论坛举行 聚焦留学人才与国家发展-新闻频道-和讯网...
哈工大新闻网,哈尔滨工业大学新闻网...《Cortex(TM)-A系列编程者指南(V3.0)》第四章&ARM寄存器、工作模式和指令集&笔记 - 推酷
《Cortex(TM)-A系列编程者指南(V3.0)》第四章&ARM寄存器、工作模式和指令集&笔记
DEN0013C_cortex_a_series_PG.pdf
:前三章略过,值得关注的是Linaro网站:
本章介绍ARM处理器的基础特性,包括
的细节。我们也会涉及一些处理器实现细节,包括
指令流水线
是一个32位处理器架构。它是一种
load/store架构
,意味着数据处理指令操作
通用寄存器
中的值。只有
加载(load)和
存储(store)指令
访问存储器
。通用存储器也是32位的。本书中,字(word)代表32位,双字(doubleword)代表64位,半字(halfword)代表16位宽。
尽管ARMv7架构是一种32位架构,单独的处理器对
所有模块和内部连接的实现
不一定必须都是32位宽
。例如,对于指令获取和数据访问,具有64位或更宽的路径是可能的。
实现ARMv7-A架构的处理器
不具有由架构固定的存储器映射
。处理器能访问
4GB的虚拟地址空间
,存储器和外设都可以在那个空间范围之内自由地映射。我们将会在第9章和第10章中讲述存储器管理,那里我们会看到缓存和内存管理单元(MMU)。
4.1 指令集
--- 一种32位指令集
--- 一种16位指令集,具有
更好的代码密度
(但是相比ARM代码,
性能有所降低
在程序的控制之下,处理器可以在这两种指令集之间来回切换。
所有的Cortex-A系列
处理器实现了
Thumb-2技术
,它扩展了Thumb指令集。混合使用32位和16位指令,以Thumb指令集的代码密度和接近ARM指令集的性能。自从所有的Cortex-A系列处理器支持这一扩展,针对它们的软件常被编译成Thumb指令集。(本文作者注:按照文章
所述,Thumb-2代码大小约为ARM代码的74%,性能则为其98%)
9种处理器模式
,在表4-1中所总结。有
8种特权模式
一种非特权模的用户模式
。在用户模式,在某些操作上具有限制,例如MMU访问,修改操作模式是一种特权操作。注意,模式与异常事件有联系,将会在第12章异常处理中讲述。
4.3 寄存器
ARM架构具有一批通用寄存器,提供处理器内部的数据存储。除了
通用寄存器
程序计数器
包含ALU标志位与其它执行状态信息的
程序状态寄存器
。这些寄存器中很多是分组的,那就是,除非是在特定处理器模式,否则处理器不能访问。当进入一个不同的处理器模式,这些分组的寄存器自动地切入和换出。每个异常模式(不包括系统模式)附加有一个备份程序状态寄存器,包含一份异常触发时程序状态寄存器的拷贝。
因此,在图4-1中,如果处理器是在IRQ模式,我们可以看见R0,R1...R12(与在用户模式看到的相同的寄存器),加上SP_IRQ和LR_IRQ(仅在IRQ模式中可以访问的寄存器)和R15(程序计数器,PC)。我们
通常不必指定模式中的寄存器名
。如果我们在一行代码中引用R13,
处理器会访问当前模式对应的SP寄存器
程序状态寄存器(CPSR)的受限形式
应用程序状态寄存器(APSR)
。R15是程序计数器,保持当前程序地址(实际上,在ARM状态,它总是指向
提前8个字节
当前指令的位置;在Thumb状态,它总是指向提前4个字节当前指令的位置)。
我们可以写值到PC以修改程序流。
链接寄存器
,存放函数或异常的返回地址。
,通常被用作
通用寄存器
。一些16位Thumb指令可访问的寄存器受限---可访问的子集被称为低寄存器(
low registers
),由R0-R7组成。图4-2显示了对通用数据处理指令可见的寄存器子集。
R0-R14的复位值不可预测。
,在使用堆栈之前,必须被启动代码
。AAPCS或AEABI(见第17章 应用二进制接口)指定了软件应该如何使用通用寄存器,为了不同工具链或编程语言之间的互操作。
4.3.1 程序状态寄存器
程序状态寄存器形成了一组额外的分组寄存器集。每中异常模式有它自己的
备份程序状态寄存器
(Saved Program Status Register ,
当一个异常发生时自动保存一份异常前CPSR拷贝
《ARM架构参考手册》(ARM Architecture Reference Manual)
描述了程序状态是如何在32位应用程序状态寄存器(Application Program Status Register ,APSR)中报告的,其它状态和控制位(系统级信息)任然保留在CPSR。本书中涉及的
ARMv7-A架构
APSR实际上同CPSR是
相同的寄存器
,尽管它们有分开的名字。APSR只能访问N/Z/C/V/Q和GE[3:0]位。这些位通常不能直接访问,由条件代码设置指令设置,并由有条件执行的指令测试。重命名因此是尝试清理旧的ARM架构中CPSR的混合访问,图4-3显示了CPSR的组成。
独立位代表如下:
& N --- 来自ALU的负结果
& Z --- 来自ALU的零结果
& C --- ALU操作进位
& V --- ALU操作溢出
& Q --- 累积饱和
& J --- 指示处理器是否在加速状态
GE[3:0] --- 由一些SIMD指令使用
& IT[7:2] --- Thumb-2指令组的If-Then条件执行
& E --- 控制load/store字节序
& A --- 禁止异步中止
& I --- 禁止IRQ
& F --- 禁止FIQ
& T --- 指示处理器是否在Thumb状态
& M[4:0] --- 指定处理器模式(FIQ,IRQ等)
处理器可以在模式间切换通过指令直接写CPSR模式位(用户模式不能)。更为常见的,
处理器修改模式
异常事件的结果
4.4 指令流水线
指令流水线
是一种被用于处理器设计的技术,
提升指令的吞吐量
。信息的处理由一连串对输入数据不同的操作组成。为了优化性能,处理器核被设计为
级联的基本功能单元块
,每个块由前面单元的输出作为输入:在每个时钟,单元N处理单元N-1的输出数据。这么选择主要的原因是
简单的处理块能够比复杂的运行得快
,因此流水线的结构能够让数字电路设计工作在GHz时钟频率。每个指令从一步移动到另一步,通过几个时钟周期。每个流水线阶段处理执行一个指令过程的一部分,因此在给定的任何时钟周期,一些不同的指令可能会在流水线的不同阶段。
处理器的总体速度由
最慢一步的速度决定
,这比执行所有步骤需要的时间极大地减少。一个非流水线架构较为低效,因为处理器内一些模块会在指令执行期间被闲置。
经典的流水线
由三个阶段组成 ---
取指、译码和执行
,如图4-4中所示。更为普遍地,一个指令流水线会被分成下面广泛的定义:
:决定将会被获取指令在内存中的位置,执行相关总线访问
:从内存系统中读取读取将被执行的指令
:得出将被执行的指令,为数据路径生成合适的控制信号
寄存器获取
:提供正确的寄存器值
:发出指令到合适的执行单元
:实际的ALU或乘法器操作等
:执行数据加载或存储
寄存器写回
:用结果更新处理器寄存器
在单独的处理器实现时,这些步骤的一些可被组合成一个单一的流水线阶段,或一些步骤可被分布在几个周期。较长的流水线意味着每个流水线之间的关键路径中更少的逻辑门,从而更快地执行。然而,
指令之间会有依赖
。如果一个指令依赖于前一指令的结果,控制逻辑需要
插入位置(或泡沫)
到流水线,直到依赖解决。需要附加的逻辑来检测和解决这样的依赖。
更近一步的缺点
是有时来自内存的
指令的串行执行会被打断
。这可能会发生在一个
分支指令执行的结果
一个异常事件
(例如一个中断)。当此发生时,处理器无法决定下一条应该被获取指令的正确位置,直到分支被解决。在典型的代码中,很多分支指令是有条件的,作为循环或者if声明的结果。因此,分支是否会被执行不能再指令获取时决定。如果我们获取的指令紧跟着一个分支,并且分支被执行,流水线必须清空,来自分支目的地的指令新指令集必须从内存获取。
随着流水线变长,分支惩罚的代价变得更高
Cortex-A系列处理器具有
分支预测逻辑
减少分支惩罚的影响
。本质上,处理器预测一个分支是否会被执行,获取的指令要么来自紧跟分支之后的指令(如果预测表明条件分支不会被执行),要么来自分支的目标指令(如果预测表明分支会被执行)。
如果预测正确,分支不会清空流水线
流水线必须清空
,并且获取来自正确位置的指令来充填
。我们将在下面的分支预测里看到更多细节。
4.4.1 多发布流水线
一个精致的处理器流水线是我们可以有超过一个硬件单元来处理流水线阶段。在ARM11处理器家族,例如,有三个并行后端流水线 --- 一个ALU流水线,一个load/store流水线和一个乘法流水线。指令可被发布进这些中的任何流水线。这个想法的一个合乎逻辑的发展是,有多个执行硬件的实例 --- 例如两个ALU流水线。我们就可以在一个周期发布超过一个指令到这些并行流水线 --- 一个指令级并行的例子。这样的处理器被称为
超标量体系结构(superscalar)
Cortex-A15
超标量处理器
--- 它们可以
在一个时钟周期中潜在地
译码和发布超过一个指令
。Cortex-A5和Cortex-A7处理器相对受限制,只能双发射特定指令的组合 --- 例如,一个分支和一个数据处理指令可以在同一周期内发布。指令仍然从内存中的串行指令流中发布。
需要额外的硬件逻辑来检查指令间的依赖性
,例如,在一个指令必须等待其它指令结果的情况下。
乱序执行为提升流水线效率提供了空间。如果指令被串行执行,一个指令在下一个处理之前完全退休。在乱序处理中,多内存访问可以是立刻显著的,并且可以以不同的顺序完成。
一个指令必须停滞,由于依赖
(例如,需要使用来自前面指令的结果)。我们
执行下面的没有共享这一依赖的指令
,提供指令之间的逻辑危害是严格推崇的。
Cortex-A15
处理器使用这一技术
实现非常高等级的效率和指令吞吐量
。它们可以被认为是
可变长度的流水线
,因为流水线长度取决于一个指令使用的后端执行流水线。它们可以独立地执行指令,并且在每个时钟可以译码两个指令,但是有在一个独立时钟周期发布最高四条指令的能力。这可以提高性能,如果流水线已经变得畅通,前面由于一些原因停滞了。
4.4.2 寄存器重命名
处理器有一个有趣的微架构实现,使用了一个
寄存器重命名方案
。作为标准ARM架构一部分的寄存器集对程序员可见,但是
处理器的硬件实现
一个更为大的物理寄存器池
动态地映射程序员可见寄存器到物理寄存器
。图4-5显示了分开的架构寄存器池和物理寄存器池。
考虑一种情况,代码
写一个寄存器的值到外部存储器
紧接着其后
读取一个不同外部存储器位置的值到相同的寄存器
。这在前面的处理器中可能
会引起流水线停滞
,尽管在此特殊的例子中,没有实际上的数据依赖。寄存器重命名避免这个问题,
通过确保两个R0实例被重命名到不同的物理寄存器,移除了依赖
。这允许了一个编译器或汇编程序员在没有内部指令之间的依赖时,重用寄存器,而不需要考虑因为重用寄存器导致的架构上的惩罚。重要的是,这
允许了write-after-write和write-after-read序列的乱序执行
。(write-after-write的危害出现在两个独立的指令写值到相同的寄存器。处理器必须确保来自这两条指令之后的指令看到的是后一条指令的结果)
为避免与标志位设置和比较相关的指令间的依赖,
APSR标志也使用相同的技术
4.5 分支预测
一个条件跳转指令第一次被获取时,没有关于下一条指令地址的可依赖信息。旧的ARM处理器使用
静态分支预测
。这是最简单的分支预测方法,因为
它不需要关于分支的先前信息
推测向后的分支会被采用
向前的分支不会
。向后的分支具有一个目标地址,低于它自己的地址。我们因此可以看一个单一的操作位来决定分支方向。这个技术可以给与合理的预测精度,
归因于代码中循环的普遍
,循环代码总是包含后向分支,并且后向总比前向多很多
。由于Cortex-A系列处理器的流水线长度,我们通过使用更为复杂的给予更好预测精度的分支预测方法,可以获得更好的性能。
动态分支预测
可以进一步减少平均分支惩罚,
在前面执行时条件分支是否被采用的
处理器中的
分支目标地址缓存(Branch Target Address Cache ,BTAC)
分支目标缓冲(Branch Target Buffer ,BTB)
保存有前次分支指令执行的信息
。它使得硬件能够推测一个条件分支是否会被采用。
仍然必须评估
附带在分支指令上的条件代码
。如果分支预测硬件预测正确,流水线不必停滞。
如果分支预测硬件评估错误,处理器必须清空流水线并充填它。
4.5.1 返回堆栈(return stack)
在分支预测中的描述看到了处理器可以用于预测分支是否会被采用的策略。
对绝大多数分支指令,目标地址固定并编码在指令中
。然而,有一类分支,
分支目标的目的地不能通过看指令决定
。例如,如果我们执行一个数据处理操作,它修改了PC(例如,MOV,ADD or SUB),我们必须等待ALU来评估结果,在我们能够直到分支目标之前。类似的,如果我们从内存加载PC,使用一个LDR,LSM,或POP指令,我们不能知道目标地址直到加载完成。
通常,这样的分支(常称为
)不能在硬件上被预测。然而,有一个常见的情况可以很有用地被优化,在
预取硬件中使用一个
后进先出堆栈(return stack)
。任何时候一个
函数调用(BL或BLX)指令被执行
,我们进入
压入接下来的指令到这个堆栈
。任何时候当我们遇到一个指令,它可以被识别为
函数返回指令(BX LR,或一个在寄存器列表中包含PC的堆栈pop操作)
,我们可以
投机地从堆栈pop一个条目
硬件比较指令生成的地址和堆栈预测的地址
。如果未命中,流水线被清空,我们从正确的位置重新开始。
返回堆栈有固定的大小(例如,在Cortex-A8或Cortex-A9处理器中有8个条目)。如果一个特殊的代码序列包含大量嵌套的函数调用,一个8条目返回堆栈可以预测前8个函数返回。
4.5.2 程序员的角度
对于大多数应用级的程序员,分支预测是硬件实现的一部分,可以安全的被忽略。然而,
处理器分支行为的知识可以是有用的
编写高度优化的代码时
硬件性能监视器计数器
生成关于分支正确与否预测数目的信息
。这一硬件在第19章被进一步描述。
分支预测逻辑在
复位时被禁止
。启动代码序列的一部分典型地会被用于
设置CP15:SCTLR(系统控制寄存器)的Z位
,这使能了分支预测。有一个其它的情形编程者需要注意。当在一个地址移动或修改代码,在此地址上的代码已在系统中被执行,从分支历史逻辑中移除旧的条目是必要的(并且总是明智的),通过使用CP15指令作废所有条目。
已发表评论数()
&&登&&&陆&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见

我要回帖

更多关于 指令寄存器 的文章

 

随机推荐