Guest User

Untitled

a guest
Feb 21st, 2018
301
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.31 KB | None | 0 0
  1. // "emp.cpp"
  2.  
  3. // Programmer: Dustin McCormick < djmccormick@bsu.edu >
  4. // Course: CS230
  5. // Assignment: Project 3 - MIPS Emulator
  6. // Due Date: Wednesday, December 6, 2006
  7.  
  8. // This MIPS emulator will perform operations on MIPS fragments composed of the following instructions:
  9. // lw, sw, add, addi, sub, and, or, beq, slt
  10.  
  11. #include <iostream>
  12. #include <fstream>
  13. #include <string>
  14. #include <sstream>
  15. using namespace std;
  16.  
  17. void openBinaryFile(ifstream& fin, char const* filename);
  18. void openTextFile(ofstream& fout, char const* filename);
  19. void process(ifstream& fin, ofstream& fout);
  20. unsigned short int readInstructions(ifstream& fin, unsigned long int (&i)[4096]);
  21. unsigned short int calculate(unsigned long int i, long int (&d)[4096], long int (&r)[32], unsigned short int current_line);
  22. string outputState(long int (&d)[4096], long int (&r)[32]);
  23. string registerNumberToName(unsigned short int number);
  24. string decimalToHex(unsigned long int number);
  25.  
  26. int main(int argc, char** argv){
  27. // Make sure the program has been invoked correctly:
  28. if(argc < 2){
  29. cerr << "emp: missing file argument\nTry 'emp --help' for more information." << endl;
  30. exit(1);
  31. } else if( string(argv[1]) == "--help"){
  32. cout << "Usage: emp [BINARY FILE] [-o OUTPUT FILE]" << endl;
  33. cout << "The binary file is required. The output file defaults to \"core.txt\"." << endl;
  34. cout << "Send bug reports to <djmccormick@bsu.edu>." << endl;
  35. } else{
  36. ifstream fin;
  37. ofstream fout;
  38. string filename, state;
  39.  
  40. // Open the input file:
  41. openBinaryFile(fin, argv[1]);
  42.  
  43. // Open the output file:
  44. if( argc >= 4 && string(argv[2]) == "-o" ){
  45. openTextFile(fout, argv[3]);
  46. filename = argv[3];
  47. } else{
  48. openTextFile(fout, "core.txt");
  49. filename = "core.txt";
  50. }
  51.  
  52. // Perform the emulation:
  53. process(fin, fout);
  54.  
  55. // Write the state of the machine to the output file:
  56.  
  57.  
  58. // Close the files
  59. fin.close();
  60. fout.close();
  61.  
  62. // Output a termination message:
  63. cout << "The final state of the system has been stored in " + filename + "." << endl;
  64. }
  65.  
  66. return 0;
  67. }
  68.  
  69. void openBinaryFile(ifstream& fin, char const* filename){
  70. // Open the file:
  71. fin.open(filename, ios::in | ios::binary);
  72.  
  73. // Validate the file:
  74. if( !fin.good() ){
  75. cerr << "Error: binary file '" << filename << "' could not be opened for reading." << endl;
  76. exit(1);
  77. }
  78. }
  79.  
  80. void openTextFile(ofstream& fout, char const* filename){
  81. // Open the file:
  82. fout.open(filename);
  83.  
  84. // Validate the file:
  85. if( !fout.good() ){
  86. cerr << "Error: text file '" << filename << "' could not be opened for writing." << endl;
  87. exit(1);
  88. }
  89. }
  90.  
  91. void process(ifstream& fin, ofstream& fout){
  92. // Create the instruction memory, data memory, and registers:
  93. unsigned long int i[4096];
  94. long int d[4096], r[32];
  95.  
  96. // Set register $0 to 0:
  97. r[0] = 0;
  98.  
  99. // Read the instructions into instruction memory:
  100. unsigned short int lines = readInstructions(fin, i);
  101.  
  102. // Perform each instruction
  103. unsigned short int iterator = 0;
  104.  
  105. while(iterator <= lines){
  106. unsigned short int branch_to = calculate(i[iterator], d, r, iterator);
  107.  
  108. // Branch if necessary:
  109. if(branch_to <= lines){
  110. iterator = branch_to;
  111. } else{
  112. iterator++;
  113. }
  114. }
  115.  
  116. // Output the current system state to the output file:
  117. fout << outputState(d, r);
  118. }
  119.  
  120. unsigned short int readInstructions(ifstream& fin, unsigned long int (&i)[4096]){
  121. unsigned long int num;
  122. unsigned short int lines;
  123.  
  124. // Read each instruction into instruction memory:
  125. for(unsigned int line=0; fin.read((char *) &num, sizeof(num)); line++){
  126. i[line] = num;
  127. lines = line;
  128. }
  129.  
  130. return lines;
  131. }
  132.  
  133. unsigned short int calculate(unsigned long int i, long int (&d)[4096], long int (&r)[32], unsigned short int current_line){
  134. unsigned short int op;
  135. short int rs, rt, line;
  136. op = (i & 0xFC000000) >> 26;
  137. rs = (i & 0x03E00000) >> 21;
  138. rt = (i & 0x001F0000) >> 16;
  139.  
  140. if(op == 0){
  141. // It's an R-Type instruction:
  142. unsigned short int rd, addr_shamt, funct;
  143. rd = (i & 0x0000F800) >> 11;
  144. addr_shamt = (i & 0x000007C0) >> 6;
  145. funct = (i & 0x0000003F);
  146.  
  147. // We'll never be branching with R-Type instructions, so set line to an obviously invalid value:
  148. line = 5000;
  149.  
  150. // Figure out which and perform instruction:
  151. switch(funct){
  152. case 32: // add
  153. r[rd] = r[rs] + r[rt];
  154. break;
  155. case 34: // sub
  156. r[rd] = r[rs] - r[rt];
  157. break;
  158. case 36: // and
  159. r[rd] = r[rs] & r[rt];
  160. break;
  161. case 37: // or
  162. r[rd] = r[rs] | r[rt];
  163. break;
  164. case 42: // slt
  165. r[rd] = (r[rs] < r[rt]) ? 1 : 0;
  166. break;
  167. }
  168. } else{
  169. // It's an I-Type instruction:
  170. signed long int imm, signext_imm;
  171. unsigned short int sign;
  172. imm = (i & 0x0000FFFF);
  173.  
  174. // No branching by default, so set line to an obviously invalid value:
  175. line = 5000;
  176.  
  177. // Get the sign of the immediate field:
  178. sign = (imm >> 15);
  179.  
  180. // If the sign is one, we'll have to fill the first 16 bits with ones:
  181. if(sign == 1){
  182. signext_imm = (imm | 0xFFFF0000);
  183. } else{
  184. signext_imm = imm;
  185. }
  186.  
  187. // Figure out which and perform instruction:
  188. switch(op){
  189. case 35: // lw
  190. r[rt] = d[ (r[rs] + signext_imm) ];
  191. break;
  192. case 42: // sw
  193. d[ (r[rs] + signext_imm) ] = r[rt];
  194. break;
  195. case 8: // addi
  196. r[rt] = r[rs] + signext_imm;
  197. break;
  198. case 4: // beq
  199. if(r[rs] == r[rt]){
  200. line = (current_line + 1) + signext_imm;
  201. }
  202. break;
  203. }
  204. }
  205.  
  206. return line;
  207. }
  208.  
  209. string outputState(long int (&d)[4096], long int (&r)[32]){
  210. string output = "", number, register_name, decimal, hexadecimal, iterator_string, modified_iterator_string;
  211.  
  212. // Set up a stream for use with conversions:
  213. ostringstream s;
  214.  
  215. // Begin formatting of the output for registers:
  216. output += " ----------------------------------------------------------\n";
  217. output += "| Registers |\n";
  218. output += " ---------------------------------------------------------- \n";
  219. output += "| Number | Name | Value in Decimal | Value in Hexadecimal |\n";
  220. output += " ---------------------------------------------------------- \n";
  221.  
  222. // Add each register to the output:
  223. for(unsigned short int iterator = 0; iterator < 32; iterator++){
  224. // Convert iterator to string and pad:
  225. s << iterator;
  226. number = s.str();
  227. s.clear();
  228. s.str("");
  229. number.resize(6, ' ');
  230.  
  231. // Pad register name:
  232. register_name = registerNumberToName(iterator);
  233. register_name.resize(4, ' ');
  234.  
  235. // Convert decimal representation of register contents to string and pad:
  236. s << r[iterator];
  237. decimal = s.str();
  238. s.clear();
  239. s.str("");
  240. decimal.resize(16, ' ');
  241.  
  242. // Pad hexadecimal representation of register contents:
  243. hexadecimal = decimalToHex(r[iterator]);
  244. hexadecimal.resize(18, ' ');
  245.  
  246. // Add values to the output:
  247. output += "| " + number;
  248. output += " | $" + register_name;
  249. output += " | " + decimal;
  250. output += " | 0x" + hexadecimal;
  251. output += " |\n";
  252. }
  253. output += " ---------------------------------------------------------- \n";
  254.  
  255. // Begin formatting of the output for data memory:
  256. bool every_four = true; // Set to true for outout of address once per line, false for each word.
  257. output += " ------------------------------------------------------------------------------\n";
  258. output += "| Data Memory |\n";
  259. output += " ------------------------------------------------------------------------------ \n";
  260. for(unsigned short int iterator = 0; iterator < 4096; iterator += 4){
  261. output += "| ";
  262.  
  263. for(unsigned short int inner_iterator = 0; inner_iterator < 4; inner_iterator++){
  264. unsigned short int modified_iterator = iterator + inner_iterator;
  265.  
  266. // Convert iterator to string and pad:
  267. s << iterator;
  268. iterator_string = s.str();
  269. s.clear();
  270. s.str("");
  271. iterator_string.resize(4, ' ');
  272.  
  273. // Convert modified iterator to string and pad:
  274. s << modified_iterator;
  275. modified_iterator_string = s.str();
  276. s.clear();
  277. s.str("");
  278. modified_iterator_string.resize(4, ' ');
  279.  
  280. // Pad hexadecimal representation of data memory contents:
  281. hexadecimal = decimalToHex(d[modified_iterator]);
  282. hexadecimal.resize(8, ' ');
  283.  
  284. // Add values to the output:
  285. if( every_four == true ){
  286. if(inner_iterator == 0){
  287. output += iterator_string + ": ";
  288. }
  289. } else{
  290. output += modified_iterator_string + ": ";
  291. }
  292.  
  293. output += "0x" + hexadecimal;
  294. if(inner_iterator != 3){
  295. if( every_four == true ){
  296. output += " ";
  297. } else{
  298. output += " ";
  299. }
  300. }
  301. }
  302.  
  303. output += " |\n";
  304. }
  305. output += " ------------------------------------------------------------------------------ \n";
  306.  
  307. return output;
  308. }
  309.  
  310. string registerNumberToName(unsigned short int number){
  311. string titles[] = {
  312. "zero", "at", "v0", "v1",
  313. "a0", "a1", "a2", "a3",
  314. "t0", "t1", "t2", "t3",
  315. "t4", "t5", "t6", "t7",
  316. "s0", "s1", "s2", "s3",
  317. "s4", "s5", "s6", "s7",
  318. "t8", "t9", "k0", "k1",
  319. "gp", "sp", "fp", "ra"
  320. };
  321.  
  322. return titles[number];
  323. }
  324.  
  325. string decimalToHex(unsigned long int number){
  326. string hex = "";
  327.  
  328. // This one takes advantage of character arrays:
  329. for(int i=2*sizeof(int)-1; i>=0; i--){
  330. hex += "0123456789ABCDEF"[((number >> i*4) & 0xF)];
  331. }
  332.  
  333. return hex;
  334. }
Add Comment
Please, Sign In to add comment