#include "instr.h" // Gets the immediate bits, clearing others and shifting right. uint32_t get_i(const uint32_t instr) { return instr & IMMEDIATE_BITS; } // Gets the pattern bits, clearing others and shifting right. uint32_t get_p(const uint32_t instr) { return (instr & PATTERN_BITS) >> 26; } // Gets the d bits, clearing others and shifting right. uint32_t get_d(const uint32_t instr) { return (instr & D_BITS) >> 11; } // Gets the t bits, clearing others and shifting right. uint32_t get_t(const uint32_t instr) { return (instr & T_BITS) >> 16; } // Gets the s bits, clearing others and shifting right. uint32_t get_s(const uint32_t instr) { return (instr & S_BITS) >> 21; } // $d = $s + $t. void mips_add(const uint32_t instr, uint32_t registers[32]) { int d = (int16_t)get_d(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); registers[d] = registers[s] + registers[t]; } // $d = $s - $t. void mips_sub(const uint32_t instr, uint32_t registers[32]) { int d = (int16_t)get_d(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); registers[d] = registers[s] - registers[t]; } // $d = $s & $t. void mips_and(const uint32_t instr, uint32_t registers[32]) { int d = (int16_t)get_d(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); registers[d] = registers[s] & registers[t]; } // $d = $s | $t. void mips_or(const uint32_t instr, uint32_t registers[32]) { int d = (int16_t)get_d(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); registers[d] = registers[s] | registers[t]; } // $d = ($s < $t). void mips_slt(const uint32_t instr, uint32_t registers[32]) { int d = (int16_t)get_d(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); registers[d] = registers[s] < registers[t]; } // $d = $s * $t. void mips_mul(const uint32_t instr, uint32_t registers[32]) { int d = (int16_t)get_d(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); registers[d] = registers[s] * registers[t]; } // If ($s == $t) PC += i. void mips_beq(FILE *const fptr, const uint32_t instr, uint32_t registers[32]) { int i = (int16_t)get_i(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); if (registers[s] != registers[t]) { return; } if (i >= 0) { for (int j = 0; j <= i; ++j) { get_next_instruction(fptr); } } else { for (int j = 0; j <= -1 * i; ++j) { goto_previous_instruction(fptr); } } } // If ($s != $t) PC += i. void mips_bne(FILE *const fptr, const uint32_t instr, uint32_t registers[32]) { int i = (int16_t)get_i(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); if (registers[s] == registers[t]) { return; } if (i >= 0) { for (int j = 0; j <= i; ++j) { get_next_instruction(fptr); } } else { for (int j = 0; j <= -1 * i; ++j) { goto_previous_instruction(fptr); } } } // $t = $s + i. void mips_addi(const uint32_t instr, uint32_t registers[32]) { int i = (int16_t)get_i(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); registers[t] = registers[s] + (uint32_t)i; } // $t = $s < i. void mips_slti(const uint32_t instr, uint32_t registers[32]) { int i = (int16_t)get_i(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); registers[t] = registers[s] < (uint32_t)i; } // $t = $s & i. void mips_andi(const uint32_t instr, uint32_t registers[32]) { int i = (int16_t)get_i(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); registers[t] = registers[s] & (uint32_t)i; } // $t = $s | i. void mips_ori(const uint32_t instr, uint32_t registers[32]) { int i = (int16_t)get_i(instr); int t = (int16_t)get_t(instr); int s = (int16_t)get_s(instr); registers[t] = registers[s] | (uint32_t)i; } // $t = i << 16u. void mips_lui(const uint32_t instr, uint32_t registers[32]) { int i = (int16_t)get_i(instr); int t = (int16_t)get_t(instr); registers[t] = (uint32_t)i << 16u; } // Syscall function which returns non-zero if execution should stop. int mips_syscall(uint32_t registers[32]) { uint32_t v0 = registers[2]; uint32_t a0 = registers[4]; switch (v0) { case 1: printf("%u", a0); break; case 11: printf("%c", a0 & 0xFFu); break; case 10: return 1; default: printf("Unknown system call: %d\n", v0); return 1; } return 0; }