ISA操作码-它们来自哪里?


13

工程师在设计指令集体系结构时,将某些二进制代码指定为指令时会遵循什么程序或协议(如果有)。例如,如果我有一个说10110是加载指令的ISA,那么二进制数字是从哪里来的?是否从状态表中为表示加载操作的有限状态机建模?

编辑:经过更多研究,我相信我要问的问题涉及如何分配各种CPU指令的操作码。可以使用10011的操作码来指定ADD;一条加载指令可能指定为10110。为指令集分配这些二进制操作码有什么思路?


8
Monte Dalrymple的“使用Verilog HDL进行微处理器设计”为Z80 CPU提供了非常详细的设计方法,从中我想您会学到很多有关您的问题的知识。但是,有许多考虑因素需要进入特定的选择,包括对其他指令集的统计分析,编译器输出等。不过,我还是建议从本书开始。尽管它始于一个已知的设计,但他详细介绍了它,我想您会学到一些东西。好书。
jonk

或者,也许您是在询问执行引擎的设计,并且想知道指令中的位会如何发挥作用?从您的措辞不确定。
jonk

2
有人问这个问题。必须是星期二。
伊格纳西奥·巴斯克斯

5
@Steven考虑一下。如果要设计一个ISA,你会想起什么?如果您的指令长度不尽相同,将如何选择较短或较长的指令字?如果必须设计一个解码级,您希望 ISA看起来像什么?我认为这个问题是不必要的广泛问题(因此几乎不可能完全回答),但是您可以通过添加一些自己的想法并提出一个不需要我们写书来回答的精确问题来进行很多改进它。
MarcusMüller17年

4
RISC-V规格谈论他们在各级各类,包括公平一点关于机器指令编码的设计决策。(对于处理器手册,这是不寻常的;与大多数情况不同,RISC-V首先是学术练习,其次是CPU体系结构。)
zwol

Answers:


6

在很多情况下,随着ISA的增长,选择是相当随意的,或者是基于“最适合的地方”。但是,MOS 6502是芯片的一个很好的例子,在该芯片中,ISA设计受尽了最大的努力,因为它试图从有限的晶体管中尽可能地挤压出来。

看看这个视频说明6502如何逆向工程,特别是从34:20开始。

6502是1975年推出的8位微处理器。尽管它的门数比Z80少60%,但速度却是Z80的两倍,尽管它受到更多限制(在寄存器等方面),但它还是用了优雅的指令集。

它仅包含3510个晶体管,这些晶体管是由一小群人在一些大的塑料板上爬行并手工拉出的,这些塑料板随后被光学收缩,形成了6502的各个层。

如下所示,6502将指令操作码和时序数据传递到解码ROM,然后将其传递到“随机控制逻辑”组件,其目的可能是在某些复杂情况下否决ROM的输出。

6502框图

在视频中的37:00,您可以看到解码ROM的表,该表显示输入必须满足哪些条件才能为给定的控制输出获得“ 1”。您也可以在此页面上找到它。

您可以看到该表中的大多数内容在各个位置都有X。让我们举个例子

011XXXXX 2 X RORRORA

这意味着操作码的前3位必须为011,G必须为2;别的都无所谓。如果是这样,则名为RORRORA的输出将为true。所有ROR操作码均以011开头;但是还有其他说明也以011开头。这些可能需要由“随机控制逻辑”单元过滤掉。

因此,基本上,选择了操作码,以便需要彼此执行相同操作的指令在其位模式中具有某些共同点。您可以通过查看操作码表来看到这一点;所有“或”指令均以000开头,所有“存储”指令均以010开头,所有使用零页寻址的指令均采用xxxx01xx的形式。当然,某些指令似乎并不“适合”,因为其目的不是要具有完全规则的操作码格式,而是要提供功能强大的指令集。这就是为什么需要“随机控制逻辑”的原因。

我在上面提到的页面上说,ROM中的某些输出行出现了两次,“我们假设这样做是因为它们无法将所需行的输出路由到所需的位置,因此将同一行放在不同的位置再次定位。” 我可以想象工程师们一个接一个地绘制这些门,突然意识到设计中存在缺陷,并试图提出一种避免重新启动整个过程的方法。


22

这取决于ISA的年龄。

在手工设计的早期,甚​​至更多的情况是,当CPU由离散逻辑组装而成时,逻辑设计将首先出现并被广泛地最小化,然后,ISA位模式将是使该最小化所需的任何值。逻辑工作。

因此,可能会有一种特殊的控制信号模式,使某些多路复用器能够将ALU输出连接到GP寄存器文件的输入,还有一些控制信号指示ALU加,减,AND,OR等,还有一些地址位进入寄存器文件。这三组信号将在指令内形成字段。每个组将保持在一起,其详细含义从该单元(ALU等)的设计中产生,但是这些组可以以任何顺序排列,直到您设计指令解码器为止。(x86足够旧,如果您在正确的位置查看,您可以检测到其中一些-这不是全新的设计,而是借鉴了较旧的8080)

以后的ISA可能会被“清理”,并变得更加常规和易于使用,并且硬件有时会通过“微码”在它们和实际的硬件级控制信号之间进行转换。这些被称为“ CISC”或“复杂指令集编码”。x86“ Rep”指令前缀就是一个简单的例子-它使以下指令重复多次,从而省去了编写FOR循环的麻烦。

后来(在1980年代),人们又回到了更简单的直接编码样式(RISC-精简指令集编码),您可以在ARM处理器中看到这种样式。这是由于当时ASIC的尺寸较小,并且希望在其上放置32位CPU,因此没有足够的空间用于复杂的指令集解码器,以使整个CPU降至约20,000门。(这是暂时的性能提升,因为人们尚未开发出使CISC解码器更快的技术-大约在1995年,奔腾Pro就出现了。)

如今,这无关紧要-CPU一次读取几条指令,并投入数百万个晶体管对其进行解码,重新排序并一次执行尽可能多的指令,以加快可能是最早编写的程序的速度。 ISA的样式。


2
我不确定我是否真的将CISC称为“更易于使用”。那可能是最初的意图,但是30年后,它们有点像“易于使用”(至少与RISC ISA相比)。
tonysdg

2
在某些方面,它们更易于使用...早在编译器是相对琐碎的程序时就可以使用正则性(正交性是一个大话题),或者可以通过直接支持更高级别的操作来减少编译器的转换。但这是很久以前的事了,任何尚存的CISC都在其原始指令集的基础上进行了如此多的修订。编译器也已经改变了所有的认知-那时gcc执行的约1000次优化遍历是不可想象的。因此,当时和现在几乎没有什么关系。
Brian Drummond

4
这种区别既被侵蚀(添加更多指令的“ RISC”集),又被新的甚至更复杂的体系结构(例如VLIW)所取代;真正唯一的共识是x86(16和32位)很难使用
pjc50

1
@tonysdg:很难使用RISC和CISC。“程序员友好性”的一个很好比较是比较68k与ARM。ARM是为编译器设计的,因此您必须进行大量手动工作才能从RAM中获取数据并将其写回RAM。68k是为汇编程序员设计的,可让您直接对RAM中的数据进行操作。如果您查看68k ISA,您会发现它看起来很像现代RISC ISA,但有一个例外-您可以直接在RAM上进行操作,而RISC仅允许您在寄存器上进行操作。
slebetman

1
微码主要是CISC属性。但是,您可以在没有微代码的情况下实现CISC:指令解码器会更复杂。您还将看到从Pentium-Pro开始的一些CISC在内部被描述为RISC。将每条CISC指令翻译成一个或多个内部RISC操作:微代码的另一个名称(尽管区别在超标量执行单元中变得模糊)
Brian Drummond

9

如果将类似的说明分组在一起,则会出现模式。这在ARM中非常明显,ISA手册实际上向您显示了指令字的哪一位对应于功能,寄存器选择等。但是对于X86也可以推断出来。

最终,操作码的“功能”部分进入某种二进制到单字节的解码器中,该解码器实际上会激活特定功能或流水线操作序列。它们通常与任何状态机的内容都不相关,除非我们考虑使用需要状态机解码的可变长度指令。


您基本上是在说他们正在争取芯片上尽可能少的晶体管数量。我完全同意OP的问题,因为他们无法负担得起数百个额外晶体管的整洁指令集。上百万个晶体管的CPU没有太多需要理会的理由,但是当然有许多理由保留它是为了向后兼容。
哈珀-恢复莫妮卡

@Harper仍然有原因,因为尽管晶体管变小了,但它们仍然具有尺寸-同时时钟速率也增加了很多。因此,太大的指令解码器仍可能是性能的瓶颈(许多CPU选择提前对指令进行解码的原因之一)。这与晶体管数量无关,而与时钟速率和芯片面积有关。信息仍然需要花费时间来传播,并且尽管现代CPU并没有以光速运行,但距离速度极限还远远不够,无法期待显着的改进。
六安'17

@Luaan:实际上,“如今我们如何处理所有这些晶体管”是一个真正的问题。看一下当今抛出的所有L2 / L3缓存。这是一个默默的承认,我们没有更好地使用所有数百万个晶体管。最新的Xeon专用缓存超过20 亿个晶体管!
MSalters

6

有人在某个时候坐下​​来对它们进行了定义。

良好的ISA将使解码器尽可能简单。

例如,使用ALU指令,您可以让操作码的某些位直接发送到ALU的控制线中。


感谢所有人的出色回答。你们都帮助我更好地理解了这一点。
史蒂文

4
实际上,除了解码器的简便性之外,还有很多其他因素需要考虑。取决于环境和预期用途,其他方面(例如,代码密度)可能比解码器的简化更为重要。在现代处理器中,大多数情况下,代码密度可能超过解码器的简便性。
杰里·科芬

5

通常,您会将ISA分为功能组。(对于逻辑优化或整洁而言)有意义的是,互补对通过单个位更改(加载与存储)来区分,并且您具有影响解码决策树的某些位层次结构。

归根结底,为功能块分配任意位(与在指令中放置“数据”字段相反)只会对您的整体设计效率产生很小的影响-但是您可以选择很多方法根据您的感受,“优化” ISA编码是一个重要参数。


1

指令编码之间是一个丑陋的折衷。

使解码变得简单,为此,您需要一组简单的字段,每个字段可以分别解码,然后路由到执行引擎的单独部分。

将尽可能多的功能打包到有限大小的指令字中。这就导致了诸如特殊的常量格式之类的事情,该格式可以对各种通用数字进行编码。

向前和向后兼容性。如果为每个可能的操作码分配功能,那么您将没有空间扩展以后的体系结构。如果要添加到现有体系结构,则必须将新指令放入备用操作码中。


1

兰迪·海德(Randy Hyde)的出色著作(如果有些过时)在第3.3.4节“控制单元和指令集”及其后的章节中,x86指令集对组装艺术进行了详细介绍。

早期(冯·诺依曼之前)计算机系统中的程序通常“硬连线”到电路中。也就是说,计算机的布线确定了计算机将要解决的问题。为了更改程序,必须重新布线。一项非常艰巨的任务。计算机设计的下一个进步是可编程计算机系统,它使计算机程序员可以使用一系列插座和插头线轻松地“重新布线”计算机系统。计算机程序由一组孔(插槽)组成,每行代表程序执行期间的一个操作。程序员可以通过将电线插入所需指令的特定插座中来选择多个指令之一。

然后,他展示了相当吸引人的内容,并详细介绍了前几个插件代表指令的方式,接下来的插件对源和目标进行编码。当然,今天没有人再“插入”了,但是对于真正古老的ISA,操作码中的位基本上与以前的插入工作相同。

您最终得到这样的结果:

在此处输入图片说明


感谢您从海德获得的链接!这非常有用,他似乎具有出色的教学风格。
史蒂文
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.