Archlab 实验报告
Part A
1. SUM.YS 计算链表的和
简要说明
将链表起始地址存入%edi
将求和结果存入%eax
用一个循环实现加和,当到达最末尾元素,用 andl 判断,再 jne 指令跳出
结果显示,%eax=0x00000cba.
每行程序对应 C 语言
.pos 0
init: irmovl Stack,%esp
call Main
halt
.align 4
list:
ele1:
.long 0x00a
.long ele2
ele2:
.long 0x0b0
.long ele3
ele3:
.long 0xc00
.long 0
Main: irmovl list,%edi
call sum_list
ret
sum_list:
irmovl $0,%eax
Loop:
mrmovl (%edi),%ecx
addl %ecx,%eax
mrmovl 4(%edi),%edi
andl %edi,%edi
#Execution begins at address 0
#set up stack pointer
#execute main program
#terminate program
#list of 3 elements
#get ls
#sum_list(list_ptr ls)
#int val=0
#while
#get ls->val
#val+=ls_val
#ls=ls->next
#if ls==0
jne Loop
ret
.pos 0x200
Stack:
#stop when 0
#return
#stack starts here and grows to lower
addresses
2. RSUM.YS 递归计算链表的和
简要说明
将链表起始地址存入%edi
将求和结果存入%eax
利用栈结构实现递归循环:每次把 val 值压入栈,并且触发 call 函数跳转,直到读
到末尾元素,把%eax 值赋 0;然后依次 ret 回到上一级位置,再将 pop 出来的 val
值和当前%eax 值相加并存入%eax,循环,一直到 ret 回主函数。
结果显示,%eax=0x00000cba
每行程序对应 C 语言
.pos 0
init: irmovl Stack,%esp
call Main
halt
.align 4
list:
ele1:
.long 0x00a
.long ele2
ele2:
.long 0x0b0
.long ele3
ele3:
.long 0xc00
.long 0
Main:
irmovl list,%edi
call rsum_list
ret
rsum_list:
loop:
#Execution begins at address 0
#set up stack pointer
#execute main program
#terminate program
#list of 3 elements
#get ls
#rsum_list(list_ptr ls)
#while
andl %edi,%edi
je zero
mrmovl (%edi),%edx
pushl %edx
mrmovl 4(%edi),%edi
call rsum_list
popl %edx
addl %edx,%eax
jmp end
zero:
irmovl $0,%eax
ret
end:
ret
.pos 0x100
Stack:
#if ls==0
#jump to zero if ls==0
#get ls->val
#put ls->val on the stack
#ls=ls->next
#iteration
#get current val
# rest=val+rest
#return 0
#return to last address
#return to last address
#stack starts here and grows to lower
addresses
3. COPY.YS 复制并计算异或
简要说明
将 src 首地址存入%edi,将 dest 首地址存入%esi
将异或结果存入%eax
用一个循环实现:将(%edi)存入(%esi),由于 Y86 指令中没有 mmmovl 指
令,因此需要借助%ecx 来实现,即先 mrmovl,再 rmmovl。然后将%ecx 和%eax
异或,即是 c 语言中的 result^=val。然后对%edi 和%esi 分别加 4,对%edx(len)
减 1,通过判断 len 是否为 0,跳出。
结果显示,%eax=0x00000cba
每行程序对应 C 语言
.pos 0
init:
irmovl Stack, %esp
call Main
halt
.align 4
src:
.long 0x00a
.long 0x0b0
.long 0xc00 # Destination block
#Execution begins at address 0
#set up stack pointer
#execute main program
#terminate program
#source block
dest:
.long 0x111
.long 0x222
.long 0x333
Main:
irmovl src,%edi
irmovl dest,%esi
irmovl $0x3,%edx #len
call copy
ret
copy:
irmovl $0,%eax
loop:
mrmovl (%edi),%ecx
rmmovl %ecx,(%esi)
xorl %ecx,%eax
irmovl $4,%ecx
addl %ecx,%edi
addl %ecx,%esi
irmovl $1,%ecx
subl %ecx,%edx
jne loop
ret
.pos 0x200
Stack:
#destination block
#get src
#get dest
#let len=3
#copy_block(int* src,int* dest,int len)
#int result=0
#while
#int val=*src
#*dest=val
#result^=val
#src+4
#dest+4
#len—
#back to loop if len>0
#stack starts here and grows to lower
addresses
Part B
将立即数与寄存器相加
对应于如下 Y86 代码:
rrmovl %ebp,%esp
popl %ebp
1. SEQ-FULL.HCL
指令说明
IIADDL
ILEAVE
指令分析
模拟器修改过程
在 instr_valid 添加 IIADDL 和 ILEAVE 让指令有效。
在 need_regids 添加 IIADDL。leave 指令不需要寄存器参数。
在 need_valC 添加 IIADDL。leave 指令不需要常数参数。
srcA 中,iaddl 指令无需设置,leave 指令设为 REBP。
srcB 中,iaddl 指令设为 rB, leave 指令设为 REBP。
dstE 中,iaddl 指令设为 rB, leave 指令设为 RESP。
dstM 中,iaddl 指令无需设置,leave 指令设为 REBP。
aluA 中,iaddl 指令设为 valC, leave 指令设为 4。
aluB 中,iaddl 指令和 leave 指令均设为 valB。
在 set_cc 中添加 IIADDL, leave 指令不影响标志位。
在 mem_read 中添加 ILEAVE, iaddl 指令无需访存。
mem_addr 中,leave 指令设为 valA, iaddl 指令无需设置。
2. PIPE-FULL.HCL
指令分析
与顺序流水线类似,需要注意的是,iaddl 不存在加载/使用冒险,而 leave 存在加载/
使用冒险,故应该在 F 阶插入 stall, D 阶段插入 stall, E 阶段插入 bubble。
条件
加载使用冒险 暂停
F
D
暂停
E
气泡
M
正常
W
正常
模拟器修改过程
在 INSTR_VALID 添加 IIADDL 和 ILEAVE 让指令有效。
BOOL INSTR_VALID = F_ICODE IN
IOPL, IJXX, ICALL, IRET, IPUSHL, IPOPL, IIADDL, ILEAVE };
{ INOP, IHALT, IRRMOVL, IIRMOVL, IRMMOVL, IMRMOVL,
在 NEED_REGIDS 添加 IIADDL。LEAVE 指令不需要寄存器参数。
BOOL NEED_REGIDS =
F_ICODE IN { IRRMOVL, IOPL, IPUSHL, IPOPL,
IIRMOVL, IRMMOVL, IMRMOVL, IIADDL };
在 NEED_VALC 添加 IIADDL。LEAVE 指令不需要常数参数。
BOOL NEED_VALC =
F_ICODE IN { IIRMOVL, IRMMOVL, IMRMOVL, IJXX, ICALL, IIADDL };
D_SRCA 中,IADDL 指令无需设置,LEAVE 指令设为 REBP。
INT D_SRCA = [
D_ICODE IN { IRRMOVL, IRMMOVL, IOPL, IPUSHL } : D_RA;
D_ICODE IN { IPOPL, IRET } : RESP;
D_ICODE IN { ILEAVE } : REBP;
1 : RNONE; # DON'T NEED REGISTER
];
D_SRCB 中,IADDL 指令设为 RB,LEAVE 指令设为 REBP。
INT D_SRCB = [
D_ICODE IN { IOPL, IRMMOVL, IMRMOVL, IIADDL } : D_RB;
D_ICODE IN { IPUSHL, IPOPL, ICALL, IRET } : RESP;
D_ICODE IN { ILEAVE } : REBP;
1 : RNONE; # DON'T NEED REGISTER
];
D_DSTE 中,IADDL 指令设为 RB,LEAVE 指令设为 RESP。
INT D_DSTE = [
D_ICODE IN { IRRMOVL, IIRMOVL, IOPL, IIADDL } : D_RB;
D_ICODE IN { IPUSHL, IPOPL, ICALL, IRET, ILEAVE } : RESP;
1 : RNONE; # DON'T WRITE ANY REGISTER
];
D_DSTM 中,IADDL 指令无需设置,LEAVE 指令设为 REBP。
INT D_DSTM = [
D_ICODE IN { IMRMOVL, IPOPL } : D_RA;
D_ICODE IN { ILEAVE } : REBP;
1 : RNONE; # DON'T WRITE ANY REGISTER
];
ALUA 中,IADDL 指令设为 VALC, LEAVE 指令设为 4。
INT ALUA = [
E_ICODE IN { IRRMOVL, IOPL } : E_VALA;
E_ICODE IN { IIRMOVL, IRMMOVL, IMRMOVL, IIADDL } : E_VALC;
E_ICODE IN { ICALL, IPUSHL } : -4;
E_ICODE IN { IRET, IPOPL, ILEAVE } : 4;
# OTHER INSTRUCTIONS DON'T NEED ALU
];
ALUB 中,IADDL 指令和 LEAVE 指令均设为 VALB。
INT ALUB = [
IPUSHL, IRET, IPOPL, IIADDL, ILEAVE } : E_VALB;
E_ICODE IN { IRMMOVL, IMRMOVL, IOPL, ICALL,
E_ICODE IN { IRRMOVL, IIRMOVL } : 0;
# OTHER INSTRUCTIONS DON'T NEED ALU
];
在 SET_CC 中添加 IIADDL,LEAVE 指令不影响标志位。
BOOL SET_CC = E_ICODE IN { IOPL, IIADDL } &&
!M_STAT IN { SADR, SINS, SHLT } && !W_STAT IN { SADR, SINS, SHLT };
# STATE CHANGES ONLY DURING NORMAL OPERATION
MEM_ADDR 中,LEAVE 指令设为 VALA,IADDL 指令无需设置。
INT MEM_ADDR = [
M_ICODE IN { IRMMOVL, IPUSHL, ICALL, IMRMOVL } : M_VALE;
M_ICODE IN { IPOPL, IRET, ILEAVE } : M_VALA;
# OTHER INSTRUCTIONS DON'T NEED ADDRESS
];
在 MEM_READ 中添加 ILEAVE,IADDL 指令无需访存。
BOOL MEM_READ = M_ICODE IN { IMRMOVL, IPOPL, IRET, ILEAVE };
以上指令和SEQ-FULL.HCL中对应一致。
在 F_STALL 的 E_ICODE 条件中添加 ILEAVE,IADDL 指令不存在加载/使用冒险。
BOOL F_STALL =
IRET IN { D_ICODE, E_ICODE, M_ICODE };
# CONDITIONS FOR A LOAD/USE HAZARD
E_ICODE IN { IMRMOVL, IPOPL, ILEAVE } &&
E_DSTM IN { D_SRCA, D_SRCB } ||
# STALLING AT FETCH WHILE RET PASSES THROUGH PIPELINE
在 D_STALL 的 E_ICODE 条件中添加 ILEAVE,IADDL 指令不存在加载/使用冒险。
BOOL D_STALL =
E_DSTM IN { D_SRCA, D_SRCB };
# CONDITIONS FOR A LOAD/USE HAZARD
E_ICODE IN { IMRMOVL, IPOPL, ILEAVE } &&
在 D_BULLLE 的 E_ICODE 条件中添加 ILEAVE,防止插入 D_BUBBLE。IADDL 指令不
存在加载/使用冒险。
BOOL D_BUBBLE =
&&
# MISPREDICTED BRANCH
(E_ICODE == IJXX && !E_CND) ||
# STALLING AT FETCH WHILE RET PASSES THROUGH PIPELINE
# BUT NOT CONDITION FOR A LOAD/USE HAZARD
!(E_ICODE IN { IMRMOVL, IPOPL, ILEAVE } && E_DSTM IN { D_SRCA, D_SRCB })
IRET IN { D_ICODE, E_ICODE, M_ICODE };
在 E_BUBBLE 的 E_ICODE 条件中添加 ILEAVE,IADDL 指令不存在加载/使用冒险。
BOOL E_BUBBLE =
E_DSTM IN { D_SRCA, D_SRCB};
# MISPREDICTED BRANCH
(E_ICODE == IJXX && !E_CND) ||
# CONDITIONS FOR A LOAD/USE HAZARD
E_ICODE IN { IMRMOVL, IPOPL, ILEAVE } &&
Part C