I've been tasked with programming an emulator to translate and execute MIPS machine code in C.
Currently, the program takes the MIPS code, translates it into binary, and stores it in an array that all currently works. The issue lies within the execute function of the code.
Most of the instructions execute but JR, JAL, BNE and BLEZ are not functional. I believe this is because when I attempt to change the PC counter to execute the instruction it causes an error. The registry output must remain the same as when it is returned on MARS and the program counter must increment correctly.
// JR
else if((text[TEXT_POS(pc)] & 0x0000003F) == 0x8)
{
printf("| Executing JR:\n");
int s = (text[TEXT_POS(pc)] & 0x03E00000);
pc = registers[s]; // <-- I believe the issue lies here.
}
// JAL
else if((text[TEXT_POS(pc)] & 0xFC000000) == 0x0C000000)
{
printf("| Executing JAL:");
int address = (text[TEXT_POS(pc)] & 0x03FFFFFF);
registers[/*$*/31] = pc + 8; // <-- And here
pc = address;
}
I am attempting to set the PC counter = to the variable s Since this is how the MIPS Green sheet says it should be executed. However, it is not returning the expected value.
// BNE
else if((text[TEXT_POS(pc)] & 0xFC000000) == 0x14000000)
{
printf("| EXECUTING BNE:\n");
int s = (text[TEXT_POS(pc)] & 0x03E00000) >> 21;
int t = (text[TEXT_POS(pc)] & 0x001F0000) >> 16;
int imm = (text[TEXT_POS(pc)] & 0xFFFF)/*>> 2*/;
if(registers[s] != registers[t])
{
printf("| EXECUTING PC BRANCH - BNE:\n");
printf("PC (START) = %x\n",pc);
printf("imm = %d\n", imm);
pc = pc + 4 + imm; // <-- Unsure about '<< 2' (BLEZ Too)
printf("PC (END) = %x\n",pc);
}
}
// BLEZ
else if ((text[TEXT_POS(pc)] & 0xFC000000) == 0x18000000)
{
printf("| EXECUTING BLEZ:\n");
int s = (text[TEXT_POS(pc)] & 0x03E00000) >> 21;
int tempJump = (text[TEXT_POS(pc)] & 0xFFFF) >> 2;
if(registers[s] <= 0)
{
printf("| EXECUTING PC BRANCH - BLEZ :\n");
pc = pc + 4 + tempJump; // <-- 'Label'? (MIPS REFERENCE SHEET)
}
}
All this code is doing is executing the operations and this has proved successful for the other types like ADD, ADDI and SLL. However as soon as I try to change the program counter (PC) everything breaks and it no longer works.
int exec_bytecode()
{
printf("EXECUTING PROGRAM ...\n");
pc = ADDR_TEXT; // Set program counter to the start of our program.
int count = 1; // <-- Stops while loop running forever. (REMOVE WHEN DONE!)
// Debugging for checking value of program counter.
printf("----- TESTING THE OPERATOR -----\n");
printf("FIRST ADDRESS = %x\n",pc);
for(int c1=0; c1<3; c1++)
{
printf("index[%d] = %x\n", c1,TEXT_POS(pc));
pc=pc+4;
printf("PC (inside the loop) = %x\n",pc);
}
// Debugging for checking value of text array.
printf("----- TEST TEXT ARRAY -----\n");
for(int c=0; c<3; c++)
{
printf("text[%d] = %x\n", c,text[c]);
}
pc = ADDR_TEXT; // Set program counter to the start of our program.
// While loop to execute bytecode until text array is null.
while(text[TEXT_POS(pc)] != 0)
{
printf("----- WHILE LOOP EXECUTED -----\n");
printf("text array = %x\n", text[TEXT_POS(pc)]);
printf("PC = %x\n",pc);
// ADDI - Finished
if((text[TEXT_POS(pc)] & 0xFC000000) == 0x20000000)
{
printf("| EXECUTING ADDI:\n"); // <-- Printf for debuggin purposes
int s = (text[TEXT_POS(pc)] & 0x03E00000) >> 21;
int t = (text[TEXT_POS(pc)] & 0x001F0000) >> 16;
short int imm = text[TEXT_POS(pc)] & 0xFFFF; // Last 16 bits
registers[t] = registers[s] + imm;
pc = pc + 4;
}
// ANDI - Finished
else if((text[TEXT_POS(pc)] & 0xFC000000) == 0x30000000)
{
printf("| EXECUTING ANDI:\n"); // <-- Printf for debuggin purposes
int s = (text[TEXT_POS(pc)] & 0x03E00000) >> 21;
int t = (text[TEXT_POS(pc)] & 0x001F0000) >> 16;
short int imm = text[TEXT_POS(pc)] & 0xFFFF;
registers[t] = registers[s] + imm;
pc = pc + 4;
}
// BNE
else if((text[TEXT_POS(pc)] & 0xFC000000) == 0x14000000)
{
printf("| EXECUTING BNE:\n");
int s = (text[TEXT_POS(pc)] & 0x03E00000) >> 21;
int t = (text[TEXT_POS(pc)] & 0x001F0000) >> 16;
int imm = (text[TEXT_POS(pc)] & 0xFFFF)/*>> 2*/;
if(registers[s] != registers[t])
{
printf("| EXECUTING PC BRANCH - BNE:\n");
printf("PC (START) = %x\n",pc);
printf("imm = %d\n", imm);
pc = pc + 4 + imm; // <-- Unsure about '<< 2' (BLEZ Too)
printf("PC (END) = %x\n",pc);
}
}
// BLEZ
else if ((text[TEXT_POS(pc)] & 0xFC000000) == 0x18000000)
{
printf("| EXECUTING BLEZ:\n");
int s = (text[TEXT_POS(pc)] & 0x03E00000) >> 21;
int tempJump = (text[TEXT_POS(pc)] & 0xFFFF) >> 2;
if(registers[s] <= 0)
{
printf("| EXECUTING PC BRANCH - BLEZ :\n");
pc = pc + 4 + tempJump; // <-- 'Label'? (MIPS REFERENCE SHEET)
}
}
else if((text[TEXT_POS(pc)] & 0xFC000000) == 0)
{
printf("| R-TYPE IF STATEMENT |\n");
// ADD - Finished
if((text[TEXT_POS(pc)] & 0x0000003F) == 0x20)
{
printf("| Executing ADD:\n");
int d = (text[TEXT_POS(pc)] & 0x0000F800) >> 11;
int s = (text[TEXT_POS(pc)] & 0x03E00000) >> 21;
int t = (text[TEXT_POS(pc)] & 0x001F0000) >> 16;
registers[d] = registers[s] + registers[t];
pc = pc + 4;
}
// SLL - Finished
else if((text[TEXT_POS(pc)] & 0x0000003F) == 0x00)
{
printf("| Executing SLL:\n");
int t = (text[TEXT_POS(pc)] & 0x001F0000) >> 16;
int d = (text[TEXT_POS(pc)] & 0x0000F800) >> 11;
short int shamt = (text[TEXT_POS(pc)] & 0x000007C0);
registers[d] = registers[t] << shamt;
pc = pc + 4;
}
// SRL - Finished
else if((text[TEXT_POS(pc)] & 0x0000003F) == 0x2)
{
printf("| Executing SRL:\n");
int t = (text[TEXT_POS(pc)] & 0x001F0000) >> 16;
int d = (text[TEXT_POS(pc)] & 0x0000F800) >> 11;
short int shamt = (text[TEXT_POS(pc)] & 0x000007C0);
registers[d] = registers[t] >> shamt;
pc = pc + 4;
}
// JR
else if((text[TEXT_POS(pc)] & 0x0000003F) == 0x8)
{
printf("| Executing JR:\n");
int s = (text[TEXT_POS(pc)] & 0x03E00000);
pc = registers[s]; // <-- I believe the issue lies here.
}
}
// JAL
else if((text[TEXT_POS(pc)] & 0xFC000000) == 0x0C000000)
{
printf("| Executing JAL:");
int address = (text[TEXT_POS(pc)] & 0x03FFFFFF);
registers[/*$*/31] = pc + 8; // <-- And here
pc = address;
}
if(count == 10)
{
break;
}
count++;
}
printf("----- PRINTING REGISTERS -----\n");
print_registers(); // print out the state of registers at the end of execution
printf("... DONE!\n");
return (0);
}
Above is the full EXC function
ADDI was given as an example to base the rest on!