diff options
| author | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2025-02-13 18:00:17 +1100 |
|---|---|---|
| committer | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2025-02-13 18:00:17 +1100 |
| commit | 98cef5e9a772602d42acfcf233838c760424db9a (patch) | |
| tree | 5277fa1d7cc0a69a0f166fcbf10fd320f345f049 /comp1521/smips/instr.c | |
initial commit
Diffstat (limited to 'comp1521/smips/instr.c')
| -rw-r--r-- | comp1521/smips/instr.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/comp1521/smips/instr.c b/comp1521/smips/instr.c new file mode 100644 index 0000000..645fbae --- /dev/null +++ b/comp1521/smips/instr.c @@ -0,0 +1,160 @@ +#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; +} |
