146 lines
5.3 KiB
C
146 lines
5.3 KiB
C
//
|
||
// Created by bruno on 2.2.2025.
|
||
//
|
||
|
||
#ifndef RISCB_CORE_H
|
||
#define RISCB_CORE_H
|
||
|
||
#include <stdint.h>
|
||
#include <SDL_render.h>
|
||
#include "stdio.h"
|
||
|
||
#define MEM_SIZE 2097120
|
||
// Register count (register names R0 to R7)
|
||
#define REG_COUNT 64
|
||
#define STACK_SIZE 255
|
||
|
||
#define CPU_FLAG_ZERO (1 << 0)
|
||
#define CPU_FLAG_NEGATIVE (1 << 1)
|
||
|
||
#define CPU_MODE_PAUSED (1 << 0)
|
||
#define CPU_MODE_HALTED (1 << 1)
|
||
#define CPU_MODE_ERROR (1 << 2)
|
||
#define CPU_MODE_LOOP (1 << 3)
|
||
#define CPU_MODE_STEP (1 << 4)
|
||
#define CPU_MODE_SECOND (1 << 5)
|
||
#define CPU_MODE_FRAME (1 << 6)
|
||
|
||
#define CPU_INSTRUCTION_SIZE 8 //Biggest instruction
|
||
|
||
|
||
// CPU state
|
||
typedef struct {
|
||
uint8_t regs[REG_COUNT];
|
||
uint8_t memory[MEM_SIZE];
|
||
uint32_t stack[STACK_SIZE]; // Stack pointer
|
||
uint32_t addrToLineMapper[MEM_SIZE / CPU_INSTRUCTION_SIZE];
|
||
uint32_t pc; // Program counter
|
||
uint32_t stack_ptr; // Stack pointer
|
||
uint8_t flags; // Status flags
|
||
uint32_t programEnd;
|
||
uint8_t mode;
|
||
uint32_t cycle;
|
||
SDL_Renderer *renderer;
|
||
} CPU;
|
||
|
||
void step(CPU *cpu);
|
||
|
||
void init_cpu(CPU *cpu, SDL_Renderer *renderer);
|
||
|
||
// Helper function for setting flags in the CPU (here we assume bit0 is the Zero flag,
|
||
// and bit1 is the Negative flag).
|
||
static inline void set_flags(CPU *cpu, int32_t result);
|
||
|
||
// Opcode definitions (should match the CPU’s enum)
|
||
typedef enum {
|
||
NOP, // NOP - No operation (does nothing, advances to next instruction)
|
||
|
||
BRK, // BRK - Pause CPU (halts execution until resumed)
|
||
|
||
HLT,
|
||
|
||
MOV_IMM_RN, // MOV Rn, Imm - Move immediate to register (Rn = Imm)
|
||
MOV_RN_RM, // MOV Rn, Rm - Move value from one register to another (Rn = Rm)
|
||
MOV_RN_ADDR, // MOV Rn, [Addr] - Load value from memory address into register (Rn = [Addr])
|
||
MOV_ADDR_RN, // MOV [Addr], Rn - Store register value into memory address ([Addr] = Rn)
|
||
|
||
SWAP, // SWAP Rn, Rm - Swap values between two registers (Rn <-> Rm)
|
||
|
||
SWAPN, // SWAPN Rn - Swap nibbles within a register (Rn high/low nibbles swapped)
|
||
|
||
ADD_RN_RM, // ADD Rn, Rm - Add values of two registers (Rn = Rn + Rm)
|
||
ADD_RN_IMM, // ADD Rn, Imm - Add immediate value to register (Rn = Rn + Imm)
|
||
|
||
SUB_RN_RM, // SUB Rn, Rm - Subtract one register from another (Rn = Rn - Rm)
|
||
SUB_RN_IMM, // SUB Rn, Imm - Subtract immediate value from register (Rn = Rn - Imm)
|
||
|
||
MUL_RN_RM, // MUL Rn, Rm - Multiply two registers (Rn = Rn * Rm)
|
||
MUL_RN_IMM, // MUL Rn, Imm - Multiply register by immediate (Rn = Rn * Imm)
|
||
|
||
DIV_RN_RM, // DIV Rn, Rm - Divide one register by another (Rn = Rn / Rm)
|
||
DIV_RN_IMM, // DIV Rn, Imm - Divide register by immediate (Rn = Rn / Imm)
|
||
|
||
MOD_RN_RM, // MOD Rn, Rm - Compute remainder of division (Rn = Rn % Rm)
|
||
MOD_RN_IMM, // MOD Rn, Imm - Compute remainder using immediate (Rn = Rn % Imm)
|
||
|
||
NEG_RN, // NEG Rn - Negate register value (Rn = -Rn)
|
||
|
||
AND_RN_RM, // AND Rn, Rm - Bitwise AND two registers (Rn = Rn & Rm)
|
||
AND_RN_IMM, // AND Rn, Imm - Bitwise AND register with immediate (Rn = Rn & Imm)
|
||
|
||
OR_RN_RM, // OR Rn, Rm - Bitwise OR two registers (Rn = Rn | Rm)
|
||
OR_RN_IMM, // OR Rn, Imm - Bitwise OR register with immediate (Rn = Rn | Imm)
|
||
|
||
XOR_RN_RM, // XOR Rn, Rm - Bitwise XOR two registers (Rn = Rn ^ Rm)
|
||
XOR_RN_IMM, // XOR Rn, Imm - Bitwise XOR register with immediate (Rn = Rn ^ Imm)
|
||
|
||
NOT_RN, // NOT Rn - Bitwise NOT (Rn = ~Rn)
|
||
|
||
SHL_RN_IMM, // SHL Rn, Imm - Logical shift left (Rn = Rn << Imm)
|
||
|
||
SHR_RN_IMM, // SHR Rn, Imm - Logical shift right (Rn = Rn >> Imm)
|
||
|
||
SAR_RN_IMM, // SAR Rn, Imm - Arithmetic shift right (Rn = Rn >> Imm with sign extension)
|
||
|
||
JMP, // JMP Addr - Jump to address (PC = Addr)
|
||
|
||
JMP_REL, // JMP Offset - relative jump (offset is signed)
|
||
|
||
INC_RN, //INC Rn - Increment register
|
||
INC_ADDR, //INC [Addr] - Increment address
|
||
|
||
DEC_RN, //DEC Rn - Increment register
|
||
DEC_ADDR, //DEC [Addr] - Increment address
|
||
|
||
CMP, // CMP Rn, Rm - Compare two registers (sets flags based on Rn - Rm)
|
||
|
||
JE, // JE Addr - Jump if equal (if zero flag set, PC = Addr)
|
||
JNE, // JNE Addr - Jump if not equal (if zero flag not set, PC = Addr)
|
||
|
||
BIT_TS_RN, // jump relative if a given bit in a register is set
|
||
BIT_TS_ADDR, // jump relative if a given bit in memory is set
|
||
|
||
BIT_TC_RN, // jump relative if a given bit in a register is not set
|
||
BIT_TC_ADDR, // jump relative if a given bit in memory is not set
|
||
|
||
BITS_RN, // jump relative if a given bit in a register is set
|
||
BITS_ADDR, // jump relative if a given bit in memory is set
|
||
|
||
BITC_RN, // jump relative if a given bit in a register is not set
|
||
BITC_ADDR, // jump relative if a given bit in memory is not set
|
||
|
||
JG, // JG Addr - Jump if greater (if greater flag set, PC = Addr)
|
||
|
||
JL, // JL Addr - Jump if less (if less flag set, PC = Addr)
|
||
|
||
JGE, // JGE Addr - Jump if greater or equal (if greater or zero flag set, PC = Addr)
|
||
|
||
JLE, // JLE Addr - Jump if less or equal (if less or zero flag set, PC = Addr)
|
||
|
||
CALL, // CALL Addr - Call subroutine (push PC, flags and registers to stack, PC = Addr)
|
||
|
||
RET, // RET - Return from subroutine (pop PC, flags and registers from stack)
|
||
} Opcode;
|
||
|
||
#endif //RISCB_CORE_H
|