Skip to content
Snippets Groups Projects
ee.hpp 2.34 KiB
Newer Older
#pragma once
#include <cpu/cop0.hpp>
Geo Ster's avatar
Geo Ster committed
#include <array>

/* Nice interface for instructions */
Geo Ster's avatar
Geo Ster committed
struct Instruction {
    union {
        uint32_t value;
        struct { /* Used when polling for the opcode */
            uint32_t : 26;
            uint32_t opcode : 6;
        };
        struct {
            uint32_t immediate : 16;
            uint32_t rt : 5;
            uint32_t rs : 5;
            uint32_t opcode : 6;
        } i_type;
        struct {
            uint32_t target : 26;
            uint32_t opcode : 6;
        } j_type;
        struct {
            uint32_t funct : 6;
            uint32_t sa : 5;
            uint32_t rd : 5;
            uint32_t rt : 5;
            uint32_t rs : 5;
            uint32_t opcode : 6;
        } r_type;
Geo Ster's avatar
Geo Ster committed
    uint32_t pc;

    Instruction operator=(const Instruction& instr)
Geo Ster's avatar
Geo Ster committed
        value = instr.value;
        pc = instr.pc;

        return *this;
    }
};

union Register {
    uint64_t dword[2];
Geo Ster's avatar
Geo Ster committed
    uint32_t word[4];
};

constexpr uint8_t SPECIAL_OPCODE = 0b000000;

class ComponentManager;

/* A class implemeting the MIPS R5900 CPU. */
class EmotionEngine {
public:
    EmotionEngine(ComponentManager* parent);
    ~EmotionEngine() = default;

    /* CPU functionality. */
    void tick();
    void reset_state();
    void fetch_instruction();

Geo Ster's avatar
Geo Ster committed
    /* Memory operations */
    template <typename T>
    T read(uint32_t addr);

    template <typename T>
    void write(uint32_t addr, T data);

    /* Opcodes */
    void op_cop0(); void op_mfc0(); void op_sw();
    void op_special(); void op_sll(); void op_slti();
Geo Ster's avatar
Geo Ster committed
    void op_bne(); void op_ori(); void op_addi();
    void op_lq(); void op_lui(); void op_jr(); void op_addiu();
    void op_tlbwi(); void op_mtc0(); void op_lw(); void op_mmi();
    void op_madd1(); void op_jalr(); void op_sd(); void op_jal();
    void op_sra(); void op_regimm(); void op_bgez(); void op_addu();
    void op_daddu(); void op_andi(); void op_beq(); void op_or();
    void op_mult(); void op_divu(); void op_beql(); void op_mflo();
    void op_sltiu(); void op_bnel();
protected:
    ComponentManager* manager;

    /* Registers. */
    Register gpr[32];
    uint32_t pc;
Geo Ster's avatar
Geo Ster committed
    uint64_t hi0, hi1, lo0, lo1;
    uint32_t sa;
    Instruction instr, next_instr;
    bool skip_branch_delay = false;

Geo Ster's avatar
Geo Ster committed
    /* Scratchpad */
    uint8_t scratchpad[16 * 1024];

    /* Coprocessors */
    COP0 cop0;