代码在github
part A
做这个实验之前先看那两个文档,其中simguid中
这个图告诉我们写的汇编代码的大体结构,然后开始,第一个是sum.ys,自己建文件,然后仿照这个结构哦写一个
sum.ys
#Execution begins at address
.pos 0
irmovq stack, %rsp
irmovq stack, %rbp
call main
halt
.align 4
ele1:
.long 0x00a
.long ele2
ele2:
.long 0x0b0
.long ele3
ele3:
.long 0xc00
.long 0
main:
irmovq ele1, %rdi
call sum_list
ret
sum_list:
push %rbp
rrmovq %rsp,%rbp
sub %rsp,0x10
xor %rax,%rax
jmp test
loop:
mrmovq (%rdi),%rbx
addq %rbx,%rax
mrmovq (%rdi+8),%rdi
test:
andq %rdi,%rdi
jne loop
ret
#alloc stack space
.pos 0x1000
stack:
我多了进入函数内部的提升堆栈的操作,本来main函数中也有这一步,但是后来觉得这一步在这里加不加无所谓,打算都去掉,但是我好像忘了去光了。
rsum.ys
#Execution begins at address
.pos 0
irmovq stack, %rsp
irmovq stack, %rbp
call main
halt
.align 4
ele1:
.long 0x00a
.long ele2
ele2:
.long 0x0b0
.long ele3
ele3:
.long 0xc00
.long 0
main:
push %rbp #提升栈空间
rrmovq %rsp,%rbp
sub %rsp,0x10
irmovq ele1, %rdi
call sum_list
ret
sum_list:
push %rbp #提升栈空间
rrmovq %rsp,%rbp
sub %rsp,0x10
xor %rax,%rax
andq %rdi,%rdi #sat CC
jne last
mrmovq (%rdi),%rbx
pushq %rbx
mrmovq (%rdi+8),%rdi
call sum_list
popq %rbx
addq %rbx,%rax
ret
last:
irmovq $0,%rax
ret
#alloc stack space
.pos 0x1000
stack:
copy.ys
#Execution begins at address
.pos 0
irmovq stack, %rsp
irmovq stack, %rbp
call main
halt
.align 8
# Source block
src:
.quad 0x00a
.quad 0x0b0
.quad 0xc00
# Destination block
dest:
.quad 0x111
.quad 0x222
.quad 0x333
main:
push %rbp #提升栈空间
rrmovq %rsp,%rbp
sub %rsp,0x10
irmovq src, %rdi
irmovq dest,%rsi
irmovq $3, %r8
call copy_block
ret
copy_block:
push %rbp #提升栈空间
rrmovq %rsp,%rbp
sub %rsp,0x10
xor %rax,%rax
jmp test
ret
loop:
mrmovq (%rsi),%rbx
mrmovq (%rdi),%rcx
rmmovq %rbx,(%rdi)
rmmovq %rcx,(%rsi)
xorq %rax,%rbx
mrmovq 8(%rdi),%rdi
mrmovq 8(%rsi),%rsi
subq %r8,0x1
test:
addq %r8,%r8
jne loop
ret
#alloc stack space
.pos 0x1000
stack:
part B
让在seq-full.hcl中添加一条指令,知道现在我才想起来我写的不是汇编,写的是y86,还好这俩比较像,添加指令我有点蒙蔽不知道怎么添加,看了眼别人的,发现在文件涉及到的地方加上IADDL就好,具体答案可以看我的代码
part C
把在seq-full.hcl添加的部分复制到pip-ful.hcl里,然后再改ncopy.ys,使其变得更加高效,首先我们知道,一般的循环代码优化编译器都会给我们完成,但是这次我们要写编译器优化之后的汇编,所以我们完全可以写出c再编译以下,看他的汇编借鉴来一遍,不过我没这么干,因为我知道的优化方法就是,迭代语句从+1变为+2,或者更多,目前来说这点大概是够的,然后就是冒险的处理,不能这条语句取内存中x对应的值,上一条语句就是更改这条语句的值,因为在流水线中会有一个时间差就是,上一条指令修改还没放回,下一条指令已经将其取出,这样取出的是之前的值,修改之前的值,正常情况下应该是修改之后的值,这种情况应该在两条指令之间插入另一条指令,可以是无用的nop也可以是其他,在这题中可以放多路展开之后的取值操作
具体代码,我本来写的是8路并行,但是我写的不对,仔细看发现我的优化不对劲,就跟把示例代码复制八分差不太多,最后借鉴的别人的答案
正确版本我就不贴了,毕竟是看的别人的
贴出错误版本引以为戒
下面完全没有看的必要
xorl %rax , %rax
jmp Done
Loop: mrmovl (%rdi) , %r8 #第一二个赋值
mrmovl 8(%rdi), %r9 #插在两指令之间防止冒险
rmmovl %r8 , (%rsi) #移去第一个
andl %r9, %r9
jnle Done
iaddl $1 , %eax
pos1: rmmovl %r9 , 8(%rsi) #移去第二个
andl %rdx, %rdx
jnle Done
iaddl $1, %rax
pos2: mrmovl 16(%rdi),%r8 #第三四个赋值
mrmovl 24(%rdi),%r9 #插在两指令之间
rmmovl $r8 ,16(%rsi) #移去第三个
andl %r9,%r9
jnle Done
iaddl $1 , %rax
pos3: rmmovl %r9 , 24(%rsi) #移去第四个
andl %rdx,%rdx
jnle Done
iaddl $1, %rax
pos4: mrmovl 32(%rdi),%r8 #第五六个赋值
mrmovl 40(%rdi),%r9 #插在两指令之间
rmmovl $r8 ,32(%rsi) #移去第五个
andl %r9,%r9
jnle Done
iaddl $1 , %rax
pos5: rmmovl %r9 , 40(%rsi) #移去第六个
andl %rdx,%rdx
jnle Done
iaddl $1, %rax
pos6: mrmovl 48(%rdi),%r8 #第七八个赋值
mrmovl 56(%rdi),%r9 #插在两指令之间
rmmovl $r8 ,48(%rsi) #移去第七个
andl %r9,%r9
jnle Done
iaddl $1 , %rax
pos7: rmmovl %r9 , 56(%rsi) #移去第八个
andl %rdx,%rdx
jnle Done
iaddl $1, %rax
nextLoop:
iaddl $rax,%rdi
iaddl $rax,%rsi
iaddl $rax,%rdx
jge Loop