Simulator Lab
ICS Lab5: Y86-64 Simulator
在Lab5中,我们要实现一个Y86-64 Simulator来模拟执行y86二进制代码的硬件行为。
y86sim.c
程序读进一个y86 instruction文件,根据y86指令结构来parse二进制代码。分析并确定指令后,该程序修改y86处理器状态。
Skeleton Code
开始coding之前先认真看一下skeleton code的结构:
关键是y64sim_t
结构,用了4个变量分别表示y86处理器状态:PC, 寄存器,内存和CC,其中寄存器和内存各自用一块连续空间的数组表示,通过register specifer和内存地址作为数组index访问相应的寄存器和内存地址。
1 |
|
Implementation (Code Alert!)
这个lab的关键在于实现nexti
函数,这个函数的输入是当前的y86 image(包括PC, 寄存器,内存和CC)。
首先第一步是parse指令,根据instruction code来获取寄存器和立即数。获取到的寄存器分别存在rA和rB里面,立即数存在valC里面。
1 |
|
这里我用了两个helper function: get_register_needed
和get_immediate_needed
来根据instruction code确定是否需要获取register specifier和8位的immediate,参考下图y86指令集:

然后就是补全switch语句根据指令前4 bits的instruction code来分别执行相应的操作,需要注意以下几类指令:
-
OPq
: 根据function code确定具体需要执行的ALU操作。需要实现compute_alu
执行ALU操作,compute_cc
根据ALU操作结果设置CC。如何判断ADD和SUB操作有无overflow?
如果两个
long_t
类型数相加,得到的和的符号与原本两个数符号相反,则overflow:1
ovf = ((argA ^ val) & (argB ^ val)) >> 63;
减法可以转化成第一个数加第二个数的相反数,与加法overflow判断方式相同。
-
jXX
和cmovXX
: 需要实现cond_doit
,先根据function code和当前的cc来判断能否执行。如何判断Less和Greater?
两个数相减,如果是负数且没有overflow,或是正数但overflow,那么说明第一个数Less than第二个数:
1
2case C_L:
return (sf ^ of);Greater就是Less反过来并加上!zero。
完整的switch代码:
1 |
|
这个lab的error handling容易出错!:
status code的返回,只要是invalid address的错误,无论是invalid instruction address, invalid data address, invalid stack address,都是返回
STAT_ADR
pushq
和call
都是先decrementrsp
,然后尝试写入栈中。如果写入失败应该重新incrementrsp
到原来的值,如果忘记这一步的话test会fail:1
2
3
4
5
6
7
8
9
10
11
12
13
14[ Testing instruction: call ]
3a4
> %rsp: 0x0000000000000000 0xfffffffffffffff8
[ Result: Fail ]
[ Testing instruction: pushq ]
3a4
> %rsp: 0x0000000000000000 0xfffffffffffffff8
[ Result: Fail ]
[ Testing application: prog10 ]
4a5
> %rsp: 0x0000000000000000 0xfffffffffffffff8
[ Result: Fail ]
Test
To test and evaluate your Simulator:
1 |
|
All tests pass!🤗
总结
这个Simulator Lab就是在编写底层硬件执行上层y86指令的行为,很机械很有意思!
完成这个Lab后,你就能理解为什么程序就是一台状态机!这个状态机每次读取一条指令,然后调动底层硬件更新处理器的状态,然后根据status code决定接下来是继续执行,halt,还是出错。