Browse Source

Add secondary opcodes and error handling

master
Forest Belton 2 years ago
parent
commit
0dc36c6bc6
6 changed files with 85 additions and 18 deletions
  1. +2
    -1
      Makefile
  2. +31
    -0
      include/insn.h
  3. +6
    -0
      include/util.h
  4. +0
    -17
      src/cpu.c
  5. +31
    -0
      src/insn.c
  6. +15
    -0
      src/util.c

+ 2
- 1
Makefile View File

@ -1,5 +1,6 @@
CFLAGS ?= -Wall -Wextra -Iinclude CFLAGS ?= -Wall -Wextra -Iinclude
HFILES := $(shell find include -type f -name '*.h')
CFILES := $(shell find src -type f -name '*.c') CFILES := $(shell find src -type f -name '*.c')
OFILES := $(CFILES:%.c=%.o) OFILES := $(CFILES:%.c=%.o)
@ -8,7 +9,7 @@ OFILES := $(CFILES:%.c=%.o)
psxc: $(OFILES) psxc: $(OFILES)
$(CC) $(OFILES) -o $@ $(CC) $(OFILES) -o $@
%.o: %.c
%.o: %.c $(HFILES)
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
clean: clean:

+ 31
- 0
include/insn.h View File

@ -1,6 +1,8 @@
#ifndef PSXC_INSN_H_ #ifndef PSXC_INSN_H_
#define PSXC_INSN_H_ #define PSXC_INSN_H_
#include "cpu.h"
#include <stdint.h> #include <stdint.h>
typedef enum { typedef enum {
@ -52,10 +54,39 @@ static inline op_primary_t extract_primary_op(uint32_t insn) {
typedef enum { typedef enum {
SLL = 0x00, 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; } op_secondary_t;
static inline op_secondary_t extract_secondary_op(uint32_t insn) { static inline op_secondary_t extract_secondary_op(uint32_t insn) {
return (insn >> 0) & 0x3f; return (insn >> 0) & 0x3f;
} }
void insn_execute(cpu_t *cpu, uint32_t insn);
#endif #endif

+ 6
- 0
include/util.h View File

@ -0,0 +1,6 @@
#ifndef PSXC_UTIL_H_
#define PSXC_UTIL_H_
void fatal(const char *fmt, ...);
#endif

+ 0
- 17
src/cpu.c View File

@ -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);
}

+ 31
- 0
src/insn.c View File

@ -0,0 +1,31 @@
#include "insn.h"
#include "cpu.h"
#include "util.h"
#include <stddef.h>
#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);
}

+ 15
- 0
src/util.c View File

@ -0,0 +1,15 @@
#include "util.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
void fatal(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(EXIT_FAILURE);
}

Loading…
Cancel
Save