143 lines
3.5 KiB
C
143 lines
3.5 KiB
C
//
|
|
// Created by bruno on 2.2.2025.
|
|
//
|
|
|
|
#include "memory.h"
|
|
|
|
uint8_t write_mem(CPU *cpu, uint32_t addr, uint8_t value) {
|
|
if (addr >= MEM_SIZE) {
|
|
return 1;
|
|
}
|
|
|
|
switch (addr) {
|
|
|
|
default:
|
|
cpu->memory[addr] = value;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint8_t read_mem(CPU *cpu, uint32_t addr) {
|
|
if (addr >= MEM_SIZE) {
|
|
return 0;
|
|
}
|
|
switch (addr) {
|
|
|
|
default:
|
|
return cpu->memory[addr];
|
|
}
|
|
}
|
|
|
|
uint16_t read_mem16(CPU *cpu, uint32_t addr) {
|
|
return read_mem(cpu, addr) | (read_mem(cpu, addr + 1) << 8);
|
|
}
|
|
|
|
uint32_t read_mem32(CPU *cpu, uint32_t addr) {
|
|
return read_mem16(cpu, addr) | (read_mem16(cpu, addr + 2) << 16);
|
|
}
|
|
|
|
uint32_t read_address_argument(CPU *cpu) {
|
|
uint32_t out = read_mem32(cpu, cpu->pc);
|
|
cpu->pc += 4;
|
|
if (out >= MEM_SIZE) {
|
|
out = MEM_SIZE - 1;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
// Push a 32-bit program counter (PC) onto the stack
|
|
void write_stack(CPU *cpu) {
|
|
if (cpu->pc >= MEM_SIZE) {
|
|
return; // Invalid memory address
|
|
}
|
|
if (cpu->stack_ptr >= STACK_SIZE - 1) {
|
|
return; // Stack overflow protection
|
|
}
|
|
cpu->stack[++cpu->stack_ptr] = cpu->pc;
|
|
for (uint32_t reg = 0; reg < REG_COUNT; reg += 4) {
|
|
uint32_t packed = cpu->regs[reg] |
|
|
((reg + 1 < REG_COUNT) ? (cpu->regs[reg + 1] << 8) : 0) |
|
|
((reg + 2 < REG_COUNT) ? (cpu->regs[reg + 2] << 16) : 0) |
|
|
((reg + 3 < REG_COUNT) ? (cpu->regs[reg + 3] << 24) : 0);
|
|
cpu->stack[++cpu->stack_ptr] = packed;
|
|
}
|
|
cpu->stack[++cpu->stack_ptr] = cpu->flags;
|
|
}
|
|
|
|
// Pop a 32-bit program counter (PC) and registers from the stack
|
|
void read_stack(CPU *cpu) {
|
|
if (cpu->stack_ptr == 0) {
|
|
return; // Stack underflow protection
|
|
}
|
|
|
|
// Restore flags
|
|
cpu->flags = cpu->stack[cpu->stack_ptr--];
|
|
|
|
// Restore registers
|
|
for (int32_t reg = REG_COUNT - 1; reg >= 0; reg -= 4) {
|
|
if (cpu->stack_ptr == 0) {
|
|
return; // Stack underflow protection
|
|
}
|
|
uint32_t packed = cpu->stack[cpu->stack_ptr--];
|
|
cpu->regs[reg] = (packed & 0xFF);
|
|
if (reg - 1 >= 0) cpu->regs[reg - 1] = ((packed >> 8) & 0xFF);
|
|
if (reg - 2 >= 0) cpu->regs[reg - 2] = ((packed >> 16) & 0xFF);
|
|
if (reg - 3 >= 0) cpu->regs[reg - 3] = ((packed >> 24) & 0xFF);
|
|
}
|
|
|
|
// Restore PC
|
|
if (cpu->stack_ptr == 0) {
|
|
return; // Stack underflow protection
|
|
}
|
|
cpu->pc = cpu->stack[cpu->stack_ptr--];
|
|
}
|
|
|
|
|
|
uint8_t read_reg_number(CPU *cpu) {
|
|
uint8_t out = read_mem(cpu, cpu->pc++);
|
|
if (out >= REG_COUNT) {
|
|
return 0;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
uint8_t read_reg(CPU *cpu, uint8_t number) {
|
|
if (number >= REG_COUNT) {
|
|
return 0;
|
|
}
|
|
return cpu->regs[number];
|
|
}
|
|
|
|
uint8_t write_reg(CPU *cpu, uint8_t number, uint8_t value) {
|
|
if (number >= REG_COUNT) {
|
|
return 1;
|
|
}
|
|
cpu->regs[number] = value;
|
|
return 0;
|
|
}
|
|
|
|
uint8_t write_mem16(CPU *cpu, uint32_t addr, uint16_t value) {
|
|
uint8_t status = write_mem(cpu, addr, value & 0xFF);
|
|
if (status) {
|
|
return status;
|
|
}
|
|
status = write_mem(cpu, addr + 1, (value >> 8) & 0xFF);
|
|
if (status) {
|
|
return status;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint8_t write_mem32(CPU *cpu, uint32_t addr, uint32_t value) {
|
|
uint8_t status = write_mem16(cpu, addr, value & 0xFFFF);
|
|
if (status) {
|
|
return status;
|
|
}
|
|
status = write_mem16(cpu, addr + 2, (value >> 16) & 0xFFFF);
|
|
if (status) {
|
|
return status;
|
|
}
|
|
return 0;
|
|
}
|