From 12f959f311fb136f11ac6f9616588ef7e50bc46b Mon Sep 17 00:00:00 2001 From: zedarider Date: Thu, 27 Oct 2016 19:25:25 +0100 Subject: cleaning up --- src/ymh15/2test_mips.cpp | 482 ----------- src/ymh15/mips_cpu.cpp | 97 ++- src/ymh15/mips_cpu.o | Bin 27856 -> 27832 bytes src/ymh15/mips_instruction_test.h | 74 -- src/ymh15/test_mips | Bin 448336 -> 346432 bytes src/ymh15/test_mips.cpp | 1639 +++++++++++-------------------------- src/ymh15/test_mips.h | 74 -- src/ymh15/test_mips.o | Bin 216592 -> 46200 bytes 8 files changed, 507 insertions(+), 1859 deletions(-) delete mode 100644 src/ymh15/2test_mips.cpp delete mode 100644 src/ymh15/mips_instruction_test.h delete mode 100644 src/ymh15/test_mips.h diff --git a/src/ymh15/2test_mips.cpp b/src/ymh15/2test_mips.cpp deleted file mode 100644 index 75afaa8..0000000 --- a/src/ymh15/2test_mips.cpp +++ /dev/null @@ -1,482 +0,0 @@ -#include "../../include/mips.h" -#include "test_mips_ymh15.hpp" - -#include - -using namespace std; - -int main(int argc, char** argv) { - mips_mem_h ram = mips_mem_create_ram(4096); - mips_cpu_h cpu = mips_cpu_create(ram); - - srand(time(NULL)); - - if(argc == 2) { - mips_cpu_set_debug_level(cpu, argv[1][0]-'0', stdout); - } else { - mips_cpu_set_debug_level(cpu, 0, NULL); - } - - mips_test_begin_suite(); - - int testId = mips_test_begin_test("ADD"); - mips_test_end_test(testId, test_add(ram, cpu, ADD, 0x3fffffff, 0, 10), "Testing the adder without overflow"); - - testId = mips_test_begin_test("ADD"); - mips_test_end_test(testId, !test_add(ram, cpu, ADD, 0x7fffffff, 1, 1), "Testing the adder with overflow"); - - testId = mips_test_begin_test("ADDU"); - mips_test_end_test(testId, test_add(ram, cpu, ADDU, 0x3fffffff, 0, 10), "testing without overflow"); - - testId = mips_test_begin_test("ADDU"); - mips_test_end_test(testId, test_add(ram, cpu, ADDU, 0x7fffffff, 1, 1), "Testing the adder with overflow"); - - testId = mips_test_begin_test("SUB"); - mips_test_end_test(testId, test_add(ram, cpu, SUB, 0x3fffffff, 0, 10), "Testing the adder without overflow"); - - testId = mips_test_begin_test("SUB"); - mips_test_end_test(testId, !test_add(ram, cpu, SUB, 0x7fffffff, 1, 1), "Testing the adder with overflow"); - - testId = mips_test_begin_test("SUBU"); - mips_test_end_test(testId, test_add(ram, cpu, SUBU, 0x3fffffff, 0, 10), "Testing the adder without overflow"); - - testId = mips_test_begin_test("SUBU"); - mips_test_end_test(testId, test_add(ram, cpu, SUBU, 0x7fffffff, 1, 1), "Testing the adder with overflow"); - - testId = mips_test_begin_test("AND"); - mips_test_end_test(testId, test_bitwise(ram, cpu, AND), "Testing bitwise and"); - - testId = mips_test_begin_test("OR"); - mips_test_end_test(testId, test_bitwise(ram, cpu, OR), "Testing bitwise or"); - - testId = mips_test_begin_test("XOR"); - mips_test_end_test(testId, test_bitwise(ram, cpu, XOR), "Testing bitwise xor"); - - testId = mips_test_begin_test("ADDI"); - mips_test_end_test(testId, test_I(ram, cpu, ADDI, 20, 10), "Testing addi"); - - testId = mips_test_begin_test("ADDIU"); - mips_test_end_test(testId, test_I(ram, cpu, ADDIU, 20, 10), "Testing addiu"); - - testId = mips_test_begin_test("ANDI"); - mips_test_end_test(testId, test_I(ram, cpu, ANDI, 20, 10), "Testing addi"); - - testId = mips_test_begin_test("ORI"); - mips_test_end_test(testId, test_I(ram, cpu, ORI, 20, 10), "Testing addi"); - - testId = mips_test_begin_test("XORI"); - mips_test_end_test(testId, test_I(ram, cpu, XORI, 20, 10), "Testing addi"); - - testId = mips_test_begin_test("BEQ"); - mips_test_end_test(testId, test_branch(ram, cpu, 4, 4, 0, 9, 4), "Testing BEQ"); - - testId = mips_test_begin_test("BNE"); - mips_test_end_test(testId, test_branch(ram, cpu, 5, 4, 0, 9, 10), "Testing BNE"); - - testId = mips_test_begin_test("BGEZ"); - mips_test_end_test(testId, test_branch(ram, cpu, 1, 4, 0, 1, 20), "Testing BGEZ"); - - testId = mips_test_begin_test("BLEZ"); - mips_test_end_test(testId, test_branch(ram, cpu, 6, -1, 0, 0, 20), "Testing BGEZ"); - - testId = mips_test_begin_test("BGTZ"); - mips_test_end_test(testId, test_branch(ram, cpu, 7, 4, 0, 0, 20), "Testing BGEZ"); - - testId = mips_test_begin_test("BGEZAL"); - mips_test_end_test(testId, test_branch(ram, cpu, 1, 4, 1, 17, 20), "Testing BGEZ"); - - testId = mips_test_begin_test("BLTZAL"); - mips_test_end_test(testId, test_branch(ram, cpu, 1, -1, 1, 16, 20), "Testing BGEZ"); - - testId = mips_test_begin_test("BLTZ"); - mips_test_end_test(testId, test_branch(ram, cpu, 1, -1, 0, 16, 20), "Testing BGEZ"); - - testId = mips_test_begin_test("J"); - mips_test_end_test(testId, test_jump(ram, cpu, J), "Testing J"); - - testId = mips_test_begin_test("JAL"); - mips_test_end_test(testId, test_jump(ram, cpu, JAL), "Testing JAL"); - - testId = mips_test_begin_test("JALR"); - mips_test_end_test(testId, test_jump(ram, cpu, JALR), "Testing JALR"); - - testId = mips_test_begin_test("JR"); - mips_test_end_test(testId, test_jump(ram, cpu, JR), "Testing JR"); - - testId = mips_test_begin_test("LB"); - mips_test_end_test(testId, test_load(ram, cpu, LB, 0xf7), "Testing LB"); - - testId = mips_test_begin_test("LBU"); - mips_test_end_test(testId, test_load(ram, cpu, LBU, 0xf7), "Testing LBU"); - - testId = mips_test_begin_test("LH"); - mips_test_end_test(testId, test_load(ram, cpu, LH, 0xff7f), "Testing LH"); - - testId = mips_test_begin_test("LHU"); - mips_test_end_test(testId, test_load(ram, cpu, LHU, 0xff7f), "Testing LHU"); - - testId = mips_test_begin_test("LW"); - mips_test_end_test(testId, test_load(ram, cpu, LW, 0xffffff7f), "Testing LW"); - - testId = mips_test_begin_test("LUI"); - mips_test_end_test(testId, test_load(ram, cpu, LUI, 0xff7f), "Testing LUI"); - - testId = mips_test_begin_test("LWL"); - mips_test_end_test(testId, test_load(ram, cpu, LWL, 0xff6fff7f), "Testing LWL"); - - testId = mips_test_begin_test("LWR"); - mips_test_end_test(testId, test_load(ram, cpu, LWR, 0xff6fff7f), "Testing LWR"); - - testId = mips_test_begin_test("MULT"); - mips_test_end_test(testId, test_mult_div(ram, cpu, MULT, 5, -4), "Testing LWR"); - - testId = mips_test_begin_test("MULTU"); - mips_test_end_test(testId, test_mult_div(ram, cpu, MULTU, 5, -4), "Testing LWR"); - - testId = mips_test_begin_test("DIV"); - mips_test_end_test(testId, test_mult_div(ram, cpu, DIV, 5, -4), "Testing LWR"); - - testId = mips_test_begin_test("DIVU"); - mips_test_end_test(testId, test_mult_div(ram, cpu, DIVU, 5, -4), "Testing LWR"); - - mips_test_end_suite(); - return 0; -} - -// R Type -uint32_t gen_instruction(uint32_t src1, uint32_t src2, uint32_t dest, - uint32_t shift, uint32_t function) { - uint32_t inst = 0; - inst = inst | src1 << 21 | src2 << 16 | dest << 11 | shift << 6 | - function; - return inst; -} - -// I Type -uint32_t gen_instruction(uint32_t opcode, uint32_t src, uint32_t dest, - uint32_t Astart) { - uint32_t inst = 0; - inst = inst | opcode << 26 | src << 21 | dest << 16 | Astart; - return inst; -} - -// J Type -uint32_t gen_instruction(uint32_t opcode, uint32_t memory) { - uint32_t inst = 0; - inst = inst | opcode << 26 | memory; - return inst; -} - -uint32_t change_endianness(uint32_t inst) { - inst = (inst << 24 | ((inst << 8)&0xff0000) | - ((inst >> 8)&0xff00) |inst >> 24); - return inst; -} - -int test_add(mips_mem_h ram, mips_cpu_h cpu, uint32_t type, uint32_t max, uint8_t value, unsigned i_t) { - - uint32_t inst, ans, a, b; - - for(unsigned i = 0; i < i_t; ++i) { - mips_error mips_err; - mips_cpu_reset(cpu); - inst = change_endianness(gen_instruction(9, 10, 8, 0, type)); - if(value) { - a = max; - if(type > 0x21) { - b = -max; - } else { - b = max; - } - } else { - a = rand() % max; - b = rand() % max; - } - - mips_mem_write(ram, 0, 4, (uint8_t*)&inst); - - mips_cpu_set_register(cpu, 9, a); - mips_cpu_set_register(cpu, 10, b); - - mips_err = mips_cpu_step(cpu); - - mips_cpu_get_register(cpu, 8, &ans); - - if(type < 0x22) { - //printf("%#10x + %#10x = %#10x\t%#10x\n", a, b, ans, mips_err); - if(mips_err == mips_ExceptionArithmeticOverflow || a+b!=ans) { - return 0; - } - } else { - //printf("%#10x - %#10x = %#10x\t%#10x\n", a, b, ans, mips_err); - if(mips_err == mips_ExceptionArithmeticOverflow || a-b!=ans) { - return 0; - } - } - } - - return 1; -} - -int test_bitwise(mips_mem_h ram, mips_cpu_h cpu, uint8_t op) { - uint32_t a, b, ans, inst; - int passed; - for(unsigned i = 0; i < 10; ++i) { - passed = 0; - mips_cpu_reset(cpu); - inst = change_endianness(gen_instruction(8, 9, 7, 0, op)); - - a = rand() % 0xffffffff; - b = rand() % 0xffffffff; - - mips_mem_write(ram, 0, 4, (uint8_t*)&inst); - - mips_cpu_set_register(cpu, 8, a); - mips_cpu_set_register(cpu, 9, b); - - mips_error mips_err = mips_cpu_step(cpu); - - mips_cpu_get_register(cpu, 7, &ans); - - if(op == AND) { - //printf("%#10x & %#10x = %#10x\t%#10x\n", a, b, ans, mips_err); - if((a & b) == ans) { - passed = 1; - } - } else if(op == OR) { - //printf("%#10x | %#10x = %#10x\t%#10x\n", a, b, ans, mips_err); - if((a | b) == ans) { - passed = 1; - } - } else { - //printf("%#10x ^ %#10x = %#10x\t%#10x\n", a, b, ans, mips_err); - if((a ^ b) == ans) { - passed = 1; - } - } - - - if(mips_err != mips_Success || !passed) { - return 0; - } - } - return 1; -} - -int test_I(mips_mem_h ram, mips_cpu_h cpu, uint32_t type, - uint32_t num1, uint32_t num2) { - int passed = 0; - uint32_t result, inst; - - mips_cpu_reset(cpu); - inst = change_endianness(gen_instruction(type, 8, 7, num1)); - - mips_mem_write(ram, 0, 4, (uint8_t*)&inst); - mips_cpu_set_register(cpu, 8, num2); - - mips_cpu_step(cpu); - - mips_cpu_get_register(cpu, 7, &result); - - switch(type) { - case 8: - if(result == num1 + num2) { - passed = 1; - } - case 9: - if(result == num1 + num2) { - passed = 1; - } - case 12: - if(result == (num1 & num2)) { - passed = 1; - } - case 13: - if(result == (num1 | num2)) { - passed = 1; - } - case 14: - if(result == (num1 ^ num2)) { - passed = 1; - } - default:; - } - - return passed; -} - -int test_branch(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode, uint32_t a, uint8_t l, uint32_t opc2, uint32_t b) { - int passed = 0; - int pass = 0; - uint32_t reg10, reg11, reg31, pc_set; - pc_set = 32; - mips_cpu_reset(cpu); - mips_cpu_set_pc(cpu, pc_set); - - uint32_t inst = change_endianness(gen_instruction(opcode, 8, opc2, 3)); - mips_mem_write(ram, pc_set, 4, (uint8_t*)&inst); - inst = change_endianness(gen_instruction(8, 9, 10, 0, ADDU)); - mips_mem_write(ram, pc_set+4, 4, (uint8_t*)&inst); - inst = change_endianness(gen_instruction(8, 12, 11, 0, ADDU)); - mips_mem_write(ram, pc_set+16, 4, (uint8_t*)&inst); - inst = change_endianness(gen_instruction(8, 13, 10, 0, ADDU)); - mips_mem_write(ram, pc_set+8, 4, (uint8_t*)&inst); - - mips_cpu_set_register(cpu, 8, a); - mips_cpu_set_register(cpu, 9, b); - mips_cpu_set_register(cpu, 12, 30); - mips_cpu_set_register(cpu, 13, 100); - - mips_cpu_step(cpu); - mips_cpu_step(cpu); - mips_cpu_step(cpu); - - mips_cpu_get_register(cpu, 10, ®10); - mips_cpu_get_register(cpu, 11, ®11); - - if(l == 1) { - mips_cpu_get_register(cpu, 31, ®31); - if(reg31 == pc_set+8) { - pass = 1; - } - } else { - pass = 1; - } - - if(reg10 == a+b && reg11 == a+30 && pass) { - passed = 1; - } else { - passed = 0; - } - - return passed; -} - -int test_jump(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode) { - int passed = 0; - uint32_t inst, reg10, reg13, reg16, reg31; - - mips_cpu_reset(cpu); - - if(opcode == 2 || opcode == 3) { - inst = change_endianness(gen_instruction(opcode, 0x20)); - } else if(opcode == 8 || opcode == 9) { - inst = change_endianness(gen_instruction(25, 0, 31, 0, opcode)); - } - - mips_mem_write(ram, 0, 4, (uint8_t*)&inst); - - inst = change_endianness(gen_instruction(8, 9, 10, 0, ADDU)); - mips_mem_write(ram, 4, 4, (uint8_t*)&inst); - inst = change_endianness(gen_instruction(11, 12, 13, 0, ADDU)); - mips_mem_write(ram, 8, 4, (uint8_t*)&inst); - inst = change_endianness(gen_instruction(14, 15, 16, 0, ADDU)); - mips_mem_write(ram, 0x20<<2, 4, (uint8_t*)&inst); - - mips_cpu_set_register(cpu, 8, 8); - mips_cpu_set_register(cpu, 9, 9); - mips_cpu_set_register(cpu, 10, 10); - mips_cpu_set_register(cpu, 11, 11); - mips_cpu_set_register(cpu, 12, 12); - mips_cpu_set_register(cpu, 13, 13); - mips_cpu_set_register(cpu, 14, 14); - mips_cpu_set_register(cpu, 15, 15); - mips_cpu_set_register(cpu, 16, 16); - mips_cpu_set_register(cpu, 25, 0x20<<2); - - mips_cpu_step(cpu); - mips_cpu_step(cpu); - mips_cpu_step(cpu); - - mips_cpu_get_register(cpu, 10, ®10); - mips_cpu_get_register(cpu, 13, ®13); - mips_cpu_get_register(cpu, 16, ®16); - mips_cpu_get_register(cpu, 31, ®31); - - if(reg10 == 9+8 && reg13 == 13 && reg16 == 14+15) { - passed = 1; - } - - if((opcode == 3 || opcode == 9) && reg31 != 8) { - passed = 0; - } - - return passed; -} - -int test_load(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode, uint32_t word) { - int passed = 0; - uint16_t half_word; - uint8_t byte; - uint32_t res; - - half_word = (uint16_t)word; - byte = (uint8_t)word; - - mips_cpu_reset(cpu); - - uint32_t inst = change_endianness(gen_instruction(opcode, 8, 9, 4)); - - mips_mem_write(ram, 0, 4, (uint8_t*)&inst); - - if(opcode == LB || opcode == LBU) { - mips_mem_write(ram, 0x30, 1, &byte); - } else if(opcode == LH || opcode == LHU) { - uint16_t tmp = (half_word<<8) | (half_word>>8); - mips_mem_write(ram, 0x30, 2, (uint8_t*)&tmp); - } else { - uint32_t tmp = change_endianness(word); - mips_mem_write(ram, 0x30, 4, (uint8_t*)&tmp); - } - - mips_cpu_set_register(cpu, 8, 0x2c); - if(opcode == LWR) { - mips_cpu_set_register(cpu, 8, 0x2f); - } - mips_cpu_set_register(cpu, 9, 0xbabacdcd); - - mips_cpu_step(cpu); - - mips_cpu_get_register(cpu, 9, &res); - - if((res == (uint32_t)(int8_t)byte && opcode == LB) || (res == (uint32_t)byte && opcode == LBU) || (res == (uint32_t)(int16_t)half_word && opcode == LH) || (res == (uint32_t)half_word && opcode == LHU) || (res == word && opcode == LW) || (res == 4<<16 && opcode == LUI) || (res == ((word&0xffff)|(0xbaba0000)) && (opcode == LWR)) || (res == ((word&0xffff0000)|(0xcdcd)))) { - passed = 1; - } - - return passed; -} - -int test_mult_div(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode, uint32_t num1, uint32_t num2) { - int passed = 0; - uint64_t result; - uint32_t hi, lo; - - mips_cpu_reset(cpu); - - uint32_t inst = change_endianness(gen_instruction(8, 9, 0, 0, opcode)); - mips_mem_write(ram, 0, 4, (uint8_t*)&inst); - inst = change_endianness(gen_instruction(0, 0, 10, 0, MFHI)); - mips_mem_write(ram, 4, 4, (uint8_t*)&inst); - inst = change_endianness(gen_instruction(0, 0, 11, 0, MFLO)); - mips_mem_write(ram, 8, 4, (uint8_t*)&inst); - - mips_cpu_set_register(cpu, 8, num1); - mips_cpu_set_register(cpu, 9, num2); - mips_cpu_set_register(cpu, 10, 0xabcde); - mips_cpu_set_register(cpu, 11, 0xf193b); - - mips_cpu_step(cpu); - mips_cpu_step(cpu); - mips_cpu_step(cpu); - - mips_cpu_get_register(cpu, 10, &hi); - mips_cpu_get_register(cpu, 11, &lo); - - result = (((uint64_t)hi)<<32) | ((uint64_t)lo); - - if((opcode == MULT && result == (uint64_t)((int64_t)(int32_t)num1*(int64_t)(int32_t)num2)) || (opcode == MULTU && result == (uint64_t)((uint32_t)num1)*(uint32_t)num2) || (opcode == DIV && lo == (uint32_t)((int32_t)num1/(int32_t)num2) && hi == (uint32_t)((int32_t)num1%(int32_t)num2)) || (opcode == DIVU && lo == num1/num2 && hi == num1%num2)) { - passed = 1; - } - - return passed; -} diff --git a/src/ymh15/mips_cpu.cpp b/src/ymh15/mips_cpu.cpp index 37bf08a..5a67d47 100644 --- a/src/ymh15/mips_cpu.cpp +++ b/src/ymh15/mips_cpu.cpp @@ -68,7 +68,7 @@ mips_error mips_cpu_get_register(mips_cpu_h state, unsigned index, mips_error mips_cpu_set_register(mips_cpu_h state, unsigned index, uint32_t value) { if(index > 31 || index < 1) { - return mips_ErrorInvalidArgument; + return mips_ExceptionAccessViolation; } // set reg state state->regs[index] = value; @@ -102,18 +102,26 @@ mips_error mips_cpu_step(mips_cpu_h state) { // change the instruction back from big endian as it was read as little endian inst = (inst<<24) | ((inst>>8)&0xff00) | ((inst<<8)&0xff0000) | (inst>>24); - // it then executes the instruction by decoding it first and returns - // the state of the instruction - mips_error mips_err = exec_instruction(state, inst); - - + // if the debug level is 2 or higher it will print the register state + if(state->debug_level > 2) { + fprintf(state->debug_type, "\nCPU register state before:\n"); + for(unsigned i = 0; i < 32; ++i) { + fprintf(state->debug_type, "R%d:\t%#10x\n", i, + state->regs[i]); + } + fprintf(state->debug_type, "\n\n"); + } + if(state->debug_level > 0) { fprintf(state->debug_type, "pc: %d\tpc_next: %d\tinst: %#10x\tdelay_slot: %d\n", state->pc, state->next_pc, inst, state->delay_slot); } - // if the debug level is 2 or higher it will print the register state + // it then executes the instruction by decoding it first and returns + // the state of the instruction + mips_error err = exec_instruction(state, inst); + if(state->debug_level > 1) { - fprintf(state->debug_type, "\nCPU register state:\n"); + fprintf(state->debug_type, "\nCPU register state after:\n"); for(unsigned i = 0; i < 32; ++i) { fprintf(state->debug_type, "R%d:\t%#10x\n", i, state->regs[i]); @@ -121,8 +129,10 @@ mips_error mips_cpu_step(mips_cpu_h state) { fprintf(state->debug_type, "\n\n"); } - if(state->debug_level > 2) { + if(state->debug_level > 3) { char c = getchar(); + // do nothing with c to supress warning + (void)c; } // it then updates the pc to next_pc which could have been changed @@ -136,15 +146,11 @@ mips_error mips_cpu_step(mips_cpu_h state) { } // returns the operation error such as arithmetic overflow - return mips_err; + return err; } mips_error mips_cpu_set_debug_level(mips_cpu_h state, unsigned level, FILE *dest) { - if(!state) { - return mips_ErrorInvalidArgument; - } - // just sets the cpu values for the debug level state->debug_level = level; state->debug_type = dest; @@ -166,8 +172,6 @@ mips_error exec_instruction(mips_cpu_h state, uint32_t inst) { // creates var that holds all the information of the instruction uint32_t var[8]; - // prints pc and instruction every clock cycle - for(int i = 0; i < 8; ++i) { var[i] = 0; } @@ -175,26 +179,25 @@ mips_error exec_instruction(mips_cpu_h state, uint32_t inst) { // decodes the instruction // if first 6 bits are 0 then it is a R instruction - if(((inst >> 26)&0x3f) == 0) { - // R Type: set all necessary variables + if(((inst >> 26)&0x3f) == 0) { // R Type var[REG_S] = inst >> 21; var[REG_T] = (inst >> 16)&0x1f; var[REG_D] = (inst >> 11)&0x1f; var[SHIFT] = (inst >> 6)&0x1f; var[FUNC] = inst&0x3f; - // execute R instruction to perform operation return exec_R(state, var); - } else if(((inst >> 26)&0x3f) == J || ((inst >> 26)&0x3f) == JAL) { // as opcode is < 4 - var[OPCODE] = inst >> 26; // it has to be J type + + } else if(((inst >> 26)&0x3f) == J || ((inst >> 26)&0x3f) == JAL) { // J Type + var[OPCODE] = inst >> 26; var[MEM] = inst&0x3ffffff; return exec_J(state, var); - } else { // otherwise it is an I type + + } else { // I type var[OPCODE] = inst >> 26; var[REG_S] = (inst >> 21)&0x1f; var[REG_D] = (inst >> 16)&0x1f; var[IMM] = (uint32_t)(int16_t)(inst&0xffff); - return exec_I(state, var); } } @@ -212,19 +215,15 @@ mips_error exec_R(mips_cpu_h state, uint32_t var[8]) { return bitwise(state, var, 0); } else if(var[FUNC] == JR) { - // jr return jump(state, var, 0); } else if(var[FUNC] == JALR) { - // jalr return jump(state, var, 1); } else if(var[FUNC] >= MFHI && var[FUNC] <= MTLO) { - // mfhi mthi mflo mtlo return move(state, var); } else if(var[FUNC] >= MULT && var[FUNC] <= DIVU) { - // mult multu div divu return mult_div(state, var); } else if(var[FUNC] == SLT || var[FUNC] == SLTU) { @@ -244,9 +243,9 @@ mips_error exec_R(mips_cpu_h state, uint32_t var[8]) { mips_error exec_J(mips_cpu_h state, uint32_t var[8]) { switch(var[OPCODE]) { - case J: // j + case J: return jump(state, var, 0); - case JAL: // jal + case JAL: return jump(state, var, 1); default: return mips_ExceptionInvalidInstruction; @@ -255,19 +254,19 @@ mips_error exec_J(mips_cpu_h state, uint32_t var[8]) { mips_error exec_I(mips_cpu_h state, uint32_t var[8]) { switch(var[OPCODE]) { - case BGEZ: // bgez, bgezal, bltz, bltzal + case BGEZ: return branch(state, var); - case BEQ: // beq + case BEQ: return branch(state, var); - case BNE: // bne + case BNE: return branch(state, var); - case BLEZ: // blez + case BLEZ: return branch(state, var); - case BGTZ: // bgtz + case BGTZ: return branch(state, var); - case ADDI: // addi + case ADDI: return add_sub(state, var, 1, 1); - case ADDIU: // addiu + case ADDIU: return add_sub(state, var, 1, 2); case SLTI: return set(state, var, 1); @@ -275,31 +274,31 @@ mips_error exec_I(mips_cpu_h state, uint32_t var[8]) { return set(state, var, 1); case ANDI: return bitwise(state, var, 1); - case ORI: // ori + case ORI: return bitwise(state, var, 1); - case XORI: // xori + case XORI: return bitwise(state, var, 1); - case LUI: // lui + case LUI: return load(state, var); - case LB: // lb + case LB: return load(state, var); - case LH: // lh + case LH: return load(state, var); - case LWL: // lwl + case LWL: return load(state, var); - case LW: // lw + case LW: return load(state, var); - case LBU: // lbu + case LBU: return load(state, var); - case LHU: // lhu + case LHU: return load(state, var); - case LWR: // lwr + case LWR: return load(state, var); - case SB: // sb + case SB: return store(state, var); - case SH: // sh + case SH: return store(state, var); - case SW: // sw + case SW: return store(state, var); default: return mips_ExceptionInvalidInstruction; diff --git a/src/ymh15/mips_cpu.o b/src/ymh15/mips_cpu.o index d59e406..d96bef0 100644 Binary files a/src/ymh15/mips_cpu.o and b/src/ymh15/mips_cpu.o differ diff --git a/src/ymh15/mips_instruction_test.h b/src/ymh15/mips_instruction_test.h deleted file mode 100644 index f276124..0000000 --- a/src/ymh15/mips_instruction_test.h +++ /dev/null @@ -1,74 +0,0 @@ -#include "mips.h" - -// Used to define the generic instruction implementation -struct instruction_impl{ - char type; - uint8_t opCode; - // Only used for an 'actual' function rather than instruction set member - uint32_t data; - - // Constructor where there is actual raw data - instruction_impl(uint32_t dataIn, char typeIn): - type(typeIn), - opCode(uint8_t((dataIn & 0xFC000000) >> 26)), - data(dataIn){} -}; - -// Used for R type instructions, inherits the generic function type -struct instruction_impl_r : public instruction_impl{ - uint8_t source1; - uint8_t source2; - uint8_t dest; - uint8_t shift; - uint8_t function; - - // Constructor specifying each part of the instruction - instruction_impl_r( - uint8_t source1In, - uint8_t source2In, - uint8_t destIn, - uint8_t shiftIn, - uint8_t functionIn): - instruction_impl( - uint32_t( - 0x00000000 | ((uint32_t(source1In) & 0x0000001F) << 21) | - ((uint32_t(source2In) & 0x0000001F) << 16) | - ((uint32_t(destIn) & 0x0000001F) << 11) | - ((uint32_t(shiftIn) & 0x0000001F) << 6) | - (uint32_t(functionIn) & 0x0000003F)), - 'r'), - source1(source1In), - source2(source2In), - dest(destIn), - shift(shiftIn), - function(functionIn){} -}; - -// Used for J type instructions, inherits the generic function type -struct instruction_impl_j: public instruction_impl{ - uint32_t address; - - instruction_impl_j(uint8_t opCodeIn, uint32_t addressIn): - instruction_impl(uint32_t(((uint32_t(opCodeIn) & 0x0000003F) << 26) | (addressIn & 0x03FFFFFF)), 'j'), - address(addressIn){} -}; - -// Used for I type instructions, inherits the generic function type -struct instruction_impl_i: public instruction_impl{ - uint8_t source; - uint8_t dest; - uint16_t immediate; - - // Constructor specifying each part of the instruction - instruction_impl_i(uint8_t opCodeIn, uint8_t sourceIn, uint8_t destIn, uint16_t immediateIn): - instruction_impl( - uint32_t( - 0x00000000 | ((uint32_t(opCodeIn) & 0x0000003F) << 26) | - ((uint32_t(sourceIn) & 0x0000001F) << 21) | - ((uint32_t(destIn) & 0x0000001F) << 16) | - (uint32_t(immediateIn))), - 'i'), - source(sourceIn), - dest(destIn), - immediate(immediateIn){} -}; diff --git a/src/ymh15/test_mips b/src/ymh15/test_mips index 0368d58..69c8282 100755 Binary files a/src/ymh15/test_mips and b/src/ymh15/test_mips differ diff --git a/src/ymh15/test_mips.cpp b/src/ymh15/test_mips.cpp index 67bed8f..75afaa8 100644 --- a/src/ymh15/test_mips.cpp +++ b/src/ymh15/test_mips.cpp @@ -1,1203 +1,482 @@ -#include "test_mips.h" - -int main(){ - - mips_test_begin_suite(); - - // Create 512MB of RAM - PHWOAAAR (used to test J and JAL instructions) - mips_mem_h testMem = mips_mem_create_ram(512000000); - mips_cpu_h testCPU = mips_cpu_create(testMem); - - // Check get and set for R1 to R31 - for (unsigned i = 1; i < 32; i++){ - test cpu_getSetReg("", "Verify that the value from a register is " - "the same as the value the register was set to", 0); - writeReg(testCPU, i, 0xABCDEF12); - cpu_getSetReg.checkReg(i, 0xABCDEF12); - cpu_getSetReg.perform_test(testCPU, testMem); - } - - test cpu_getSetPc("", "Verify that the program counter is the same " - "as it was set to", 0); - writeReg(testCPU, 255, 404); // Joke: Program Counter not found? - cpu_getSetPc.checkReg(255, 404); - cpu_getSetPc.perform_test(testCPU, testMem); - - test set_zero("", "Verify that R0 = 0 after an attempted set", 0); - writeReg(testCPU, 0, 0xABCDEF12); - set_zero.checkReg(0, 0); - set_zero.perform_test(testCPU, testMem); - - test cpu_reset("", "Verify all regs and " - "pc set to 0 after reset", 0); - // Example of using for loops to define a test -- Why it isn't from a file - for (unsigned i = 0; i < 32; i++){ - // Set the value of each register to its index - writeReg(testCPU, i, i); - cpu_reset.checkReg(i, 0); - } - mips_cpu_reset(testCPU); - cpu_reset.perform_test(testCPU, testMem); - - // Check that each combination of registers can be uses as source1, source2 - // and dest - Yes this does ~28,000 tests (Uses addu as simple instruction - // to implement) - // Could take this approach with every instruction but that would be OTT - // Changed according to formative feedback for speed purposes! - for (unsigned r1 = 1; r1 < 32; r1 += 7){ - for (unsigned r2 = 1; r2 < 32; r2 += 5){ - for (unsigned r3 = 1; r3 < 32; r3 += 3){ - // Make sure Source1 and Source 2 are different - if(r2 != r3){ - test basic_addu("", - "Verify the result of addu with no overflow for each combination of" - " source1, source2 and destination", 1); - writeMem(testMem, get_pc(testCPU), - instruction_impl_r(r2, r3, r1, 0, 33).data); - writeReg(testCPU, r2, 0x1374BAB3); - writeReg(testCPU, r3, 0x3A947118); - basic_addu.checkReg(r1, 0x4E092BCB); - basic_addu.perform_test(testCPU, testMem); - // Reset CPU after each test to keep instruction executing in same - // memory location - mips_cpu_reset(testCPU); - } - } +#include "../../include/mips.h" +#include "test_mips_ymh15.hpp" + +#include + +using namespace std; + +int main(int argc, char** argv) { + mips_mem_h ram = mips_mem_create_ram(4096); + mips_cpu_h cpu = mips_cpu_create(ram); + + srand(time(NULL)); + + if(argc == 2) { + mips_cpu_set_debug_level(cpu, argv[1][0]-'0', stdout); + } else { + mips_cpu_set_debug_level(cpu, 0, NULL); } - } - - test reg_all("", "Verify that a register can be used as both " - "sources and a destination, all at once", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(8, 8, 8, 0, 33).data); - writeReg(testCPU, 8, 0x1AFAC3B0); - reg_all.checkReg(8, 0x35F58760); - reg_all.perform_test(testCPU, testMem); - - test basic_sll("sll", "Verify that R8 = R9 << 5 and R9 unchanged", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(0, 9, 8, 5, 0).data); - writeReg(testCPU, 9, 0xFBABABAB); - basic_sll.checkReg(8, 0x75757560); - basic_sll.checkReg(9, 0xFBABABAB); - basic_sll.perform_test(testCPU, testMem); - - test basic_srl("srl", "Verify that R8 = R9 >> 5 and R9 unchanged", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(0, 9, 8, 5, 2).data); - writeReg(testCPU, 9, 0xFBABABAB); - basic_srl.checkReg(8, 0x7DD5D5D); - basic_srl.checkReg(9, 0xFBABABAB); - basic_srl.perform_test(testCPU, testMem); - - test basic_sra("sra", "Verify that R8 = R9 arith>> 5 and R9 unchanged", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(0, 9, 8, 5, 3).data); - writeReg(testCPU, 9, 0x80309000); - basic_sra.checkReg(8, 0xFC018480); - basic_sra.checkReg(9, 0x80309000); - basic_sra.perform_test(testCPU, testMem); - - test basic_sraPos("sra", "Verify that R8 = R9 arith>> 5 and R9 unchanged when" - " R9 is positive", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(0, 9, 8, 19, 3).data); - writeReg(testCPU, 9, 0x0ABA1A34); - basic_sraPos.checkReg(8, 0x157); - basic_sraPos.checkReg(9, 0x0ABA1A34); - basic_sraPos.perform_test(testCPU, testMem); - - test basic_sllv("sllv", "Verify that R8 = R9 << R10 and R9 R10 unchanged", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(10, 9, 8, 0, 4).data); - writeReg(testCPU, 9, 0xFBABABAB); - writeReg(testCPU, 10, 5); - basic_sllv.checkReg(8, 0x75757560); - basic_sllv.checkReg(9, 0xFBABABAB); - basic_sllv.checkReg(10, 5); - basic_sllv.perform_test(testCPU, testMem); - - test basic_srlv("srlv", "Verify that R8 = R9 >> R10 and R9 R10 unchanged", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(10, 9, 8, 0, 6).data); - writeReg(testCPU, 9, 0xFBABABAB); - writeReg(testCPU, 10, 5); - basic_srlv.checkReg(8, 0x7DD5D5D); - basic_srlv.checkReg(9, 0xFBABABAB); - basic_srlv.checkReg(10, 5); - basic_srlv.perform_test(testCPU, testMem); - - test basic_srav("srav", - "Verify that R8 = R9 arith>> R10 and R9 R10 unchanged", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(10, 9, 8, 0, 7).data); - writeReg(testCPU, 9, 0x80000000); - writeReg(testCPU, 10, 5); - basic_srav.checkReg(8, 0xFC000000); - basic_srav.checkReg(9, 0x80000000); - basic_srav.checkReg(10, 5); - basic_srav.perform_test(testCPU, testMem); - - test basic_sravPos("srav", - "verify that R8 = R9 >> R10 and R9 R10 unchanged when R9 is positive", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(10, 9, 8, 0, 7).data); - writeReg(testCPU, 9, 0x74BABBC1); - writeReg(testCPU, 10, 9); - basic_sravPos.checkReg(8, 0x003A5D5D); - basic_sravPos.checkReg(9, 0x74BABBC1); - basic_sravPos.checkReg(10, 9); - basic_sravPos.perform_test(testCPU, testMem); - - test basic_jr("jr", "Verify that pc = R9 and R9 unchanged as well as that the" - " instruction in the branch delay slot is executed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 0, 0, 0, 8).data); - // R8 = R9 >> 1 in the branch delay slot - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 9, 8, 1, 2).data); - writeReg(testCPU, 9, 0x000000A4); - basic_jr.checkReg(255, 0x000000A4); - basic_jr.checkReg(8, 0x00000052); - basic_jr.checkReg(9, 0x000000A4); - basic_jr.perform_test(testCPU, testMem); - - test basic_jalr("jalr", - "Verify that pc = R9, R1 = R9 + 8 and R9 unchangedas well as that the" - " instruction in the branch delay slot is executed and R31 set", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 0, 31, 0, 9).data); - // R8 = R9 >> 3 in the branch delay slot - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 9, 8, 3, 2).data); - writeReg(testCPU, 9, 0x000000B4); - basic_jalr.checkReg(255, 0x000000B4); - basic_jalr.checkReg(8, 0x00000016); - basic_jalr.checkReg(31, get_pc(testCPU) + 8); - basic_jalr.perform_test(testCPU, testMem); - - // nops after since: - // "Reads of the HI or LO special registers must be separated from - // subsequent instructions that write to them by two or more other - // instructions." - test basic_mthi("mthi", "Checks value from mfhi is same as given in mthi", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(8, 0, 0, 0, 17).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 9, 0, 16).data); - writeMem(testMem, get_pc(testCPU) + 8, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeMem(testMem, get_pc(testCPU) + 12, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x0BABABAC); - basic_mthi.checkReg(9, 0x0BABABAC); - basic_mthi.perform_test(testCPU, testMem); - - test basic_mfhi("mfhi", "Checks value from mfhi is same as given in mthi", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(8, 0, 0, 0, 17).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 9, 0, 16).data); - writeMem(testMem, get_pc(testCPU) + 8, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeMem(testMem, get_pc(testCPU) + 12, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x1F1C1D1A); - basic_mfhi.checkReg(9, 0x1F1C1D1A); - basic_mfhi.perform_test(testCPU, testMem); - - test basic_mtlo("mtlo", "Checks value from mflo is same as given in mtlo", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(8, 0, 0, 0, 17).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 9, 0, 16).data); - writeMem(testMem, get_pc(testCPU) + 8, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeMem(testMem, get_pc(testCPU) + 12, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x0BABABAC); - basic_mtlo.checkReg(9, 0x0BABABAC); - basic_mtlo.perform_test(testCPU, testMem); - - test basic_mflo("mflo", "Checks value from mflo is same as given in mtlo", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(8, 0, 0, 0, 17).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 9, 0, 16).data); - writeMem(testMem, get_pc(testCPU) + 8, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeMem(testMem, get_pc(testCPU) + 12, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x1F1C1D1A); - basic_mflo.checkReg(9, 0x1F1C1D1A); - basic_mflo.perform_test(testCPU, testMem); - - test basic_multu("multu", "Verify values of hi and lo after R10 * R11", 5); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(10, 11, 0, 0, 25).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 8, 0, 16).data); - writeMem(testMem, get_pc(testCPU) + 8, - instruction_impl_r(0, 0, 9, 0, 18).data); - writeMem(testMem, get_pc(testCPU) + 12, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeMem(testMem, get_pc(testCPU) + 16, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 10, 0x0BABABAB); - writeReg(testCPU, 11, 0xFEFEFEFE); - basic_multu.checkReg(8, 0x0B9FF447); - basic_multu.checkReg(9, 0xE651FDAA); - basic_multu.perform_test(testCPU, testMem); - - test basic_mult("mult", "Verify values of hi and lo after R10 * R11 with R10 " - "and R11 both positive", 5); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(10, 11, 0, 0, 24).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 8, 0, 16).data); - writeMem(testMem, get_pc(testCPU) + 8, - instruction_impl_r(0, 0, 9, 0, 18).data); - writeMem(testMem, get_pc(testCPU) + 12, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeMem(testMem, get_pc(testCPU) + 16, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 10, 0x1ACDC121); - writeReg(testCPU, 11, 0x22BBC999); - basic_mult.checkReg(8, 0x03A2FD0E); - basic_mult.checkReg(9, 0x06B655B9); - basic_mult.perform_test(testCPU, testMem); - - test mult_negative("mult", "Verify values of hi and lo after R10 * R11", 5); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(10, 11, 0, 0, 24).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 8, 0, 16).data); - writeMem(testMem, get_pc(testCPU) + 8, - instruction_impl_r(0, 0, 9, 0, 18).data); - writeMem(testMem, get_pc(testCPU) + 12, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeMem(testMem, get_pc(testCPU) + 16, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 10, 0x0BABABAB); - writeReg(testCPU, 11, 0xFEFEFEFE); - mult_negative.checkReg(8, 0xFFF4489C); - mult_negative.checkReg(9, 0xE651FDAA); - mult_negative.perform_test(testCPU, testMem); - - test basic_divu("divu", "Check hi and lo after R10 / R11", 5); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(10, 11, 0, 0, 27).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 8, 0, 16).data); - writeMem(testMem, get_pc(testCPU) + 8, - instruction_impl_r(0, 0, 9, 0, 18).data); - writeMem(testMem, get_pc(testCPU) + 12, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeMem(testMem, get_pc(testCPU) + 16, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 10, 0xF1489B44); - writeReg(testCPU, 11, 0x000000A1); - basic_divu.checkReg(8, 121); - basic_divu.checkReg(9, 25143275); - basic_divu.perform_test(testCPU, testMem); - - test basic_div("div", "Check hi and lo after R10 / R11 (signed)", 3); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(10, 11, 0, 0, 26).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 8, 0, 16).data); - writeMem(testMem, get_pc(testCPU) + 8, - instruction_impl_r(0, 0, 9, 0, 18).data); - writeMem(testMem, get_pc(testCPU) + 12, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeMem(testMem, get_pc(testCPU) + 16, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 10, 0xF1489B44); - writeReg(testCPU, 11, 0x000000A1); - basic_div.checkReg(8, 0xffffff87); - basic_div.checkReg(9, 0xffe8999d); - basic_div.perform_test(testCPU, testMem); - - test div_negop2("div", "Check hi and lo after R10 / R11 (signed) where R11 is" - " negative", 3); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(10, 11, 0, 0, 26).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 8, 0, 16).data); - writeMem(testMem, get_pc(testCPU) + 8, - instruction_impl_r(0, 0, 9, 0, 18).data); - writeReg(testCPU, 10, 0x0BF9F147); - writeReg(testCPU, 11, 0xFFFFFF12); - div_negop2.checkReg(8, 0xB); - div_negop2.checkReg(9, 0xfff31e2e); - div_negop2.perform_test(testCPU, testMem); - - test basic_add("add", - "Verify the result of an add where there is no overflow", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 32).data); - writeReg(testCPU, 9, 0x0BB8BB8F); - writeReg(testCPU, 10, 0x00AAA1C1); - basic_add.checkReg(8, 0xC635D50); - basic_add.perform_test(testCPU, testMem); - - writeReg(testCPU, 8, 0xFAFAFAFA); - test add_overflow_pos("add", "Check that dest register doesn't change if " - "positive overflow occurs in add", 1, mips_ExceptionArithmeticOverflow); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 32).data); - writeReg(testCPU, 9, 0x7A8B8BB1); - writeReg(testCPU, 10, 0x71649BCD); - add_overflow_pos.checkReg(8, 0xFAFAFAFA); - add_overflow_pos.perform_test(testCPU, testMem); - - writeReg(testCPU, 8, 0xFAFAFAFA); - test add_overflow_neg("add", "Check that dest register doesn't change if " - "negative overflow occurs in add", 1, mips_ExceptionArithmeticOverflow); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 32).data); - writeReg(testCPU, 9, 0x80ABAF14); - writeReg(testCPU, 10, 0xF1649BCD); - add_overflow_neg.checkReg(8, 0xFAFAFAFA); - add_overflow_neg.perform_test(testCPU, testMem); - - test basic_addu("addu", "Verify the result of addu with no overflow", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 33).data); - writeReg(testCPU, 9, 0x1374BAB3); - writeReg(testCPU, 10, 0x3A947118); - basic_addu.checkReg(8, 0x4E092BCB); - basic_addu.perform_test(testCPU, testMem); - - test addu_overflow("addu", - "Verify that addu result valid even with overflow", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 33).data); - writeReg(testCPU, 9, 0xF374BAB3); - writeReg(testCPU, 10, 0x3A947118); - addu_overflow.checkReg(8, 0x2E092BCB); - addu_overflow.perform_test(testCPU, testMem); - - test basic_sub("sub", - "Verify the result of a sub where there is no overflow", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 34).data); - writeReg(testCPU, 9, 0x0BB8BB8F); - writeReg(testCPU, 10, 0x00AAA1C1); - basic_sub.checkReg(8, 0xB0E19CE); - basic_sub.perform_test(testCPU, testMem); - - test sub_overflow_pos("sub", "Check that dest register doesn't change if " - "positive overflow occurs in sub", 1, mips_ExceptionArithmeticOverflow); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 34).data); - writeReg(testCPU, 8, 0xFAFAFAFA); - writeReg(testCPU, 9, 0x7A8B8BB1); - writeReg(testCPU, 10, 0x81649BCD); - sub_overflow_pos.checkReg(8, 0xFAFAFAFA); - sub_overflow_pos.perform_test(testCPU, testMem); - - test sub_overflow_neg("sub", "Check that dest register doesn't change if " - "negative overflow occurs in sub", 1, mips_ExceptionArithmeticOverflow); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 34).data); - writeReg(testCPU, 8, 0xFAFAFAFA); - writeReg(testCPU, 9, 0x80ABAF14); - writeReg(testCPU, 10, 0x71649BCD); - sub_overflow_neg.checkReg(8, 0xFAFAFAFA); - sub_overflow_neg.perform_test(testCPU, testMem); - - test basic_subu("subu", "Verify the result of subu with no overflow", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 35).data); - writeReg(testCPU, 9, 0x1374BAB3); - writeReg(testCPU, 10, 0x3A947118); - basic_subu.checkReg(8, 0xD8E0499B); - basic_subu.perform_test(testCPU, testMem); - - test subu_overflow("subu", - "Verify that subu result valid even with overflow", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 35).data); - writeReg(testCPU, 9, 0x7374BAB3); - writeReg(testCPU, 10, 0xF14A8BC1); - subu_overflow.checkReg(8, 0x822A2EF2); - subu_overflow.perform_test(testCPU, testMem); - - test and_basic("and", "Verify the result of R8 = R9 & R10", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 36).data); - writeReg(testCPU, 9, 0x1337C3D0); - writeReg(testCPU, 10, 0xBB81A1AC); - and_basic.checkReg(8, 0x13018180); - and_basic.perform_test(testCPU, testMem); - - test or_basic("or", "Verify the result of R8 = R9 | R10", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 37).data); - writeReg(testCPU, 9, 0x1337C3D0); - writeReg(testCPU, 10, 0xBB81A1AC); - or_basic.checkReg(8, 0xBBB7E3FC); - or_basic.perform_test(testCPU, testMem); - - test xor_basic("xor", "Verify the result of R8 = R9 ^ R10", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 38).data); - writeReg(testCPU, 9, 0x1337C3D0); - writeReg(testCPU, 10, 0xBB81A1AC); - xor_basic.checkReg(8, 0xA8B6627C); - xor_basic.perform_test(testCPU, testMem); - - test slt_basic_unset("slt", - "Check that R8 isn't set since R9 > R10 (signed)", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 42).data); - writeReg(testCPU, 8, 0x1234ABCD); - writeReg(testCPU, 9, 0x03456789); - writeReg(testCPU, 10, 0xF4F4BEEE); - slt_basic_unset.checkReg(8, 0); - slt_basic_unset.perform_test(testCPU, testMem); - - test sltu_basic("sltu", "Check that R8 is set since R9 < R10 (unsigned)", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 43).data); - writeReg(testCPU, 8, 0x1234ABCD); - writeReg(testCPU, 9, 0x03456789); - writeReg(testCPU, 10, 0xF4F4BEEE); - sltu_basic.checkReg(8, 1); - sltu_basic.perform_test(testCPU, testMem); - - test slt_basic_set("slt", "Check that R8 is set since R9 < R10 (signed)", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_r(9, 10, 8, 0, 42).data); - writeReg(testCPU, 8, 0xBBBBBBBB); - writeReg(testCPU, 9, 0x08008501); - writeReg(testCPU, 10, 0x0F00F13D); - slt_basic_set.checkReg(8, 1); - slt_basic_set.perform_test(testCPU, testMem); - - test j_basic("j", "Check that pc has correct value after branch delay slot " - "and the instruction in the branch delay slot is executed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_j(2, 99).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(9, 0, 8, 0, 32).data); - writeReg(testCPU, 9, 0xAB); - j_basic.checkReg(255, 396); - j_basic.checkReg(8, 0xAB); - j_basic.perform_test(testCPU, testMem); - - test j_aligned("j", "Check that the upper 4 bits of the pc remain unchanged", - 2); - writeReg(testCPU, 255, 0x1ABCDEF4); - writeMem(testMem, get_pc(testCPU), instruction_impl_j(2, 99).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - j_aligned.checkReg(255, 0x1000018C); - j_aligned.perform_test(testCPU, testMem); - - test j_alignedWithBranch("j", "Check that the new PC is aligned with the " - "instruction in the branch delay slot", 2); - writeReg(testCPU, 255, 0x0FFFFFFC); - writeMem(testMem, get_pc(testCPU), instruction_impl_j(2, 99).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - j_alignedWithBranch.checkReg(255, 0x1000018C); - j_alignedWithBranch.perform_test(testCPU, testMem); - - test jal_basic("jal", "Check that pc and link register have correct values " - "after branch delay slot and the instruction in the branch delay slot is " - "executed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_j(3, 109).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(9, 0, 8, 0, 32).data); - writeReg(testCPU, 9, 0xAB); - jal_basic.checkReg(255, 436); - jal_basic.checkReg(8, 0xAB); - jal_basic.checkReg(31, get_pc(testCPU) + 8); - jal_basic.perform_test(testCPU, testMem); - - test jal_aligned("jal", "Check that the upper 4 bits of the pc remain " - "unchanged", 2); - writeReg(testCPU, 255, 0x1ABCDEF4); - writeMem(testMem, get_pc(testCPU), instruction_impl_j(3, 99).data); - writeMem(testMem, get_pc(testCPU) + 4, instruction_impl_r(0, 0, 0, 0, 0).data); - j_aligned.checkReg(255, 0x1000018C); - j_aligned.perform_test(testCPU, testMem); - - test jal_alignedWithBranch("j", "Check that the new PC is aligned with the " - "instruction in the branch delay slot", 2); - writeReg(testCPU, 255, 0x0FFFFFFC); - writeMem(testMem, get_pc(testCPU), instruction_impl_j(3, 99).data); - writeMem(testMem, get_pc(testCPU) + 4, instruction_impl_r(0, 0, 0, 0, 0).data); - jal_alignedWithBranch.checkReg(255, 0x1000018C); - jal_alignedWithBranch.perform_test(testCPU, testMem); - - test bltz_basic_no("bltz", "Check that branch isn't taken if source register " - "is equal to 0. Also check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 0, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0); - bltz_basic_no.checkReg(8, 0); - bltz_basic_no.checkReg(255, get_pc(testCPU) + 8); - bltz_basic_no.perform_test(testCPU, testMem); - - test bltz_basic_noPos("bltz", "Check that branch isn't taken if source " - "register is > 0. Also check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 0, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x1349DE40); - bltz_basic_noPos.checkReg(8, 0x1349DE40); - bltz_basic_noPos.checkReg(255, get_pc(testCPU) + 8); - bltz_basic_noPos.perform_test(testCPU, testMem); - - test bltz_basic_yes("bltz", "Check that branch is taken if source register " - "is < 0. Also check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 0, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x80FAB131); - bltz_basic_yes.checkReg(8, 0x80FAB131); - bltz_basic_yes.checkReg(255, get_pc(testCPU) - 36); - bltz_basic_yes.perform_test(testCPU, testMem); - - test bgez_basic_yesZero("bgez", "Check that branch is taken if source " - "register is = 0. Also check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 1, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0); - bgez_basic_yesZero.checkReg(8, 0); - bgez_basic_yesZero.checkReg(255, get_pc(testCPU) - 36); - bgez_basic_yesZero.perform_test(testCPU, testMem); - - test bgez_basic_yesPos("bgez", "Check that branch is taken if source register" - " is > 0. Also check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 1, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x3323); - bgez_basic_yesPos.checkReg(8, 0x3323); - bgez_basic_yesPos.checkReg(255, get_pc(testCPU) - 36); - bgez_basic_yesPos.perform_test(testCPU, testMem); - - test bgez_basic_no("bgez", "Check that branch isn't taken if source register " - "is < 0. Also check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 1, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x8349DE40); - bgez_basic_no.checkReg(8, 0x8349DE40); - bgez_basic_no.checkReg(255, get_pc(testCPU) + 8); - bgez_basic_no.perform_test(testCPU, testMem); - - test bltzal_basic_no("bltzal", "Check that branch isn't taken if source " - "register is equal to 0. Also check that source isn't changed and the " - "return address is set", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 16, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0); - bltzal_basic_no.checkReg(8, 0); - bltzal_basic_no.checkReg(255, get_pc(testCPU) + 8); - bltzal_basic_no.checkReg(31, get_pc(testCPU) + 8); - bltzal_basic_no.perform_test(testCPU, testMem); - - test bltzal_basic_noPos("bltzal", "Check that branch isn't taken if source " - "register is > 0. Also check that source isn't changed and the return " - "address is set", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 16, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x1349DE40); - bltzal_basic_noPos.checkReg(8, 0x1349DE40); - bltzal_basic_noPos.checkReg(255, get_pc(testCPU) + 8); - bltzal_basic_noPos.checkReg(31, get_pc(testCPU) + 8); - bltzal_basic_noPos.perform_test(testCPU, testMem); - - test bltzal_basic_yes("bltzal", "Check that branch is taken if source " - "register is < 0. Also check that source isn't changed and the return " - "address is set", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 16, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x80FAB131); - bltzal_basic_yes.checkReg(8, 0x80FAB131); - bltzal_basic_yes.checkReg(255, get_pc(testCPU) - 36); - bltzal_basic_yes.checkReg(31, get_pc(testCPU) + 8); - bltzal_basic_yes.perform_test(testCPU, testMem); - - test bgezal_basic_yesZero("bgezal", "Check that branch is taken if source " - "register is = 0. Also check that source isn't changed and the return " - "address is set", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 17, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0); - bgezal_basic_yesZero.checkReg(8, 0); - bgezal_basic_yesZero.checkReg(255, get_pc(testCPU) - 36); - bgezal_basic_yesZero.checkReg(31, get_pc(testCPU) + 8); - bgezal_basic_yesZero.perform_test(testCPU, testMem); - - test bgezal_basic_yesPos("bgezal", "Check that branch is taken if source " - "register is > 0. Also check that source isn't changed and the return " - "address is set", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 17, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x3323); - bgezal_basic_yesPos.checkReg(8, 0x3323); - bgezal_basic_yesPos.checkReg(255, get_pc(testCPU) - 36); - bgezal_basic_yesPos.checkReg(31, get_pc(testCPU) + 8); - bgezal_basic_yesPos.perform_test(testCPU, testMem); - - test bgezal_basic_no("bgezal", "Check that branch isn't taken if source " - "register is < 0. Also check that source isn't changed and the return " - "address is set", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(1, 8, 17, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x8349DE40); - bgezal_basic_no.checkReg(8, 0x8349DE40); - bgezal_basic_no.checkReg(255, get_pc(testCPU) + 8); - bgezal_basic_no.checkReg(31, get_pc(testCPU) + 8); - bgezal_basic_no.perform_test(testCPU, testMem); - - test beq_no("beq", "Check that branch isn't taken if " - "source register != destination register. Also check that source, " - "destination aren't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(4, 8, 9, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0xBA11DEEE); - writeReg(testCPU, 9, 0xEEED11AB); - beq_no.checkReg(8, 0xBA11DEEE); - beq_no.checkReg(9, 0xEEED11AB); - beq_no.checkReg(255, get_pc(testCPU) + 8); - beq_no.perform_test(testCPU, testMem); - - test bne_yes("bne", "Check that branch is taken if " - "source register != destination register. Also check that source, " - "destination aren't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(5, 8, 9, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0xBA11DEEE); - writeReg(testCPU, 9, 0xEEED11AB); - bne_yes.checkReg(8, 0xBA11DEEE); - bne_yes.checkReg(9, 0xEEED11AB); - bne_yes.checkReg(255, get_pc(testCPU) - 36); - bne_yes.perform_test(testCPU, testMem); - - test beq_yes("beq", "Check that branch is taken if " - "source register = destination register. Also check that source, " - "destination aren't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(4, 8, 9, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x1EAFEEEE); - writeReg(testCPU, 9, 0x1EAFEEEE); - beq_yes.checkReg(8, 0x1EAFEEEE); - beq_yes.checkReg(9, 0x1EAFEEEE); - beq_yes.checkReg(255, get_pc(testCPU) - 36); - beq_yes.perform_test(testCPU, testMem); - - test bne_no("bne", "Check that the branch isn't taken if " - "source register = destination register. Also check that source, " - "destination aren't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(5, 8, 9, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x1EAFEEEE); - writeReg(testCPU, 9, 0x1EAFEEEE); - bne_no.checkReg(8, 0x1EAFEEEE); - bne_no.checkReg(9, 0x1EAFEEEE); - bne_no.checkReg(255, get_pc(testCPU) + 8); - bne_no.perform_test(testCPU, testMem); - - test blez_yes("blez", "Check that the branch is taken if source < 0. Also " - "check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(6, 8, 0, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x80009D04); - blez_yes.checkReg(8, 0x80009D04); - blez_yes.checkReg(255, get_pc(testCPU) - 36); - blez_yes.perform_test(testCPU, testMem); - - test blez_yesZero("blez", "Check that the branch is taken if source = 0. " - "Also check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(6, 8, 0, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0); - blez_yesZero.checkReg(8, 0); - blez_yesZero.checkReg(255, get_pc(testCPU) - 36); - blez_yesZero.perform_test(testCPU, testMem); - - test blez_no("blez", "Check that the branch isn't taken if source > 0. Also " - "check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(6, 8, 0, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x333F125A); - blez_no.checkReg(8, 0x333F125A); - blez_no.checkReg(255, get_pc(testCPU) + 8); - blez_no.perform_test(testCPU, testMem); - - test bgtz_no("bgtz", "Check that the branch isn't taken if source < 0. Also " - "check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(7, 8, 0, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x80009D04); - bgtz_no.checkReg(8, 0x80009D04); - bgtz_no.checkReg(255, get_pc(testCPU) + 8); - bgtz_no.perform_test(testCPU, testMem); - - test bgtz_noZero("bgtz", "Check that the branch isn't taken if source = 0. " - "Also check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(7, 8, 0, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0); - bgtz_noZero.checkReg(8, 0); - bgtz_noZero.checkReg(255, get_pc(testCPU) + 8); - bgtz_noZero.perform_test(testCPU, testMem); - - test bgtz_yes("bgtz", "Check that the branch is taken if source > 0. Also " - "check that source isn't changed", 2); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(7, 8, 0, 0xFFF6).data); - writeMem(testMem, get_pc(testCPU) + 4, - instruction_impl_r(0, 0, 0, 0, 0).data); - writeReg(testCPU, 8, 0x333F125A); - bgtz_yes.checkReg(8, 0x333F125A); - bgtz_yes.checkReg(255, get_pc(testCPU) - 36); - bgtz_yes.perform_test(testCPU, testMem); - - test basic_addi("addi", "Verify the result of an addi where there is no " - "overflow", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(8, 9, 8, 0x034D).data); - writeReg(testCPU, 9, 0x0BB8BB8F); - basic_addi.checkReg(8, 0x0BB8BEDC); - basic_addi.perform_test(testCPU, testMem); - - writeReg(testCPU, 8, 0xFAFAFAFA); - test addi_overflow_pos("addi", "Check that dest register doesn't change if " - "positive overflow occurs in addi", 1, mips_ExceptionArithmeticOverflow); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(8, 9, 8, 0x734D).data); - writeReg(testCPU, 9, 0x7FFFFBCD); - addi_overflow_pos.checkReg(8, 0xFAFAFAFA); - addi_overflow_pos.perform_test(testCPU, testMem); - - writeReg(testCPU, 8, 0xFAFAFAFA); - test addi_overflow_neg("addi", "Check that dest register doesn't change if " - "negative overflow occurs in addi", 1, mips_ExceptionArithmeticOverflow); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(8, 9, 8, 0x8003).data); - writeReg(testCPU, 9, 0x80000014); - addi_overflow_neg.checkReg(8, 0xFAFAFAFA); - addi_overflow_neg.perform_test(testCPU, testMem); - - test basic_addiu("addiu", "Verify the result of addiu with no overflow", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(9, 9, 8, 0x1437).data); - writeReg(testCPU, 9, 0x1374BAB3); - basic_addiu.checkReg(8, 0x1374CEEA); - basic_addiu.perform_test(testCPU, testMem); - - test addiu_overflow("addiu", "Verify that addiu result valid even with " - "overflow", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(9, 9, 8, 0xABCD).data); - writeReg(testCPU, 9, 0xFFFFFAB3); - addiu_overflow.checkReg(8, 0xFFFFA680); - addiu_overflow.perform_test(testCPU, testMem); - - test slti_yesNeg("slti", "Verify that R8 is 1 when R9 is less than the " - "negative immediate", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(10, 9, 8, 0xFFD3).data); - writeReg(testCPU, 9, 0xF14D3E0B); - writeReg(testCPU, 8, 2); - slti_yesNeg.checkReg(8, 1); - slti_yesNeg.perform_test(testCPU, testMem); - - test slti_noNeg("slti", "Verify that R8 is 0 when R9 is more than the " - "negative immediate", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(10, 9, 8, 0x80D3).data); - writeReg(testCPU, 9, 0xFFFFF329); - writeReg(testCPU, 8, 2); - slti_noNeg.checkReg(8, 0); - slti_noNeg.perform_test(testCPU, testMem); - - test slti_yesPos("slti", "Verify that R8 is 1 when R9 is less than the " - "positive immediate", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(10, 9, 8, 0x74D1).data); - writeReg(testCPU, 9, 0x63D0); - writeReg(testCPU, 8, 2); - slti_yesPos.checkReg(8, 1); - slti_yesPos.perform_test(testCPU, testMem); - - test slti_noPos("slti", "Verify that R8 is 0 when R9 is more than the " - "positive immediate", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(10, 9, 8, 0x034C).data); - writeReg(testCPU, 9, 0x1AAAAAA4); - writeReg(testCPU, 8, 2); - slti_noPos.checkReg(8, 0); - slti_noPos.perform_test(testCPU, testMem); - - test slti_noPosEq("slti", "Verify that R8 is 0 when R9 is equal to the " - "positive immediate", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(10, 9, 8, 0x3B3B).data); - writeReg(testCPU, 9, 0x3B3B); - writeReg(testCPU, 8, 2); - slti_noPosEq.checkReg(8, 0); - slti_noPosEq.perform_test(testCPU, testMem); - - test slti_noNegEq("slti", "Verify that R8 is 0 when R9 is equal to the " - "negative immediate", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(10, 9, 8, 0x8303).data); - writeReg(testCPU, 9, 0xFFFF8303); - writeReg(testCPU, 8, 2); - slti_noNegEq.checkReg(8, 0); - slti_noNegEq.perform_test(testCPU, testMem); - - test sltiu_yesSmall("sltiu", "Verify that R8 is 1 when R9 is less than the " - "immediate", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(11, 9, 8, 0x7432).data); - writeReg(testCPU, 9, 0x6DF0); - writeReg(testCPU, 8, 2); - sltiu_yesSmall.checkReg(8, 1); - sltiu_yesSmall.perform_test(testCPU, testMem); - - test sltiu_yesBig("sltiu", "Verify that R8 is 1 when R9 is less than the " - "immediate using the fact the immediate is still sign extended", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(11, 9, 8, 0xFF14).data); - writeReg(testCPU, 9, 0xFFFF7D1b); - writeReg(testCPU, 8, 2); - sltiu_yesBig.checkReg(8, 1); - sltiu_yesBig.perform_test(testCPU, testMem); - - test sltiu_noSmall("sltiu", "Verify that R8 is 0 when R9 is more than the " - "immediate", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(11, 9, 8, 0x6B1F).data); - writeReg(testCPU, 9, 0x7BF12734); - writeReg(testCPU, 8, 2); - sltiu_noSmall.checkReg(8, 0); - sltiu_noSmall.perform_test(testCPU, testMem); - - test sltiu_noBig("sltiu", "Verify that R8 is 0 when R9 is more than the " - "immediate using the fact the immediate is still sign extended", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(11, 9, 8, 0x8932).data); - writeReg(testCPU, 9, 0xFFFF9632); - writeReg(testCPU, 8, 2); - sltiu_noBig.checkReg(8, 0); - sltiu_noBig.perform_test(testCPU, testMem); - - test basic_andi("andi", "Verify the result of R8 after R9 ANDed with " - "immediate", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(12, 9, 8, 0xF6D7).data); - writeReg(testCPU, 9, 0xAB34965B); - basic_andi.checkReg(8, 0x9653); - basic_andi.perform_test(testCPU, testMem); - - test basic_ori("ori", "Verify the result of R8 after R9 ORed with " - "immediate", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(13, 9, 8, 0x2864).data); - writeReg(testCPU, 9, 0xFABADAB1); - basic_ori.checkReg(8, 0xFABAFAF5); - basic_ori.perform_test(testCPU, testMem); - - test basic_xori("xori", "Verify the result of R8 after R9 XORed with " - "immediate", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(14, 9, 8, 0x31AB).data); - writeReg(testCPU, 9, 0x1DABAD00); - basic_xori.checkReg(8, 0x1DAB9CAB); - basic_xori.perform_test(testCPU, testMem); - - test basic_lui("lui", "Verify that the immediate is placed in the 16 MSBs of " - "R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(15, 0, 8, 0xB153).data); - writeReg(testCPU, 8, 0xFABFABFA); - basic_lui.checkReg(8, 0xB1530000); - basic_lui.perform_test(testCPU, testMem); - - test basic_lb("lb", "Verify that the byte from the effective address is " - "stored in R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(32, 9, 8, 0xFFF2).data); - writeReg(testCPU, 9, 512); - writeMem(testMem, 496, 0xABAB1DAB); - basic_lb.checkReg(8, 0x1D); - basic_lb.perform_test(testCPU, testMem); - - test lb_signExtend("lb", "Verify that the sign extended byte from the " - "effective address is stored in R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(32, 9, 8, 0xFF8F).data); - writeReg(testCPU, 9, 616); - writeMem(testMem, 500, 0x777777F3); - lb_signExtend.checkReg(8, 0xFFFFFFF3); - lb_signExtend.perform_test(testCPU, testMem); - - test lb_posOffset("lb", "Verify that the byte from the effective address " - "(generated with a positive offset) is stored in R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(32, 9, 8, 15).data); - writeReg(testCPU, 9, 640); - writeMem(testMem, 652, 0xBFBFBF75); - lb_posOffset.checkReg(8, 0x00000075); - lb_posOffset.perform_test(testCPU, testMem); - - test basic_lh("lh", "Verify that the half-word from the effective address is " - "stored in R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(33, 9, 8, 0xFFF3).data); - writeReg(testCPU, 9, 551); - writeMem(testMem, 536, 0x55557B7B); - basic_lh.checkReg(8, 0x00007B7B); - basic_lh.perform_test(testCPU, testMem); - - test lh_signExtend("lh", "Verify that the sign extended half-word from the " - "effective address is stored in R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(33, 9, 8, 0xFFF4).data); - writeReg(testCPU, 9, 540); - writeMem(testMem, 528, 0x84F37676); - lh_signExtend.checkReg(8, 0xFFFF84F3); - lh_signExtend.perform_test(testCPU, testMem); - - test lh_posOffset("lh", "Verify that the half-word from the effective " - "address (generated with a positive offset) is stored in R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(33, 9, 8, 10).data); - writeReg(testCPU, 9, 510); - writeMem(testMem, 520, 0x7BBCC3D0); - lh_posOffset.checkReg(8, 0x00007BBC); - lh_posOffset.perform_test(testCPU, testMem); - - test lh_unalignedReg("lh", "Verify that the destination register isn't " - "changed after an Invalid Alignment Exception", 1, - mips_ExceptionInvalidAlignment); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(33, 9, 8, 11).data); - writeReg(testCPU, 9, 520); - writeReg(testCPU, 8, 0xA4C3B177); - lh_unalignedReg.checkReg(8, 0xA4C3B177); - lh_unalignedReg.perform_test(testCPU, testMem); - - test basic_lwl1("lwl", "Verify that the most significant byte of the " - "unaligned word replaces the most significant byte of R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(34, 9, 8, 3).data); - writeMem(testMem, 600, 0xF13BA4A4); - writeReg(testCPU, 8, 0x17462538); - writeReg(testCPU, 9, 600); - basic_lwl1.checkReg(8, 0xA4462538); - basic_lwl1.perform_test(testCPU, testMem); - - test basic_lwl2("lwl", "Verify that the 2 most significant bytes of the " - "unaligned word replaces the 2 most significant bytes of R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(34, 9, 8, 2).data); - writeMem(testMem, 600, 0xF13BA4A4); - writeReg(testCPU, 8, 0x17462538); - writeReg(testCPU, 9, 600); - basic_lwl2.checkReg(8, 0xA4A42538); - basic_lwl2.perform_test(testCPU, testMem); - - test basic_lw("lw", "Verify that the contents of the aligned word are loaded " - "into R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(35, 9, 8, -3).data); - writeReg(testCPU, 9, 543); - writeMem(testMem, 540, 0xBADBADBA); - basic_lw.checkReg(8, 0xBADBADBA); - basic_lw.perform_test(testCPU, testMem); - - test lw_unaligned("lw", "Verify an Invalid Aligment error occurs for lw", 1, - mips_ExceptionInvalidAlignment); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(35, 9, 8, 0).data); - writeReg(testCPU, 9, 474); - lw_unaligned.perform_test(testCPU, testMem); - - test basic_lbu("lbu", "Verify that the byte is not sign extended when loaded " - "into R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(36, 9, 8, 24).data); - writeReg(testCPU, 9, 500); - writeMem(testMem, 524, 0x83D14751); - basic_lbu.checkReg(8, 0x00000083); - basic_lbu.perform_test(testCPU, testMem); - - test basic_lhu("lhu", "Verify that the half-word is not sign extended when " - "loaded into R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(37, 9, 8, 8).data); - writeReg(testCPU, 9, 540); - writeMem(testMem, 548, 0x01189998); - basic_lhu.checkReg(8, 0x00000118); - basic_lhu.perform_test(testCPU, testMem); - - test lhu_unaligned("lhu", "Verify an Invalid Alignment error occurs for lhu", - 1, mips_ExceptionInvalidAlignment); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(37, 9, 8, 3).data); - writeReg(testCPU, 9, 574); - lhu_unaligned.perform_test(testCPU, testMem); - - test basic_lwr1("lwr", "Verify that the least significant byte of an " - "unaligned word replaces the least significant byte in R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(38, 9, 8, 0).data); - writeMem(testMem, 564, 0x73B04E1C); - writeReg(testCPU, 8, 0x075936AB); - writeReg(testCPU, 9, 564); - basic_lwr1.checkReg(8, 0x07593673); - basic_lwr1.perform_test(testCPU, testMem); - - test basic_lwr2("lwr", "Verify that the 3 least significant bytes of an " - "unaligned word replace the 3 least significant bytes in R8", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(38, 9, 8, 2).data); - writeMem(testMem, 564, 0x73B04E1C); - writeReg(testCPU, 8, 0x075936AB); - writeReg(testCPU, 9, 564); - basic_lwr2.checkReg(8, 0x0773B04E); - basic_lwr2.perform_test(testCPU, testMem); - - test basic_sb("sb", - "Verify that the least significant byte of R8 is stored in the effective " - "address without overwriting the rest of the word in memory", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(40, 9, 8, 3).data); - writeMem(testMem, 540, 0x1ACD4B3D); - writeReg(testCPU, 8, 0xABCDEF93); - writeReg(testCPU, 9, 540); - basic_sb.checkMem(540, 0x1ACD4B93); - basic_sb.perform_test(testCPU, testMem); - - test basic_sb1("sb", "With offset 0, verify that the least significant byte " - "of R8 is stored in the effective address without overwriting the rest of " - "the word in memory", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(40, 9, 8, 0).data); - writeMem(testMem, 536, 0xB3310463); - writeReg(testCPU, 8, 0x123B4582); - writeReg(testCPU, 9, 536); - basic_sb1.checkMem(536, 0x82310463); - basic_sb1.perform_test(testCPU, testMem); - - test basic_sh("sh", "Verify that the least significant half-word of R8 is " - "stored in the effective address without overwriting the rest of the word " - "in memory", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(41, 9, 8, 2).data); - writeMem(testMem, 544, 0x3E459C12); - writeReg(testCPU, 8, 0xABCD1149); - writeReg(testCPU, 9, 544); - basic_sh.checkMem(544, 0x3E451149); - basic_sh.perform_test(testCPU, testMem); - - test basic_sh1("sh", "With offset 0, verify that the least significant " - "half-word of R8 is stored in the effective address without overwriting " - "the rest of the word in memory", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(41, 9, 8, 0).data); - writeMem(testMem, 548, 0xBB8C13D0); - writeReg(testCPU, 8, 0x9932B712); - writeReg(testCPU, 9, 548); - basic_sh1.checkMem(548, 0xB71213D0); - basic_sh1.perform_test(testCPU, testMem); - - test basic_sw("sw", "Check that the value from R8 is correctly loaded into " - "memory", 1); - writeMem(testMem, get_pc(testCPU), instruction_impl_i(43, 9, 8, 0).data); - writeMem(testMem, 552, 0xABABABAB); - writeReg(testCPU, 8, 0x01590624); - writeReg(testCPU, 9, 552); - basic_sw.checkMem(552, 0x01590624); - basic_sw.perform_test(testCPU, testMem); - - // This test ensures that instructions don't just work independantly - // Expected number of steps is 5496 for 12th fibonacci number - test fib("", "Check that the CPU can calculate the 12th fibonacci " - "number using various instructions", 5496); - writeMem(testMem, 0x0, 0x27bdffe0); // addiu sp,sp,-32 - writeMem(testMem, 0x4, 0x2c820002); // sltiu v0,a0,2 - writeMem(testMem, 0x8, 0xafb20018); // sw s2,24(sp); - writeMem(testMem, 0xc, 0xafbf001c); // sw ra,28(sp); - writeMem(testMem, 0x10, 0xafb10014); // sw s1,20(sp); - writeMem(testMem, 0x14, 0xafb00010); // sw s0,16(sp); - writeMem(testMem, 0x18, 0x14400011); // bnez v0,60 - writeMem(testMem, 0x1c, 0x00809021); // move s2,a0 - writeMem(testMem, 0x20, 0x00808021); // move s0,a0 - writeMem(testMem, 0x24, 0x00008821); // move s1,zero - writeMem(testMem, 0x28, 0x2604ffff); // addiu a0,s0,-1 - writeMem(testMem, 0x2c, 0x0c000000); // jal 0 - writeMem(testMem, 0x30, 0x2610fffe); // addiu s0,s0,-2 - writeMem(testMem, 0x34, 0x2e030002); // sltiu v1,s0,2 - writeMem(testMem, 0x38, 0x1060fffb); // beqz v1,28 - writeMem(testMem, 0x3c, 0x02228821); // addu s1,s1,v0 - writeMem(testMem, 0x40, 0x32520001); // andi s2,s2,0x1 - writeMem(testMem, 0x44, 0x8fbf001c); // lw ra,28(sp); - writeMem(testMem, 0x48, 0x02321021); // addu v0,s1,s2 - writeMem(testMem, 0x4c, 0x8fb00010); // lw s0,16(sp); - writeMem(testMem, 0x50, 0x8fb20018); // lw s2,24(sp); - writeMem(testMem, 0x54, 0x8fb10014); // lw s1,20(sp); - writeMem(testMem, 0x58, 0x03e00008); // jr ra - writeMem(testMem, 0x5c, 0x27bd0020); // addiu sp,sp,32 - writeMem(testMem, 0x60, 0x08000011); // j 44 - writeMem(testMem, 0x64, 0x00008821); // move s1,zero - writeReg(testCPU, 31, 0x10000000); - writeReg(testCPU, 4, 12); // 12th fibonacci number - writeReg(testCPU, 29, 0x1000); // stack pointer - fib.checkReg(2, 144); // Expected result is 144 - fib.perform_test(testCPU, testMem); - - mips_mem_free(testMem); - testMem = NULL; - mips_cpu_free(testCPU); - testCPU = NULL; - - mips_test_end_suite(); - - return 0; + + mips_test_begin_suite(); + + int testId = mips_test_begin_test("ADD"); + mips_test_end_test(testId, test_add(ram, cpu, ADD, 0x3fffffff, 0, 10), "Testing the adder without overflow"); + + testId = mips_test_begin_test("ADD"); + mips_test_end_test(testId, !test_add(ram, cpu, ADD, 0x7fffffff, 1, 1), "Testing the adder with overflow"); + + testId = mips_test_begin_test("ADDU"); + mips_test_end_test(testId, test_add(ram, cpu, ADDU, 0x3fffffff, 0, 10), "testing without overflow"); + + testId = mips_test_begin_test("ADDU"); + mips_test_end_test(testId, test_add(ram, cpu, ADDU, 0x7fffffff, 1, 1), "Testing the adder with overflow"); + + testId = mips_test_begin_test("SUB"); + mips_test_end_test(testId, test_add(ram, cpu, SUB, 0x3fffffff, 0, 10), "Testing the adder without overflow"); + + testId = mips_test_begin_test("SUB"); + mips_test_end_test(testId, !test_add(ram, cpu, SUB, 0x7fffffff, 1, 1), "Testing the adder with overflow"); + + testId = mips_test_begin_test("SUBU"); + mips_test_end_test(testId, test_add(ram, cpu, SUBU, 0x3fffffff, 0, 10), "Testing the adder without overflow"); + + testId = mips_test_begin_test("SUBU"); + mips_test_end_test(testId, test_add(ram, cpu, SUBU, 0x7fffffff, 1, 1), "Testing the adder with overflow"); + + testId = mips_test_begin_test("AND"); + mips_test_end_test(testId, test_bitwise(ram, cpu, AND), "Testing bitwise and"); + + testId = mips_test_begin_test("OR"); + mips_test_end_test(testId, test_bitwise(ram, cpu, OR), "Testing bitwise or"); + + testId = mips_test_begin_test("XOR"); + mips_test_end_test(testId, test_bitwise(ram, cpu, XOR), "Testing bitwise xor"); + + testId = mips_test_begin_test("ADDI"); + mips_test_end_test(testId, test_I(ram, cpu, ADDI, 20, 10), "Testing addi"); + + testId = mips_test_begin_test("ADDIU"); + mips_test_end_test(testId, test_I(ram, cpu, ADDIU, 20, 10), "Testing addiu"); + + testId = mips_test_begin_test("ANDI"); + mips_test_end_test(testId, test_I(ram, cpu, ANDI, 20, 10), "Testing addi"); + + testId = mips_test_begin_test("ORI"); + mips_test_end_test(testId, test_I(ram, cpu, ORI, 20, 10), "Testing addi"); + + testId = mips_test_begin_test("XORI"); + mips_test_end_test(testId, test_I(ram, cpu, XORI, 20, 10), "Testing addi"); + + testId = mips_test_begin_test("BEQ"); + mips_test_end_test(testId, test_branch(ram, cpu, 4, 4, 0, 9, 4), "Testing BEQ"); + + testId = mips_test_begin_test("BNE"); + mips_test_end_test(testId, test_branch(ram, cpu, 5, 4, 0, 9, 10), "Testing BNE"); + + testId = mips_test_begin_test("BGEZ"); + mips_test_end_test(testId, test_branch(ram, cpu, 1, 4, 0, 1, 20), "Testing BGEZ"); + + testId = mips_test_begin_test("BLEZ"); + mips_test_end_test(testId, test_branch(ram, cpu, 6, -1, 0, 0, 20), "Testing BGEZ"); + + testId = mips_test_begin_test("BGTZ"); + mips_test_end_test(testId, test_branch(ram, cpu, 7, 4, 0, 0, 20), "Testing BGEZ"); + + testId = mips_test_begin_test("BGEZAL"); + mips_test_end_test(testId, test_branch(ram, cpu, 1, 4, 1, 17, 20), "Testing BGEZ"); + + testId = mips_test_begin_test("BLTZAL"); + mips_test_end_test(testId, test_branch(ram, cpu, 1, -1, 1, 16, 20), "Testing BGEZ"); + + testId = mips_test_begin_test("BLTZ"); + mips_test_end_test(testId, test_branch(ram, cpu, 1, -1, 0, 16, 20), "Testing BGEZ"); + + testId = mips_test_begin_test("J"); + mips_test_end_test(testId, test_jump(ram, cpu, J), "Testing J"); + + testId = mips_test_begin_test("JAL"); + mips_test_end_test(testId, test_jump(ram, cpu, JAL), "Testing JAL"); + + testId = mips_test_begin_test("JALR"); + mips_test_end_test(testId, test_jump(ram, cpu, JALR), "Testing JALR"); + + testId = mips_test_begin_test("JR"); + mips_test_end_test(testId, test_jump(ram, cpu, JR), "Testing JR"); + + testId = mips_test_begin_test("LB"); + mips_test_end_test(testId, test_load(ram, cpu, LB, 0xf7), "Testing LB"); + + testId = mips_test_begin_test("LBU"); + mips_test_end_test(testId, test_load(ram, cpu, LBU, 0xf7), "Testing LBU"); + + testId = mips_test_begin_test("LH"); + mips_test_end_test(testId, test_load(ram, cpu, LH, 0xff7f), "Testing LH"); + + testId = mips_test_begin_test("LHU"); + mips_test_end_test(testId, test_load(ram, cpu, LHU, 0xff7f), "Testing LHU"); + + testId = mips_test_begin_test("LW"); + mips_test_end_test(testId, test_load(ram, cpu, LW, 0xffffff7f), "Testing LW"); + + testId = mips_test_begin_test("LUI"); + mips_test_end_test(testId, test_load(ram, cpu, LUI, 0xff7f), "Testing LUI"); + + testId = mips_test_begin_test("LWL"); + mips_test_end_test(testId, test_load(ram, cpu, LWL, 0xff6fff7f), "Testing LWL"); + + testId = mips_test_begin_test("LWR"); + mips_test_end_test(testId, test_load(ram, cpu, LWR, 0xff6fff7f), "Testing LWR"); + + testId = mips_test_begin_test("MULT"); + mips_test_end_test(testId, test_mult_div(ram, cpu, MULT, 5, -4), "Testing LWR"); + + testId = mips_test_begin_test("MULTU"); + mips_test_end_test(testId, test_mult_div(ram, cpu, MULTU, 5, -4), "Testing LWR"); + + testId = mips_test_begin_test("DIV"); + mips_test_end_test(testId, test_mult_div(ram, cpu, DIV, 5, -4), "Testing LWR"); + + testId = mips_test_begin_test("DIVU"); + mips_test_end_test(testId, test_mult_div(ram, cpu, DIVU, 5, -4), "Testing LWR"); + + mips_test_end_suite(); + return 0; } -uint32_t get_pc(mips_cpu_h state){ - uint32_t pc; - mips_cpu_get_pc(state, &pc); - return pc; +// R Type +uint32_t gen_instruction(uint32_t src1, uint32_t src2, uint32_t dest, + uint32_t shift, uint32_t function) { + uint32_t inst = 0; + inst = inst | src1 << 21 | src2 << 16 | dest << 11 | shift << 6 | + function; + return inst; } -mips_error test::perform_test(mips_cpu_h state, mips_mem_h mem){ +// I Type +uint32_t gen_instruction(uint32_t opcode, uint32_t src, uint32_t dest, + uint32_t Astart) { + uint32_t inst = 0; + inst = inst | opcode << 26 | src << 21 | dest << 16 | Astart; + return inst; +} - mips_error lastError = mips_Success; +// J Type +uint32_t gen_instruction(uint32_t opcode, uint32_t memory) { + uint32_t inst = 0; + inst = inst | opcode << 26 | memory; + return inst; +} - int testID = mips_test_begin_test(testName); +uint32_t change_endianness(uint32_t inst) { + inst = (inst << 24 | ((inst << 8)&0xff0000) | + ((inst >> 8)&0xff00) |inst >> 24); + return inst; +} - // Make the CPU perform the required number of instructions for the test - for(unsigned i = 0; i < numInstructions; i++){ - mips_error attemptStep = mips_cpu_step(state); - if(attemptStep != mips_Success){ - lastError = attemptStep; - } - } - - // Check the state of the mem is as expected afterward - for(unsigned i = 0; i < unsigned(memCheck.size()); i++){ - uint32_t testValue; - mips_mem_read(mem, memCheck[i].address, 4, (uint8_t*)&testValue); - byte_swap_test(testValue); - if (testValue != memCheck[i].value) { - fprintf(stderr, "[Test %d] Mem[0x%X] is 0x%X - Expected 0x%X\n", - testID, memCheck[i].address, testValue, memCheck[i].value); - success = 0; +int test_add(mips_mem_h ram, mips_cpu_h cpu, uint32_t type, uint32_t max, uint8_t value, unsigned i_t) { + + uint32_t inst, ans, a, b; + + for(unsigned i = 0; i < i_t; ++i) { + mips_error mips_err; + mips_cpu_reset(cpu); + inst = change_endianness(gen_instruction(9, 10, 8, 0, type)); + if(value) { + a = max; + if(type > 0x21) { + b = -max; + } else { + b = max; + } + } else { + a = rand() % max; + b = rand() % max; + } + + mips_mem_write(ram, 0, 4, (uint8_t*)&inst); + + mips_cpu_set_register(cpu, 9, a); + mips_cpu_set_register(cpu, 10, b); + + mips_err = mips_cpu_step(cpu); + + mips_cpu_get_register(cpu, 8, &ans); + + if(type < 0x22) { + //printf("%#10x + %#10x = %#10x\t%#10x\n", a, b, ans, mips_err); + if(mips_err == mips_ExceptionArithmeticOverflow || a+b!=ans) { + return 0; + } + } else { + //printf("%#10x - %#10x = %#10x\t%#10x\n", a, b, ans, mips_err); + if(mips_err == mips_ExceptionArithmeticOverflow || a-b!=ans) { + return 0; + } + } } - } - - // Check the state of the regs is as expected afterward - for(unsigned i = 0; i < unsigned(regCheck.size()); i++){ - uint32_t testValue = 0; - if (regCheck[i].index < 32){ - mips_cpu_get_register(state, unsigned(regCheck[i].index), &testValue); - if (testValue != regCheck[i].value){ - fprintf(stderr, "[Test %d] Reg[%d] is 0x%X - Expected 0x%X\n", - testID, regCheck[i].index, testValue, regCheck[i].value); - success = 0; - } - } else if (regCheck[i].index == 255){ - mips_cpu_get_pc(state, &testValue); - if (testValue != regCheck[i].value){ - fprintf(stderr, "[Test %d] PC is 0x%X - Expected 0x%X\n", - testID, testValue, regCheck[i].value); - success = 0; - } + + return 1; +} + +int test_bitwise(mips_mem_h ram, mips_cpu_h cpu, uint8_t op) { + uint32_t a, b, ans, inst; + int passed; + for(unsigned i = 0; i < 10; ++i) { + passed = 0; + mips_cpu_reset(cpu); + inst = change_endianness(gen_instruction(8, 9, 7, 0, op)); + + a = rand() % 0xffffffff; + b = rand() % 0xffffffff; + + mips_mem_write(ram, 0, 4, (uint8_t*)&inst); + + mips_cpu_set_register(cpu, 8, a); + mips_cpu_set_register(cpu, 9, b); + + mips_error mips_err = mips_cpu_step(cpu); + + mips_cpu_get_register(cpu, 7, &ans); + + if(op == AND) { + //printf("%#10x & %#10x = %#10x\t%#10x\n", a, b, ans, mips_err); + if((a & b) == ans) { + passed = 1; + } + } else if(op == OR) { + //printf("%#10x | %#10x = %#10x\t%#10x\n", a, b, ans, mips_err); + if((a | b) == ans) { + passed = 1; + } + } else { + //printf("%#10x ^ %#10x = %#10x\t%#10x\n", a, b, ans, mips_err); + if((a ^ b) == ans) { + passed = 1; + } + } + + + if(mips_err != mips_Success || !passed) { + return 0; + } } + return 1; +} + +int test_I(mips_mem_h ram, mips_cpu_h cpu, uint32_t type, + uint32_t num1, uint32_t num2) { + int passed = 0; + uint32_t result, inst; - } + mips_cpu_reset(cpu); + inst = change_endianness(gen_instruction(type, 8, 7, num1)); - if (expectedError != lastError){ - fprintf(stderr, "[Test %d] Returned error 0x%X - Expected error 0x%X\n", - testID, lastError, expectedError); - success = 0; - } + mips_mem_write(ram, 0, 4, (uint8_t*)&inst); + mips_cpu_set_register(cpu, 8, num2); - if (success == 0){ - // Test has failed - fprintf(stderr, "[Test %d] FAILED\n", testID); - fprintf(stderr, "[Test %d] '%s' - %s\n", testID, testName, testDescription); - fprintf(stderr, "-------------------------------------------\n"); - } + mips_cpu_step(cpu); - mips_test_end_test(testID, success, testDescription); + mips_cpu_get_register(cpu, 7, &result); - // Reset the state of the CPU after each test to ensure independance - mips_cpu_reset(state); + switch(type) { + case 8: + if(result == num1 + num2) { + passed = 1; + } + case 9: + if(result == num1 + num2) { + passed = 1; + } + case 12: + if(result == (num1 & num2)) { + passed = 1; + } + case 13: + if(result == (num1 | num2)) { + passed = 1; + } + case 14: + if(result == (num1 ^ num2)) { + passed = 1; + } + default:; + } - return lastError; + return passed; } -void writeMem(mips_mem_h mem, uint32_t address, uint32_t value){ - byte_swap_test(value); - mips_mem_write(mem, address, 4, (uint8_t*)&value); +int test_branch(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode, uint32_t a, uint8_t l, uint32_t opc2, uint32_t b) { + int passed = 0; + int pass = 0; + uint32_t reg10, reg11, reg31, pc_set; + pc_set = 32; + mips_cpu_reset(cpu); + mips_cpu_set_pc(cpu, pc_set); + + uint32_t inst = change_endianness(gen_instruction(opcode, 8, opc2, 3)); + mips_mem_write(ram, pc_set, 4, (uint8_t*)&inst); + inst = change_endianness(gen_instruction(8, 9, 10, 0, ADDU)); + mips_mem_write(ram, pc_set+4, 4, (uint8_t*)&inst); + inst = change_endianness(gen_instruction(8, 12, 11, 0, ADDU)); + mips_mem_write(ram, pc_set+16, 4, (uint8_t*)&inst); + inst = change_endianness(gen_instruction(8, 13, 10, 0, ADDU)); + mips_mem_write(ram, pc_set+8, 4, (uint8_t*)&inst); + + mips_cpu_set_register(cpu, 8, a); + mips_cpu_set_register(cpu, 9, b); + mips_cpu_set_register(cpu, 12, 30); + mips_cpu_set_register(cpu, 13, 100); + + mips_cpu_step(cpu); + mips_cpu_step(cpu); + mips_cpu_step(cpu); + + mips_cpu_get_register(cpu, 10, ®10); + mips_cpu_get_register(cpu, 11, ®11); + + if(l == 1) { + mips_cpu_get_register(cpu, 31, ®31); + if(reg31 == pc_set+8) { + pass = 1; + } + } else { + pass = 1; + } + + if(reg10 == a+b && reg11 == a+30 && pass) { + passed = 1; + } else { + passed = 0; + } + + return passed; } -void writeReg(mips_cpu_h state, uint8_t index, uint32_t value){ - if (index < 32){ - mips_cpu_set_register(state, index, value); - } else if (index == 255){ - mips_cpu_set_pc(state, value); - } +int test_jump(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode) { + int passed = 0; + uint32_t inst, reg10, reg13, reg16, reg31; + + mips_cpu_reset(cpu); + + if(opcode == 2 || opcode == 3) { + inst = change_endianness(gen_instruction(opcode, 0x20)); + } else if(opcode == 8 || opcode == 9) { + inst = change_endianness(gen_instruction(25, 0, 31, 0, opcode)); + } + + mips_mem_write(ram, 0, 4, (uint8_t*)&inst); + + inst = change_endianness(gen_instruction(8, 9, 10, 0, ADDU)); + mips_mem_write(ram, 4, 4, (uint8_t*)&inst); + inst = change_endianness(gen_instruction(11, 12, 13, 0, ADDU)); + mips_mem_write(ram, 8, 4, (uint8_t*)&inst); + inst = change_endianness(gen_instruction(14, 15, 16, 0, ADDU)); + mips_mem_write(ram, 0x20<<2, 4, (uint8_t*)&inst); + + mips_cpu_set_register(cpu, 8, 8); + mips_cpu_set_register(cpu, 9, 9); + mips_cpu_set_register(cpu, 10, 10); + mips_cpu_set_register(cpu, 11, 11); + mips_cpu_set_register(cpu, 12, 12); + mips_cpu_set_register(cpu, 13, 13); + mips_cpu_set_register(cpu, 14, 14); + mips_cpu_set_register(cpu, 15, 15); + mips_cpu_set_register(cpu, 16, 16); + mips_cpu_set_register(cpu, 25, 0x20<<2); + + mips_cpu_step(cpu); + mips_cpu_step(cpu); + mips_cpu_step(cpu); + + mips_cpu_get_register(cpu, 10, ®10); + mips_cpu_get_register(cpu, 13, ®13); + mips_cpu_get_register(cpu, 16, ®16); + mips_cpu_get_register(cpu, 31, ®31); + + if(reg10 == 9+8 && reg13 == 13 && reg16 == 14+15) { + passed = 1; + } + + if((opcode == 3 || opcode == 9) && reg31 != 8) { + passed = 0; + } + + return passed; } -void byte_swap_test(uint32_t &value){ - value = - (value<<24) | - ((value>>8)&0x0000FF00) | - ((value<<8)&0x00FF0000) | - (value>>24); +int test_load(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode, uint32_t word) { + int passed = 0; + uint16_t half_word; + uint8_t byte; + uint32_t res; + + half_word = (uint16_t)word; + byte = (uint8_t)word; + + mips_cpu_reset(cpu); + + uint32_t inst = change_endianness(gen_instruction(opcode, 8, 9, 4)); + + mips_mem_write(ram, 0, 4, (uint8_t*)&inst); + + if(opcode == LB || opcode == LBU) { + mips_mem_write(ram, 0x30, 1, &byte); + } else if(opcode == LH || opcode == LHU) { + uint16_t tmp = (half_word<<8) | (half_word>>8); + mips_mem_write(ram, 0x30, 2, (uint8_t*)&tmp); + } else { + uint32_t tmp = change_endianness(word); + mips_mem_write(ram, 0x30, 4, (uint8_t*)&tmp); + } + + mips_cpu_set_register(cpu, 8, 0x2c); + if(opcode == LWR) { + mips_cpu_set_register(cpu, 8, 0x2f); + } + mips_cpu_set_register(cpu, 9, 0xbabacdcd); + + mips_cpu_step(cpu); + + mips_cpu_get_register(cpu, 9, &res); + + if((res == (uint32_t)(int8_t)byte && opcode == LB) || (res == (uint32_t)byte && opcode == LBU) || (res == (uint32_t)(int16_t)half_word && opcode == LH) || (res == (uint32_t)half_word && opcode == LHU) || (res == word && opcode == LW) || (res == 4<<16 && opcode == LUI) || (res == ((word&0xffff)|(0xbaba0000)) && (opcode == LWR)) || (res == ((word&0xffff0000)|(0xcdcd)))) { + passed = 1; + } + + return passed; +} + +int test_mult_div(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode, uint32_t num1, uint32_t num2) { + int passed = 0; + uint64_t result; + uint32_t hi, lo; + + mips_cpu_reset(cpu); + + uint32_t inst = change_endianness(gen_instruction(8, 9, 0, 0, opcode)); + mips_mem_write(ram, 0, 4, (uint8_t*)&inst); + inst = change_endianness(gen_instruction(0, 0, 10, 0, MFHI)); + mips_mem_write(ram, 4, 4, (uint8_t*)&inst); + inst = change_endianness(gen_instruction(0, 0, 11, 0, MFLO)); + mips_mem_write(ram, 8, 4, (uint8_t*)&inst); + + mips_cpu_set_register(cpu, 8, num1); + mips_cpu_set_register(cpu, 9, num2); + mips_cpu_set_register(cpu, 10, 0xabcde); + mips_cpu_set_register(cpu, 11, 0xf193b); + + mips_cpu_step(cpu); + mips_cpu_step(cpu); + mips_cpu_step(cpu); + + mips_cpu_get_register(cpu, 10, &hi); + mips_cpu_get_register(cpu, 11, &lo); + + result = (((uint64_t)hi)<<32) | ((uint64_t)lo); + + if((opcode == MULT && result == (uint64_t)((int64_t)(int32_t)num1*(int64_t)(int32_t)num2)) || (opcode == MULTU && result == (uint64_t)((uint32_t)num1)*(uint32_t)num2) || (opcode == DIV && lo == (uint32_t)((int32_t)num1/(int32_t)num2) && hi == (uint32_t)((int32_t)num1%(int32_t)num2)) || (opcode == DIVU && lo == num1/num2 && hi == num1%num2)) { + passed = 1; + } + + return passed; } diff --git a/src/ymh15/test_mips.h b/src/ymh15/test_mips.h deleted file mode 100644 index adf4b35..0000000 --- a/src/ymh15/test_mips.h +++ /dev/null @@ -1,74 +0,0 @@ -#include "mips_instruction_test.h" - -#include - -using namespace std; - -struct memory_state{ - uint32_t address; - uint32_t value; - - memory_state(uint32_t addressIn, uint32_t valueIn): - address(addressIn), - value(valueIn){} -}; - -struct register_state{ - uint8_t index; // 255 for checking program counter - uint32_t value; - - register_state(uint8_t indexIn, uint32_t valueIn): - index(indexIn), - value(valueIn){} -}; - -struct test{ - const char* testName; - const char* testDescription; - unsigned numInstructions; - vector memCheck; - vector regCheck; - int success; - mips_error expectedError; - - // Constructor for test - test( - const char* testNameIn, - const char* testDescriptionIn, - unsigned numInstructionsIn): - testName(testNameIn), - testDescription(testDescriptionIn), - numInstructions(numInstructionsIn), - // Assume the test passes - success(1), - expectedError(mips_Success){} - - // Constructor for test where the expected error isn't mips_Success - test( - const char* testNameIn, - const char* testDescriptionIn, - unsigned numInstructionsIn, - mips_error expectedErrorIn): - testName(testNameIn), - testDescription(testDescriptionIn), - numInstructions(numInstructionsIn), - // Assume the test passes - success(1), - expectedError(expectedErrorIn){} - - mips_error perform_test(mips_cpu_h state, mips_mem_h mem); - - void checkMem(uint32_t address, uint32_t value){ - memCheck.push_back(memory_state(address, value)); - } - - void checkReg(uint8_t index, uint32_t value){ - regCheck.push_back(register_state(index, value)); - } -}; - -uint32_t get_pc(mips_cpu_h state); -void writeMem(mips_mem_h mem, uint32_t address, uint32_t value); -void writeReg(mips_cpu_h state, uint8_t index, uint32_t value); - -void byte_swap_test(uint32_t &value); diff --git a/src/ymh15/test_mips.o b/src/ymh15/test_mips.o index 2e4b3df..32a3fd1 100644 Binary files a/src/ymh15/test_mips.o and b/src/ymh15/test_mips.o differ -- cgit