WIP: preparing to setup metaprogramming codegen for PS1 processors.

This commit is contained in:
2026-06-01 02:57:56 -04:00
parent 8b5fb7a5a1
commit fe4bd6d86d
11 changed files with 649 additions and 367 deletions
+203
View File
@@ -0,0 +1,203 @@
#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