aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzedarider <ymherklotz@gmail.com>2016-10-25 20:32:55 +0100
committerzedarider <ymherklotz@gmail.com>2016-10-25 20:32:55 +0100
commit5b5ae1e32eef63ca9990fb80134851b402d51906 (patch)
tree6987a731f18828786080382c2479c66f6ac006d0
parent605222ecca9d1745787fe0f440cb06cd475a6eff (diff)
downloadMipsCPU-5b5ae1e32eef63ca9990fb80134851b402d51906.tar.gz
MipsCPU-5b5ae1e32eef63ca9990fb80134851b402d51906.zip
adding more instructions to the test cases and the cpu
-rw-r--r--src/ymh15/mips_cpu.cpp325
-rw-r--r--src/ymh15/mips_cpu.obin13968 -> 21024 bytes
-rw-r--r--src/ymh15/mips_cpu_ymh15.hpp20
-rw-r--r--src/ymh15/test.s15
-rwxr-xr-xsrc/ymh15/test_mipsbin328056 -> 335808 bytes
-rw-r--r--src/ymh15/test_mips.cpp208
-rw-r--r--src/ymh15/test_mips.obin32664 -> 40168 bytes
-rw-r--r--src/ymh15/test_mips_ymh15.hpp27
8 files changed, 520 insertions, 75 deletions
diff --git a/src/ymh15/mips_cpu.cpp b/src/ymh15/mips_cpu.cpp
index ea7cce1..02ca75a 100644
--- a/src/ymh15/mips_cpu.cpp
+++ b/src/ymh15/mips_cpu.cpp
@@ -4,32 +4,52 @@
struct mips_cpu_impl {
mips_mem_h mem;
uint32_t regs[32];
+ // lo and hi registers
+ uint32_t lo, hi;
+ // program counter
uint32_t pc;
- uint32_t overflow;
+ // next pc used for branches and set the pc correctly
+ uint32_t next_pc;
+ // delay slot that makes branches work as expected
+ uint32_t delay_slot;
+
+ // sets the debug level so that you can print more information
+ int debug_level;
+ FILE *debug_type;
};
mips_cpu_h mips_cpu_create(mips_mem_h mem) {
- mips_cpu_impl* new_mips_cpu = new mips_cpu_impl;
-
- new_mips_cpu->mem = mem;
- new_mips_cpu->pc = 0;
- new_mips_cpu->overflow = 0;
+ // creates new instance of a cpu explicitly
+ mips_cpu_impl* state = new mips_cpu_impl;
+
+ // reset all the variables
+ state->mem = mem;
+ state->pc = 0;
+ state->next_pc = state->pc + 4;
+ state->delay_slot = 0;
+ state->debug_level = 0;
+ state->debug_type = NULL;
+
+ // sets all registers to 0
for(int i = 0; i < 32; ++i) {
- new_mips_cpu->regs[i] = 0;
+ state->regs[i] = 0;
}
- return new_mips_cpu;
+ return state;
}
mips_error mips_cpu_reset(mips_cpu_h state) {
if(!state) {
return mips_ErrorInvalidArgument;
}
-
+
+ // resets both program counters
state->pc = 0;
- state->overflow = 0;
+ state->next_pc = state->pc + 4;
+ state->delay_slot = 0;
+ // and registers
for(int i = 0; i < 32; ++i) {
state->regs[i] = 0;
}
@@ -39,10 +59,11 @@ mips_error mips_cpu_reset(mips_cpu_h state) {
mips_error mips_cpu_get_register(mips_cpu_h state, unsigned index,
uint32_t *value) {
- if(!state || !value) {
+ if(!state || !value || index > 31) {
return mips_ErrorInvalidArgument;
}
-
+
+ // get the state of a current register by using the provided pointer;
*value = state->regs[index];
return mips_Success;
@@ -50,10 +71,11 @@ 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(!state) {
+ if(!state || index > 31) {
return mips_ErrorInvalidArgument;
}
-
+
+ // set reg state
state->regs[index] = value;
return mips_Success;
@@ -64,8 +86,10 @@ mips_error mips_cpu_set_pc(mips_cpu_h state, uint32_t pc) {
if(!state) {
return mips_ErrorInvalidArgument;
}
-
+
+ // set the pc and next_pc to the right values
state->pc = pc;
+ state->next_pc = state->pc+4;
return mips_Success;
}
@@ -74,121 +98,302 @@ mips_error mips_cpu_get_pc(mips_cpu_h state, uint32_t *pc) {
if(!state || !pc) {
return mips_ErrorInvalidArgument;
}
-
+
+ // get the value of the current pc
*pc = state->pc;
return mips_Success;
}
+// This function executes the code that is found in memory at the address
+// of the program counter
mips_error mips_cpu_step(mips_cpu_h state) {
if(!state) {
return mips_ErrorInvalidArgument;
}
- mips_error mips_err = read_instruction(state);
+ // gets the instruction from memory
+ uint32_t inst;
+ mips_mem_read(state->mem, state->pc, 4, (uint8_t*)&inst);
+
+ // 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(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
+ if(state->debug_level > 1) {
+ fprintf(state->debug_type, "\nCPU register state:\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 > 2) {
+ char c = getchar();
+ }
- state->pc += 4;
+ // it then updates the pc to next_pc which could have been changed
+ // by a branch, it only does this if it is not in a delay slot
+ if(!state->delay_slot) {
+ state->pc = state->next_pc;
+ state->next_pc += 4;
+ } else {
+ state->pc += 4;
+ --state->delay_slot;
+ }
+ // returns the operation error such as arithmetic overflow
return mips_err;
}
mips_error mips_cpu_set_debug_level(mips_cpu_h state, unsigned level,
FILE *dest) {
- if(!state || !dest) {
+ if(!state) {
return mips_ErrorInvalidArgument;
}
-
- //TODO
+
+ // just sets the cpu values for the debug level
+ state->debug_level = level;
+ state->debug_type = dest;
return mips_Success;
}
void mips_cpu_free(mips_cpu_h state) {
+ // deletes the state pointer of mips_cpu_impl* type
if(state) {
delete state;
}
}
-mips_error read_instruction(mips_cpu_h state) {
- uint32_t inst;
- mips_mem_read(state->mem, state->pc, 4, (uint8_t*)&inst);
-
- return exec_instruction(state, inst);
-}
+// The following functions are not present in the api as they are
+// functions defined in a private header file
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;
}
-
+
+ // decodes the instruction
+
+ // if first 6 bits are 0 then it is a R instruction
if(((inst >> 26)&0x3f) == 0) {
- // R Type
+ // R Type: set all necessary variables
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) < 4) {
- var[OPCODE] = inst >> 26;
+ } else if(((inst >> 26)&0x3f) < 4 && ((inst >> 26)&0x3f) != 1) { // as opcode is < 4
+ var[OPCODE] = inst >> 26; // it has to be J type
+ var[MEM] = inst&0x3ffffff;
+ return exec_J(state, var);
+ } else { // otherwise it is an I type
+ var[OPCODE] = inst >> 26;
var[REG_S] = (inst >> 21)&0x1f;
var[REG_D] = (inst >> 16)&0x1f;
var[IMM] = inst&0xffff;
-
- return exec_J(state, var);
- } else {
- var[OPCODE] = inst >> 26;
- var[MEM] = inst&0x3ffffff;
+ if((var[IMM]&0x8000) == 0x8000) {
+ var[IMM] = (var[IMM]|0xffff0000);
+ }
return exec_I(state, var);
}
-
- return mips_ExceptionInvalidInstruction;
}
mips_error exec_R(mips_cpu_h state, uint32_t var[8]) {
+ // if the function code is between 0x1f and 0x24 then it is addition
+ // or subtraction
if((var[FUNC]&0xf0) == 0x20 && (var[FUNC]&0xf) < 4) {
- return add_sub(state, var, ((int32_t)-(var[FUNC]&0xf)/2)*2+1);
+ // calls add with -1 if it is a subtractin and 1 if it is addition
+ return add_sub(state, var, ((int32_t)-(var[FUNC]&0xf)/2)*2+1, 0);
+
} else if((var[FUNC]&0xf0) == 0x20 && (var[FUNC]&0xf) < 7) {
- return bitwise(state, var);
+ // else if the number is between 0x23 and 0x27 which means it
+ // is a bitwise operation
+ return bitwise(state, var, 0);
+
+ } else if(var[FUNC] == 8) {
+ // jr
+ return jump(state, var, 0);
+ } else if(var[FUNC] == 9) {
+ // jalr
+ return jump(state, var, 1);
+ } else {
+ // otherwise return that it was an invalid instruction
+ return mips_ExceptionInvalidInstruction;
}
-
- return mips_ExceptionInvalidInstruction;
}
mips_error exec_J(mips_cpu_h state, uint32_t var[8]) {
- //TODO
-
- return mips_ExceptionInvalidInstruction;
+ switch(var[OPCODE]) {
+ case 0:
+ case 2: // j
+ return jump(state, var, 0);
+ case 3: // jal
+ return jump(state, var, 1);
+ default:
+ return mips_ExceptionInvalidInstruction;
+ }
}
mips_error exec_I(mips_cpu_h state, uint32_t var[8]) {
- //TODO
-
- return mips_ExceptionInvalidInstruction;
+ switch(var[OPCODE]) {
+ case 1: // bgez, bgezal, bltz, bltzal
+ return branch(state, var);
+ case 4: // beq
+ return branch(state, var);
+ case 5: // bne
+ return branch(state, var);
+ case 6: // blez
+ return branch(state, var);
+ case 7: // bgtz
+ return branch(state, var);
+ case 8: // addi
+ return add_sub(state, var, 1, 1);
+ case 9: // addiu
+ return add_sub(state, var, 1, 2);
+ case 12: // andi
+ return bitwise(state, var, 1);
+ case 13: // ori
+ return bitwise(state, var, 1);
+ case 14: // xori
+ return bitwise(state, var, 1);
+ case 32: // lb
+ return load(state, var);
+ case 36: // lbu
+ return load(state, var);
+ default:
+ return mips_ExceptionInvalidInstruction;
+ }
}
-mips_error add_sub(mips_cpu_h state, uint32_t var[8], int32_t add_sub) {
+mips_error add_sub(mips_cpu_h state, uint32_t var[8], int32_t add_sub,
+ int32_t imm) {
+ // sets initial values of the registers as local variables
int32_t reg_s, reg_t, reg_d;
- reg_s = (int32_t)state->regs[var[REG_S]];
- reg_t = (int32_t)state->regs[var[REG_T]];
+
+ // set the locals to the correct value from the register
+ mips_cpu_get_register(state, var[REG_S], (uint32_t*)&reg_s);
+ if(imm > 0) {
+ reg_t = (int32_t)var[IMM];
+ } else {
+ mips_cpu_get_register(state, var[REG_T], (uint32_t*)&reg_t);
+ }
+
+ // perform the addition or subtraction
reg_d = reg_s + add_sub*reg_t;
- if((var[FUNC]&0x1) == 1 || !((reg_s > 0 && add_sub*reg_t > 0 && reg_d < 0) || (reg_s < 0 && add_sub*reg_t < 0 && reg_d > 0))) {
- state->regs[var[REG_D]] = (uint32_t)reg_d;
+
+ // check for overflow conditions and if it is an unsigned operation
+ if((var[FUNC]&0x1) == 1 || imm > 1 || !((reg_s > 0 && add_sub*reg_t > 0 && reg_d < 0) || (reg_s < 0 && add_sub*reg_t < 0 && reg_d > 0))) {
+
+ // sets the destination register to the right answer
+ mips_cpu_set_register(state, var[REG_D], (uint32_t)reg_d);
return mips_Success;
}
+
return mips_ExceptionArithmeticOverflow;
}
-mips_error bitwise(mips_cpu_h state, uint32_t var[8]) {
- if((var[FUNC]&0xf) == 4) {
- state->regs[var[REG_D]] = state->regs[var[REG_S]] & state->regs[var[REG_T]];
- } else if((var[FUNC]&0xf) == 5) {
- state->regs[var[REG_D]] = state->regs[var[REG_S]] | state->regs[var[REG_T]];
+mips_error bitwise(mips_cpu_h state, uint32_t var[8], unsigned imm) {
+ // selects the right bitwise operation to perform then sets the register to the right value
+ uint32_t reg_s, reg_t, reg_d;
+
+ mips_cpu_get_register(state, var[REG_S], &reg_s);
+ if(imm == 0) {
+ mips_cpu_get_register(state, var[REG_T], &reg_t);
} else {
- state->regs[var[REG_D]] = state->regs[var[REG_S]] ^ state->regs[var[REG_T]];
+ reg_t = var[IMM];
+ }
+
+ // performs correct bitwise operation and sets register;
+ if((var[FUNC]&0xf) == 4 || var[OPCODE] == 0xc) reg_d = reg_s & reg_t;
+ else if((var[FUNC]&0xf) == 5 || var[OPCODE] == 0xd) reg_d = reg_s | reg_t;
+ else reg_d = reg_s ^ reg_t;
+
+ // set register to the answer
+ mips_cpu_set_register(state, var[REG_D], reg_d);
+
+ return mips_Success;
+}
+
+mips_error branch(mips_cpu_h state, uint32_t var[8]) {
+ if(var[OPCODE] == 1 && (var[REG_D] == 0x11 || var[REG_D] == 0x10)) {
+ state->regs[31] = state->pc+8;
}
+
+ if((state->regs[var[REG_S]] == state->regs[var[REG_D]] && var[OPCODE] == 4) || // bez
+ (state->regs[var[REG_S]] != state->regs[var[REG_D]] && var[OPCODE] == 5) || // bne
+ (((int32_t)state->regs[var[REG_S]] >= 0) && (var[OPCODE] == 1) && (var[REG_D]&1) == 1) || // bgez / bgezal
+ ((int32_t)state->regs[var[REG_S]] < 0 && var[OPCODE] == 1 && (var[REG_D]&1) == 0) || // bltz / bltzal
+ ((int32_t)state->regs[var[REG_S]] > 0 && var[OPCODE] == 7 && (var[REG_D]&1) == 0) || // bgtz
+ ((int32_t)state->regs[var[REG_S]] <= 0 && var[OPCODE] == 6 && (var[REG_D]&1) == 0)) { // blez
+
+ state->next_pc += (var[IMM]<<2);
+ state->delay_slot += 1;
+ }
+
+ return mips_Success;
+}
+
+mips_error jump(mips_cpu_h state, uint32_t var[8], uint8_t link) {
+ uint8_t reg_d;
+ uint32_t jump_loc;
+ if(var[FUNC] == 9 || var[FUNC] == 8) {
+ jump_loc = state->regs[var[REG_S]];
+ reg_d = var[REG_D];
+ } else {
+ jump_loc = var[IMM]<<2;
+ reg_d = 31;
+ }
+
+ if(link) {
+ state->regs[reg_d] = state->pc+8;
+ }
+
+ state->next_pc = jump_loc;
+ state->delay_slot += 1;
+
+ return mips_Success;
+}
+
+mips_error load(mips_cpu_h state, uint32_t var[8]) {
+ uint32_t addr;
+ uint8_t mem_byte;
+
+ addr = state->regs[var[REG_S]] + var[IMM];
+
+ mips_mem_read(state->mem, addr, 1, &mem_byte);
+
+ if(var[OPCODE] == 0x24) {
+ state->regs[var[REG_D]] = (uint32_t)mem_byte;
+ } else if(var[OPCODE] == 0x20){
+ state->regs[var[REG_D]] = (uint32_t)(int8_t)mem_byte;
+ } else {
+ return mips_ExceptionInvalidInstruction;
+ }
+
+ return mips_Success;
+}
+
+mips_error store(mips_cpu_h state, uint32_t var[8]) {
return mips_Success;
}
diff --git a/src/ymh15/mips_cpu.o b/src/ymh15/mips_cpu.o
index 1781493..1422c47 100644
--- a/src/ymh15/mips_cpu.o
+++ b/src/ymh15/mips_cpu.o
Binary files differ
diff --git a/src/ymh15/mips_cpu_ymh15.hpp b/src/ymh15/mips_cpu_ymh15.hpp
index 1e2900a..2a95db1 100644
--- a/src/ymh15/mips_cpu_ymh15.hpp
+++ b/src/ymh15/mips_cpu_ymh15.hpp
@@ -1,8 +1,11 @@
#ifndef MIPS_CPU_YMH15_H
#define MIPS_CPU_YMH15_H
+#include <cstdio>
+
#include "../../include/mips.h"
+// defines the location of the things in the array var
#define OPCODE 0
#define REG_S 1
#define REG_T 2
@@ -12,15 +15,24 @@
#define IMM 6
#define MEM 7
-mips_error read_instruction(mips_cpu_h state);
+// executes an instruction by first decoding it and sending the right
+// variables to the different functions to be correctly interpreted
mips_error exec_instruction(mips_cpu_h state, uint32_t inst);
mips_error exec_R(mips_cpu_h state, uint32_t var[8]);
mips_error exec_J(mips_cpu_h state, uint32_t var[8]);
mips_error exec_I(mips_cpu_h state, uint32_t var[8]);
-mips_error add_sub(mips_cpu_h state, uint32_t var[8], int32_t add_sub);
-mips_error bitwise(mips_cpu_h state, uint32_t var[8]);
+// performs addition and subtraction
+mips_error add_sub(mips_cpu_h state, uint32_t var[8], int32_t add_sub,
+ int32_t imm);
+// performs bitwise operations
+mips_error bitwise(mips_cpu_h state, uint32_t var[8], unsigned imm);
+
+mips_error branch(mips_cpu_h state, uint32_t var[8]);
+
+mips_error jump(mips_cpu_h state, uint32_t var[8], uint8_t link);
-uint8_t get_msb(uint32_t word);
+mips_error load(mips_cpu_h state, uint32_t var[8]);
+mips_error store(mips_cpu_h state, uint32_t var[8]);
#endif // MIPS_CPU_YMH15_H
diff --git a/src/ymh15/test.s b/src/ymh15/test.s
new file mode 100644
index 0000000..80f645a
--- /dev/null
+++ b/src/ymh15/test.s
@@ -0,0 +1,15 @@
+ .text
+ .globl main
+
+main:
+ li $8, 10
+ li $9, 0
+ li $10, 17
+loop:
+ beq $9, $8, end
+ add $10, $10, $9
+ addi $9, $9, 1
+ j loop
+end:
+ ori $2, $0, 10
+ syscall
diff --git a/src/ymh15/test_mips b/src/ymh15/test_mips
index 07c381a..ba7ccb4 100755
--- a/src/ymh15/test_mips
+++ b/src/ymh15/test_mips
Binary files differ
diff --git a/src/ymh15/test_mips.cpp b/src/ymh15/test_mips.cpp
index d515b9b..5078b45 100644
--- a/src/ymh15/test_mips.cpp
+++ b/src/ymh15/test_mips.cpp
@@ -5,14 +5,20 @@
using namespace std;
-int main() {
+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));
- mips_test_begin_suite();
+ 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");
@@ -45,6 +51,63 @@ int main() {
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_branch(ram, cpu, 1, -1, 0, 16, 20), "Testing BGEZ");
+
+ testId = mips_test_begin_test("JAL");
+ mips_test_end_test(testId, test_branch(ram, cpu, 1, -1, 0, 16, 20), "Testing BGEZ");
+
+ testId = mips_test_begin_test("JALR");
+ mips_test_end_test(testId, test_branch(ram, cpu, 1, -1, 0, 16, 20), "Testing BGEZ");
+
+ testId = mips_test_begin_test("JR");
+ mips_test_end_test(testId, test_branch(ram, cpu, 1, -1, 0, 16, 20), "Testing BGEZ");
+
+ testId = mips_test_begin_test("LB");
+ mips_test_end_test(testId, test_load(ram, cpu, LB, 0xff), "Testing LB");
+
+ testId = mips_test_begin_test("LBU");
+ mips_test_end_test(testId, test_load(ram, cpu, LBU, 0xff), "Testing LB");
mips_test_end_suite();
return 0;
@@ -87,7 +150,7 @@ int test_add(mips_mem_h ram, mips_cpu_h cpu, uint32_t type, uint32_t max, uint8_
for(unsigned i = 0; i < i_t; ++i) {
mips_error mips_err;
mips_cpu_reset(cpu);
- inst = gen_instruction(9, 10, 8, 0, type);
+ inst = change_endianness(gen_instruction(9, 10, 8, 0, type));
if(value) {
a = max;
if(type > 0x21) {
@@ -110,17 +173,16 @@ int test_add(mips_mem_h ram, mips_cpu_h cpu, uint32_t type, uint32_t max, uint8_
mips_cpu_get_register(cpu, 8, &ans);
if(type < 0x22) {
- printf("%#10x + %#10x = %#10x\t%#10x\n", a, b, ans, mips_err);
+ //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);
+ //printf("%#10x - %#10x = %#10x\t%#10x\n", a, b, ans, mips_err);
if(mips_err == mips_ExceptionArithmeticOverflow || a-b!=ans) {
return 0;
}
}
-
}
return 1;
@@ -132,7 +194,7 @@ int test_bitwise(mips_mem_h ram, mips_cpu_h cpu, uint8_t op) {
for(unsigned i = 0; i < 10; ++i) {
passed = 0;
mips_cpu_reset(cpu);
- inst = gen_instruction(8, 9, 7, 0, op);
+ inst = change_endianness(gen_instruction(8, 9, 7, 0, op));
a = rand() % 0xffffffff;
b = rand() % 0xffffffff;
@@ -147,17 +209,17 @@ int test_bitwise(mips_mem_h ram, mips_cpu_h cpu, uint8_t op) {
mips_cpu_get_register(cpu, 7, &ans);
if(op == AND) {
- printf("%#10x & %#10x = %#10x\t%#10x\n", a, b, ans, mips_err);
+ //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);
+ //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);
+ //printf("%#10x ^ %#10x = %#10x\t%#10x\n", a, b, ans, mips_err);
if((a ^ b) == ans) {
passed = 1;
}
@@ -171,3 +233,129 @@ int test_bitwise(mips_mem_h ram, mips_cpu_h cpu, uint8_t op) {
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, &reg10);
+ mips_cpu_get_register(cpu, 11, &reg11);
+
+ if(l == 1) {
+ mips_cpu_get_register(cpu, 31, &reg31);
+ 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;
+
+ mips_cpu_reset(cpu);
+
+ if(opcode == 2 || opcode == 3) {
+ inst = change_endianness(gen_instruction(opcode, 0x20));
+ }
+
+ return passed;
+}
+
+int test_load(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode, uint8_t num) {
+ int passed = 0;
+ uint32_t res;
+
+ mips_cpu_reset(cpu);
+
+ uint32_t inst = change_endianness(gen_instruction(opcode, 8, 9, 4));
+
+ mips_mem_write(ram, 0, 4, (uint8_t*)&inst);
+ mips_mem_write(ram, 0x30, 1, &num);
+
+ mips_cpu_set_register(cpu, 8, 0x2c);
+
+ mips_cpu_step(cpu);
+
+ mips_cpu_get_register(cpu, 9, &res);
+
+ if((res == (uint32_t)(int8_t)num && opcode == LB) || (res == (uint32_t)num && opcode == LBU)) {
+ passed = 1;
+ }
+
+ return passed;
+}
+
diff --git a/src/ymh15/test_mips.o b/src/ymh15/test_mips.o
index c7f9ef4..e62b5d1 100644
--- a/src/ymh15/test_mips.o
+++ b/src/ymh15/test_mips.o
Binary files differ
diff --git a/src/ymh15/test_mips_ymh15.hpp b/src/ymh15/test_mips_ymh15.hpp
index 60004f1..a1d1a7f 100644
--- a/src/ymh15/test_mips_ymh15.hpp
+++ b/src/ymh15/test_mips_ymh15.hpp
@@ -5,6 +5,9 @@
#include <cstdlib>
#include <ctime>
+// Functions
+#define JR 0x8
+#define JALR 0x9
#define ADD 0x20
#define ADDU 0x21
#define SUB 0x22
@@ -13,6 +16,22 @@
#define OR 0x25
#define XOR 0x26
+// OPcodes
+#define BGEZ 0x1
+#define J 0x2
+#define JAL 0x3
+#define BEQ 0x4
+#define BNE 0x5
+#define BLEZ 0x6
+#define BGTZ 0x7
+#define ADDI 0x8
+#define ADDIU 0x9
+#define ANDI 0xc
+#define ORI 0xd
+#define XORI 0xe
+#define LB 0x20
+#define LBU 0x24
+
uint32_t gen_instruction(uint32_t src1, uint32_t src2, uint32_t dest,
uint32_t shift, uint32_t function);
uint32_t gen_instruction(uint32_t opcode, uint32_t src, uint32_t dest,
@@ -20,7 +39,13 @@ uint32_t gen_instruction(uint32_t opcode, uint32_t src, uint32_t dest,
uint32_t gen_instruction(uint32_t opcode, uint32_t memory);
uint32_t change_endianness(uint32_t inst);
-int test_add(mips_mem_h ram, mips_cpu_h cpu, uint32_t type, uint32_t max, uint8_t value, unsigned i_t);
+int test_add(mips_mem_h ram, mips_cpu_h cpu, uint32_t type, uint32_t max,
+ uint8_t value, unsigned i_t);
int test_bitwise(mips_mem_h ram, mips_cpu_h cpu, uint8_t op);
+int test_I(mips_mem_h ram, mips_cpu_h cpu, uint32_t type, uint32_t num1,
+ uint32_t num2);
+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 test_jump(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode);
+int test_load(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode, uint8_t num);
#endif // TEST_MIPS_YMH15_H