I don't like c asm

This commit is contained in:
2026-06-01 09:25:21 -04:00
parent fe4bd6d86d
commit b81221cbf5
3 changed files with 503 additions and 129 deletions
+143 -129
View File
@@ -1,138 +1,146 @@
#ifdef INTELLISENSE_DIRECTIVES
# pragma once
# include "dsl.h"
# include "gcc_asm.h"
#endif
enum {
/* --- 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
};
R_0 = 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) */
, rdiscard = R_0 /* Hardwired to 0 */
, rret_0 = R_V0 /* Function return value */
, rret_1 = R_V1 /* Second return value (e.g., 64-bit) */
, rarg_0 = R_A0 /* First function argument */
, rarg_1 = R_A1 /* Second function argument */
, rarg_2 = R_A2 /* Third function argument */
, rarg_3 = R_A3 /* Fourth function argument */
, rtmp_0 = R_T0 /* Temporary (Caller saved) */
, rtmp_1 = R_T1 /* Temporary (Caller saved) */
, rtmp_2 = R_T2 /* Temporary (Caller saved) */
, rsaved_0 = R_S0 /* Saved register (Callee saved) */
, rstack_ptr = R_SP /* Stack Pointer */
, rret_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 */
, op_special = 0x00 /* R-Type instructions (uses FUNCT field) */
, op_bcond = 0x01 /* Branch on condition */
, op_j = 0x02 /* Jump */
, op_jal = 0x03 /* Jump and Link */
, op_beq = 0x04 /* Branch on Equal */
, op_bne = 0x05 /* Branch on Not Equal */
, op_blez = 0x06 /* Branch on Less Than or Equal to Zero */
, op_bgtz = 0x07 /* Branch on Greater Than Zero */
, op_addi = 0x08 /* Add Immediate */
, op_addiu = 0x09 /* Add Immediate Unsigned */
, op_slti = 0x0A /* Set on Less Than Immediate */
, op_sltiu = 0x0B /* Set on Less Than Immediate Unsigned */
, op_andi = 0x0C /* AND Immediate */
, op_ori = 0x0D /* OR Immediate */
, op_xori = 0x0E /* XOR Immediate */
, op_lui = 0x0F /* Load Upper Immediate */
, op_cop0 = 0x10 /* Coprocessor 0 (System) */
, op_cop2 = 0x12 /* Coprocessor 2 (GTE) */
, op_la = 0
, op_li = 0
, op_lb = 0x20 /* Load Byte */
, op_lh = 0x21 /* Load Halfword */
, op_lw = 0x23 /* Load Word */
, op_lbu = 0x24 /* Load Byte Unsigned */
, op_lhu = 0x25 /* Load Halfword Unsigned */
, op_sb = 0x28 /* Store Byte */
, op_sh = 0x29 /* Store Halfword */
, op_sw = 0x2B /* Store Word */
, op_load_addr = op_la
, op_load_imm = op_li
, op_jump = op_j
, op_jump_nlink = op_jal
/* --- 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 */
, fc_sll = 0x00 /* Shift Word Left Logical */
, fc_srl = 0x02 /* Shift Word Right Logical */
, fc_sra = 0x03 /* Shift Word Right Arithmetic */
, fc_sllv = 0x04 /* Shift Word Left Logical Variable */
, fc_srlv = 0x06 /* Shift Word Right Logical Variable */
, fc_srav = 0x07 /* Shift Word Right Arithmetic Variable */
, fc_jr = 0x08 /* Jump Register */
, fc_jalr = 0x09 /* Jump and Link Register */
, fc_syscall = 0x0C /* System Call */
, fc_break = 0x0D /* Breakpoint */
, fc_mfhi = 0x10 /* Move From HI */
, fc_mthi = 0x11 /* Move To HI */
, fc_mflo = 0x12 /* Move From LO */
, fc_mtlo = 0x13 /* Move To LO */
, fc_mult = 0x18 /* Multiply Word */
, fc_multu = 0x19 /* Multiply Unsigned Word */
, fc_div = 0x1A /* Divide Word */
, fc_divu = 0x1B /* Divide Unsigned Word */
, fc_add = 0x20 /* Add Word */
, fc_addu = 0x21 /* Add Unsigned Word */
, fc_sub = 0x22 /* Subtract Word */
, fc_subu = 0x23 /* Subtract Unsigned Word */
, fc_and = 0x24 /* AND */
, fc_or = 0x25 /* OR */
, fc_xor = 0x26 /* XOR */
, fc_nor = 0x27 /* NOR */
, fc_slt = 0x2A /* Set on Less Than */
, fc_sltu = 0x2B /* Set on Less Than Unsigned */
, fc_jump_reg = fc_jr
/* --- Coprocessor 0 (System Control & Exceptions) --- */
#define MIPS_COP_MF 0x00 /* Move From Coprocessor */
#define MIPS_COP_MT 0x04 /* Move To Coprocessor */
, cop_mf = 0x00 /* Move From Coprocessor */
, cop_mt = 0x04 /* Move To Coprocessor */
};
// Bitfield Packets (Encoders)
enum { _BitOffsets = 0
/* 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
, OPCODE_SHIFT = 26
, RS_SHIFT = 21
, RT_SHIFT = 16
, RD_SHIFT = 11
, SHAMT_SHIFT = 6 /* Shift Amount */
, 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
, OPCODE_MASK = 0x3F
, REG_MASK = 0x1F
, SHAMT_MASK = 0x1F /* Shift Amount */
, FC_MASK = 0x3F
, IMM_MASK = 0xFFFF
};
#define enc_op(op) (((op) & OPCODE_MASK) << OPCODE_SHIFT)
#define enc_rs(rs) (((rs) & REG_MASK) << RS_SHIFT)
#define enc_rt(rt) (((rt) & REG_MASK) << RT_SHIFT)
#define enc_rd(rd) (((rd) & REG_MASK) << RD_SHIFT)
#define enc_shamt(shamt) (((shamt) & SHAMT_MASK) << SHAMT_SHIFT)
#define enc_fc(fc) (((fc) & FC_MASK) << FC_SHIFT)
#define enc_imm(imm) (((imm) & IMM_MASK))
/* 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))
#define enc_r(op, rs, rt, rd, shamt, fc) enc_op(op) | enc_rs(rs) | enc_rt(rt) | enc_rd(rd) | enc_shamt(shamt) | enc_fc(fc)
/* 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)))
#define enc_i(op, rs, rt, imm) enc_op(op) | enc_rs(rs) | enc_rt(rt) | enc_imm(imm)
/* COP0 (System) Transfer Format */
#define ENC_COP0_TX(sub, rt, rd) \
@@ -141,14 +149,24 @@ typedef enum {
(((rt) & MIPS_REG_MASK) << MIPS_RT_SHIFT) | \
(((rd) & MIPS_REG_MASK) << MIPS_RD_SHIFT))
/* COP0 Return From Exception (rfe) */
#define ENC_RFE() 0x42000010
/* COP0 Return From Exception (rfe) */
#define enc_rfe() 0x42000010
#define load_imm(rs,rt,imm) enc_i(op_lw, rs, rt, imm)
#define store_word(rs,rt,imm) enc_i(op_sw, rs, rt, imm)
#define add_ui(rs,rt,imm) enc_i(op_addiu, rs, rt, imm)
#define shift_ll(rs,rt,rd) enc_r(op_special, rs, rt, rd, 0, fc_sll)
#define jump_reg(rs) enc_r(op_special, rs, R_0, R_0, 0, fc_jr)
#define jump_nreg(rs,rt,rd) enc_r(op_special, rs, rt, rd, 0, fc_jalr)
#define nop() shift_ll(rdiscard, rdiscard, rdiscard)
// Binary Metaprogramming
typedef U4 const Code;
#define def_code_blob(sym) sym ## _ ## blob [] align_(4) =
#define CodeBlob_(sym) tmpl(codeblob,sym) [] align_(4) =
// #define def_code_blob(func_name, func_signature, ...) \
// internal U4 const \
@@ -158,28 +176,24 @@ typedef U4 const Code;
// }; \
// 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)
enum {
bios_flushcache = 0x44,
bios_table_addr = 0xA0,
};
FI_ void mips_flush_icache(void) { C_(VoidFn*, mips_flush_icache_blob)(); }
internal
Code CodeBlob_(mips_flush_icache) {
add_ui(rstack_ptr, rstack_ptr, -8),
store_word(rstack_ptr, rret_addr, 4),
add_ui(rdiscard, rret_0, bios_flushcache),
add_ui(rdiscard, rtmp_0, bios_table_addr),
jump_nreg(rtmp_0, rdiscard, rret_addr),
nop(),
load_imm(rstack_ptr, rret_addr, 4),
jump_reg(rret_addr),
add_ui(rstack_ptr, rstack_ptr, 8)
};
FI_ void mips_flush_icache(void) { C_(VoidFn*, codeblob_mips_flush_icache)(); }
/* Flushes the Instruction Cache so the CPU sees our newly written tape */
// FI_ void mips_flush_icache(void) {