aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xmakefile2
-rw-r--r--src/shared/mips_mem_ram.obin0 -> 10000 bytes
-rw-r--r--src/shared/mips_test_framework.obin0 -> 337728 bytes
l---------src/ymh15/.#mips_cpu.cpp1
-rw-r--r--src/ymh15/mips_cpu.cpp566
-rw-r--r--src/ymh15/mips_cpu.obin0 -> 25904 bytes
-rw-r--r--src/ymh15/mips_cpu_ymh15.hpp93
-rw-r--r--src/ymh15/test.s15
-rwxr-xr-xsrc/ymh15/test_mipsbin0 -> 341840 bytes
-rw-r--r--src/ymh15/test_mips.cpp482
-rw-r--r--src/ymh15/test_mips.obin0 -> 46200 bytes
-rw-r--r--src/ymh15/test_mips_ymh15.hpp82
12 files changed, 1240 insertions, 1 deletions
diff --git a/makefile b/makefile
index cebf386..a5597ae 100755
--- a/makefile
+++ b/makefile
@@ -1,6 +1,6 @@
# Your login. For example, mine is dt10. Yours
# won't be eie2ugs...
-LOGIN ?= eie2ugs
+LOGIN ?= ymh15
# Turn on all warnings
CPPFLAGS += -W -Wall
diff --git a/src/shared/mips_mem_ram.o b/src/shared/mips_mem_ram.o
new file mode 100644
index 0000000..718d8dc
--- /dev/null
+++ b/src/shared/mips_mem_ram.o
Binary files differ
diff --git a/src/shared/mips_test_framework.o b/src/shared/mips_test_framework.o
new file mode 100644
index 0000000..9790ca3
--- /dev/null
+++ b/src/shared/mips_test_framework.o
Binary files differ
diff --git a/src/ymh15/.#mips_cpu.cpp b/src/ymh15/.#mips_cpu.cpp
new file mode 120000
index 0000000..5a5142f
--- /dev/null
+++ b/src/ymh15/.#mips_cpu.cpp
@@ -0,0 +1 @@
+yannherklotz@Yann-Arch.800:1477569971 \ No newline at end of file
diff --git a/src/ymh15/mips_cpu.cpp b/src/ymh15/mips_cpu.cpp
new file mode 100644
index 0000000..34107de
--- /dev/null
+++ b/src/ymh15/mips_cpu.cpp
@@ -0,0 +1,566 @@
+#include "../../include/mips.h"
+#include "mips_cpu_ymh15.hpp"
+
+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;
+ // 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) {
+ // 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->lo = 0;
+ state->hi = 0;
+
+ state->debug_level = 0;
+ state->debug_type = NULL;
+
+ // sets all registers to 0
+ for(int i = 0; i < 32; ++i) {
+ state->regs[i] = 0;
+ }
+
+ return state;
+}
+
+mips_error mips_cpu_reset(mips_cpu_h state) {
+ if(!state) {
+ return mips_ErrorInvalidArgument;
+ }
+
+ // resets both program counters
+ state->pc = 0;
+ state->next_pc = state->pc + 4;
+ state->delay_slot = 0;
+ state->hi = 0;
+ state->lo = 0;
+
+ // and registers
+ for(int i = 0; i < 32; ++i) {
+ state->regs[i] = 0;
+ }
+
+ return mips_Success;
+}
+
+mips_error mips_cpu_get_register(mips_cpu_h state, unsigned index,
+ uint32_t *value) {
+ if(!state || !value || index > 31 || index == 0) {
+ return mips_ErrorInvalidArgument;
+ }
+
+ // get the state of a current register by using the provided pointer;
+ *value = state->regs[index];
+
+ return mips_Success;
+}
+
+mips_error mips_cpu_set_register(mips_cpu_h state, unsigned index,
+ uint32_t value) {
+ if(!state || index > 31 || index == 0) {
+ return mips_ErrorInvalidArgument;
+ }
+
+ // set reg state
+ state->regs[index] = value;
+
+ return mips_Success;
+}
+
+
+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;
+}
+
+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;
+ }
+
+ // 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();
+ }
+
+ // 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) {
+ return mips_ErrorInvalidArgument;
+ }
+
+ // 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;
+ }
+}
+
+// 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: 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 && ((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;
+ if((var[IMM]&0x8000) == 0x8000) {
+ var[IMM] = (var[IMM]|0xffff0000);
+ }
+
+ return exec_I(state, var);
+ }
+}
+
+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) {
+ // 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) {
+ // 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 if(var[FUNC] >= 0x10 && var[FUNC] <= 0x13) {
+ // mfhi mthi mflo mtlo
+ return move(state, var);
+
+ } else if(var[FUNC] >= 0x18 && var[FUNC] <= 0x1b) {
+ // mult multu div divu
+ return mult_div(state, var);
+
+ } else {
+ // otherwise return that it was an invalid instruction
+ return mips_ExceptionInvalidInstruction;
+ }
+}
+
+mips_error exec_J(mips_cpu_h state, uint32_t var[8]) {
+ 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]) {
+ switch(var[OPCODE]) {
+ case 0x1: // bgez, bgezal, bltz, bltzal
+ return branch(state, var);
+ case 0x4: // beq
+ return branch(state, var);
+ case 0x5: // bne
+ return branch(state, var);
+ case 0x6: // blez
+ return branch(state, var);
+ case 0x7: // bgtz
+ return branch(state, var);
+ case 0x8: // addi
+ return add_sub(state, var, 1, 1);
+ case 0x9: // addiu
+ return add_sub(state, var, 1, 2);
+ case 0xc: // andi
+ return bitwise(state, var, 1);
+ case 0xd: // ori
+ return bitwise(state, var, 1);
+ case 0xe: // xori
+ return bitwise(state, var, 1);
+ case 0xf: // lui
+ return load(state, var);
+ case 0x20: // lb
+ return load(state, var);
+ case 0x21: // lh
+ return load(state, var);
+ case 0x22: // lwl
+ return load(state, var);
+ case 0x23: // lw
+ return load(state, var);
+ case 0x24: // lbu
+ return load(state, var);
+ case 0x25: // lhu
+ return load(state, var);
+ case 0x26: // lwr
+ return load(state, var);
+ case 0x28: // sb
+ return store(state, var);
+ case 0x29: // sh
+ return store(state, var);
+ case 0x2b: // sw
+ return store(state, var);
+ default:
+ return mips_ExceptionInvalidInstruction;
+ }
+}
+
+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;
+
+ // 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;
+
+ // 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], 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 {
+ 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[MEM]<<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;
+ uint16_t mem_halfword;
+ uint32_t mem_word;
+
+ addr = state->regs[var[REG_S]] + var[IMM];
+
+ if(var[OPCODE] == 0x24 || var[OPCODE] == 0x20) { // lb lbu
+ mips_mem_read(state->mem, addr, 1, &mem_byte);
+ } else if(var[OPCODE] == 0x21 || var[OPCODE] == 0x25) { // lh lhu
+ if((addr&0b1) == 1) {
+ return mips_ExceptionInvalidAddress;
+ }
+ mips_mem_read(state->mem, addr, 2, (uint8_t*)&mem_halfword);
+ mem_halfword = mem_halfword>>8 | mem_halfword<<8;
+ } else if(var[OPCODE] == 0x23 || var[OPCODE] == 0x22) { // lw lwl
+ if((addr&0b1) == 1 || (addr&0b10)>>1 == 1) {
+ return mips_ExceptionInvalidAddress;
+ }
+ mips_mem_read(state->mem, addr, 4, (uint8_t*)&mem_word);
+ mem_word = (mem_word<<24) | ((mem_word>>8)&0xff00) | ((mem_word<<8)&0xff0000) | (mem_word>>24);
+ } else if(var[OPCODE] == 0x26) { // lwr
+ if((addr&0b1) == 0 || (addr&0b10)>>1 == 0) {
+ return mips_ExceptionInvalidAddress;
+ }
+ mips_mem_read(state->mem, addr-3, 4, (uint8_t*)&mem_word);
+ mem_word = (mem_word<<24) | ((mem_word>>8)&0xff00) | ((mem_word<<8)&0xff0000) | (mem_word>>24);
+ }
+
+ switch(var[OPCODE]) {
+ case 0xf:
+ state->regs[var[REG_D]] = var[IMM]<<16;
+ return mips_Success;
+ case 0x20:
+ state->regs[var[REG_D]] = (uint32_t)(int8_t)mem_byte;
+ return mips_Success;
+ case 0x21:
+ state->regs[var[REG_D]] = (uint32_t)(int16_t)mem_halfword;
+ return mips_Success;
+ case 0x22:
+ state->regs[var[REG_D]] = (mem_word&0xffff0000)|(state->regs[var[REG_D]]&0xffff);
+ return mips_Success;
+ case 0x23:
+ state->regs[var[REG_D]] = mem_word;
+ return mips_Success;
+ case 0x24:
+ state->regs[var[REG_D]] = (uint32_t)mem_byte;
+ return mips_Success;
+ case 0x25:
+ state->regs[var[REG_D]] = (uint32_t)mem_halfword;
+ return mips_Success;
+ case 0x26:
+ state->regs[var[REG_D]] = (state->regs[var[REG_D]]&0xffff0000)|(mem_word&0xffff);
+ return mips_Success;
+ default:
+ return mips_ExceptionInvalidInstruction;
+ }
+}
+
+mips_error store(mips_cpu_h state, uint32_t var[8]) {
+ uint32_t addr;
+ uint32_t word;
+ uint16_t half_word;
+ uint8_t byte;
+
+ addr = state->regs[var[REG_S]] + var[IMM];
+ word = state->regs[var[REG_D]];
+ half_word = (uint16_t)state->regs[var[REG_D]];
+ byte = (uint8_t)state->regs[var[REG_D]];
+
+ if(var[OPCODE] == 0x28) {
+ mips_mem_write(state->mem, addr, 1, &byte);
+ } else if(var[OPCODE] == 0x29) {
+ if((addr&0b1) == 1) {
+ return mips_ExceptionInvalidAddress;
+ }
+ uint16_t tmp = half_word << 8 | half_word >> 8;
+ mips_mem_write(state->mem, addr, 2, (uint8_t*)&tmp);
+ } else if(var[OPCODE] == 0x2b) {
+ if((addr&0b1) == 1 || (addr&0b10)>>1 == 1) {
+ return mips_ExceptionInvalidAddress;
+ }
+ uint32_t tmp = word<<24 | ((word>>8)&0xff00) | ((word<<8)&0xff0000) | word>>24;
+ mips_mem_write(state->mem, addr, 4, (uint8_t*)&tmp);
+ } else {
+ return mips_ExceptionInvalidInstruction;
+ }
+ return mips_Success;
+}
+
+mips_error move(mips_cpu_h state, uint32_t var[8]) {
+ switch(var[FUNC]) {
+ case 0x10:
+ return mips_cpu_set_register(state, var[REG_D], state->hi);
+ case 0x11:
+ return mips_cpu_get_register(state, var[REG_D], &state->hi);
+ case 0x12:
+ return mips_cpu_set_register(state, var[REG_D], state->lo);
+ case 0x13:
+ return mips_cpu_get_register(state, var[REG_D], &state->lo);
+ default:
+ return mips_ExceptionInvalidInstruction;
+ }
+ return mips_Success;
+}
+
+mips_error mult_div(mips_cpu_h state, uint32_t var[8]) {
+ uint64_t unsigned_result, signed_result;
+ switch(var[FUNC]) {
+ case 0x18: // mult
+ signed_result = ((int64_t)(int32_t)state->regs[var[REG_S]])*((int64_t)(int32_t)state->regs[var[REG_T]]);
+ state->lo = (uint32_t)signed_result;
+ state->hi = (uint32_t)(signed_result>>32);
+ return mips_Success;
+
+ case 0x19: // multu
+ unsigned_result = ((uint64_t)state->regs[var[REG_S]])*((uint64_t)state->regs[var[REG_T]]);
+ state->lo = (uint32_t)unsigned_result;
+ state->hi = (uint32_t)(unsigned_result>>32);
+ return mips_Success;
+
+ case 0x1a: // div
+ if(var[REG_T] == 0) {
+ state->lo = 0;
+ state->hi = 0;
+ return mips_Success;
+ }
+
+ state->lo = ((int32_t)state->regs[var[REG_S]])/((int32_t)state->regs[var[REG_T]]);
+ state->hi = ((int32_t)state->regs[var[REG_S]])%((int32_t)state->regs[var[REG_T]]);
+ return mips_Success;
+
+ case 0x1b: // divu
+ if(var[REG_T] == 0) {
+ state->lo = 0;
+ state->hi = 0;
+ return mips_Success;
+ }
+
+ state->lo = (state->regs[var[REG_S]])/(state->regs[var[REG_T]]);
+ state->hi = (state->regs[var[REG_S]])%(state->regs[var[REG_T]]);
+ return mips_Success;
+
+ default:
+ return mips_ExceptionInvalidInstruction;
+ }
+}
+
+mips_error shift(mips_cpu_h state, uint32_t var[8]) {
+ if(var[FUNC] == 0 && var[OPCODE] == 0) {
+ state->regs[var[REG_D]] = state->regs[var[REG_T]] << var[SHIFT];
+ } else if(var[FUNC] == 4) {
+ state->regs[var[REG_D]] = state->regs[var[REG_T]] << state->regs[var[REG_S]];
+ } else if(var[FUNC] == 2/*TODO*/);
+ return mips_Success;
+}
diff --git a/src/ymh15/mips_cpu.o b/src/ymh15/mips_cpu.o
new file mode 100644
index 0000000..4092c0a
--- /dev/null
+++ 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
new file mode 100644
index 0000000..085c59c
--- /dev/null
+++ b/src/ymh15/mips_cpu_ymh15.hpp
@@ -0,0 +1,93 @@
+#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
+#define REG_D 3
+#define SHIFT 4
+#define FUNC 5
+#define IMM 6
+#define MEM 7
+
+// Functions
+#define SLL 0x0
+#define SRL 0x2
+#define SRA 0x3
+#define SLLV 0x4
+#define SRLV 0x6
+#define SRAV 0x7
+#define JR 0x8
+#define JALR 0x9
+#define MFHI 0x10
+#define MTHI 0x11
+#define MFLO 0x12
+#define MTLO 0x13
+#define MULT 0x18
+#define MULTU 0x19
+#define DIV 0x1a
+#define DIVU 0x1b
+#define ADD 0x20
+#define ADDU 0x21
+#define SUB 0x22
+#define SUBU 0x23
+#define AND 0x24
+#define OR 0x25
+#define XOR 0x26
+#define SLT 0x2a
+#define SLTU 0x2b
+
+// OPcodes
+#define BGEZ 0x1
+#define BGEZAL 0x1
+#define BLTZ 0x1
+#define BLTZAL 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 SLTI 0xa
+#define SLTIU 0xb
+#define ANDI 0xc
+#define ORI 0xd
+#define XORI 0xe
+#define LUI 0xf
+#define LB 0x20
+#define LH 0x21
+#define LWL 0x22
+#define LW 0x23
+#define LBU 0x24
+#define LHU 0x25
+#define LWR 0x26
+#define SB 0x28
+#define SH 0x29
+#define SW 0x2b
+
+// 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]);
+// 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);
+mips_error load(mips_cpu_h state, uint32_t var[8]);
+mips_error store(mips_cpu_h state, uint32_t var[8]);
+mips_error move(mips_cpu_h state, uint32_t var[8]);
+mips_error mult_div(mips_cpu_h state, uint32_t var[8]);
+mips_error shift(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
new file mode 100755
index 0000000..3c01c18
--- /dev/null
+++ b/src/ymh15/test_mips
Binary files differ
diff --git a/src/ymh15/test_mips.cpp b/src/ymh15/test_mips.cpp
new file mode 100644
index 0000000..75afaa8
--- /dev/null
+++ b/src/ymh15/test_mips.cpp
@@ -0,0 +1,482 @@
+#include "../../include/mips.h"
+#include "test_mips_ymh15.hpp"
+
+#include <iostream>
+
+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, &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, 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, &reg10);
+ mips_cpu_get_register(cpu, 13, &reg13);
+ mips_cpu_get_register(cpu, 16, &reg16);
+ mips_cpu_get_register(cpu, 31, &reg31);
+
+ 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/test_mips.o b/src/ymh15/test_mips.o
new file mode 100644
index 0000000..32a3fd1
--- /dev/null
+++ 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
new file mode 100644
index 0000000..054068b
--- /dev/null
+++ b/src/ymh15/test_mips_ymh15.hpp
@@ -0,0 +1,82 @@
+#ifndef TEST_MIPS_YMH15_H
+#define TEST_MIPS_YMH15_H
+
+#include "../../include/mips.h"
+#include <cstdlib>
+#include <ctime>
+
+// Functions
+#define SLL 0x0
+#define SRL 0x2
+#define SRA 0x3
+#define SLLV 0x4
+#define SRLV 0x6
+#define SRAV 0x7
+#define JR 0x8
+#define JALR 0x9
+#define MFHI 0x10
+#define MTHI 0x11
+#define MFLO 0x12
+#define MTLO 0x13
+#define MULT 0x18
+#define MULTU 0x19
+#define DIV 0x1a
+#define DIVU 0x1b
+#define ADD 0x20
+#define ADDU 0x21
+#define SUB 0x22
+#define SUBU 0x23
+#define AND 0x24
+#define OR 0x25
+#define XOR 0x26
+#define SLT 0x2a
+#define SLTU 0x2b
+
+// OPcodes
+#define BGEZ 0x1
+#define BGEZAL 0x1
+#define BLTZ 0x1
+#define BLTZAL 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 SLTI 0xa
+#define SLTIU 0xb
+#define ANDI 0xc
+#define ORI 0xd
+#define XORI 0xe
+#define LUI 0xf
+#define LB 0x20
+#define LH 0x21
+#define LWL 0x22
+#define LW 0x23
+#define LBU 0x24
+#define LHU 0x25
+#define LWR 0x26
+#define SB 0x28
+#define SH 0x29
+#define SW 0x2b
+
+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,
+ uint32_t Astart);
+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_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, uint32_t word);
+int test_mult_div(mips_mem_h ram, mips_cpu_h cpu, uint32_t opcode, uint32_t num1, uint32_t num2);
+
+#endif // TEST_MIPS_YMH15_H