commit e9dd53c3268ecb0a7177545d5abe7cce6e0cbb34
parent fc19c67b4fd962219973c677cbf399163b142823
Author: root <root@fif>
Date: Sat, 30 Mar 2024 17:03:19 +0000
Made it through gpu endless loop. Now few ops are left
Diffstat:
10 files changed, 454 insertions(+), 174 deletions(-)
diff --git a/build.sh b/build.sh
@@ -1 +1 @@
-cc -static -std=c99 -O3 -Wall -pedantic -g src/*.c -o bin/ultimecia
+c++ -Wall -Wpedantic -static -O3 -Wall -pedantic -g src/*.c -o bin/ultimecia
diff --git a/src/cpu.c b/src/cpu.c
@@ -10,20 +10,26 @@
CPU*
new_cpu(Interconnect* inter) {
CPU* cpu = (CPU*)malloc(sizeof(CPU));
+
cpu->pc = 0xBFC00000;
- cpu->sr = 0x0;
- cpu->hi = 0xdeaddead;
- cpu->lo = 0xdeaddead;
+ cpu->next_pc = cpu->pc + 4;
+ cpu->current_pc = 0;
+
+ cpu->cause = 0x0; cpu->epc = 0x0; cpu->sr = 0x0;
+ cpu->hi = 0xdeaddead;
+ cpu->lo = 0xdeaddead;
+ cpu->branch = 0;
+ cpu->delay_slot = 0;
cpu->inter = inter;
cpu->load._0 = 0; cpu->load._1 = 0;
- cpu->next_instruction = new_instr(0x0); /* NOP */
+ cpu->next_instruction = new_instr(0); /* NOP */
memset(cpu->regs, 0, sizeof(cpu->regs));
memset(cpu->out_regs, 0, sizeof(cpu->out_regs));
return cpu;
}
u32 CPU_load32(CPU* cpu, u32 addr) { return INTER_load32(cpu->inter, addr); }
-//u16 CPU_load16(CPU* cpu, u16 addr) { return INTER_load16(cpu->inter, addr); }
+u16 CPU_load16(CPU* cpu, u32 addr) { return INTER_load16(cpu->inter, addr); }
u8 CPU_load8(CPU* cpu, u32 addr) { return INTER_load8(cpu->inter, addr); }
void CPU_store32(CPU* cpu, u32 addr, u32 val) { INTER_store32(cpu->inter, addr, val); }
@@ -44,6 +50,31 @@ reg(CPU* cpu, u32 reg)
}
void
+exception(CPU* cpu, EXCEPTION cause)
+{
+ u32 handler, mode;
+
+ handler = ((cpu->sr & (1 << 22)) != 0) ? 0xBFC00180 : 0x80000080;
+ mode = cpu->sr & 0x3f;
+ cpu->sr &= ~0x3f;
+ cpu->sr |= (mode << 2) & 0x3f;
+ cpu->cause = (u32)cause << 2;
+ cpu->epc = cpu->current_pc;
+
+ if (cpu->delay_slot)
+ {
+ cpu->epc -= 4;
+ cpu->cause |= 1 << 31;
+ }
+
+ cpu->pc = handler;
+ cpu->next_pc = cpu->pc + 4;
+
+ return;
+}
+
+
+void
op_lui(CPU* cpu, instruction* i)
{
u32 v = i->imm << 16;
@@ -59,6 +90,14 @@ op_or(CPU* cpu, instruction* i)
}
void
+op_nor(CPU* cpu, instruction* i)
+{
+ u32 v;
+ v = !(reg(cpu, i->s) | reg(cpu, i->t));
+ set_reg(cpu, i->d, v);
+}
+
+void
op_and(CPU* cpu, instruction* i)
{
u32 v;
@@ -91,7 +130,14 @@ op_sw(CPU* cpu, instruction* i)
addr = reg(cpu, s) + imm_se;
v = reg(cpu, t);
- CPU_store32(cpu, addr, v);
+ if ((addr % 4) == 0)
+ {
+ CPU_store32(cpu, addr, v);
+ }
+ else
+ {
+ exception(cpu, E_STORE_ADRESS_ERROR);
+ }
}
void
@@ -111,7 +157,17 @@ op_sh(CPU* cpu, instruction* i)
addr = reg(cpu, s) + imm_se;
v = reg(cpu, t);
- CPU_store16(cpu, addr, (u16)v);
+
+ if ((addr % 2) == 0)
+ {
+ CPU_store16(cpu, addr, (u16)v);
+ }
+ else
+ {
+ exception(cpu, E_STORE_ADRESS_ERROR);
+ }
+
+
}
void
@@ -149,6 +205,24 @@ op_sll(CPU* cpu, instruction* i)
}
void
+op_srlv(CPU* cpu, instruction* i)
+{
+ u32 v;
+
+ v = reg(cpu, i->t) >> (reg(cpu, i->s) & 0x1f);
+ set_reg(cpu, i->d, v);
+}
+
+void
+op_sllv(CPU* cpu, instruction* i)
+{
+ u32 v;
+
+ v = reg(cpu, i->t) << (reg(cpu, i->s) & 0x1f);
+ set_reg(cpu, i->d, v);
+}
+
+void
op_addiu(CPU* cpu, instruction* i)
{
u32 v;
@@ -169,22 +243,35 @@ op_addi(CPU* cpu, instruction* i)
if(checked_addi32(v, imm_se, &res))
set_reg(cpu, i->t, res);
else
- fprintf(stderr, "ADDI OVERFLOW!"), exit(EXIT_FAILURE);
+ exception(cpu, E_OVERFLOW);
}
void
op_j(CPU* cpu, instruction* i)
{
- cpu->pc = (cpu->pc & 0xf0000000) | (i->imm_jump << 2);
+ cpu->next_pc = (cpu->next_pc & 0xf0000000) | (i->imm_jump << 2);
+ cpu->branch = 1;
+}
+
+void
+op_jal(CPU* cpu, instruction* i)
+{
+ set_reg(cpu, 31, cpu->next_pc);
+ op_j(cpu, i);
}
-void op_jal(CPU* cpu, instruction* i) { set_reg(cpu, 31, cpu->pc); op_j(cpu, i); }
-void op_jr(CPU* cpu, instruction* i) { cpu->pc = reg(cpu, i->s); }
+void
+op_jr(CPU* cpu, instruction* i)
+{
+ cpu->next_pc = reg(cpu, i->s);
+ cpu->branch = 1;
+}
void op_jalr(CPU* cpu, instruction* i)
{
- set_reg(cpu, i->d, cpu->pc);
- cpu->pc = reg(cpu, i->s);
+ set_reg(cpu, i->d, cpu->next_pc);
+ cpu->next_pc = reg(cpu, i->s);
+ cpu->branch = 1;
}
void
@@ -232,8 +319,12 @@ op_mfc0(CPU* cpu, instruction* i)
cpu->load._1 = cpu->sr;
break;
case 13:
- fprintf(stderr, "Unhandled read from CAUSE register\n");
- exit(EXIT_FAILURE);
+ cpu->load._0 = i->t;
+ cpu->load._1 = cpu->cause;
+ break;
+ case 14:
+ cpu->load._0 = i->t;
+ cpu->load._1 = cpu->epc;
break;
default:
fprintf(stderr, "Unhandled read from cop0r%d\n", cop_r);
@@ -242,19 +333,37 @@ op_mfc0(CPU* cpu, instruction* i)
}
void
+op_rfe(CPU* cpu, instruction* i)
+{
+ u32 mode;
+
+ if ((i->_0 & 0x3f) != 0x10)
+ {
+ fprintf(stderr, "Invalid cop0 instruction %08X\n", i->_0);
+ exit(EXIT_FAILURE);
+ }
+
+ mode = cpu->sr & 0x3f;
+ cpu->sr &= ~0x3f;
+ cpu->sr |= mode >> 2;
+}
+
+void
op_cop0(CPU* cpu, instruction* i)
{
switch (i->cop_opcode) {
case 0x00: op_mfc0(cpu, i); break;
case 0x04: op_mtc0(cpu, i); break;
- default: printf("Unhandled cop0 instruction %08X", i->_0); exit(EXIT_FAILURE);
+ case 0x10: op_rfe(cpu, i); break;
+ default: printf("Unhandled cop0 instruction %08X\n", i->_0); exit(EXIT_FAILURE);
}
}
void
branch(CPU* cpu, u32 offset)
{
- cpu->pc += (offset << 2) - 4;
+ cpu->next_pc += (offset << 2) - 4;
+ cpu->branch = 1;
}
void
@@ -322,10 +431,20 @@ op_lw(CPU* cpu, instruction* i)
u32 v, addr;
addr = reg(cpu, i->s) + i->imm_se;
- v = CPU_load32(cpu, addr);
- cpu->load._0 = i->t;
- cpu->load._1 = v;
+ if ((addr % 4) == 0)
+ {
+ v = CPU_load32(cpu, addr);
+
+ cpu->load._0 = i->t;
+ cpu->load._1 = v;
+ }
+ else
+ {
+ exception(cpu, E_STORE_ADRESS_ERROR);
+ }
+
+
}
void
@@ -354,6 +473,47 @@ op_lbu(CPU* cpu, instruction* i)
}
void
+op_lh(CPU* cpu, instruction* i)
+{
+ u32 addr;
+ i16 v;
+
+ addr = reg(cpu, i->s) + i->imm_se;
+
+ if (addr % 2 == 0)
+ {
+ v = (i16)CPU_load16(cpu, addr);
+
+ cpu->load._0 = i->t;
+ cpu->load._1 = (u32)v;
+ }
+ else
+ {
+ exception(cpu, E_LOAD_ADRESS_ERROR);
+ }
+}
+
+void
+op_lhu(CPU* cpu, instruction* i)
+{
+ u32 v, addr;
+
+ addr = reg(cpu, i->s) + i->imm_se;
+
+ if (addr % 2 == 0)
+ {
+ v = CPU_load16(cpu, addr);
+
+ cpu->load._0 = i->t;
+ cpu->load._1 = (u32)v;
+ }
+ else
+ {
+ exception(cpu, E_LOAD_ADRESS_ERROR);
+ }
+}
+
+void
op_slt(CPU* cpu, instruction* i)
{
u32 v;
@@ -399,7 +559,7 @@ op_add(CPU* cpu, instruction* i)
if(checked_addi32(s, t, &res))
set_reg(cpu, i->d, (u32)res);
else
- fprintf(stderr, "ADD OVERFLOW!"), exit(EXIT_FAILURE);
+ exception(cpu, E_OVERFLOW);
}
void
@@ -417,7 +577,7 @@ op_subu(CPU* cpu, instruction* i)
{
u32 v;
- v = reg(cpu, i->t) - reg(cpu, i->s);
+ v = reg(cpu, i->s) - reg(cpu, i->t);
set_reg(cpu, i->d, v);
}
@@ -439,6 +599,15 @@ op_sra(CPU* cpu, instruction* i)
}
void
+op_srav(CPU* cpu, instruction* i)
+{
+ i32 v;
+
+ v = (i32)reg(cpu, i->t) >> (reg(cpu, i->s) & 0x1f);
+ set_reg(cpu, i->d, (u32)v);
+}
+
+void
op_srl(CPU* cpu, instruction* i)
{
u32 v;
@@ -493,6 +662,22 @@ op_divu(CPU* cpu, instruction* i)
cpu->lo = (n / d);
}
}
+
+void
+op_multu(CPU* cpu, instruction* i)
+{
+ u64 a, b, v;
+
+ a = (u64)reg(cpu, i->s);
+ b = (u64)reg(cpu, i->t);
+
+ v = a * b;
+
+ cpu->hi = (u32)(v >> 32);
+ cpu->lo = (u32)v;
+}
+
+
void
op_mflo(CPU* cpu, instruction* i)
{
@@ -500,12 +685,30 @@ op_mflo(CPU* cpu, instruction* i)
}
void
+op_mtlo(CPU* cpu, instruction* i)
+{
+ cpu->lo = reg(cpu, i->s);
+}
+
+void
op_mfhi(CPU* cpu, instruction* i)
{
set_reg(cpu, i->d, cpu->hi);
}
void
+op_mthi(CPU* cpu, instruction* i)
+{
+ cpu->hi = reg(cpu, i->s);
+}
+
+void op_syscall(CPU* cpu, instruction* i)
+{
+ exception(cpu, E_SYSCALL);
+}
+
+
+void
CPU_decode_and_execute(CPU* cpu, instruction* i)
{
@@ -515,10 +718,14 @@ CPU_decode_and_execute(CPU* cpu, instruction* i)
case 0x0: op_sll(cpu, i); break;
case 0x02: op_srl(cpu, i); break;
case 0x03: op_sra(cpu, i); break;
+ case 0x07: op_srav(cpu, i); break;
+ case 0x04: op_sllv(cpu, i); break;
+ case 0x06: op_srlv(cpu, i); break;
case 0x08: op_jr(cpu, i); break;
case 0x09: op_jalr(cpu, i); break;
case 0x24: op_and(cpu, i); break;
case 0x25: op_or(cpu, i); break;
+ case 0x27: op_nor(cpu, i); break;
case 0x2a: op_slt(cpu, i); break;
case 0x2B: op_sltu(cpu, i); break;
case 0x20: op_add(cpu, i); break;
@@ -527,7 +734,11 @@ CPU_decode_and_execute(CPU* cpu, instruction* i)
case 0x1a: op_div(cpu, i); break;
case 0x1b: op_divu(cpu, i); break;
case 0x10: op_mfhi(cpu, i); break;
+ case 0x11: op_mthi(cpu, i); break;
case 0x12: op_mflo(cpu, i); break;
+ case 0x13: op_mtlo(cpu, i); break;
+ case 0x19: op_multu(cpu, i); break;
+ case 0x0C: op_syscall(cpu, i); break;
default: printf("Unhandled instruction %08X\n", i->_0); exit(EXIT_FAILURE);
}
break;
@@ -547,8 +758,10 @@ CPU_decode_and_execute(CPU* cpu, instruction* i)
case 0x0f: op_lui(cpu, i); break;
case 0x10: op_cop0(cpu, i); break;
case 0x20: op_lb(cpu, i); break;
+ case 0x21: op_lh(cpu, i); break;
case 0x23: op_lw(cpu, i); break;
case 0x24: op_lbu(cpu, i); break;
+ case 0x25: op_lhu(cpu, i); break;
case 0x2b: op_sw(cpu, i); break;
case 0x28: op_sb(cpu, i); break;
case 0x29: op_sh(cpu, i); break;
@@ -560,18 +773,26 @@ CPU_decode_and_execute(CPU* cpu, instruction* i)
void
CPU_run_next_instruction(CPU* cpu)
{
- u32 pc = cpu->pc;
+ instruction i = new_instr(CPU_load32(cpu, cpu->pc));
+
+ cpu->delay_slot = cpu->branch;
+ cpu->branch = 0;
- /* Use previously loaded instruction */
- instruction i = cpu->next_instruction;
+ cpu->current_pc = cpu->pc;
- cpu->next_instruction = new_instr(CPU_load32(cpu, pc));
+ if ((cpu->current_pc % 4) != 0)
+ {
+ exception(cpu, E_LOAD_ADRESS_ERROR);
+ return;
+ }
- cpu->pc += 4;
+ cpu->pc = cpu->next_pc;
+ cpu->next_pc = cpu->next_pc + 4;
- set_reg(cpu, cpu->load._0, cpu->load._1);
+ set_reg(cpu, cpu->load._0, cpu->load._1);
- cpu->load._0 = 0; cpu->load._1 = 0;
+ cpu->load._0 = 0;
+ cpu->load._1 = 0;
CPU_decode_and_execute(cpu, &i);
@@ -590,8 +811,8 @@ new_instr(u32 i)
ins.d = (i >> 11) & 0x1f;
ins.shift = (i >> 6) & 0x1f;
ins.imm = i & 0xffff;
- ins.imm_se = (u32)((i16)(i & 0xffff));
- ins.imm_jump = i & 0x3ffffff;
- ins.cop_opcode = (i >> 21) & 0x1f;
+ ins.imm_se = (u32)((i16)(i & 0xffff));
+ ins.imm_jump = i & 0x3ffffff;
+ ins.cop_opcode = (i >> 21) & 0x1f;
return ins;
}
diff --git a/src/cpu.h b/src/cpu.h
@@ -2,8 +2,9 @@
#include "interconnect.h"
#include "types.h"
+#include <iostream>
-struct instruction {
+typedef struct {
u32 _0;
u32 fn;
u32 t;
@@ -15,24 +16,26 @@ struct instruction {
u32 sub;
u32 shift;
u32 cop_opcode;
-};
-
-typedef struct instruction instruction;
+} instruction;
-struct load {
+typedef struct {
u32 _0;
u32 _1;
-};
-
-typedef struct load load;
+} Load;
struct CPU {
/* Program Counter register */
u32 pc;
/* Cop0 register 12: Status Register*/
+ u32 next_pc;
+ u32 current_pc;
+ u32 cause;
+ u32 epc;
u32 sr;
u32 hi;
u32 lo;
+ u32 branch;
+ u32 delay_slot;
instruction next_instruction;
Interconnect* inter;
/* General Registers */
@@ -41,11 +44,18 @@ struct CPU {
They contain the output of the current instruction */
u32 out_regs[32];
/* LOAD -> on load delay slots */
- load load;
+ Load load;
};
typedef struct CPU CPU;
+typedef enum {
+ E_SYSCALL = 0x8,
+ E_LOAD_ADRESS_ERROR = 0x4,
+ E_STORE_ADRESS_ERROR = 0x5,
+ E_OVERFLOW = 0xc,
+} EXCEPTION;
+
CPU* new_cpu(Interconnect*);
u32 CPU_load32(CPU*, u32);
void CPU_decode_and_execute(CPU*, instruction*);
diff --git a/src/interconnect.c b/src/interconnect.c
@@ -11,8 +11,8 @@
Interconnect*
new_interconnect(void) {
Interconnect* inter = (Interconnect*)malloc(sizeof(Interconnect));
- inter->BIOS = BIOS_new("roms/scph1001.bin");
- inter->RAM = RAM_new();
+ inter->bios = BIOS_new("roms/scph1001.bin");
+ inter->ram = RAM_new();
return inter;
}
@@ -21,40 +21,83 @@ INTER_load8(Interconnect* inter, u32 addr)
{
u32 offset;
u32 abs_addr;
+ u32 contains;
offset = 0;
+ contains = 0;
abs_addr = mask_region(addr);
/* Assert abs_address Mappings */
- offset = UTIL_contains(BIOS_START, BIOS_SIZE, abs_addr);
- if (offset != -1)
- return BIOS_load8(inter->BIOS, offset);
+ contains = UTIL_contains(BIOS_START, BIOS_SIZE, abs_addr, &offset);
+ if (contains)
+ return BIOS_load8(inter->bios, offset);
- offset = UTIL_contains(EXPANSION1_START, EXPANSION1_SIZE, abs_addr);
- if (offset != -1)
+ contains = UTIL_contains(EXPANSION1_START, EXPANSION1_SIZE, abs_addr, &offset);
+ if (contains)
return 0xff;
- offset = UTIL_contains(RAM_START, RAM_SIZE, abs_addr);
- if (offset != -1)
- return RAM_load8(inter->RAM, offset);
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains)
+ return RAM_load8(inter->ram, offset);
- offset = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr);
- if (offset != -1)
+ contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
+ if (contains)
{
- printf("IRQ CONTROL read %08X", offset);
+ printf("IRQ CONTROL read %08X\n", offset);
return 0;
}
PANIC("Unhandled Load8 At Address %08X\n", addr);
}
+u16
+INTER_load16(Interconnect* inter, u32 addr)
+{
+ u32 offset;
+ u32 abs_addr;
+ u32 contains;
+
+ offset = 0;
+ contains = 0;
+ abs_addr = mask_region(addr);
+
+ if (addr % 2 != 0)
+ {
+ fprintf(stderr, "Unaligned_load16_abs_address: %08X\n", abs_addr);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Assert abs_address Mappings */
+ contains = UTIL_contains(SPU_START, SPU_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ fprintf(stderr, "Unhandled read from SPU register: %08X\n", offset);
+ return 0;
+ }
+
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains)
+ return RAM_load16(inter->ram, offset);
+
+ contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ printf("IRQ CONTROL read %08X\n", offset);
+ return 0;
+ }
+
+ PANIC("Unhandled Load16 At Address %08X\n", abs_addr);
+}
+
u32
INTER_load32(Interconnect* inter, u32 addr)
{
u32 offset;
u32 abs_addr;
+ u32 contains;
offset = 0;
+ contains = 0;
abs_addr = mask_region(addr);
if (addr % 4 != 0)
@@ -64,18 +107,32 @@ INTER_load32(Interconnect* inter, u32 addr)
}
/* Assert abs_address Mappings */
- offset = UTIL_contains(BIOS_START, BIOS_SIZE, abs_addr);
- if (offset != -1)
- return BIOS_load32(inter->BIOS, offset);
+ contains = UTIL_contains(BIOS_START, BIOS_SIZE, abs_addr, &offset);
+ if (contains)
+ return BIOS_load32(inter->bios, offset);
+
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains)
+ return RAM_load32(inter->ram, offset);
- offset = UTIL_contains(RAM_START, RAM_SIZE, abs_addr);
- if (offset != -1)
- return RAM_load32(inter->RAM, offset);
+ contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ printf("IRQ CONTROL read %08X\n", offset);
+ return 0;
+ }
+
+ contains = UTIL_contains(DMA_START, DMA_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ printf("DMA read %08X\n", abs_addr);
+ return 0;
+ }
- offset = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr);
- if (offset != -1)
+ contains = UTIL_contains(GPU_START, GPU_SIZE, abs_addr, &offset);
+ if (contains)
{
- printf("IRQ CONTROL read %08X", offset);
+ printf("GPU read %08X\n", abs_addr);
return 0;
}
@@ -85,130 +142,75 @@ INTER_load32(Interconnect* inter, u32 addr)
void
INTER_store8(Interconnect* inter, u32 addr, u8 val)
{
- u32 offset = 0;
+ u32 offset;
+ u32 contains;
u32 abs_addr;
+ offset = 0;
+ contains = 0;
abs_addr = mask_region(addr);
- offset = UTIL_contains(EXPANSION2_START, EXPANSION2_SIZE, abs_addr);
- if (offset != -1)
+ contains = UTIL_contains(EXPANSION2_START, EXPANSION2_SIZE, abs_addr, &offset);
+ if (contains)
{
fprintf(stdout, "Ignoring write to EXPANSION2 register at: %08X\n", abs_addr);
return;
}
- offset = UTIL_contains(RAM_START, RAM_SIZE, abs_addr);
- if (offset != -1)
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains)
{
- RAM_store8(inter->RAM, offset, val);
+ RAM_store8(inter->ram, offset, val);
return;
}
- //offset = UTIL_contains(RAM_SIZE_START, RAM_SIZE_SIZE, abs_addr);
- //if (offset != -1)
- //{
- // fprintf(stdout, "Ignoring RAM_SIZE register write %X\n", abs_addr);
- // return;
- //}
-
- //offset = UTIL_contains(CACHECONTROL_START, CACHECONTROL_SIZE, abs_addr);
- //if (offset != -1)
- //{
- // fprintf(stdout, "Ignoring CACHECONTROL abs_address write: %X\n", abs_addr);
- // return;
- //}
-
- //offset = UTIL_contains(SYSCONTROL_START, SYSCONTROL_SIZE, abs_addr);
- //if (offset != -1)
- //{
- // switch(offset) {
- // case 0:
- // if (val != 0x1F000000) {
- // fprintf(stderr, "Bad Expansion 1 base abs_address: %08X", val);
- // exit(EXIT_FAILURE);
- // }
- // break;
- // case 4:
- // if (val != 0x1F802000) {
- // fprintf(stderr, "Bad expansion 2 base abs_address: %08X", val);
- // exit(EXIT_FAILURE);
- // }
- // break;
- // default:
- // fprintf(stderr, "Unhandled write to SYSCONTROL register\n");
- // return;
- // }
- // return;
- //}
-
PANIC("Unhandled store8 into abs_address: %08X\n", abs_addr);
}
void
INTER_store16(Interconnect* inter, u32 addr, u16 val)
{
- u32 offset = 0;
+ u32 offset;
+ u32 contains;
u32 abs_addr;
+ offset = 0;
+ contains = 0;
abs_addr = mask_region(addr);
if (addr % 2 != 0)
{
fprintf(stderr, "Unaligned_store16_address: %08X", addr);
exit(EXIT_FAILURE);
+ }
+ contains = UTIL_contains(SPU_START, SPU_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ fprintf(stdout, "Ignoring SPU register write: %X\n", abs_addr);
+ return;
}
- offset = UTIL_contains(SPU_START, SPU_SIZE, abs_addr);
- if (offset != -1)
+ contains = UTIL_contains(TIMERS_START, TIMERS_SIZE, abs_addr, &offset);
+ if (contains)
{
- fprintf(stdout, "Ignoring SPU register write; %X\n", abs_addr);
+ fprintf(stdout, "Ignoring TIMER register write to offset: %X\n", offset);
return;
}
- //offset = UTIL_contains(RAM_START, RAM_SIZE, abs_addr);
- //if (offset != -1)
- //{
- // fprintf(stdout, "Ignoring RAM write; %X\n", abs_addr);
- // return;
- //}
-
- //offset = UTIL_contains(RAM_SIZE_START, RAM_SIZE_SIZE, abs_addr);
- //if (offset != -1)
- //{
- // fprintf(stdout, "Ignoring RAM_SIZE register write %X\n", abs_addr);
- // return;
- //}
-
- //offset = UTIL_contains(CACHECONTROL_START, CACHECONTROL_SIZE, abs_addr);
- //if (offset != -1)
- //{
- // fprintf(stdout, "Ignoring CACHECONTROL abs_address write: %X\n", abs_addr);
- // return;
- //}
-
- //offset = UTIL_contains(SYSCONTROL_START, SYSCONTROL_SIZE, abs_addr);
- //if (offset != -1)
- //{
- // switch(offset) {
- // case 0:
- // if (val != 0x1F000000) {
- // fprintf(stderr, "Bad Expansion 1 base abs_address: %08X", val);
- // exit(EXIT_FAILURE);
- // }
- // break;
- // case 4:
- // if (val != 0x1F802000) {
- // fprintf(stderr, "Bad expansion 2 base abs_address: %08X", val);
- // exit(EXIT_FAILURE);
- // }
- // break;
- // default:
- // fprintf(stderr, "Unhandled write to SYSCONTROL register\n");
- // return;
- // }
- // return;
- //}
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ RAM_store16(inter->ram, offset, val);
+ return;
+ }
+
+ contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ printf("IRQ control write %08X\n at address %08X\n", val, offset);
+ return;
+ }
PANIC("Unhandled store16 into abs_address: %08X\n", abs_addr);
}
@@ -216,44 +218,68 @@ INTER_store16(Interconnect* inter, u32 addr, u16 val)
void
INTER_store32(Interconnect* inter, u32 addr, u32 val)
{
- u32 offset = 0;
+ u32 offset;
+ u32 contains;
u32 abs_addr;
+ offset = 0;
+ contains = 0;
abs_addr = mask_region(addr);
if (addr % 4 != 0)
fprintf(stderr, "Unaligned_store32_address: %08X", addr);
- offset = UTIL_contains(RAM_START, RAM_SIZE, abs_addr);
- if (offset != -1)
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains)
{
- RAM_store32(inter->RAM, offset, val);
+ RAM_store32(inter->ram, offset, val);
return;
}
- offset = UTIL_contains(RAM_SIZE_START, RAM_SIZE_SIZE, abs_addr);
- if (offset != -1)
+ contains = UTIL_contains(RAM_SIZE_START, RAM_SIZE_SIZE, abs_addr, &offset);
+ if (contains)
{
fprintf(stdout, "Ignoring RAM_SIZE register write %X\n", abs_addr);
return;
}
- offset = UTIL_contains(CACHECONTROL_START, CACHECONTROL_SIZE, abs_addr);
- if (offset != -1)
+ contains = UTIL_contains(CACHECONTROL_START, CACHECONTROL_SIZE, abs_addr, &offset);
+ if (contains)
{
fprintf(stdout, "Ignoring CACHECONTROL abs_address write: %X\n", abs_addr);
return;
}
- offset = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr);
- if (offset != -1)
+ contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
+ if (contains)
{
fprintf(stdout, "Ignoring IRQ CONTROL write %08X to address %08X\n", val, offset);
return;
}
- offset = UTIL_contains(SYSCONTROL_START, SYSCONTROL_SIZE, abs_addr);
- if (offset != -1)
+ contains = UTIL_contains(DMA_START, DMA_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ fprintf(stdout, "Ignoring DMA write %08X to address %08X\n", val, offset);
+ return;
+ }
+
+ contains = UTIL_contains(TIMERS_START, TIMERS_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ fprintf(stdout, "TIMER register write %08X to offset: %08X\n", val, offset);
+ return;
+ }
+
+ contains = UTIL_contains(GPU_START, GPU_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ fprintf(stdout, "GPU write %08X to address %08X\n", val, offset);
+ return;
+ }
+
+ contains = UTIL_contains(SYSCONTROL_START, SYSCONTROL_SIZE, abs_addr, &offset);
+ if (contains)
{
switch(offset) {
case 0:
@@ -275,5 +301,5 @@ INTER_store32(Interconnect* inter, u32 addr, u32 val)
return;
}
- PANIC("Unhandled store 32 into abs_address: %08X\n", abs_addr);
+ PANIC("Unhandled store32 into abs_address: %08X\n", addr);
}
diff --git a/src/interconnect.h b/src/interconnect.h
@@ -5,14 +5,15 @@
#include "types.h"
struct Interconnect {
- BIOS* BIOS;
- RAM* RAM;
+ BIOS* bios;
+ RAM* ram;
};
typedef struct Interconnect Interconnect;
Interconnect* new_interconnect(void);
u32 INTER_load32(Interconnect*, u32);
+u16 INTER_load16(Interconnect*, u32);
u8 INTER_load8(Interconnect*, u32);
void INTER_store32(Interconnect*, u32, u32);
void INTER_store16(Interconnect*, u32, u16);
diff --git a/src/mem.c b/src/mem.c
@@ -23,6 +23,17 @@ RAM_load32(RAM* r, u32 offset)
(r->data[offset + 0]);
}
+u16
+RAM_load16(RAM* r, u32 offset)
+{
+ u16 b0, b1;
+
+ b0 = (u16)r->data[offset];
+ b1 = (u16)r->data[offset + 1];
+
+ return b0 | (b1 << 8);
+}
+
u8
RAM_load8(RAM* r, u32 offset)
{
@@ -36,6 +47,13 @@ RAM_store8(RAM* r, u32 offset, u8 val)
}
void
+RAM_store16(RAM* r, u32 offset, u16 val)
+{
+ r->data[offset]=val;
+ r->data[offset+1] = val >> 8;
+}
+
+void
RAM_store32(RAM* r, u32 offset, u32 val)
{
u8 b0 = val;
diff --git a/src/mem.h b/src/mem.h
@@ -10,7 +10,9 @@ struct RAM {
typedef struct RAM RAM;
RAM* RAM_new(void);
-u32 RAM_load32(RAM*, u32);
u8 RAM_load8(RAM*, u32);
-void RAM_store32(RAM* r, u32, u32);
+u16 RAM_load16(RAM*, u32);
+u32 RAM_load32(RAM*, u32);
void RAM_store8(RAM* r, u32, u8);
+void RAM_store16(RAM* r, u32, u16);
+void RAM_store32(RAM* r, u32, u32);
diff --git a/src/util.c b/src/util.c
@@ -14,9 +14,10 @@ const u32 REGION_MASK[8] = {
};
u32
-UTIL_contains(u32 start, u32 length, u32 addr)
+UTIL_contains(u32 start, u32 length, u32 addr, u32 *res)
{
- return (addr >= start && addr < start + length) ? addr-start : -1;
+ *res = addr-start;
+ return (addr >= start && addr < start + length) ? 1 : 0;
}
u8
diff --git a/src/util.h b/src/util.h
@@ -38,6 +38,6 @@
#define GPU_START 0x1F801810
#define GPU_SIZE 8
-u32 UTIL_contains(u32, u32, u32);
+u32 UTIL_contains(u32, u32, u32, u32*);
u8 checked_addi32(i32, i32, i32*);
u32 mask_region(u32);
diff --git a/test.c b/test.c
@@ -10,6 +10,7 @@ void
bar(struct foo *foo1)
{
foo1->pc +=1;
+ foo1->pc === 1;k
}