aboutsummaryrefslogtreecommitdiffstats
path: root/src/ymh15/mips_cpu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ymh15/mips_cpu.cpp')
-rw-r--r--src/ymh15/mips_cpu.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/ymh15/mips_cpu.cpp b/src/ymh15/mips_cpu.cpp
new file mode 100644
index 0000000..49e8cff
--- /dev/null
+++ b/src/ymh15/mips_cpu.cpp
@@ -0,0 +1,176 @@
+#include "../../include/mips.h"
+#include "mips_cpu_ymh15.hpp"
+
+struct mips_cpu_impl {
+ mips_mem_h mem;
+ uint32_t regs[32];
+ uint32_t pc;
+ uint32_t overflow;
+};
+
+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;
+
+ for(int i = 0; i < 32; ++i) {
+ new_mips_cpu->regs[i] = 0;
+ }
+
+ return new_mips_cpu;
+}
+
+mips_error mips_cpu_reset(mips_cpu_h state) {
+ if(!state) {
+ return mips_ErrorInvalidArgument;
+ }
+
+ state->pc = 0;
+ state->overflow = 0;
+
+ 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) {
+ return mips_ErrorInvalidArgument;
+ }
+
+ *value = state->regs[index];
+
+ return mips_Success;
+}
+
+mips_error mips_cpu_set_register(mips_cpu_h state, unsigned index,
+ uint32_t value) {
+ if(!state) {
+ return mips_ErrorInvalidArgument;
+ }
+
+ 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;
+ }
+
+ state->pc = pc;
+
+ return mips_Success;
+}
+
+mips_error mips_cpu_get_pc(mips_cpu_h state, uint32_t *pc) {
+ if(!state || !pc) {
+ return mips_ErrorInvalidArgument;
+ }
+
+ *pc = state->pc;
+
+ return mips_Success;
+}
+
+mips_error mips_cpu_step(mips_cpu_h state) {
+ if(!state) {
+ return mips_ErrorInvalidArgument;
+ }
+
+ read_instruction(state);
+
+ state->pc += 4;
+
+ return mips_Success;
+}
+
+mips_error mips_cpu_set_debug_level(mips_cpu_h state, unsigned level,
+ FILE *dest) {
+ if(!state || !dest) {
+ return mips_ErrorInvalidArgument;
+ }
+
+ //TODO
+
+ return mips_Success;
+}
+
+void mips_cpu_free(mips_cpu_h state) {
+ 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);
+
+ exec_instruction(state, inst);
+
+ return mips_Success;
+}
+
+mips_error exec_instruction(mips_cpu_h state, uint32_t inst) {
+ uint32_t var[8];
+ for(int i = 0; i < 8; ++i) {
+ var[i] = 0;
+ }
+
+ 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;
+
+ exec_R(state, var);
+ } else if(((inst >> 26)&0x3f) < 4) {
+ var[OPCODE] = inst >> 26;
+ var[REG_S] = (inst >> 21)&0x1f;
+ var[REG_D] = (inst >> 16)&0x1f;
+ var[IMM] = inst&0xffff;
+
+ exec_J(state, var);
+ } else {
+ var[OPCODE] = inst >> 26;
+ var[MEM] = inst&0x3ffffff;
+
+ exec_I(state, var);
+ }
+
+ return mips_Success;
+}
+
+void exec_R(mips_cpu_h state, uint32_t var[8]) {
+ if((var[FUNC]&0xf0) == 0x20 && (var[FUNC]&0xf) < 4) {
+ add_sub(state, var);
+ }
+}
+
+void exec_J(mips_cpu_h state, uint32_t var[8]) {
+ //TODO
+}
+
+void exec_I(mips_cpu_h state, uint32_t var[8]) {
+ //TODO
+}
+
+void add_sub(mips_cpu_h state, uint32_t var[8]) {
+ if((var[FUNC]&0xf) < 2) {
+ state->regs[var[REG_D]] = state->regs[var[REG_S]] +
+ state->regs[var[REG_T]];
+ state->overflow = 0;
+ if((var[FUNC]&0xf) == 0) {
+ state->overflow = 1;
+ }
+ }
+}