Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // "emp.cpp"
- // Programmer: Dustin McCormick < djmccormick@bsu.edu >
- // Course: CS230
- // Assignment: Project 3 - MIPS Emulator
- // Due Date: Wednesday, December 6, 2006
- // This MIPS emulator will perform operations on MIPS fragments composed of the following instructions:
- // lw, sw, add, addi, sub, and, or, beq, slt
- #include <iostream>
- #include <fstream>
- #include <string>
- #include <sstream>
- using namespace std;
- void openBinaryFile(ifstream& fin, char const* filename);
- void openTextFile(ofstream& fout, char const* filename);
- void process(ifstream& fin, ofstream& fout);
- unsigned short int readInstructions(ifstream& fin, unsigned long int (&i)[4096]);
- unsigned short int calculate(unsigned long int i, long int (&d)[4096], long int (&r)[32], unsigned short int current_line);
- string outputState(long int (&d)[4096], long int (&r)[32]);
- string registerNumberToName(unsigned short int number);
- string decimalToHex(unsigned long int number);
- int main(int argc, char** argv){
- // Make sure the program has been invoked correctly:
- if(argc < 2){
- cerr << "emp: missing file argument\nTry 'emp --help' for more information." << endl;
- exit(1);
- } else if( string(argv[1]) == "--help"){
- cout << "Usage: emp [BINARY FILE] [-o OUTPUT FILE]" << endl;
- cout << "The binary file is required. The output file defaults to \"core.txt\"." << endl;
- cout << "Send bug reports to <djmccormick@bsu.edu>." << endl;
- } else{
- ifstream fin;
- ofstream fout;
- string filename, state;
- // Open the input file:
- openBinaryFile(fin, argv[1]);
- // Open the output file:
- if( argc >= 4 && string(argv[2]) == "-o" ){
- openTextFile(fout, argv[3]);
- filename = argv[3];
- } else{
- openTextFile(fout, "core.txt");
- filename = "core.txt";
- }
- // Perform the emulation:
- process(fin, fout);
- // Write the state of the machine to the output file:
- // Close the files
- fin.close();
- fout.close();
- // Output a termination message:
- cout << "The final state of the system has been stored in " + filename + "." << endl;
- }
- return 0;
- }
- void openBinaryFile(ifstream& fin, char const* filename){
- // Open the file:
- fin.open(filename, ios::in | ios::binary);
- // Validate the file:
- if( !fin.good() ){
- cerr << "Error: binary file '" << filename << "' could not be opened for reading." << endl;
- exit(1);
- }
- }
- void openTextFile(ofstream& fout, char const* filename){
- // Open the file:
- fout.open(filename);
- // Validate the file:
- if( !fout.good() ){
- cerr << "Error: text file '" << filename << "' could not be opened for writing." << endl;
- exit(1);
- }
- }
- void process(ifstream& fin, ofstream& fout){
- // Create the instruction memory, data memory, and registers:
- unsigned long int i[4096];
- long int d[4096], r[32];
- // Set register $0 to 0:
- r[0] = 0;
- // Read the instructions into instruction memory:
- unsigned short int lines = readInstructions(fin, i);
- // Perform each instruction
- unsigned short int iterator = 0;
- while(iterator <= lines){
- unsigned short int branch_to = calculate(i[iterator], d, r, iterator);
- // Branch if necessary:
- if(branch_to <= lines){
- iterator = branch_to;
- } else{
- iterator++;
- }
- }
- // Output the current system state to the output file:
- fout << outputState(d, r);
- }
- unsigned short int readInstructions(ifstream& fin, unsigned long int (&i)[4096]){
- unsigned long int num;
- unsigned short int lines;
- // Read each instruction into instruction memory:
- for(unsigned int line=0; fin.read((char *) &num, sizeof(num)); line++){
- i[line] = num;
- lines = line;
- }
- return lines;
- }
- unsigned short int calculate(unsigned long int i, long int (&d)[4096], long int (&r)[32], unsigned short int current_line){
- unsigned short int op;
- short int rs, rt, line;
- op = (i & 0xFC000000) >> 26;
- rs = (i & 0x03E00000) >> 21;
- rt = (i & 0x001F0000) >> 16;
- if(op == 0){
- // It's an R-Type instruction:
- unsigned short int rd, addr_shamt, funct;
- rd = (i & 0x0000F800) >> 11;
- addr_shamt = (i & 0x000007C0) >> 6;
- funct = (i & 0x0000003F);
- // We'll never be branching with R-Type instructions, so set line to an obviously invalid value:
- line = 5000;
- // Figure out which and perform instruction:
- switch(funct){
- case 32: // add
- r[rd] = r[rs] + r[rt];
- break;
- case 34: // sub
- r[rd] = r[rs] - r[rt];
- break;
- case 36: // and
- r[rd] = r[rs] & r[rt];
- break;
- case 37: // or
- r[rd] = r[rs] | r[rt];
- break;
- case 42: // slt
- r[rd] = (r[rs] < r[rt]) ? 1 : 0;
- break;
- }
- } else{
- // It's an I-Type instruction:
- signed long int imm, signext_imm;
- unsigned short int sign;
- imm = (i & 0x0000FFFF);
- // No branching by default, so set line to an obviously invalid value:
- line = 5000;
- // Get the sign of the immediate field:
- sign = (imm >> 15);
- // If the sign is one, we'll have to fill the first 16 bits with ones:
- if(sign == 1){
- signext_imm = (imm | 0xFFFF0000);
- } else{
- signext_imm = imm;
- }
- // Figure out which and perform instruction:
- switch(op){
- case 35: // lw
- r[rt] = d[ (r[rs] + signext_imm) ];
- break;
- case 42: // sw
- d[ (r[rs] + signext_imm) ] = r[rt];
- break;
- case 8: // addi
- r[rt] = r[rs] + signext_imm;
- break;
- case 4: // beq
- if(r[rs] == r[rt]){
- line = (current_line + 1) + signext_imm;
- }
- break;
- }
- }
- return line;
- }
- string outputState(long int (&d)[4096], long int (&r)[32]){
- string output = "", number, register_name, decimal, hexadecimal, iterator_string, modified_iterator_string;
- // Set up a stream for use with conversions:
- ostringstream s;
- // Begin formatting of the output for registers:
- output += " ----------------------------------------------------------\n";
- output += "| Registers |\n";
- output += " ---------------------------------------------------------- \n";
- output += "| Number | Name | Value in Decimal | Value in Hexadecimal |\n";
- output += " ---------------------------------------------------------- \n";
- // Add each register to the output:
- for(unsigned short int iterator = 0; iterator < 32; iterator++){
- // Convert iterator to string and pad:
- s << iterator;
- number = s.str();
- s.clear();
- s.str("");
- number.resize(6, ' ');
- // Pad register name:
- register_name = registerNumberToName(iterator);
- register_name.resize(4, ' ');
- // Convert decimal representation of register contents to string and pad:
- s << r[iterator];
- decimal = s.str();
- s.clear();
- s.str("");
- decimal.resize(16, ' ');
- // Pad hexadecimal representation of register contents:
- hexadecimal = decimalToHex(r[iterator]);
- hexadecimal.resize(18, ' ');
- // Add values to the output:
- output += "| " + number;
- output += " | $" + register_name;
- output += " | " + decimal;
- output += " | 0x" + hexadecimal;
- output += " |\n";
- }
- output += " ---------------------------------------------------------- \n";
- // Begin formatting of the output for data memory:
- bool every_four = true; // Set to true for outout of address once per line, false for each word.
- output += " ------------------------------------------------------------------------------\n";
- output += "| Data Memory |\n";
- output += " ------------------------------------------------------------------------------ \n";
- for(unsigned short int iterator = 0; iterator < 4096; iterator += 4){
- output += "| ";
- for(unsigned short int inner_iterator = 0; inner_iterator < 4; inner_iterator++){
- unsigned short int modified_iterator = iterator + inner_iterator;
- // Convert iterator to string and pad:
- s << iterator;
- iterator_string = s.str();
- s.clear();
- s.str("");
- iterator_string.resize(4, ' ');
- // Convert modified iterator to string and pad:
- s << modified_iterator;
- modified_iterator_string = s.str();
- s.clear();
- s.str("");
- modified_iterator_string.resize(4, ' ');
- // Pad hexadecimal representation of data memory contents:
- hexadecimal = decimalToHex(d[modified_iterator]);
- hexadecimal.resize(8, ' ');
- // Add values to the output:
- if( every_four == true ){
- if(inner_iterator == 0){
- output += iterator_string + ": ";
- }
- } else{
- output += modified_iterator_string + ": ";
- }
- output += "0x" + hexadecimal;
- if(inner_iterator != 3){
- if( every_four == true ){
- output += " ";
- } else{
- output += " ";
- }
- }
- }
- output += " |\n";
- }
- output += " ------------------------------------------------------------------------------ \n";
- return output;
- }
- string registerNumberToName(unsigned short int number){
- string titles[] = {
- "zero", "at", "v0", "v1",
- "a0", "a1", "a2", "a3",
- "t0", "t1", "t2", "t3",
- "t4", "t5", "t6", "t7",
- "s0", "s1", "s2", "s3",
- "s4", "s5", "s6", "s7",
- "t8", "t9", "k0", "k1",
- "gp", "sp", "fp", "ra"
- };
- return titles[number];
- }
- string decimalToHex(unsigned long int number){
- string hex = "";
- // This one takes advantage of character arrays:
- for(int i=2*sizeof(int)-1; i>=0; i--){
- hex += "0123456789ABCDEF"[((number >> i*4) & 0xF)];
- }
- return hex;
- }
Add Comment
Please, Sign In to add comment