📄 loader.cpp
字号:
#include "loader.h"using namespace std;Program::Program(){ instrNum = 0; labelNum = 0; flag = 1; // flag should be 0 for full assembly language simulator instrPos = 0; /*code opcode and funct. initilization*/ /*add*/ OPSet[0].type = 0; OPSet[0].code = 0; OPSet[0].funct = 32; strcpy(OPSet[0].name,"add"); /*sub*/ OPSet[1].type = 0; OPSet[1].code = 0; OPSet[1].funct = 34; strcpy(OPSet[1].name,"sub"); /*addi*/ OPSet[2].type = 1; OPSet[2].code = 8; OPSet[2].funct = 0; strcpy(OPSet[2].name,"addi"); /*and*/ OPSet[3].type = 0; OPSet[3].code = 0; OPSet[3].funct = 36; strcpy(OPSet[3].name, "and"); /*andi*/ OPSet[4].type = 1; OPSet[4].code = 12; OPSet[4].funct = 0; strcpy(OPSet[4].name, "andi"); /*or*/ OPSet[5].type = 0; OPSet[5].code = 0; OPSet[5].funct = 37; strcpy(OPSet[5].name, "or"); /*ori*/ OPSet[6].type = 1; OPSet[6].code = 13; OPSet[6].funct = 0; strcpy(OPSet[6].name, "ori"); /*sll*/ OPSet[7].type = 0; OPSet[7].code = 0; OPSet[7].funct = 0; strcpy(OPSet[7].name, "sll"); /*slt*/ OPSet[8].type = 0; OPSet[8].code = 0; OPSet[8].funct = 42; strcpy(OPSet[8].name, "slt"); /*lui*/ OPSet[9].type = 1; OPSet[9].code = 15; OPSet[9].funct = 0; strcpy(OPSet[9].name, "lui"); /*bne*/ OPSet[10].type = 1; OPSet[10].code = 5; OPSet[10].funct = 0; strcpy(OPSet[10].name, "bne"); /*j*/ OPSet[11].type = 2; OPSet[11].code = 2; OPSet[11].funct = 0; strcpy(OPSet[11].name, "j"); /*jr*/ OPSet[12].type = 3; OPSet[12].code = 0; OPSet[12].funct = 8; strcpy(OPSet[12].name, "jr"); /*lw*/ OPSet[13].type = 4; OPSet[13].code = 35; OPSet[13].funct = 0; strcpy(OPSet[13].name, "lw"); /*sw*/ OPSet[14].type = 4; OPSet[14].code = 43; OPSet[14].funct = 0; strcpy(OPSet[14].name, "sw"); /*beq*/ OPSet[15].type = 1; OPSet[15].code = 4; OPSet[15].funct = 0; strcpy(OPSet[15].name, "beq"); /*srl*/ OPSet[16].type = 0; OPSet[16].code = 0; OPSet[16].funct = 2; strcpy(OPSet[16].name, "srl"); /*Register initialization*/ /*zero*/ RegSet[0].used = 0; RegSet[0].code = 0; strcpy(RegSet[0].name, "$zero"); RegSet[0].value = 0; /*at*/ RegSet[1].used = 0; RegSet[1].code = 1; strcpy(RegSet[1].name, "$at"); RegSet[1].value = 0; /*v0*/ RegSet[2].used = 0; RegSet[2].code = 2; strcpy(RegSet[2].name, "$v0"); RegSet[2].value = 0; /*v1*/ RegSet[3].used = 0; RegSet[3].code = 3; strcpy(RegSet[3].name, "$v1"); RegSet[3].value = 0; /*a0*/ RegSet[4].used = 0; RegSet[4].code = 4; strcpy(RegSet[4].name, "$a0"); RegSet[4].value = 0; /*a1*/ RegSet[5].used = 0; RegSet[5].code = 5; strcpy(RegSet[5].name, "$a3"); RegSet[5].value = 0; /*a2*/ RegSet[6].used = 0; RegSet[6].code = 6; strcpy(RegSet[6].name, "$a2"); RegSet[6].value = 0; /*a3*/ RegSet[7].used = 0; RegSet[7].code = 7; strcpy(RegSet[7].name, "$a3"); RegSet[7].value = 0; /*t0*/ RegSet[8].used = 0; RegSet[8].code = 8; strcpy(RegSet[8].name, "$t0"); RegSet[8].value = 0; /*t1*/ RegSet[9].used = 0; RegSet[9].code = 9; strcpy(RegSet[9].name, "$t1"); RegSet[9].value = 0; /*t2*/ RegSet[10].used = 0; RegSet[10].code = 10; strcpy(RegSet[10].name, "$t2"); RegSet[10].value = 0; /*t3*/ RegSet[11].used = 0; RegSet[11].code = 11; strcpy(RegSet[11].name, "$t3"); RegSet[11].value = 0; /*t4*/ RegSet[12].used = 0; RegSet[12].code = 12; strcpy(RegSet[12].name, "$t4"); RegSet[12].value = 0; /*t5*/ RegSet[13].used = 0; RegSet[13].code = 13; strcpy(RegSet[13].name, "$t5"); RegSet[13].value = 0; /*t6*/ RegSet[14].used = 0; RegSet[14].code = 14; strcpy(RegSet[14].name, "$t6"); RegSet[14].value = 0; /*t7*/ RegSet[15].used = 0; RegSet[15].code = 15; strcpy(RegSet[15].name, "$t7"); RegSet[15].value = 0; /*s0*/ RegSet[16].used = 0; RegSet[16].code = 16; strcpy(RegSet[16].name, "$s0"); RegSet[16].value = 0; /*s1*/ RegSet[17].used = 0; RegSet[17].code = 17; strcpy(RegSet[17].name, "$s1"); RegSet[17].value = 0; /*s2*/ RegSet[18].used = 0; RegSet[18].code = 18; strcpy(RegSet[18].name, "$s2"); RegSet[18].value = 0; /*s3*/ RegSet[19].used = 0; RegSet[19].code = 19; strcpy(RegSet[19].name, "$s3"); RegSet[19].value = 0; /*s4*/ RegSet[20].used = 0; RegSet[20].code = 20; strcpy(RegSet[20].name, "$s4"); RegSet[20].value = 0; /*s5*/ RegSet[21].used = 0; RegSet[21].code = 21; strcpy(RegSet[21].name, "$s5"); RegSet[21].value = 0; /*s6*/ RegSet[22].used = 0; RegSet[22].code = 22; strcpy(RegSet[22].name, "$s6"); RegSet[22].value = 0; /*s7*/ RegSet[23].used = 0; RegSet[23].code = 23; strcpy(RegSet[23].name, "$s7"); RegSet[23].value = 0; /*t8*/ RegSet[24].used = 0; RegSet[24].code = 24; strcpy(RegSet[24].name, "$t8"); RegSet[24].value = 0; /*t9*/ RegSet[25].used = 0; RegSet[25].code = 25; strcpy(RegSet[25].name, "$t9"); RegSet[25].value = 0; /*k0*/ RegSet[26].used = 0; RegSet[26].code = 26; strcpy(RegSet[26].name, "$k0"); RegSet[26].value = 0; /*k1*/ RegSet[27].used = 0; RegSet[27].code = 27; strcpy(RegSet[27].name, "$k1"); RegSet[27].value = 0; /*gp*/ RegSet[28].used = 0; RegSet[28].code = 28; strcpy(RegSet[28].name, "$gp"); RegSet[28].value = 0; /*sp*/ RegSet[29].used = 0; RegSet[29].code = 29; strcpy(RegSet[29].name, "$sp"); RegSet[29].value = 0; /*fp*/ RegSet[30].used = 0; RegSet[30].code = 30; strcpy(RegSet[30].name, "$fp"); RegSet[30].value = 0; /*ra*/ RegSet[31].used = 0; RegSet[31].code = 31; strcpy(RegSet[31].name, "$ra"); RegSet[31].value = 0;}Program::~Program(){}unsigned int Program::GetOPCode(const char *op){ for(int i=0;i<INSTR_TYPE;i++) { if(!strcmp(op,OPSet[i].name)) return OPSet[i].code; } assert(1);}unsigned int Program::GetFunct(const char *op){ for(int i=0;i<INSTR_TYPE;i++) { if(!strcmp(op,OPSet[i].name)) return OPSet[i].funct; } assert(1);}char* Program::GetRegName(const unsigned int reg){ for(int i=0;i<REGISTER_NUM;i++) { if(RegSet[i].code == reg) return RegSet[i].name; } assert(1);}unsigned int Program::GetRegCode(const char *reg){ int i; // it is a register for(i=0;i<REGISTER_NUM;i++) { if(!strcmp(reg,RegSet[i].name)) { RegSet[i].used = 1; return RegSet[i].code; } } // it is a label for(i=0;i<MAX_LABEL_NUM;i++) { if(!strcmp(reg,labelTable[i].name)) return labelTable[i].offset; } // it is an immediate number return (unsigned int)atoi(reg);}int Program::LoadProgram(const char *fileName){ ifstream file,fix; char *line; unsigned int instrBuff; file.open(fileName,ios::in); if(file.fail()) { cout<<"The file \""<<fileName<<"\" does not exist!"<<endl; return -2; } // load the program into the program[] line = new char[MAX_LINE_LENGTH]; while( file.getline(line,MAX_LINE_LENGTH,'\n') ) { strcpy(program[instrNum].instrName, line); instrBuff = GenerateInstr(line); if(instrBuff == (unsigned)-2) continue; if(instrBuff == (unsigned)-1) { cout<<"Instruction No. "<<instrNum+1<<" has format error!"<<endl; return -1; } program[instrNum++].instrCode = instrBuff; } file.close(); // fix all labels that are used before its definition in the program fix.open(fileName,ios::in); flag = 0; while( fix.getline(line,MAX_LINE_LENGTH,'\n') ) FixLabels(line); fix.close(); return instrNum;}void Program::FixLabels(char *line){ int i, j; char space[] = " \t"; char colon[] = ":"; char *label, *op, *buff; op = new char[KEY_LENGTH]; buff = new char[MAX_LINE_LENGTH]; strcpy(buff,line); op = strtok(line, space); if(op != NULL) { for(i=0;i<INSTR_TYPE;i++) { if(!strcmp(op,OPSet[i].name)) break; } if(i != INSTR_TYPE) // it is an instruction { instrPos++; for(j=0;j<labelNum;j++) { label = strstr(buff, labelTable[j].name); if(label != NULL && strstr(label, colon) == NULL) // find a label { if(OPSet[i].type == 2) { program[flag].instrCode = ( (program[flag].instrCode >> 26) << 26 ) + labelTable[j].offset; program[flag].instr.AD = labelTable[j].offset; } if(OPSet[i].type == 1) { if(strcmp(op,"beq")!=0) { program[flag].instrCode = ( (program[flag].instrCode >> 16) << 16 ) + labelTable[j].offset; program[flag].instr.IM = labelTable[j].offset; } else { program[flag].instrCode = ( (program[flag].instrCode >> 16) << 16 ) + ((labelTable[j].offset-instrPos) << 16 >> 16); program[flag].instr.IM = labelTable[j].offset-instrPos; } } } } flag ++; } }}unsigned int Program::GenerateInstr(char *line){ int i; char space[] = " \t,"; char *op, *reg1, *reg2, *reg3; unsigned int oneInstr, tmp; op = new char[KEY_LENGTH]; reg1 = new char[KEY_LENGTH]; reg2 = new char[KEY_LENGTH]; reg3 = new char[KEY_LENGTH]; op = strtok(line, space); if(op != NULL) { for(i=0;i<INSTR_TYPE;i++) { if(!strcmp(op,OPSet[i].name)) break; } if(i != INSTR_TYPE) // it is an instruction { switch(OPSet[i].type) { // handle the R-format instructions case 0: tmp = GetOPCode(op); oneInstr = tmp << 26; program[instrNum].instr.OP = tmp; tmp = GetFunct(op); oneInstr += tmp; program[instrNum].instr.FN = tmp; program[instrNum].instr.SH = 0; program[instrNum].instr.IM = (unsigned)-1; program[instrNum].instr.AD = (unsigned)-1; reg1 = strtok(NULL, space); // get the first reg if(reg1 != NULL) { tmp = GetRegCode(reg1); program[instrNum].instr.RD = tmp; oneInstr += tmp << 11; reg2 = strtok(NULL, space); // get the second operator if(reg2 != NULL) { tmp = GetRegCode(reg2); program[instrNum].instr.RS = tmp; oneInstr += tmp << 21; reg3 = new char[KEY_LENGTH]; reg3 = strtok(NULL, space); // get the third operator if(reg3 != NULL) { tmp = GetRegCode(reg3); program[instrNum].instr.RT = tmp; oneInstr += tmp << 16; reg3 = strtok(NULL, space); // error detection if(reg3 != NULL) return (unsigned)-1; } } } break; // handle the I-format instructions case 1: tmp = GetOPCode(op); oneInstr = tmp << 26; program[instrNum].instr.OP = tmp; program[instrNum].instr.FN = (unsigned)-1; program[instrNum].instr.SH = (unsigned)-1; program[instrNum].instr.IM = 0; program[instrNum].instr.RD = (unsigned)-1; program[instrNum].instr.AD = (unsigned)-1; reg1 = strtok(NULL, space); // get the first reg if(reg1 != NULL) { tmp = GetRegCode(reg1); program[instrNum].instr.RT = tmp; oneInstr += tmp << 16; reg2 = strtok(NULL, space); // get the second operator if(reg2 != NULL) { tmp = GetRegCode(reg2); program[instrNum].instr.RS = tmp; oneInstr += tmp << 21; reg3 = new char[KEY_LENGTH]; reg3 = strtok(NULL, space); // get the third operator if(reg3 != NULL) { tmp = GetRegCode(reg3) << 16 >> 16; oneInstr += tmp; program[instrNum].instr.IM = tmp; reg3 = strtok(NULL, space); if(reg3 != NULL) // error detection return (unsigned)-1; } } } break; // handle the J-format instructions case 2: tmp = GetOPCode(op); oneInstr = tmp << 26; program[instrNum].instr.OP = tmp; program[instrNum].instr.SH = (unsigned)-1; program[instrNum].instr.RS = (unsigned)-1; program[instrNum].instr.RT = (unsigned)-1; program[instrNum].instr.RD = (unsigned)-1; program[instrNum].instr.FN = (unsigned)-1; program[instrNum].instr.IM = (unsigned)-1; reg1 = strtok(NULL, space); // get the first reg if(reg1 != NULL) { tmp = GetRegCode(reg1) << 6 >> 6; oneInstr += tmp; program[instrNum].instr.AD = tmp; reg2 = strtok(NULL, space); // get the second operator if(reg2 != NULL) return (unsigned)-1; } break; // handle instruction jr case 3: tmp = GetOPCode(op); oneInstr = tmp << 26; program[instrNum].instr.OP = tmp; tmp = GetFunct(op); oneInstr += tmp; program[instrNum].instr.FN = tmp; program[instrNum].instr.RT = (unsigned)-1; program[instrNum].instr.RD = (unsigned)-1; program[instrNum].instr.SH = (unsigned)-1; program[instrNum].instr.IM = (unsigned)-1; program[instrNum].instr.AD = (unsigned)-1; reg1 = strtok(NULL, space); // get the first reg if(reg1 != NULL) { tmp = GetRegCode(reg1); program[instrNum].instr.RS = tmp; oneInstr += tmp << 21; reg2 = strtok(NULL, space); // get the second operator if(reg2 != NULL) return (unsigned)-1; } break; // handle instruction lw, sw case 4: tmp = GetOPCode(op); oneInstr = tmp << 26; program[instrNum].instr.OP = tmp; program[instrNum].instr.FN = (unsigned)-1; program[instrNum].instr.SH = (unsigned)-1; program[instrNum].instr.IM = 0; program[instrNum].instr.RD = (unsigned)-1; program[instrNum].instr.AD = (unsigned)-1; reg1 = strtok(NULL, space); // get the first reg if(reg1 != NULL) { tmp = GetRegCode(reg1); program[instrNum].instr.RT = tmp; oneInstr += tmp << 16; reg2 = strtok(NULL, space); // get the second operator if(reg2 != NULL) { char *tmpreg = new char[KEY_LENGTH]; strcpy(tmpreg,reg2); // back up reg2 reg3 = strtok(reg2, "("); // detect if there is IM value if(reg3 != NULL) // there is { tmp = ( (unsigned int)atoi(reg3) ) << 16 >> 16; program[instrNum].instr.IM = tmp; oneInstr += tmp; reg2 = strtok(NULL, ")"); } else // there is not { strcpy(reg2,tmpreg); } tmp = GetRegCode(reg2); program[instrNum].instr.RS = tmp; oneInstr += tmp << 21; } } break; } // end of switch return oneInstr; } // end of one instruction else // find the definitions of labels { // If there is other things like data segment, this judgement // should be applied for recognizing the start of code segment // if(!strcmp(op,"__start:") && flag == 0) // flag = 1; // else { op = strtok(op, " \t:"); if(op != NULL && flag) // op is a label { labelTable[labelNum].offset = instrNum; strcpy(labelTable[labelNum++].name, op); } } } } return (unsigned)-2; // if this is not an instruction}unsigned int Program::LoadInstr(const unsigned int PC){ if(PC/4 > instrNum || PC < 0) { cout<<"The PC address "<<PC<<" is out of bound!"<<endl; assert(1); } if(PC%4 != 0) { cout<<"The PC address "<<PC<<" is an illegal instruction address!"<<endl; assert(1); } if(PC/4 == instrNum) return 0; // Here, we return the 32-bit code of the fetched instruction by default. // Then you can decode it by yourself. Otherwise, you may want to use the // decoded structure provided by us, then you should use "return PC/4" here, // and get the OP code by "prog.program[PC/4].instr.OP" in the simulator. The // rest may be deduced similarly. Read the struct CodeLine and Instr for reference. return program[PC/4].instrCode;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -