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_ADRpushq和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,还是出错。