commit fc19c67b4fd962219973c677cbf399163b142823
parent 2b441df3713557728536ea2133a5960ab6684456
Author: Edea Kramer <edea@lunarcry.my.domain>
Date: Sun, 24 Mar 2024 14:32:58 +0200
Stuck on load adress
Diffstat:
4 files changed, 129 insertions(+), 39 deletions(-)
diff --git a/build.sh b/build.sh
@@ -1 +1 @@
-tcc -static -std=c99 -O3 -Wall -pedantic -g src/*.c -o bin/ultimecia
+cc -static -std=c99 -O3 -Wall -pedantic -g src/*.c -o bin/ultimecia
diff --git a/src/cpu.c b/src/cpu.c
@@ -12,6 +12,8 @@ new_cpu(Interconnect* inter) {
CPU* cpu = (CPU*)malloc(sizeof(CPU));
cpu->pc = 0xBFC00000;
cpu->sr = 0x0;
+ cpu->hi = 0xdeaddead;
+ cpu->lo = 0xdeaddead;
cpu->inter = inter;
cpu->load._0 = 0; cpu->load._1 = 0;
cpu->next_instruction = new_instr(0x0); /* NOP */
@@ -157,8 +159,8 @@ op_addiu(CPU* cpu, instruction* i)
void
op_addi(CPU* cpu, instruction* i)
{
- u32 v;
- u32 imm_se;
+ i32 v;
+ i32 imm_se;
i32 res;
imm_se = (i32)i->imm_se;
@@ -220,10 +222,9 @@ op_mtc0(CPU* cpu, instruction* i)
void
op_mfc0(CPU* cpu, instruction* i)
{
- u32 cop_r, v;
+ u32 cop_r;
cop_r = i->d;
- v = reg(cpu, i->t);
switch(cop_r) {
case 12:
@@ -271,7 +272,7 @@ op_beq(CPU* cpu, instruction* i)
void
op_bgtz(CPU* cpu, instruction* i)
{
- u32 v;
+ i32 v;
v = (i32)reg(cpu, i->s);
@@ -282,7 +283,7 @@ op_bgtz(CPU* cpu, instruction* i)
void
op_blez(CPU* cpu, instruction* i)
{
- u32 v;
+ i32 v;
v = (i32)reg(cpu, i->s);
@@ -293,11 +294,12 @@ op_blez(CPU* cpu, instruction* i)
void
op_bxx(CPU* cpu, instruction* i)
{
- u8 is_bgez, is_link, test;
- u32 v;
+ u8 is_bgez, is_link;
+ u32 test;
+ i32 v;
is_bgez = (i->_0 >> 16) & 1;
- is_link = (i->_0 >> 20) & 1;
+ is_link = ((i->_0 >> 20) & 1) != 0;
v = (i32)reg(cpu, i->s);
@@ -329,7 +331,8 @@ op_lw(CPU* cpu, instruction* i)
void
op_lb(CPU* cpu, instruction* i)
{
- u32 v, addr;
+ i8 v;
+ u32 addr;
addr = reg(cpu, i->s) + i->imm_se;
v = (i8)CPU_load8(cpu, addr);
@@ -351,12 +354,21 @@ op_lbu(CPU* cpu, instruction* i)
}
void
+op_slt(CPU* cpu, instruction* i)
+{
+ u32 v;
+
+ v = (i32)reg(cpu, i->s) < (i32)reg(cpu, i->t);
+ set_reg(cpu, i->d, (u32)v);
+}
+
+void
op_sltu(CPU* cpu, instruction* i)
{
u32 v;
v = reg(cpu, i->s) < reg(cpu, i->t);
- set_reg(cpu, i->d, (u32)v);
+ set_reg(cpu, i->d, v);
}
void
@@ -364,13 +376,22 @@ op_slti(CPU* cpu, instruction* i)
{
u32 v;
v = (i32)reg(cpu, i->s) < (i32)i->imm_se;
- set_reg(cpu, i->t, (u32)v);
+ set_reg(cpu, i->t, v);
+}
+
+void
+op_sltiu(CPU* cpu, instruction* i)
+{
+ u32 v;
+ v = reg(cpu, i->s) < i->imm_se;
+ set_reg(cpu, i->t, v);
}
void
op_add(CPU* cpu, instruction* i)
{
- u32 v, s, t, res;
+ i32 s, t;
+ i32 res;
s = (i32)reg(cpu, i->s);
t = (i32)reg(cpu, i->t);
@@ -418,6 +439,73 @@ op_sra(CPU* cpu, instruction* i)
}
void
+op_srl(CPU* cpu, instruction* i)
+{
+ u32 v;
+ v = reg(cpu, i->t) >> i->shift;
+ set_reg(cpu, i->d, v);
+}
+
+void
+op_div(CPU* cpu, instruction* i)
+{
+ i32 n, d;
+
+ n = (i32)reg(cpu, i->s);
+ d = (i32)reg(cpu, i->t);
+
+ if (d == 0)
+ {
+ cpu->hi = (u32)n;
+ if (n >= 0)
+ cpu->lo = 0xffffffff;
+ else
+ cpu->lo = 1;
+ }
+ else if ((u32)n == 0x80000000 && d == -1)
+ {
+ cpu->hi = 0;
+ cpu->lo = 0x80000000;
+ }
+ else
+ {
+ cpu->hi = (u32)(n % d);
+ cpu->lo = (u32)(n / d);
+ }
+}
+
+void
+op_divu(CPU* cpu, instruction* i)
+{
+ u32 n, d;
+
+ n = reg(cpu, i->s);
+ d = reg(cpu, i->t);
+
+ if (d == 0)
+ {
+ cpu->hi = (u32)n;
+ cpu->lo = 0xffffffff;
+ }
+ else
+ {
+ cpu->hi = (n % d);
+ cpu->lo = (n / d);
+ }
+}
+void
+op_mflo(CPU* cpu, instruction* i)
+{
+ set_reg(cpu, i->d, cpu->lo);
+}
+
+void
+op_mfhi(CPU* cpu, instruction* i)
+{
+ set_reg(cpu, i->d, cpu->hi);
+}
+
+void
CPU_decode_and_execute(CPU* cpu, instruction* i)
{
@@ -425,15 +513,21 @@ CPU_decode_and_execute(CPU* cpu, instruction* i)
case 0x0:
switch(i->sub) {
case 0x0: op_sll(cpu, i); break;
+ case 0x02: op_srl(cpu, i); break;
case 0x03: op_sra(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 0x2a: op_slt(cpu, i); break;
case 0x2B: op_sltu(cpu, i); break;
case 0x20: op_add(cpu, i); break;
case 0x21: op_addu(cpu, i); break;
case 0x23: op_subu(cpu, i); break;
+ case 0x1a: op_div(cpu, i); break;
+ case 0x1b: op_divu(cpu, i); break;
+ case 0x10: op_mfhi(cpu, i); break;
+ case 0x12: op_mflo(cpu, i); break;
default: printf("Unhandled instruction %08X\n", i->_0); exit(EXIT_FAILURE);
}
break;
@@ -447,6 +541,7 @@ CPU_decode_and_execute(CPU* cpu, instruction* i)
case 0x08: op_addi(cpu, i); break;
case 0x09: op_addiu(cpu, i); break;
case 0x0a: op_slti(cpu, i); break;
+ case 0x0b: op_sltiu(cpu, i); break;
case 0x0c: op_andi(cpu, i); break;
case 0x0d: op_ori(cpu, i); break;
case 0x0f: op_lui(cpu, i); break;
@@ -498,19 +593,5 @@ new_instr(u32 i)
ins.imm_se = (u32)((i16)(i & 0xffff));
ins.imm_jump = i & 0x3ffffff;
ins.cop_opcode = (i >> 21) & 0x1f;
- //print_instr(&ins);
return ins;
}
-
-//void
-//print_instr(instruction *ins)
-//{
-// fprintf(stdout, "\n");
-// fprintf(stdout,"FUNCTION: "BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(ins->fn));
-// fprintf(stdout,"SUBFUNCTION: "BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(ins->sub));
-// fprintf(stdout,"SOURCE REGISTER: "BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(ins->rs));
-// fprintf(stdout,"OPERAND REGISTER: "BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(ins->rt));
-// fprintf(stdout,"DESTINATION REGISTER: "BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(ins->rd));
-// fprintf(stdout,"IMMEDIATE: "BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(ins->imm));
-// fprintf(stdout, "\n");
-//}
diff --git a/src/cpu.h b/src/cpu.h
@@ -27,27 +27,21 @@ struct load {
typedef struct load load;
struct CPU {
-
/* Program Counter register */
u32 pc;
-
/* Cop0 register 12: Status Register*/
u32 sr;
-
+ u32 hi;
+ u32 lo;
instruction next_instruction;
-
Interconnect* inter;
-
/* General Registers */
u32 regs[32];
-
/* Second set of regs to emulate the LOAD DELAY SLOT.
They contain the output of the current instruction */
u32 out_regs[32];
-
/* LOAD -> on load delay slots */
load load;
-
};
typedef struct CPU CPU;
diff --git a/src/interconnect.c b/src/interconnect.c
@@ -38,7 +38,14 @@ INTER_load8(Interconnect* inter, u32 addr)
if (offset != -1)
return RAM_load8(inter->RAM, offset);
- PANIC("Unhandled Load8 At Address %08X\n", abs_addr);
+ offset = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr);
+ if (offset != -1)
+ {
+ printf("IRQ CONTROL read %08X", offset);
+ return 0;
+ }
+
+ PANIC("Unhandled Load8 At Address %08X\n", addr);
}
u32
@@ -65,7 +72,14 @@ INTER_load32(Interconnect* inter, u32 addr)
if (offset != -1)
return RAM_load32(inter->RAM, offset);
- PANIC("Unhandled Load32 At Address %08X\n", abs_addr);
+ offset = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr);
+ if (offset != -1)
+ {
+ printf("IRQ CONTROL read %08X", offset);
+ return 0;
+ }
+
+ PANIC("Unhandled Load32 At Address %08X\n", addr);
}
void
@@ -86,7 +100,8 @@ INTER_store8(Interconnect* inter, u32 addr, u8 val)
offset = UTIL_contains(RAM_START, RAM_SIZE, abs_addr);
if (offset != -1)
{
- return RAM_store8(inter->RAM, offset, val);
+ RAM_store8(inter->RAM, offset, val);
+ return;
}
//offset = UTIL_contains(RAM_SIZE_START, RAM_SIZE_SIZE, abs_addr);