04-处理器体系结构

本节主要总结学习了Y86-64的指令流水。相比X86-64,Y86精简指令集便于学习。Y86-64有15个程序寄存器,相比X86-64,省略了%r15以简化指令的编码。每个程序寄存器存储一个64位的字。寄存器%rsp被入栈、出栈、调用和返回指令作为栈指针。除此之外寄存器没有固定的含义或固定值。有3个一位的条件码:ZF、SF和OF,他们保存着最近的算术或逻辑指令的所造成影响的有关信息。程序计数器PC存放当前正在执行的指令的地址。内存从概念上来说就是一个很大的字节数组,保存着程序和数据。程序状态的状态码表明程序执行的总体状态,指示程序正常运行还是出现异常。

-w1063

我们主要讲解一下相关Y86指令的执行流程,那么相比于x86-64的指令集,Y86-64做了简化,movq指令被分成了rrmovqirmovqrmmovqmrmovq四种。movq前面的两个祖母分别表示了源和目的的格式。

-w1066

指令编码

-w1074

可以看到一个指令,前两个位置是一个字节,高四位表示指令代码,低4位表示指令功能,关于前两个位置(一字节)的部分描述如下:
-w1084

操作数如果是寄存器,则直接填其编号,寄存器对应编号如下:
-w1075

整数操作指令:
-w1263

跳转操作指令:
-w1221

传送操作指令:
-w1227

其他系统操作指令:
-w1158

关于指令编码,举个例子,在Y86-64汇编代码中,对如下汇编代码是如何翻译成二进制表示的呢?

rmmovq %rsp, 0x123456789abcd(%rdx)

根据rmmovq指令的编码定义,该指令二进制表示中的第一个字节为0x40,寄存器%rsp编号为0x4;基址寄存器%rdx编号为0x2;因此该指令二进制表示第二个字节为0x42。指令编码中偏移量占8个字节,因此我们需要在该偏移量前面补0来凑齐8个字节。即:
00 01 23 45 67 89 ab cd

又由于我们采用小端法存储,因此还要对偏移量进行字节反序操作即:
cd ab 89 67 45 23 01 00

最终我们得到该指令的二进制表示如下:
-w646

以上则为指令编码二进制表示,那么关于Y86-64状态码:
-w1203

可以看到在Y86-64中,程序代码于x86-64不同点主要在于数据传送指令:
-w1255

-w1239

处理器执行指令流程:

阶段:
-w1205

接下来主要说明几个指令的执行流程,如subq运算指令、irmovq传送指令、rmmovq传送指令、pushq压栈指令、je跳转指令等

sub指令各个阶段:
-w1293

irmovq指令的各个阶段:
-w1324

rmmovq指令的各个阶段:

-w1318

push指令的各个阶段:

-w1149

je指令的各个阶段:

-w1137

硬件设计

取址阶段硬件设计

在取址阶段中,取址操作以程序计数器(PC)的值为起始地址。由于Y86-64指令 集中最长的指令占10字节,为了保证每次取址操作至少能够获得一条完整的指令, 取址操作每次从指令内存中读取10各字节。接下来将这10字节分为两部分,第一部分1字节,第二部分9字节。例如编码为30 f8 08 00 00 00 00 00 00 00的指令,将被分成30f80800000000000000

随后名为Split的硬件单元处理第一部分。它将这个字节又分成两部分,每部分占4个比特位,使这个字节分为两个字段,分别为指令代码和指令功能,用icodeifun表示。根据icode可以确定当前指令的状态信息,例如指令的合法性。如果icode0x00xB之间,那么它就是一条合法指令。此外,通过icode还可以判断当前指令是否包含寄存器指示符字节和常数字节。
-w1224

通过前面说的判断结果,就可以计算出当前指令的长度。例如一个指令既含寄存器指示符字节,又含常数字节,那它的长度就是10字节;如果既不含寄存器指示符字节,又不含常数字节,那它的长度就是1字节。与此同时,还可以通过将PC值加上当前的指令长度来计算内存中下一条指令的地址,用于后续的更新阶段

在前面我们处理了一条指令中的头一个字节,对于剩下的9个字节,我们通过名为Align的硬件单元来产生寄存器字段和常数字段。该硬件单元通过信号need_regids来判断该指令是否包含寄存器指示符字节。若need_regids = 1,说明该指令包含寄存器指示符字节,那么第一个字节将被分成两部分,每部分占4个比特位,然后分别装入寄存器指示符rArB中;若need_regids = 0,说明该指令不包含寄存器指示符字节,此时将rArB这两个字段设置为0xF。此外,若该指令含有常数,Align单元还将产生常数字段valC。当need_regids = 1时,valC被设为指令的第29字节;当need_regids = 0时,valC被设为指令的第18字节。

译码阶段硬件设计

译码阶段的操作是从寄存器文件中读取数据,在Y86-64处理器中寄存器文件有两个读端口,它支持同时进行两个读操作,两个读端口的地址输入为srcAsrcB,从寄存器文件中读出的数值通过valAvalB输出。读端口的srcAsrcB用于产生寄存器的ID,这需要寄存器指示符rArB。由于某些指令,例如push指令,该指令的寄存器指示符中只含有目的寄存器的ID,但执行压栈操作时,还需要获得栈顶指针rsp的值。因此srcAsrcB不仅需要传入rArB,还需要传入指令代码icode

执行阶段硬件设计

执行阶段的核心部件ALU根据指令功能ifun来判断要对输入的操作数进行何种运算。每次运行时,ALU都会产生三个与条件码相关的信号—:零、符号、溢出。我们只希望ALU在执行算术逻辑指令时才设置条件码,而计算内存引用地址以及栈操作时不要设置条件码。因此我们使用Set_CC信号根据指令代码icode来控制是否需要设置条件码。此外,我们使用名为Cond的硬件单元来控制跳转操作。Cond会根据指令功能和条件码寄存器来产生Cnd信号。对于跳转指令,如果Cnd = 1,就执行跳转;如果Cnd = 0`,则不执行跳转。

访存阶段硬件设计

该阶段的硬件设计主要包含以下四个控制块:

  • 读控制块,用于进行读操作。
  • 写控制块,用于进行写操作。
  • 内存地址控制块,用于产生内存地址。
  • 数据输入控制块,用于输入数据。

除此之外,访存阶段的最后还将根据icode判断出的指令有效性以及内存状况产生instr_validimem_error信号来计算状态码。

写回阶段硬件设计

首先为寄存器文件系统添加ME,这两个写端口,对应的地址输入为dstEdstM。需要注意的是,当执行条件传送指令 (cmov) 时,写入操作还要根据执行阶段计算出的cnd信号,当条件不满足条件时,以将目的寄存器设置为0xF来禁止写入寄存器文件。

更新阶段硬件设计

在更新阶段,PC的值有以下三种情况:

  • 当前执行的指令是函数调用指令call,此使将PC值设为call指令的常数字段。
  • 当前执行的指令是函数返回指令ret,此使将PC值设为ret指令在访存阶段从内存中读出的返回地址。
  • 当前执行的指令是跳转指令jxx,此使若满足跳转条件(cnd = 1),则新的PC值等于跳转指令的常数字段;若不满足跳转条件(cnd = 0),则新的PC 值等于当前PC值加上当前指令长度。
  • 数据输入控制块,用于输入数据。
posted @ 2023-07-13 19:44  miseryjerry  阅读(93)  评论(0编辑  收藏  举报