gpt4 book ai didi

encoding - 使用统一格式的指令有什么好处?

转载 作者:行者123 更新时间:2023-12-02 21:29:35 26 4
gpt4 key购买 nike

许多处理器的指令具有统一的格式和宽度,例如ARM,其中所有指令均为32位长。其他处理器具有多条宽度的指令,例如2、3或4个字节长,例如8086。


使所有指令具有相同的宽度和统一的格式有什么好处?
使用多种宽度的指令有什么好处?

最佳答案

固定长度指令的权衡

固定长度的指令具有相对统一的格式的优点在于,提取和解析指令实际上更为简单。

对于每个周期获取一条指令的实现,可以保证对固定大小的单个对齐内存(高速缓存)访问提供一条(也只有一条)指令,因此不需要缓冲或移位。也不必担心在一条指令中越过缓存行或页面边界。

指令指针与指令类型无关地增加固定量(执行控制流指令时,跳转和分支除外),因此下一条顺序指令的位置可以尽早使用,而所需的额外工作最少(与至少部分解码指令)。这也使得每个周期获取和解析多个指令相对简单。

每条指令具有统一的格式,可以将指令轻松解析成其各个组成部分(立即值,操作码,源寄存器名称,目标寄存器名称)。解析源寄存器名称是最关键的时序。通过将它们固定在固定位置,可以在确定指令类型之前开始读取寄存器值。 (此寄存器读值是推测性的,因为该操作可能实际上并未使用这些值,但是在错误推测的情况下,此推测不需要任何特殊的恢复,但会花费额外的精力。)在MIPS R2000的经典5级流水线中,这允许读取指令后立即开始的寄存器值,提供半个周期来比较寄存器值并解析分支的方向;通过(填充的)分支延迟时隙,可以避免没有分支预测的停顿。

(解析操作码通常比源寄存器名称在时序上要紧一些,但是操作码的提取越早,执行就越早开始。简单地从目标寄存器名称中解析就可以使检测指令之间的依赖关系变得更加简单;这也许主要是有帮助的尝试每个周期执行一条以上的指令时。)

除了可以更快地提供解析之外,更简单的编码还可以减少解析工作(能耗和晶体管逻辑)。

与典型的可变长度编码相比,固定长度指令的一个次要优势是指令地址(和分支偏移)使用的位更少。在某些ISA中已利用此方法为模式信息提供少量额外的存储。 (具有讽刺意味的是,在MIPS / MIPS16之类的情况下,使用较小或可变长度的指令来指示模式。)

定长指令编码和统一格式确实有缺点。最明显的缺点是代码密度相对较低。无法根据使用频率或需要多少不同信息来设置指令长度。严格统一的格式也倾向于排除隐式操作数(尽管即使MIPS使用链接寄存器的隐式目标寄存器名称)和可变大小的操作数(大多数RISC变长编码都有简短的指令,它们只能访问总数的子集。寄存器)。

(在面向RISC的ISA中,这还有一个较小的问题,即不允许将更多工作捆绑到一条指令中,以均衡该指令所需的信息量。)

固定长度的指令还会使使用大立即数(指令中包含的常量操作数)更加困难。经典RISC将立即长度限制为16位。如果常量较大,则必须将其作为数据加载(这意味着需要额外的加载指令,其地址计算,寄存器使用,地址转换,标签检查等开销)或第二条指令必须提供其余的常量。 (MIPS提供了一个加载高立即数的指令,部分地是在假定大常量主要用于加载地址(以后将用于访问内存中的数据)的前提下。PowerPC提供了一些使用高立即数的操作,例如,允许添加32 -位立即数(在两条指令中)。使用两条指令显然比使用一条指令要大得多的开销(尽管聪明的实现可能会使前端的两条指令融合在一起(英特尔称之为“宏运算融合”))。

固定长度的指令还使得在保持二进制兼容性(并且不需要附加操作模式)的同时扩展指令集变得更加困难。甚至严格统一的格式也会阻碍指令集的扩展,特别是对于增加可用寄存器的数量而言。

富士通的SPARC64 VIIIfx是一个有趣的示例。它使用一个两位操作码(在其32位指令中)来指示一个特殊寄存器的加载,该寄存器具有用于接下来的两条指令的两个15位指令扩展。这些扩展提供了额外的寄存器位和SIMD操作指示(即扩展了应用扩展的指令的操作码空间)。这意味着一条指令的完整寄存器名称不仅不完全位于固定位置,而且甚至不在同一“指令”中。 (可能会注意到与x86的REX前缀的相似之处-它提供了一些位来扩展指令主要部分中编码的寄存器名称。)

(固定长度编码的一个方面是对2的幂的独裁。尽管可以使用非2的幂的指令长度[Tensilica的XTensa现在具有固定的24位指令作为其基本ISA—— 16位短指令支持是一种扩展,以前它们是基本ISA的一部分; IBM拥有40位指令的实验性ISA。],这样​​会增加一点复杂性。如果一个大小(例如32位)太短,则下一个可用大小(例如64位)可能太长,从而牺牲了太多的代码密度。)

对于具有深管线的实现,解析指令所需的额外时间不太重要。对于高性能实现的重要性降低了由硬件完成的额外动态工作和额外的设计复杂性,这些高性能实现增加了复杂的分支预测,乱序执行和其他功能。

可变长度指令的权衡

对于变长指令,折衷基本上是相反的。

更高的代码密度是最明显的优势。更高的代码密度可以改善静态代码大小(给定程序所需的存储量)。这对于某些嵌入式系统(尤其是微控制器)尤其重要,因为它可能占系统成本的很大一部分,并且会影响系统的物理尺寸(这会影响其适用性和制造成本)。

改善动态代码大小可减少用于提取指令的带宽量(从内存和缓存中获取)。这样可以减少成本和能源消耗,并可以提高性能。较小的动态代码大小也可以减少给定命中率所需的缓存大小。较小的缓存可以使用更少的能量和更少的芯片面积,并且可以拥有更低的访问延迟。

(在具有狭窄内存接口的非流水或最少流水线的实现中,在某些情况下,在一个周期中仅提取一条指令的指令不会像在受流水线带宽限制的流水线设计中那样严重地损害性能。)

对于可变长度的指令,可以在指令中使用大常数,而无需所有指令都变大。使用立即数而不是从数据存储器加载常量会利用空间局部性,在流水线中更早地提供值,避免额外的指令,并删除了对数据缓存的访问。 (更广泛的访问比总大小相同的多个访问更简单。)

如果支持可变长度指令,则扩展指令集通常也比较容易。可以通过使用超长指令来包含其他信息。 (对于某些编码技术,尤其是使用前缀的编码,还可以在现有指令中添加提示信息,以实现与其他新信息的向后兼容性。x86不仅利用了这一点,还提供了分支提示[大多数未使用]和硬件锁定扩展(Hardware Lock Elision)扩展。对于固定长度的编码,很难预先选择哪些操作应保留其他操作码,以备将来可能添加提示信息。)

可变长度编码显然使查找下一个顺序指令的开始变得更加困难。这对于实现来说不是什么大问题
每个周期仅解码一条指令,但即使在这种情况下,它也会增加额外的
为硬件工作(这可能会增加周期时间或流水线长度,并消耗更多能量)。对于更广泛的解码,可以使用几种技巧来减少从指令存储器块中解析出单个指令的成本。

主要在微体系结构上使用的一种技术(即,不包括在软件公开的界面中,而仅包括在实现技术中)是使用标记位指示指令的开始或结束。将为指令编码的每个包设置此类标记位,并将其存储在指令高速缓存中。这样的延迟在指令高速缓存未命中上这种信息的可用性,但是与填充高速缓存未命中的普通延迟相比,该延迟通常很小。仅在高速缓存未命中时才需要额外的(预)解码工作,因此在高速缓存命中的常见情况下可以节省时间和能量(以一些额外的存储和带宽为代价,这会消耗一些能源)。

(一些AMD x86实现使用了标记位技术。)

可替代地,标记位可以被包括在指令编码中。由于标记位有效地成为操作码的一部分,因此这对操作码的分配和放置施加了一些限制。

IBM zSeries(S / 360和其后代)使用的另一种技术是在第一个包裹的操作码中以一种简单的方式对指令长度进行编码。 zSeries使用两位对三种不同的指令长度(16、32和48位)进行编码,而两种编码用于16位长度。通过将其放置在固定位置,相对容易地快速确定下一个顺序指令的开始位置。

(还可以进行更积极的预解码。奔腾4使用了包含固定长度微操作的跟踪缓存,而最近的英特尔处理器使用了[大概]固定长度微操作的微操作缓存。)

显然,可变长度编码需要以通常小于固定长度ISA指令的包裹粒度进行寻址。这意味着分支偏移要么失去某个范围,要么必须使用更多位。这可以通过支持更多不同的立即数来补偿。

同样,由于一条指令的开头很可能不会与2的较大幂对齐,因此获取一条指令可能会更加复杂。缓冲指令提取减少了这种影响,但是增加了(微不足道的)延迟和复杂性。

对于可变长度的指令,统一编码也更加困难。这意味着在开始指令的基本解析之前,必须经常对部分操作码进行解码。这往往会延迟寄存器名称和其他不太重要的信息的可用性。仍然可以获得显着的均匀性,但是这需要更仔细的设计和权衡取舍(这可能会在ISA的整个使用期限内发生变化)。

如前所述,使用更复杂的实现(更深的流水线,无序执行等),可以减少处理可变长度指令的额外相对复杂性。在指令解码之后,具有可变长度指令的ISA的复杂实现往往看起来与具有固定长度指令的ISA十分相似。

还可能需要注意的是,可变长度指令的许多设计复杂度都是一次性的成本。一旦组织学习了处理怪癖的技术(包括验证软件的开发),对于以后的实施,这种复杂性的成本就会降低。

由于许多嵌入式系统都担心代码密度,因此一些RISC ISA提供了可变长度的编码(例如microMIPS,Thumb2)。这些通常只有两个指令长度,因此增加了复杂度。

捆绑式折衷设计

为某些ISA选择的一种(多种中间)替代方法是使用固定长度的指令束和不同长度的指令。通过将指令包含在束中,每个束具有固定长度指令的优点,并且每个束中的第一条指令具有固定的对齐起始位置。 CDC 6600使用具有15位和30位操作的60位捆绑软件。 M32R使用带有16位和32位指令的32位捆绑软件。

(Itanium使用固定长度的2的幂次幂束来支持两个[41位]指令的非幂次,并且在少数情况下,两个“指令”结合在一起以允许64位立即数。Heidi Pan的[academic] Heads和尾部编码使用固定长度束从左到右编码固定长度基本指令部分,从右到左编码可变长度块。)

某些VLIW指令集使用固定大小的指令字,但该字内的各个操作插槽的长度可以不同(但对于特定插槽固定)。因为不同的操作类型(对应于插槽)具有不同的信息要求,所以对不同的插槽使用不同的大小是明智的。这提供了固定大小的指令的优点,并具有一些代码密度的好处。 (此外,可以分配一个插槽以有选择地为指令字中的一个操作提供立即数。)

关于encoding - 使用统一格式的指令有什么好处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21481427/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com