ultimecia

A ps1 emulator in c
Log | Files | Refs

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:
Mbuild.sh | 2+-
Msrc/cpu.c | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/cpu.h | 10++--------
Msrc/interconnect.c | 21++++++++++++++++++---
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);