Browse Source

Parse boot ROM header

master
Forest Belton 5 months ago
parent
commit
5fd3f0adc8
8 changed files with 147 additions and 23 deletions
  1. +1
    -0
      .gitignore
  2. +8
    -0
      include/boot.h
  3. +0
    -2
      include/cpu.h
  4. +33
    -9
      include/insn.h
  5. +48
    -0
      src/boot.c
  6. +15
    -6
      src/insn.c
  7. +22
    -1
      src/main.c
  8. +20
    -5
      src/util.c

+ 1
- 0
.gitignore View File

@ -1,2 +1,3 @@
psxc
*.o
boot.rom

+ 8
- 0
include/boot.h View File

@ -0,0 +1,8 @@
#ifndef PSXC_BOOT_H_
#define PSXC_BOOT_H_
#include "util.h"
void boot_psx_prgm(byte_arr_t *prgm);
#endif

+ 0
- 2
include/cpu.h View File

@ -10,6 +10,4 @@ typedef struct {
uint32_t pc;
} cpu_t;
typedef void (*cpu_insn_handler)(cpu_t *, uint32_t);
#endif

+ 33
- 9
include/insn.h View File

@ -5,7 +5,8 @@
#include <stdint.h>
typedef enum {
typedef enum
{
SPECIAL = 0x00,
BCONDZ = 0x01,
J = 0x02,
@ -48,11 +49,8 @@ typedef enum {
SWC3 = 0x3b,
} op_primary_t;
static inline op_primary_t extract_primary_op(uint32_t insn) {
return (insn >> 26) & 0x3f;
}
typedef enum {
typedef enum
{
SLL = 0x00,
SRL = 0x02,
SRA = 0x03,
@ -83,9 +81,35 @@ typedef enum {
SLTU = 0x2b,
} op_secondary_t;
static inline op_secondary_t extract_secondary_op(uint32_t insn) {
return (insn >> 0) & 0x3f;
}
typedef union
{
struct __attribute__((packed))
{
uint8_t op : 6;
uint16_t rs : 5;
uint8_t rt : 5;
uint8_t rd : 5;
uint16_t imm5 : 5;
uint8_t tail : 6;
} insn_reg;
struct __attribute__((packed))
{
uint8_t op : 6;
uint32_t comment : 20;
uint8_t tail : 6;
} insn_call;
struct __attribute__((packed))
{
uint8_t op : 6;
uint16_t rs : 5;
uint8_t rt : 5;
uint16_t imm : 16;
} insn_imm;
} insn_t;
typedef void (*cpu_insn_handler)(cpu_t *, insn_t);
void insn_execute(cpu_t *cpu, uint32_t insn);

+ 48
- 0
src/boot.c View File

@ -0,0 +1,48 @@
#include "boot.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static const uint8_t MAGIC[0x10] = "PS-X EXE";
static const uint8_t RESERVED[0x10] = {0};
typedef struct __attribute__((packed))
{
uint32_t pc;
uint32_t gp;
uint32_t addr_dest;
uint32_t size_file;
uint32_t addr_data;
uint32_t size_data;
uint32_t addr_bss;
uint32_t size_bss;
} psx_header_t;
psx_header_t parse_psx_header(byte_arr_t *prgm)
{
psx_header_t header;
// TODO: Convert asserts into recoverable error
assert(prgm->size >= 0x800);
assert(memcmp(MAGIC, prgm->data, sizeof MAGIC) == 0);
memcpy(&header, &prgm->data[sizeof MAGIC], sizeof header);
assert(header.size_file == prgm->size - 0x800);
assert(memcmp(RESERVED, &prgm->data[0x38], sizeof RESERVED) == 0);
return header;
}
void boot_psx_prgm(byte_arr_t *prgm)
{
psx_header_t header = parse_psx_header(prgm);
printf("pc = %08x\n", header.pc);
printf("gp = %08x\n", header.gp);
printf("data = %08x (%u bytes)\n", header.addr_data, header.size_data);
printf("bss = %08x (%u bytes)\n", header.addr_bss, header.size_bss);
printf("dest = %08x\n", header.addr_dest);
printf("size = %08x (%u bytes)\n", header.size_file, header.size_file);
}

+ 15
- 6
src/insn.c View File

@ -9,22 +9,31 @@
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);
static inline op_primary_t extract_primary_op(uint32_t insn) {
return (insn >> 26) & 0x3f;
}
static inline op_secondary_t extract_secondary_op(uint32_t insn) {
return (insn >> 0) & 0x3f;
}
void insn_execute(cpu_t *cpu, uint32_t raw_insn) {
const op_primary_t op = extract_primary_op(raw_insn);
const insn_t insn = *(insn_t *)&raw_insn;
if (op == SPECIAL) {
const op_secondary_t op2 = extract_secondary_op(insn);
const op_secondary_t op2 = extract_secondary_op(raw_insn);
if (op2 > TABLE_SIZE || secondary_insn_handler[op2] == NULL) {
fatal("unsupported instruction: insn=%08x, op=%02x, op2=%02x", insn, op,
op2);
fatal("unsupported instruction: insn=%08x, op=%02x, op2=%02x", raw_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);
fatal("unsupported instruction: insn=%08x, op=%02x", raw_insn, op);
}
primary_insn_handler[op](cpu, insn);

+ 22
- 1
src/main.c View File

@ -1 +1,22 @@
int main() { return 0; }
#include "boot.h"
#include "insn.h"
#include "util.h"
#include <stdio.h>
int main()
{
// uint32_t x = 0xffcdefab;
// const insn_t insn = *(insn_t *)&x;
// printf("%u", insn.insn_reg.op);
byte_arr_t *prgm = read_file("boot.rom");
if (prgm == NULL)
{
fatal("couldn't load boot.rom");
}
boot_psx_prgm(prgm);
return 0;
}

+ 20
- 5
src/util.c View File

@ -4,28 +4,40 @@
#include <stdio.h>
#include <stdlib.h>
void fatal(const char *fmt, ...) {
void fatal(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
exit(EXIT_FAILURE);
}
byte_arr_t *read_file(const char *filepath) {
byte_arr_t *read_file(const char *filepath)
{
FILE *fp = fopen(filepath, "rb");
byte_arr_t *arr = NULL;
if (fp == NULL)
{
fprintf(stderr, "%s: ", filepath);
perror("could not open");
goto end;
}
fseek(fp, 0, SEEK_END);
const long size = ftell(fp);
if (size < 0) {
if (size < 0)
{
goto end;
}
arr = malloc(sizeof *arr + size);
if (arr == NULL) {
if (arr == NULL)
{
goto end;
}
@ -35,6 +47,9 @@ byte_arr_t *read_file(const char *filepath) {
fread(arr->data, 1, size, fp);
end:
fclose(fp);
if (fp != NULL)
{
fclose(fp);
}
return arr;
}

Loading…
Cancel
Save