mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-06-01 18:41:13 -07:00
204 lines
7.6 KiB
C
204 lines
7.6 KiB
C
#ifdef INTELLISENSE_DIRECTIVES
|
|
# pragma once
|
|
# include "dsl.h"
|
|
#endif
|
|
|
|
/* --- MIPS CPU Registers --- */
|
|
typedef enum {
|
|
R_ZERO = 0, R_AT = 1, R_V0 = 2, R_V1 = 3,
|
|
R_A0 = 4, R_A1 = 5, R_A2 = 6, R_A3 = 7,
|
|
R_T0 = 8, R_T1 = 9, R_T2 = 10, R_T3 = 11,
|
|
R_T4 = 12, R_T5 = 13, R_T6 = 14, R_T7 = 15,
|
|
R_S0 = 16, R_S1 = 17, R_S2 = 18, R_S3 = 19,
|
|
R_S4 = 20, R_S5 = 21, R_S6 = 22, R_S7 = 23,
|
|
R_T8 = 24, R_T9 = 25, R_K0 = 26, R_K1 = 27,
|
|
R_GP = 28, R_SP = 29, R_FP = 30, R_RA = 31
|
|
};
|
|
|
|
/* Semantic Aliases for MIPS Registers (O32 ABI) */
|
|
|
|
#define REG_DISCARD R_ZERO /* Hardwired to 0 */
|
|
#define REG_RETURN_VAL R_V0 /* Function return value */
|
|
#define REG_RETURN_VAL2 R_V1 /* Second return value (e.g., 64-bit) */
|
|
#define REG_ARG_0 R_A0 /* First function argument */
|
|
#define REG_ARG_1 R_A1 /* Second function argument */
|
|
#define REG_ARG_2 R_A2 /* Third function argument */
|
|
#define REG_ARG_3 R_A3 /* Fourth function argument */
|
|
#define REG_TEMP_0 R_T0 /* Temporary (Caller saved) */
|
|
#define REG_TEMP_1 R_T1 /* Temporary (Caller saved) */
|
|
#define REG_TEMP_2 R_T2 /* Temporary (Caller saved) */
|
|
#define REG_SAVED_0 R_S0 /* Saved register (Callee saved) */
|
|
#define REG_STACK_PTR R_SP /* Stack Pointer */
|
|
#define REG_RETURN_ADDR R_RA /* Return Address (populated by JAL) */
|
|
|
|
/* --- MIPS CPU Opcodes (Bits 31-26) --- */
|
|
|
|
#define MIPS_OP_SPECIAL 0x00 /* R-Type instructions (uses FUNCT field) */
|
|
#define MIPS_OP_BCOND 0x01 /* Branch on condition */
|
|
#define MIPS_OP_J 0x02 /* Jump */
|
|
#define MIPS_OP_JAL 0x03 /* Jump and Link */
|
|
#define MIPS_OP_BEQ 0x04 /* Branch on Equal */
|
|
#define MIPS_OP_BNE 0x05 /* Branch on Not Equal */
|
|
#define MIPS_OP_BLEZ 0x06 /* Branch on Less Than or Equal to Zero */
|
|
#define MIPS_OP_BGTZ 0x07 /* Branch on Greater Than Zero */
|
|
#define MIPS_OP_ADDI 0x08 /* Add Immediate */
|
|
#define MIPS_OP_ADDIU 0x09 /* Add Immediate Unsigned */
|
|
#define MIPS_OP_SLTI 0x0A /* Set on Less Than Immediate */
|
|
#define MIPS_OP_SLTIU 0x0B /* Set on Less Than Immediate Unsigned */
|
|
#define MIPS_OP_ANDI 0x0C /* AND Immediate */
|
|
#define MIPS_OP_ORI 0x0D /* OR Immediate */
|
|
#define MIPS_OP_XORI 0x0E /* XOR Immediate */
|
|
#define MIPS_OP_LUI 0x0F /* Load Upper Immediate */
|
|
#define MIPS_OP_COP0 0x10 /* Coprocessor 0 (System) */
|
|
#define MIPS_OP_COP2 0x12 /* Coprocessor 2 (GTE) */
|
|
#define MIPS_OP_LB 0x20 /* Load Byte */
|
|
#define MIPS_OP_LH 0x21 /* Load Halfword */
|
|
#define MIPS_OP_LW 0x23 /* Load Word */
|
|
#define MIPS_OP_LBU 0x24 /* Load Byte Unsigned */
|
|
#define MIPS_OP_LHU 0x25 /* Load Halfword Unsigned */
|
|
#define MIPS_OP_SB 0x28 /* Store Byte */
|
|
#define MIPS_OP_SH 0x29 /* Store Halfword */
|
|
#define MIPS_OP_SW 0x2B /* Store Word */
|
|
|
|
/* --- MIPS CPU Function Codes (Bits 5-0, used when OP == MIPS_OP_SPECIAL) --- */
|
|
|
|
#define MIPS_FC_SLL 0x00 /* Shift Word Left Logical */
|
|
#define MIPS_FC_SRL 0x02 /* Shift Word Right Logical */
|
|
#define MIPS_FC_SRA 0x03 /* Shift Word Right Arithmetic */
|
|
#define MIPS_FC_SLLV 0x04 /* Shift Word Left Logical Variable */
|
|
#define MIPS_FC_SRLV 0x06 /* Shift Word Right Logical Variable */
|
|
#define MIPS_FC_SRAV 0x07 /* Shift Word Right Arithmetic Variable */
|
|
#define MIPS_FC_JR 0x08 /* Jump Register */
|
|
#define MIPS_FC_JALR 0x09 /* Jump and Link Register */
|
|
#define MIPS_FC_SYSCALL 0x0C /* System Call */
|
|
#define MIPS_FC_BREAK 0x0D /* Breakpoint */
|
|
#define MIPS_FC_MFHI 0x10 /* Move From HI */
|
|
#define MIPS_FC_MTHI 0x11 /* Move To HI */
|
|
#define MIPS_FC_MFLO 0x12 /* Move From LO */
|
|
#define MIPS_FC_MTLO 0x13 /* Move To LO */
|
|
#define MIPS_FC_MULT 0x18 /* Multiply Word */
|
|
#define MIPS_FC_MULTU 0x19 /* Multiply Unsigned Word */
|
|
#define MIPS_FC_DIV 0x1A /* Divide Word */
|
|
#define MIPS_FC_DIVU 0x1B /* Divide Unsigned Word */
|
|
#define MIPS_FC_ADD 0x20 /* Add Word */
|
|
#define MIPS_FC_ADDU 0x21 /* Add Unsigned Word */
|
|
#define MIPS_FC_SUB 0x22 /* Subtract Word */
|
|
#define MIPS_FC_SUBU 0x23 /* Subtract Unsigned Word */
|
|
#define MIPS_FC_AND 0x24 /* AND */
|
|
#define MIPS_FC_OR 0x25 /* OR */
|
|
#define MIPS_FC_XOR 0x26 /* XOR */
|
|
#define MIPS_FC_NOR 0x27 /* NOR */
|
|
#define MIPS_FC_SLT 0x2A /* Set on Less Than */
|
|
#define MIPS_FC_SLTU 0x2B /* Set on Less Than Unsigned */
|
|
|
|
/* --- Coprocessor 0 (System Control & Exceptions) --- */
|
|
|
|
#define MIPS_COP_MF 0x00 /* Move From Coprocessor */
|
|
#define MIPS_COP_MT 0x04 /* Move To Coprocessor */
|
|
|
|
|
|
|
|
|
|
// Bitfield Packets (Encoders)
|
|
|
|
/* Bit Offsets for MIPS Instruction Fields */
|
|
|
|
#define MIPS_OPCODE_SHIFT 26
|
|
#define MIPS_RS_SHIFT 21
|
|
#define MIPS_RT_SHIFT 16
|
|
#define MIPS_RD_SHIFT 11
|
|
#define MIPS_SHAMT_SHIFT 6
|
|
#define MIPS_FC_SHIFT 0
|
|
|
|
/* Bit Masks to prevent overflow into adjacent fields */
|
|
|
|
#define MIPS_OPCODE_MASK 0x3F
|
|
#define MIPS_REG_MASK 0x1F
|
|
#define MIPS_SHAMT_MASK 0x1F
|
|
#define MIPS_FC_MASK 0x3F
|
|
#define MIPS_IMM_MASK 0xFFFF
|
|
|
|
/* MIPS R-Type Instruction Format (Register-to-Register) */
|
|
#define ENC_R(op, rs, rt, rd, shamt, funct) \
|
|
((((op) & MIPS_OPCODE_MASK) << MIPS_OPCODE_SHIFT) | \
|
|
(((rs) & MIPS_REG_MASK) << MIPS_RS_SHIFT) | \
|
|
(((rt) & MIPS_REG_MASK) << MIPS_RT_SHIFT) | \
|
|
(((rd) & MIPS_REG_MASK) << MIPS_RD_SHIFT) | \
|
|
(((shamt) & MIPS_SHAMT_MASK) << MIPS_SHAMT_SHIFT) | \
|
|
(((funct) & MIPS_FC_MASK) << MIPS_FC_SHIFT))
|
|
|
|
/* MIPS I-Type Instruction Format (Immediate/Constant) */
|
|
#define ENC_I(op, rs, rt, imm) \
|
|
((((op) & MIPS_OPCODE_MASK) << MIPS_OPCODE_SHIFT) | \
|
|
(((rs) & MIPS_REG_MASK) << MIPS_RS_SHIFT) | \
|
|
(((rt) & MIPS_REG_MASK) << MIPS_RT_SHIFT) | \
|
|
(((imm) & MIPS_IMM_MASK)))
|
|
|
|
/* COP0 (System) Transfer Format */
|
|
#define ENC_COP0_TX(sub, rt, rd) \
|
|
((MIPS_OP_COP0 << MIPS_OPCODE_SHIFT) | \
|
|
(((sub) & MIPS_REG_MASK) << MIPS_RS_SHIFT) | \
|
|
(((rt) & MIPS_REG_MASK) << MIPS_RT_SHIFT) | \
|
|
(((rd) & MIPS_REG_MASK) << MIPS_RD_SHIFT))
|
|
|
|
/* COP0 Return From Exception (rfe) */
|
|
#define ENC_RFE() 0x42000010
|
|
|
|
|
|
// Binary Metaprogramming
|
|
|
|
typedef U4 const Code;
|
|
#define def_code_blob(sym) sym ## _ ## blob [] align_(4) =
|
|
|
|
// #define def_code_blob(func_name, func_signature, ...) \
|
|
// internal U4 const \
|
|
// tmpl(func_name,blob) [] align(4) \
|
|
// = { \
|
|
// __VA_ARGS__ \
|
|
// }; \
|
|
// internal func_signature func_name = (func_signature)func_name##_blob;
|
|
|
|
internal
|
|
Code def_code_blob(mips_flush_icache) {
|
|
/* addiu , , -8 */
|
|
ENC_I(MIPS_OP_ADDIU, REG_STACK_PTR, REG_STACK_PTR, -8),
|
|
/* sw , 4() */
|
|
ENC_I(MIPS_OP_SW, REG_STACK_PTR, REG_RETURN_ADDR, 4),
|
|
/* addiu , , 0x44 (BIOS Call 0x44: FlushCache) */
|
|
ENC_I(MIPS_OP_ADDIU, REG_DISCARD, REG_RETURN_VAL, 0x44),
|
|
/* addiu , , 0xA0 (BIOS A0 Table Address) */
|
|
ENC_I(MIPS_OP_ADDIU, REG_DISCARD, REG_TEMP_1, 0xA0),
|
|
/* jalr , (Jump to BIOS) */
|
|
ENC_R(MIPS_OP_SPECIAL, REG_TEMP_1, R_ZERO, REG_RETURN_ADDR, 0, MIPS_FC_JALR),
|
|
/* nop (Branch delay slot) */
|
|
ENC_R(MIPS_OP_SPECIAL, R_ZERO, R_ZERO, R_ZERO, 0, MIPS_FC_SLL),
|
|
/* lw , 4() */
|
|
ENC_I(MIPS_OP_LW, REG_STACK_PTR, REG_RETURN_ADDR, 4),
|
|
/* jr (Return to C code) */
|
|
ENC_R(MIPS_OP_SPECIAL, REG_RETURN_ADDR, R_ZERO, R_ZERO, 0, MIPS_FC_JR),
|
|
/* addiu , , 8 (Branch delay slot: restore stack pointer) */
|
|
ENC_I(MIPS_OP_ADDIU, REG_STACK_PTR, REG_STACK_PTR, 8)
|
|
};
|
|
FI_ void mips_flush_icache(void) { C_(VoidFn*, mips_flush_icache_blob)(); }
|
|
|
|
/* Flushes the Instruction Cache so the CPU sees our newly written tape */
|
|
// FI_ void mips_flush_icache(void) {
|
|
// /* Uses standard PS1 BIOS A0 table call 0x44 */
|
|
// __asm__ volatile (
|
|
// "li $v0, 0x44\n\t"
|
|
// "li $t1, 0xA0\n\t"
|
|
// "jalr $t1\n\t"
|
|
// "nop"
|
|
// : : : "v0", "t1", "ra", "memory"
|
|
// );
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// TAPE & EMITTERS
|
|
|
|
|
|
|