文章目录
- 指令系统
- 编码格式
- 一、基础:顺序结构
- 1.取值阶段:
- 2.译码阶段
- 3.执行阶段
- 4.访存阶段
- 5.写回阶段
- 6.更新PC阶段
- 详细硬件结构
- 指令在各个阶段完成的操作
- C代码实现
指令系统
编码格式
一、基础:顺序结构
1.取值阶段:
- 根据icode还可以判断当前指令是否包含寄存器指示符字节(Need regids);以及是否包含常数字节(Need valC),由此计算出指令的长度,进而计算下一条地址
- 当need_regids等于0时,表示这条指令没有寄存器指示符,rA和rB置为0xF;当指令中只含有一个寄存器操作数时,同样另一个字段置为0xF
- 当need_regids等于0时,第1个字节到第8个表示常数字段valC,1时,2~9
2.译码阶段
- 产生寄存器ID值,需要指令代码icode和rA、rB读取寄存器的数据,rA用于pop(call、ret)指令指针值
3.执行阶段
- ALU根据指令功能(ifun)来判断对输入的操作数进行何种运算,都会产生条件码信号,但对于计算内存引用地址以及栈操作时,不必设置条件码,通过设置setCC,可根据icode来控制是否要更新条件码寄存器CC;标号为cond的硬件单元会根据指令功能和条件码寄存器产生一个cnd信号
- 对于跳转指令,如果cnd=1,执行跳转,否则不跳转
4.访存阶段
- 就是从内存中读数据或者将数据写入内存中,根据信号计算状态码Stat
读控制块,写控制块,产生内存地址和输入数据的控制块
5.写回阶段
- 将数据写入寄存器文件
两个写端口分别为M和E,对应的地址输入为dstE和dstM。当执行条件传送指令(cmov)时,写入操作还需根据执行阶段计算出的cnd信号;当不满足条件时,可以将目的寄存器设置为0xF来禁止写入寄存器文件
6.更新PC阶段
- call指令
常数字段 - ret指令
内存(栈)中读出返回地址 - jxx跳转指令
满足cnd,常数字段;否则,与其他一样,加上当前指令长度
详细硬件结构
指令在各个阶段完成的操作
更多指令操作请查找:Y86指令集
C代码实现
#include<stdio.h>
#include<stdint.h>
#include<string.h>
/*
寄存器编号
*/
enum Reg {
rax = 0,
rcx = 1,
rdx = 2,
rbx = 3,
rsp = 4,
rbp = 5,
rsi = 6,
rdi = 7,
r8 = 8,
r9 = 9,
r10 = 0xA,
r11 = 0xB,
r12 = 0xC,
r13 = 0xD,
r14 = 0xE,
No_regisEer = 0xF,
};
const uint8_t PC_memory[32768] = { 0x30,0xf2,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //0x000 : irmovq $9, %rdx
,0x30,0xf3,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //0x00a : irmovq $21, %rbx
,0x61,0x23 //0x014 : subq %rdx, %rbx
,0x30,0xf4,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //0x016 : irmovq $128, %rsp
,0x40,0x43,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //0x020 : rmmovq %rsp, 100(%rbx)
,0xa0,0x2f //0x02a : pushq %rdx
,0xb0,0x0f //0x02c : popq %rax
,0x73,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //0x02e : je done
,0x80,0x41,0x03,0x00,0x00,0x00,0x00,0x00,0x00 //0x037 : call proc
//0x040 : done:
,0x00 //0x040 : halt
//0x041 : proc:
,0x90 }; //0x041 : ret
struct FReg {
int predPC;
};
struct SelectPC { //PC选择逻辑单元,预测与纠错
int predpc; //经过predicatePC单元,判断jxx,call跳转 还是 其他顺序执行PCinc单元(valp),预测
int cnd; //执行jxx valc的限制条件,默认跳转,cnd=0 顺序执行valp ,修正jxx
int M_valA; //通过selectA将valp放入valA里了
int M_icode;
int W_valM; //ret默认顺序执行valp,待从栈Datamemory中读地址后更新 ,修正ret
int W_icode;
};
struct F_DReg {
int stat;
int icode;
int ifuc;
int rA;
int rB;
int valC;
int valP;
};
struct D_EReg {
int stat;
int icode;
int ifuc;
int valC;
int valA;
int valB;
int dstE;
int dstM;
int srcA;
int srcB;
};
struct FwdB {
int register_B;
int srcB;
int E_dstE;
int E_valE;
int M_dstE;
int M_valE;
int M_dstM;
int M_valM;
int W_dstM;
int W_valM;
int W_dstE;
int W_valE;
int valB;
};
struct SelectA_and_FwdA {
int register_A;
int srcA;
int valP;
int E_dstE;
int E_valE;
int M_dstE;
int M_valE;
int M_dstM;
int M_valM;
int W_dstM;
int W_valM;
int W_dstE;
int W_valE;
int valA;
};
struct E_MReg {
int stat;
char icode;
int Cnd;
int valE;
int valA;
int dstE;
int dstM;
};
struct CC {
int ZF;
int SF;
int OF;
};
struct M_WReg {
int stat;
int icode;
int valE;
int valM;
int dstE;
int dstM;
};
struct Inst {
int icode;
int ifunct;
int rA_id;
int rB_id;
int valC;
int valP;
int len;
};
int Register_file[16] = { 0 };
int Datamemory[32768] = { 0 };
struct CC cc = { 0 };
struct FReg fReg = { 0 };
struct SelectPC selectpc = { 0,1,0,0,0,0 };
struct FwdB fwdb = { 0 };
struct SelectA_and_FwdA sel_fwda = { 0 };
/*
1.用暂停来避免冒险
只要一条指令的源操作数会被流水线后面某个阶段中的指令产生,处理器就会通过将指令阻塞在解码阶段来避免数据冒险
2.用转发来避免冒险-----》不需要暂停,但与存储器读有关的指令,是在流水线较后面发生的,仍需暂停
如mr 0(%edx),%eax 指令后紧接着add %ebx,&eax ;add的%eax需要在译码阶段得到值,而mr最早到访存阶段才能转发
显然已经来不及,所以不得不先暂停后转发
3.暂停+转发
将解码阶段中的指令暂停一个周期,导致执行阶段中插入一个气泡,同时暂停,使得F和D状态不变
需要解决的控制逻辑:插入气泡
1.加载使用冒险:1个气泡
在一条从存储器中读出一个值的指令和一条使用该值的指令之间,流水线必须暂停一个周期
2. ret:3个气泡
流水线必须暂停直到ret指令到达写回阶段
3. 预测错误的分支:两个气泡
在分支逻辑发现不应该选择分支之前(执行阶段才发现),分支目标处的几条指令已经进入流水线了。
必须从流水线中去掉这些指令。
此时第一条指令已经执行到译码阶段,第二条指令刚开始取指。
具体实现:
定义F_DReg 和F_DRegNew D_EReg 和D_ERegNew E_MReg 和E_MRegNew M_WReg 和M_WRegNew
执行过程中:
F:输入pc 输出 F_DRegNew;正常情况下需要更新 将F_DRegNew---->F_DReg,否则不变
D:输入F_DReg 输出 D_ERegNew;
E: 输入D_EReg 输出 E_MRegNew;
M: 输入E_MReg 输出 M_WRegNew
W: 输入M_WReg
每次执行完需要判断:
需要暂停,就使用原状态F_DReg
正常情况,每次执行完一个周期需要更新
F_DReg = F_DRegNew
*
//分支预测
void Select_PC(struct SelectPC* selectpc) {
if (selectpc->W_icode == 9) { //ret生效
selectpc->predpc = selectpc->W_valM;
}
if (selectpc->W_icode == 7) {
if (selectpc->cnd == 0) { //跳转失败
selectpc->predpc = selectpc->M_valA;
}
}
}
//取值阶段
int Predict_PC(int icode,int valc,int valp) {
if (icode == 7||icode == 8) {
return valc;
}
else {
return valp;
}
}
int PC_inc(int len,int pc) {
return len + pc;
}
int iValC(int valC_start,int valC_end) {
int i, j,valc = 0;
for ( j = 0,i = valC_start; i <= valC_end; i++,j = j + 2)
{
valc += PC_memory[i] << j;
}
return valc;
}
void Align(int pc,struct Inst* inst,int Need_regids,int Need_valC) {
int valC_start;
int valC_end;
if (Need_regids == 0) {
inst->rA_id = 0xF;
inst->rB_id = 0xF;
if (Need_valC) { //无寄存器、有常数 如jxx、call
valC_start = pc + 1;
valC_end = pc + 8;
inst->len = 1 + (valC_end - pc);
inst->valC = iValC(valC_start, valC_end);
}
else { //无寄存器、无常数 如halt、nop、ret
inst->len = 1;
}
}
if (Need_regids == 1) {
inst->rA_id = 0xF;
inst->rB_id = PC_memory[pc + 1] & 0x0F;
if (Need_valC) { //只有寄存器rB、有常数 如irmovq
valC_start = pc + 2;
valC_end = pc + 9;
inst->len = 1 + (valC_end - pc);
inst->valC = iValC(valC_start, valC_end);
}
//只有寄存器rB、无常数 此情况无
}
if (Need_regids == 2) {
inst->rA_id = PC_memory[pc + 1] >> 4;
inst->rB_id = 0xF;
//只有寄存器rA、有常数 此情况无
if (!Need_valC) { //有寄存器rA、无常数 如pushq、popq
inst->len = 2;
}
}
if (Need_regids == 3) {
inst->rA_id = PC_memory[pc + 1] >> 4;
inst->rB_id = PC_memory[pc + 1] & 0x0F;
if (Need_valC) { //都有寄存器、有常数 如rrmovq、rmmovq、mrmovq
valC_start = pc + 2;
valC_end = pc + 9;
inst->len = 1 + (valC_end - pc);
inst->valC = iValC(valC_start, valC_end);
}
else {
// 都有寄存器、无常数 如addq、subq、andq、xorq、rrmovq、rrmovq、cmovle、cmovl、cmove、cmovne、cmovge、cmovg
inst->len = 2;
}
}
}
void Split(int pc, struct Inst* inst, struct F_DReg* f_dReg) {
int Need_valC;
int Need_regids; //0:都为空;1:rA为空;2:rB为空;3:都不为空
uint8_t code = PC_memory[pc];
uint8_t reg = PC_memory[pc + 1];
inst->icode = (uint8_t)(code >> 4);
inst->ifunct = code & 0x0F;
if (inst->icode == 0 && inst->ifunct == 0) {
Need_regids = 0;
Need_valC = 0;
Align(pc,inst, Need_regids, Need_valC);
}
if (inst->icode == 1 && inst->ifunct == 0) {
Need_valC = 0;
Need_regids = 0;
Align(pc, inst, Need_regids, Need_valC);
}
if (inst->icode == 2) {
Need_valC = 0;
Need_regids = 3;
Align(pc, inst, Need_regids, Need_valC);
}
if (inst->icode == 3 && inst->ifunct == 0) {
Need_valC = 1;
Need_regids = 1;
Align(pc, inst, Need_regids, Need_valC);
}
if (inst->icode == 4 && inst->ifunct == 0) {
Need_valC = 1;
Need_regids = 3;
Align(pc, inst, Need_regids, Need_valC);
}
if (inst->icode == 5 && inst->ifunct == 0) {
Need_valC = 1;
Need_regids = 3;
Align(pc, inst, Need_regids, Need_valC);
}
if (inst->icode == 6) {
Need_valC = 0;
Need_regids = 3;
Align(pc, inst, Need_regids, Need_valC);
}
if (inst->icode == 7) {
Need_valC = 1;
Need_regids = 0;
Align(pc, inst, Need_regids, Need_valC);
}
if (inst->icode == 8 && inst->ifunct == 0) {
Need_valC = 1;
Need_regids = 0;
Align(pc, inst, Need_regids, Need_valC);
}
if (inst->icode == 9 && inst->ifunct == 0) {
Need_valC = 0;
Need_regids = 0;
Align(pc, inst, Need_regids, Need_valC);
}
if (inst->icode == 0xA && inst->ifunct == 0) {
Need_valC = 0;
Need_regids = 2;
Align(pc, inst, Need_regids, Need_valC);
}
if (inst->icode == 0xB && inst->ifunct == 0) {
Need_valC = 0;
Need_regids = 2;
Align(pc, inst, Need_regids, Need_valC);
}
if (!(inst->icode >= 0 && inst->icode <= 11)) {
f_dReg->stat = 0;
}
}
void Fetch(struct F_DReg* f_dReg,int pc){
struct Inst inst = {0,0,0,0,0,0,0};
Split(pc,&inst, f_dReg);
inst.valP = PC_inc(inst.len, pc);
fReg.predPC = Predict_PC(inst.icode, inst.valC, inst.valP);
selectpc.predpc = selectpc.predpc;
f_dReg->icode = inst.icode;
f_dReg->ifuc = inst.ifunct;
f_dReg->rA = inst.rA_id;
f_dReg->rB = inst.rB_id;
f_dReg->valC = inst.valC;
f_dReg->valP = inst.valP;
}
//译码阶段
/*
1.不是所以指令都需要数据转发,而且数据转发阶段也不同:(不需要回写寄存器的指令,不需要转发)
执行阶段:(ALU计算结果) valE: 3irmov 6opq 2rrmov(有条件) Apush Bpop 8call 9ret(注意:回写valE到SP寄存器)
访存前: (对寄存器写入端口E还没有进行写入的数据)valE: 就是执行阶段的指令
访存后有:(内存的输出数据) valM: 5mrmov(有点晚) Bpop (从Datememory中读出数据后才回写)
写回阶段:(对寄存器写入端口E还没进行写入的数据) valE:就是执行阶段的指令
(对寄存器写入端口M还没有进行写入的数据)valM: 就是访存后指令
2.rB寄存器作为源寄存器时,需要与rB作为目的寄存器匹配验证的指令很少。有指令:
opq: rA,rB->rB
mrmov:D(rB),rA
3.rA寄存器作为源寄存器时,需要与rA作为目的寄存器匹配验证。rA源寄存器有指令:
特别注意:jxx和call指令要经过selectA,选出的是valP,不是来自寄存器的ra值,所以不需要匹配验证
mr指令也不需要
*/
//数据转发
void SelectA_and_FwdA(struct SelectA_and_FwdA* sel_fwda) {
if (sel_fwda->srcA == 0xF) {
sel_fwda->valA = sel_fwda->valP;
}
else {
if (sel_fwda->srcA == sel_fwda->E_dstE) {
sel_fwda->valA = sel_fwda->E_valE;
}
else if (sel_fwda->srcA == sel_fwda->M_dstE) {
sel_fwda->valA = sel_fwda->M_valE;
}
else if (sel_fwda->srcA == sel_fwda->M_dstM) {
sel_fwda->valA = sel_fwda->M_valE;
}
else if (sel_fwda->srcA == sel_fwda->W_dstE) {
sel_fwda->valA = sel_fwda->W_valE;
}
else if (sel_fwda->srcA == sel_fwda->W_dstM) {
sel_fwda->valA = sel_fwda->W_valM;
}
else {
sel_fwda->valA = sel_fwda->register_A;
}
}
}
void FwdB(struct FwdB* fwdb) {
if (fwdb->srcB == fwdb->E_dstE) {
fwdb->valB = fwdb->E_valE;
}
else if (fwdb->srcB == fwdb->M_dstE) {
fwdb->valB = fwdb->M_valE;
}
else if (fwdb->srcB == fwdb->M_dstM) {
fwdb->valB = fwdb->M_valE;
}
else if (fwdb->srcB == fwdb->W_dstE) {
fwdb->valB = fwdb->W_valE;
}
else if (fwdb->srcB == fwdb->W_dstM) {
fwdb->valB = fwdb->W_valM;
}
else {
fwdb->valB = fwdb->register_B;
}
}
void Decode(struct F_DReg f_dReg, struct D_EReg* d_eReg, int* Register_file) {
d_eReg->stat = f_dReg.stat;
d_eReg->icode = f_dReg.icode;
d_eReg->valC = f_dReg.valC;
d_eReg->ifuc = f_dReg.ifuc;
if (f_dReg.icode == 0 || f_dReg.icode == 1) {
;
}
if (f_dReg.icode == 2) { //rr
d_eReg->srcA = f_dReg.rA;
sel_fwda.srcA = f_dReg.rA;
sel_fwda.register_A = Register_file[f_dReg.rA];
SelectA_and_FwdA(&sel_fwda);
d_eReg->valA = sel_fwda.valA;
d_eReg->srcB = f_dReg.rB;
d_eReg->valB = 0;
d_eReg->dstE = f_dReg.rB; //将结果valE写回寄存器rB
}
if (f_dReg.icode == 3) { //ir
d_eReg->srcA = f_dReg.rA;
d_eReg->srcB = f_dReg.rB;
d_eReg->valB = 0;
d_eReg->dstE = f_dReg.rB; //将ALU结果valE写回寄存器rB
}
if (f_dReg.icode == 4) { //rm rA,D(rB) 不需要写回寄存器
d_eReg->srcA = f_dReg.rA;
sel_fwda.srcA = f_dReg.rA;
sel_fwda.register_A = Register_file[f_dReg.rA];
SelectA_and_FwdA(&sel_fwda);
d_eReg->valA = sel_fwda.valA;
d_eReg->srcB = f_dReg.rB; //对rB去寄存器取基地址
fwdb.srcB = f_dReg.rB;
fwdb.register_B = Register_file[f_dReg.rB];
FwdB(&fwdb);
d_eReg->valB = fwdb.valB;
}
if (f_dReg.icode == 5) { //mr D(rB),rA 需要验证
d_eReg->srcB = f_dReg.rB; //对rB去寄存器取基地址
fwdb.srcB = f_dReg.rB;
fwdb.register_B = Register_file[f_dReg.rB];
FwdB(&fwdb);
d_eReg->valB = fwdb.valB;
d_eReg->dstM = f_dReg.rA; //将Datamemory结果valM写回寄存器rA
}
if (f_dReg.icode == 6) { //OPq rA,rB 需要验证
sel_fwda.srcA = f_dReg.rA;
sel_fwda.register_A = Register_file[f_dReg.rA];
SelectA_and_FwdA(&sel_fwda);
d_eReg->valA = sel_fwda.valA;
fwdb.srcB = f_dReg.rB;
fwdb.register_B = Register_file[f_dReg.rB];
FwdB(&fwdb);
d_eReg->valB = fwdb.valB;
d_eReg->dstE = f_dReg.rB; //将ALU结果valE写回寄存器rB
}
if (f_dReg.icode == 7) { //jxx
sel_fwda.srcA = f_dReg.rA;
sel_fwda.register_A = Register_file[f_dReg.rA];
SelectA_and_FwdA(&sel_fwda);
d_eReg->valA = sel_fwda.valA;
}
if (f_dReg.icode == 8) { //call
d_eReg->srcA = 4;
sel_fwda.srcA = 4;
sel_fwda.register_A = Register_file[f_dReg.rA];
SelectA_and_FwdA(&sel_fwda);
d_eReg->valA = sel_fwda.valA;
fwdb.srcB = 4;
fwdb.register_B = Register_file[f_dReg.rB];
FwdB(&fwdb);
d_eReg->valB = fwdb.valB;
d_eReg->dstE = 4; //将ALU结果valE写回寄存器sp
}
if (f_dReg.icode == 9) { //ret
d_eReg->srcA = 4; //对sp去寄存器取数据
sel_fwda.srcA = 4;
sel_fwda.register_A = Register_file[f_dReg.rA];
SelectA_and_FwdA(&sel_fwda);
d_eReg->valA = sel_fwda.valA;
d_eReg->srcB = 4;
fwdb.srcB = 4;
fwdb.register_B = Register_file[f_dReg.rB];
FwdB(&fwdb);
d_eReg->valB = fwdb.valB;
d_eReg->dstE = 4; //将ALU结果valE写回寄存器sp
}
if (f_dReg.icode == 0xA) {//push
d_eReg->srcA = f_dReg.rA;
sel_fwda.srcA = f_dReg.rA; //对rA去寄存器取数据
sel_fwda.register_A = Register_file[f_dReg.rA];
SelectA_and_FwdA(&sel_fwda);
d_eReg->valA = sel_fwda.valA;
d_eReg->srcB = 4;
fwdb.srcB = 4;
fwdb.register_B = Register_file[f_dReg.rB];
FwdB(&fwdb);
d_eReg->valB = fwdb.valB;
d_eReg->dstE = 4; //将ALU结果valE写回寄存器sp
}
if (f_dReg.icode == 0xB) {//popq
d_eReg->srcA = 4; //对sp去寄存器取数据
sel_fwda.srcA = 4;
sel_fwda.register_A = Register_file[f_dReg.rA];
SelectA_and_FwdA(&sel_fwda);
d_eReg->valA = sel_fwda.valA;
d_eReg->srcB = 4; //对sp去寄存器取数据
fwdb.srcB = 4;
fwdb.register_B = Register_file[f_dReg.rB];
FwdB(&fwdb);
d_eReg->valB = fwdb.valB;
d_eReg->dstE = 4; //将ALU结果valE写回寄存器sp
d_eReg->dstM = f_dReg.rA; //将Datamemory结果valM写回寄存器rA
}
}
//执行阶段
void setCC(struct CC* cc, int a, int b, int result, int op) {
if (op == 1) { //OF=1 两个同符号数相加(正数+正数 或 负数+负数),结果符号与其相反。
if ((a >= 0 && b >= 0) && result < 0) {
cc->OF = 1;
}
else if ((a < 0 && b < 0) && result >= 0) {
cc->OF = 1;
}
else {
cc->OF = 0;
}
}
if (op == 2) { //OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。
if ((a >= 0 && b < 0) && result >= 0) {
cc->OF = 1;
}
else if ((a < 0 && b >= 0) && result < 0) {
cc->OF = 1;
}
else {
cc->OF = 0;
}
}
if (op == 3 || op == 4) {
cc->OF = 0;
}
if (result < 0) {
cc->SF = 1;
}
else {
cc->SF = 0;
}
if (result) {
cc->ZF = 1;
}
else {
cc->ZF = 0;
}
}
int ALU(int alu_a, int alu_b, int op) {
if (op == 1)
return alu_a + alu_b;
else if (op == 2)
return alu_a - alu_b;
else if (op == 2)
return alu_a & alu_b;
else
return alu_a ^ alu_b;
}
int Cond(struct CC cc, int ifunc) {
if (ifunc == 1) {
return (cc.SF ^ cc.OF) | cc.ZF;
}
if (ifunc == 2) {
return cc.SF ^ cc.OF;
}
if (ifunc == 3) {
return cc.ZF;
}
if (ifunc == 4) {
return ~cc.ZF;
}
if (ifunc == 5) {
return ~(cc.SF ^ cc.OF);
}
if (ifunc == 6) {
return ~(cc.SF ^ cc.OF) & ~cc.ZF;
}
}
void Excecute(struct D_EReg d_eReg, struct E_MReg* e_mReg) {
int ALU_A;
int ALU_B;
e_mReg->stat = d_eReg.stat;
e_mReg->icode = d_eReg.icode;
e_mReg->valA = d_eReg.valA;
e_mReg->dstM = d_eReg.dstM;
int op = 1;//1:add,2:sub,3:and,4:xor
if (d_eReg.icode == 0) {// 不提供数据转发
e_mReg->dstE = 0xF;
}
if (d_eReg.icode == 1) {// 不提供数据转发
e_mReg->dstE = 0xF;
}
if (d_eReg.icode == 2) {//rr 如果条件满足才提供数据转发
ALU_A = d_eReg.valA;
ALU_B = d_eReg.valB;
op = 1;
e_mReg->valE = ALU(ALU_A, ALU_B, op);
fwdb.E_valE = ALU(ALU_A, ALU_B, op);
sel_fwda.E_valE = ALU(ALU_A, ALU_B, op);
if (d_eReg.ifuc == 0) {
e_mReg->Cnd = 1;
}
if (d_eReg.ifuc == 1) {
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
if (d_eReg.ifuc == 2) {
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
if (d_eReg.ifuc == 3) {
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
if (d_eReg.ifuc == 4) {
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
if (d_eReg.ifuc == 5) {
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
if (d_eReg.ifuc == 6) {
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
if (e_mReg->Cnd) {
e_mReg->dstE = d_eReg.dstE;
fwdb.E_dstE = d_eReg.dstE;
sel_fwda.E_dstE = d_eReg.dstE;
}
else {
e_mReg->dstE = 0xF;
fwdb.E_dstE = 0xF;
sel_fwda.E_dstE = 0xF;
}
}
if (d_eReg.icode == 3) {//ir 提供数据转发
op = 1;
ALU_A = d_eReg.valC;
ALU_B = d_eReg.valB;
printf("执行立即数加法\n");
e_mReg->valE = ALU(ALU_A, ALU_B, op);
fwdb.E_valE = ALU(ALU_A, ALU_B, op);
sel_fwda.E_valE = ALU(ALU_A, ALU_B, op);
fwdb.E_dstE = d_eReg.dstE;
sel_fwda.E_dstE = d_eReg.dstE;
e_mReg->dstE = d_eReg.dstE;
}
if (d_eReg.icode == 4) {//rm 不提供数据转发
op = 1;
ALU_A = d_eReg.valC;
ALU_B = d_eReg.valB;
e_mReg->valE = ALU(ALU_A, ALU_B, op);
e_mReg->dstE = 0xF;
}
if (d_eReg.icode == 5) {//mr 只有访存后才数据转发
op = 1;
ALU_A = d_eReg.valC;
ALU_B = d_eReg.valB;
e_mReg->valE = ALU(ALU_A, ALU_B, op);
e_mReg->dstE = d_eReg.dstE;
}
if (d_eReg.icode == 6) {//Opq rr 提供数据转发
ALU_A = d_eReg.valA;
ALU_B = d_eReg.valB;
e_mReg->dstE = d_eReg.dstE;
if (d_eReg.ifuc == 0) {
op = 1;
}
if (d_eReg.ifuc == 1) {
op = 2;
}
if (d_eReg.ifuc == 2) {
op = 3;
}
if (d_eReg.ifuc == 3) {
op = 4;
}
e_mReg->valE = ALU(ALU_A, ALU_B, op);
fwdb.E_valE = ALU(ALU_A, ALU_B, op);
fwdb.E_dstE = d_eReg.dstE;
fwdb.E_valE = ALU(ALU_A, ALU_B, op);
fwdb.E_dstE = d_eReg.dstE;
sel_fwda.E_valE = ALU(ALU_A, ALU_B, op);
sel_fwda.E_dstE = d_eReg.dstE;
setCC(&cc, ALU_A, ALU_B, e_mReg->valE, op);
}
if (d_eReg.icode == 7) {//jxx 不提供数据转发
if (d_eReg.ifuc == 0) { //jmp
e_mReg->Cnd = 1;
}
if (d_eReg.ifuc == 1) { //jle (SF ^ OF) | ZF
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
if (d_eReg.ifuc == 2) { //jl SF ^ OF
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
if (d_eReg.ifuc == 3) { //je ZF
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
if (d_eReg.ifuc == 4) { //jne ~ZF
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
if (d_eReg.ifuc == 5) { //jge ~(SF ^ OF)
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
if (d_eReg.ifuc == 6) { //jg ~(SF ^ OF) & ~ZF
e_mReg->Cnd = Cond(cc, d_eReg.ifuc);
}
}
if (d_eReg.icode == 8 || d_eReg.icode == 0xA) { //call push valB=R[%rsp] 提供数组转发
ALU_B = d_eReg.valB;
ALU_A = -4; //-8
op = 1;
e_mReg->valE = ALU(ALU_A, ALU_B, op);
e_mReg->dstE = d_eReg.dstE;
fwdb.E_valE = ALU(ALU_A, ALU_B, op);
fwdb.E_dstE = d_eReg.dstE;
sel_fwda.E_valE = ALU(ALU_A, ALU_B, op);
sel_fwda.E_dstE = d_eReg.dstE;
}
if (d_eReg.icode == 9) { //ret valB=R[%rsp] 提供数组转发给fwda
ALU_B = d_eReg.valB;
ALU_A = 4;
op = 1;
e_mReg->valE = ALU(ALU_A, ALU_B, op);
e_mReg->dstE = d_eReg.dstE;
fwdb.E_valE = ALU(ALU_A, ALU_B, op);
fwdb.E_dstE = d_eReg.dstE;
sel_fwda.E_valE = ALU(ALU_A, ALU_B, op);
sel_fwda.E_dstE = d_eReg.dstE;
}
if (d_eReg.icode == 0xB) { //pop valB=R[%rsp] 提供数组转发 1.执行阶段valB=R[%rsp] 2.访存后 valM
ALU_B = d_eReg.valB;
ALU_A = 4;
op = 1;
e_mReg->valE = ALU(ALU_A, ALU_B, op);
e_mReg->dstE = d_eReg.dstE;
fwdb.E_valE = ALU(ALU_A, ALU_B, op);
fwdb.E_dstE = d_eReg.dstE;
sel_fwda.E_valE = ALU(ALU_A, ALU_B, op);
sel_fwda.E_dstE = d_eReg.dstE;
}
selectpc.cnd = e_mReg->Cnd;
selectpc.M_icode = e_mReg->icode;
}
//访存阶段
void DataMemory(int addr, int Data, int* Datamemory, int MemoryControl, struct M_WReg* m_wReg) {
if (MemoryControl == 1) {
m_wReg->valM = Datamemory[addr];
}
else if (MemoryControl == 2) {
Datamemory[addr] = Data;
}
}
void MemoryAccess(struct E_MReg e_mReg, struct M_WReg* m_wReg) {
int MemoryControl = -1; //0:不读不写;1:读有效,输入地址输出valM;2:写有效,输入地址数据
int Addr = -1;
int Data = -1;
m_wReg->icode = e_mReg.icode;
m_wReg->stat = e_mReg.stat;
m_wReg->valE = e_mReg.valE;
m_wReg->dstE = e_mReg.dstE;
m_wReg->dstM = e_mReg.dstM;
if (e_mReg.icode == 0 || e_mReg.icode == 1 || e_mReg.icode == 2) {
MemoryControl = 0;
}
if (e_mReg.icode == 3 || e_mReg.icode == 8 || e_mReg.icode == 0xA) { //rm push M[valE] = valA
MemoryControl = 2;
Addr = e_mReg.valE;
Data = e_mReg.valA;
}
if (e_mReg.icode == 5) { //mr
MemoryControl = 1;
Addr = e_mReg.valE;
}
if (e_mReg.icode == 9 || e_mReg.icode == 0xB) { //ret pop M[valE] = valA
MemoryControl = 1;
Addr = e_mReg.valA;
}
//数据传递
if (e_mReg.icode == 2 || e_mReg.icode == 3 || e_mReg.icode == 6 || e_mReg.icode == 8 || e_mReg.icode == 9
|| e_mReg.icode == 0xA || e_mReg.icode == 0xB) {
fwdb.M_valE = e_mReg.valE;
fwdb.M_dstE = e_mReg.dstE;
sel_fwda.M_valE = e_mReg.valE;
sel_fwda.M_dstE = e_mReg.dstE;
}
DataMemory(Addr, Data, Datamemory, MemoryControl, m_wReg);
if (e_mReg.icode == 5 || e_mReg.icode == 0xB) {
fwdb.M_valM = m_wReg->valM;
fwdb.M_dstM = e_mReg.dstM;
sel_fwda.M_valM = m_wReg->valM;
sel_fwda.M_dstM = e_mReg.dstM;
}
selectpc.M_valA = e_mReg.valA;
}
//写回阶段
void writeBack(struct M_WReg m_wReg) {
if (m_wReg.dstE != 0xF)
Register_file[m_wReg.dstE] = m_wReg.valE;
if (m_wReg.dstM != 0xF)
Register_file[m_wReg.dstM] = m_wReg.valM;
if (m_wReg.icode == 2 || m_wReg.icode == 3 || m_wReg.icode == 6 || m_wReg.icode == 8 || m_wReg.icode == 9
|| m_wReg.icode == 0xA || m_wReg.icode == 0xB) {
fwdb.M_valE = m_wReg.valE;
fwdb.M_dstE = m_wReg.dstE;
sel_fwda.M_valE = m_wReg.valE;
sel_fwda.M_dstE = m_wReg.dstE;
}
if (m_wReg.icode == 5 || m_wReg.icode == 0xB) {
fwdb.M_valM = m_wReg.valM;
fwdb.M_dstM = m_wReg.dstM;
sel_fwda.M_valM = m_wReg.valM;
sel_fwda.M_dstM = m_wReg.dstM;
}
selectpc.W_valM = m_wReg.valM;
selectpc.W_icode = m_wReg.icode;
}
//主函数
int main() {
int i = 5;
struct F_DReg f_dReg = { 1,0,0,0,0,0,0 };
struct D_EReg d_eReg = { 1,0,0,0,0,0,0,0,0,0 };
struct E_MReg e_mReg = { 1,0,0,0,0,0,0 };
struct M_WReg m_wreg = { 1,0,0,0,0xF,0xF };
while (i--) {
if (!selectpc.predpc) {
Select_PC(&selectpc);
}
Fetch(&f_dReg, selectpc.predpc);
printf("取指阶段-------------------\n");
printf("f_dReg.icode = %d\n", f_dReg.icode);
printf("f_dReg.ifun = %d\n", f_dReg.ifuc);
printf("f_dReg.rA = %d\n", f_dReg.rA);
printf("f_dReg.rB = %d\n", f_dReg.rB);
printf("f_dReg.valC = %d\n", f_dReg.valC);
Decode(f_dReg, &d_eReg, &Register_file);
printf("译码阶段-------------------\n");
printf("d_eReg.icode = %d\n", d_eReg.icode);
printf("d_eReg.ifun = %d\n", d_eReg.ifuc);
printf("d_eReg.srcA = %d\n", d_eReg.srcA);
printf("d_eReg.valA = %d\n", d_eReg.valA);
printf("d_eReg.srcB = %d\n", d_eReg.srcB);
printf("d_eReg.valB = %d\n", d_eReg.valB);
printf("d_eReg.dstE = %d\n", d_eReg.dstE);
printf("d_eReg.dstM = %d\n", d_eReg.dstM);
printf("d_eReg.valC = %d\n", d_eReg.valC);
Excecute(d_eReg, &e_mReg);
printf("执行阶段--------------------\n");
printf("e_mReg->valE = %d\n", e_mReg.valE);
printf("e_mReg->dstE = %d\n", e_mReg.dstE);
MemoryAccess(e_mReg, &m_wreg);
printf("访存阶段----------------------\n");
writeBack(m_wreg);
printf("写回阶段----------------------\n");
printf("rbx = %d\n", Register_file[3]);
}
return 0;
}