From 0dc36c6bc645635f28c0a4951b804f64609d5d6b Mon Sep 17 00:00:00 2001 From: Forest Belton <65484+forestbelton@users.noreply.github.com> Date: Wed, 23 Jun 2021 15:21:26 -0400 Subject: [PATCH] Add secondary opcodes and error handling --- Makefile | 3 ++- include/insn.h | 31 +++++++++++++++++++++++++++++++ include/util.h | 6 ++++++ src/cpu.c | 17 ----------------- src/insn.c | 31 +++++++++++++++++++++++++++++++ src/util.c | 15 +++++++++++++++ 6 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 include/util.h delete mode 100644 src/cpu.c create mode 100644 src/insn.c create mode 100644 src/util.c diff --git a/Makefile b/Makefile index 5078efc..780303a 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ CFLAGS ?= -Wall -Wextra -Iinclude +HFILES := $(shell find include -type f -name '*.h') CFILES := $(shell find src -type f -name '*.c') OFILES := $(CFILES:%.c=%.o) @@ -8,7 +9,7 @@ OFILES := $(CFILES:%.c=%.o) psxc: $(OFILES) $(CC) $(OFILES) -o $@ -%.o: %.c +%.o: %.c $(HFILES) $(CC) $(CFLAGS) -c $< -o $@ clean: diff --git a/include/insn.h b/include/insn.h index 611c231..a35cbf3 100644 --- a/include/insn.h +++ b/include/insn.h @@ -1,6 +1,8 @@ #ifndef PSXC_INSN_H_ #define PSXC_INSN_H_ +#include "cpu.h" + #include typedef enum { @@ -52,10 +54,39 @@ static inline op_primary_t extract_primary_op(uint32_t insn) { typedef enum { SLL = 0x00, + SRL = 0x02, + SRA = 0x03, + SLLV = 0x04, + SRLV = 0x06, + SRAV = 0x07, + JR = 0x08, + JALR = 0x09, + SYSCALL = 0x0c, + BREAK = 0x0d, + MFHI = 0x10, + MTHI = 0x11, + MFLO = 0x12, + MTLO = 0x13, + MULT = 0x18, + MULTU = 0x19, + DIV = 0x1a, + DIVU = 0x1b, + ADD = 0x20, + ADDU = 0x21, + SUB = 0x22, + SUBU = 0x23, + AND = 0x24, + OR = 0x25, + XOR = 0x26, + NOR = 0x27, + SLT = 0x2a, + SLTU = 0x2b, } op_secondary_t; static inline op_secondary_t extract_secondary_op(uint32_t insn) { return (insn >> 0) & 0x3f; } +void insn_execute(cpu_t *cpu, uint32_t insn); + #endif diff --git a/include/util.h b/include/util.h new file mode 100644 index 0000000..11061bb --- /dev/null +++ b/include/util.h @@ -0,0 +1,6 @@ +#ifndef PSXC_UTIL_H_ +#define PSXC_UTIL_H_ + +void fatal(const char *fmt, ...); + +#endif diff --git a/src/cpu.c b/src/cpu.c deleted file mode 100644 index d3fac3e..0000000 --- a/src/cpu.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "cpu.h" -#include "insn.h" - -static cpu_insn_handler primary_insn_handler[0x34] = {}; -static cpu_insn_handler secondary_insn_handler[0x34] = {}; - -void cpu_execute_insn(cpu_t *cpu, uint32_t insn) { - const op_primary_t op = extract_primary_op(insn); - - if (op == SPECIAL) { - const op_secondary_t op2 = extract_secondary_op(insn); - secondary_insn_handler[op2](cpu, insn); - return; - } - - primary_insn_handler[op](cpu, insn); -} diff --git a/src/insn.c b/src/insn.c new file mode 100644 index 0000000..e3491d4 --- /dev/null +++ b/src/insn.c @@ -0,0 +1,31 @@ +#include "insn.h" +#include "cpu.h" +#include "util.h" + +#include + +#define TABLE_SIZE 0x34 + +static cpu_insn_handler primary_insn_handler[TABLE_SIZE] = {NULL}; +static cpu_insn_handler secondary_insn_handler[TABLE_SIZE] = {NULL}; + +void insn_execute(cpu_t *cpu, uint32_t insn) { + const op_primary_t op = extract_primary_op(insn); + + if (op == SPECIAL) { + const op_secondary_t op2 = extract_secondary_op(insn); + + if (op2 > TABLE_SIZE || secondary_insn_handler[op2] == NULL) { + fatal("unsupported instruction: insn=%08x, op=%02x, op2=%02x", insn, op, + op2); + } + + secondary_insn_handler[op2](cpu, insn); + } + + if (op > TABLE_SIZE || primary_insn_handler[op] == NULL) { + fatal("unsupported instruction: insn=%08x, op=%02x", insn, op); + } + + primary_insn_handler[op](cpu, insn); +} diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..59c0b3e --- /dev/null +++ b/src/util.c @@ -0,0 +1,15 @@ +#include "util.h" + +#include +#include +#include + +void fatal(const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + exit(EXIT_FAILURE); +}