Browse Source

Begin to execute program

master
Forest Belton 1 year ago
parent
commit
558926bc90
8 changed files with 160 additions and 61 deletions
  1. +14
    -0
      include/boot.h
  2. +16
    -2
      include/cpu.h
  3. +1
    -29
      include/insn.h
  4. +13
    -0
      include/psx.h
  5. +48
    -14
      src/boot.c
  6. +29
    -0
      src/cpu.c
  7. +38
    -16
      src/insn.c
  8. +1
    -0
      src/main.c

+ 14
- 0
include/boot.h View File

@ -3,6 +3,20 @@
#include "util.h"
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;
uint32_t sp;
uint32_t fp;
} psx_header_t;
void boot_psx_prgm(byte_arr_t *prgm);
#endif

+ 16
- 2
include/cpu.h View File

@ -3,11 +3,25 @@
#include <stdint.h>
#define SP(cpu) ((cpu)->regs[29])
#define REG_GP 28 // Global pointer
#define REG_SP 29 // Stack pointer
#define REG_FP 30 // Frame pointer
typedef struct {
#define MAIN_RAM_SIZE 0x200000
#define SCRATCHPAD_BASE 0x1F800000
#define SCRATCHPAD_END 0x1F8003FF
#define SCRATCHPAD_SIZE (SCRATCHPAD_END - SCRATCHPAD_BASE + 1)
typedef struct
{
uint32_t regs[32];
uint32_t pc;
uint32_t main_ram[MAIN_RAM_SIZE];
uint32_t sratchpad_ram[SCRATCHPAD_SIZE];
} cpu_t;
void cpu_write32(cpu_t *cpu, uint32_t addr, uint32_t x);
uint32_t cpu_read32(cpu_t *cpu, uint32_t addr);
#endif

+ 1
- 29
include/insn.h View File

@ -81,35 +81,7 @@ typedef enum
SLTU = 0x2b,
} op_secondary_t;
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);
typedef void (*cpu_insn_handler)(cpu_t *, uint32_t);
void insn_execute(cpu_t *cpu, uint32_t insn);

+ 13
- 0
include/psx.h View File

@ -0,0 +1,13 @@
#ifndef PSXC_PSX_H_
#define PSXC_PSX_H_
#include "boot.h"
#include "cpu.h"
typedef struct
{
psx_header_t header;
cpu_t *cpu;
} psx_t;
#endif

+ 48
- 14
src/boot.c View File

@ -1,4 +1,7 @@
#include "boot.h"
#include "cpu.h"
#include "insn.h"
#include "psx.h"
#include <assert.h>
#include <stdlib.h>
@ -8,23 +11,12 @@
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(sizeof header == 0x38 - 0x10);
assert(prgm->size >= 0x800);
assert(memcmp(MAGIC, prgm->data, sizeof MAGIC) == 0);
memcpy(&header, &prgm->data[sizeof MAGIC], sizeof header);
@ -35,14 +27,56 @@ psx_header_t parse_psx_header(byte_arr_t *prgm)
return header;
}
uint32_t translate_addr(uint32_t addr)
{
if (addr >= 0xA0000000)
{
addr = addr - 0xA0000000;
}
else if (addr >= 0x80000000)
{
addr = addr - 0x80000000;
}
return addr;
}
void boot_psx_prgm(byte_arr_t *prgm)
{
printf("parsing program header\n");
psx_header_t header = parse_psx_header(prgm);
printf("pc = %08x\n", header.pc);
printf("gp = %08x\n", header.gp);
printf("=== header ===\n");
printf("pc = %08x, gp = %08x\n", header.pc, header.gp);
printf("sp = %08x, fp = %08x\n", header.sp, header.fp);
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);
cpu_t *cpu = malloc(sizeof *cpu);
uint32_t start = translate_addr(header.addr_dest);
assert(start + header.size_file < MAIN_RAM_SIZE);
memcpy(&cpu->main_ram[start], &prgm->data[0x800], header.size_file);
cpu->pc = header.pc;
cpu->regs[REG_GP] = header.gp;
cpu->regs[REG_SP] = header.sp;
cpu->regs[REG_FP] = header.fp;
psx_t psx = {header, cpu};
const int max_insns = 1;
for (int i = 0; i < max_insns; i++)
{
printf("=== insn ===\n");
printf("pc = %08x\n", psx.cpu->pc);
const uint32_t insn = cpu_read32(cpu, psx.cpu->pc);
insn_execute(cpu, insn);
psx.cpu->pc += 1;
}
}

+ 29
- 0
src/cpu.c View File

@ -0,0 +1,29 @@
#include "cpu.h"
static uint32_t translate_addr(uint32_t addr)
{
if (addr >= 0xA0000000)
{
addr = addr - 0xA0000000;
}
else if (addr >= 0x80000000)
{
addr = addr - 0x80000000;
}
return addr;
}
void cpu_write32(cpu_t *cpu, uint32_t addr, uint32_t x)
{
printf("WRITE: %08x to %08x\n", x, addr);
addr = translate_addr(addr);
cpu->main_ram[addr] = x;
}
uint32_t cpu_read32(cpu_t *cpu, uint32_t addr)
{
printf("READ: %08x\n", addr);
addr = translate_addr(addr);
return cpu->main_ram[addr];
}

+ 38
- 16
src/insn.c View File

@ -3,38 +3,60 @@
#include "util.h"
#include <stddef.h>
#include <stdio.h>
#define TABLE_SIZE 0x34
static cpu_insn_handler primary_insn_handler[TABLE_SIZE] = {NULL};
void insn_lw(cpu_t *cpu, uint32_t insn);
static cpu_insn_handler primary_insn_handler[TABLE_SIZE] = {
[LW] = insn_lw,
};
static cpu_insn_handler secondary_insn_handler[TABLE_SIZE] = {NULL};
static inline op_primary_t extract_primary_op(uint32_t insn) {
return (insn >> 26) & 0x3f;
}
#define BITS(x, start, len) (((x) >> (start)) & ((1 << (len)) - 1))
static inline op_secondary_t extract_secondary_op(uint32_t insn) {
return (insn >> 0) & 0x3f;
}
#define OP(insn) BITS(insn, 26, 6)
#define RS(insn) BITS(insn, 21, 5)
#define RT(insn) BITS(insn, 16, 5)
#define RD(insn) BITS(insn, 11, 5)
#define COMMENT(insn) BITS(insn, 6, 20)
#define IMM5(insn) BITS(insn, 6, 5)
#define OP2(insn) BITS(insn, 0, 6)
#define IMM(insn) BITS(insn, 0, 16)
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;
void insn_execute(cpu_t *cpu, uint32_t insn)
{
const op_primary_t op = OP(insn);
if (op == SPECIAL) {
const op_secondary_t op2 = extract_secondary_op(raw_insn);
if (op == SPECIAL)
{
const op_secondary_t op2 = OP2(insn);
if (op2 > TABLE_SIZE || secondary_insn_handler[op2] == NULL) {
fatal("unsupported instruction: insn=%08x, op=%02x, op2=%02x", raw_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", raw_insn, op);
if (op > TABLE_SIZE || primary_insn_handler[op] == NULL)
{
fatal("unsupported instruction: insn=%08x, op=%02x", insn, op);
}
primary_insn_handler[op](cpu, insn);
}
void insn_lw(cpu_t *cpu, uint32_t insn)
{
const uint8_t rs = RS(insn);
const uint8_t rt = RT(insn);
const uint16_t imm = IMM(insn);
printf("LW R%u, [R%u + %x]\n", rt, rs, imm);
cpu->regs[rt] = cpu_read32(cpu, cpu->regs[rs] + imm);
}

+ 1
- 0
src/main.c View File

@ -10,6 +10,7 @@ int main()
// const insn_t insn = *(insn_t *)&x;
// printf("%u", insn.insn_reg.op);
printf("loading boot rom\n");
byte_arr_t *prgm = read_file("boot.rom");
if (prgm == NULL)
{

Loading…
Cancel
Save