Author SHA1 Message Date
ed 159ead625e fixing weird identifiers... 2026-08-22 22:48:58 -04:00
ed 52888015de reviewing 2026-08-22 21:03:57 -04:00
16 changed files with 61 additions and 126 deletions
+2 -2
View File
@@ -21,7 +21,7 @@ const TOKEN_TYPES = [
"tapeGprRegister", "tapeGprRegister",
"tapeCop2Register", "tapeCop2Register",
"tapeDuffleType", "tapeDuffleType",
"tapeAttribute", "tapeAt__ibute",
"keyword", "keyword",
"macro", "macro",
]; ];
@@ -43,7 +43,7 @@ const DSL_KEYWORDS = new Set([
"Slice_", "TypeR_", "TypeV_", "align_", "internal", "local_persist", "global", "Slice_", "TypeR_", "TypeV_", "align_", "internal", "local_persist", "global",
"RO_", "LP_", "gknown", "expect_", "cexpr_", "RO_", "LP_", "gknown", "expect_", "cexpr_",
"asm", "asm_words", "asm_rpins", "asm_clobber", "asm", "asm_words", "asm_rpins", "asm_clobber",
"O_", "S_", "C_", "T_", "tmpl", "glue", "r_", "v_", "tr_", "tv_", "O_", "S_", "C_", "T_", "tmpl", "glue", "r_", "v_", "rt_", "vt_",
"rgcc", "r_use", "r_set", "r_mod", "r_imm", "r_mem", "rgcc", "r_use", "r_set", "r_mod", "r_imm", "r_mem",
"u1_", "u2_", "u4_", "u8_", "s1_", "s2_", "s4_", "s8_", "u1_", "u2_", "u4_", "u8_", "s1_", "s2_", "s4_", "s8_",
"u1_r", "u2_r", "u4_r", "u8_r", "u1_v", "u2_v", "u4_v", "u8_v", "u1_r", "u2_r", "u4_r", "u8_r", "u1_v", "u2_v", "u4_v", "u8_v",
+1 -1
View File
@@ -19,7 +19,7 @@ const BASE_ATTRIBUTES = [
"Slice_", "TypeR_", "TypeV_", "align_", "internal", "local_persist", "global", "Slice_", "TypeR_", "TypeV_", "align_", "internal", "local_persist", "global",
"RO_", "LP_", "gknown", "expect_", "cexpr_", "RO_", "LP_", "gknown", "expect_", "cexpr_",
"asm", "asm_words", "asm_rpins", "asm_clobber", "asm", "asm_words", "asm_rpins", "asm_clobber",
"O_", "S_", "C_", "T_", "tmpl", "glue", "r_", "v_", "tr_", "tv_", "O_", "S_", "C_", "T_", "tmpl", "glue", "r_", "v_", "rt_", "vt_",
"rgcc", "r_use", "r_set", "r_mod", "r_imm", "r_mem", "rgcc", "r_use", "r_set", "r_mod", "r_imm", "r_mem",
"u1_", "u2_", "u4_", "u8_", "s1_", "s2_", "s4_", "s8_", "u1_", "u2_", "u4_", "u8_", "s1_", "s2_", "s4_", "s8_",
"u1_r", "u2_r", "u4_r", "u8_r", "u1_v", "u2_v", "u4_v", "u8_v", "u1_r", "u2_r", "u4_r", "u8_r", "u1_v", "u2_v", "u4_v", "u8_v",
+1 -1
View File
@@ -44,7 +44,7 @@
* *
* Annotation rules * Annotation rules
* ---------------- * ----------------
* 1. atom_info(...) is OPTIONAL. Atoms without atom_info are silently skipped by the metaprogram. * 1. atom_info(...) is optional. Atoms without atom_info are silently skipped by the metaprogram.
* 2. If present, atom_info takes up to three sub-calls, all order-independent within the arg list: * 2. If present, atom_info takes up to three sub-calls, all order-independent within the arg list:
* - atom_bind(Binds_X) * - atom_bind(Binds_X)
* - atom_reads(...) * - atom_reads(...)
+5 -4
View File
@@ -29,7 +29,7 @@
#define asm __asm__ #define asm __asm__
#define A_(data) (& data) #define A_(data) (& (data))
#define align_(value) __attribute__((aligned (value))) // for easy alignment #define align_(value) __attribute__((aligned (value))) // for easy alignment
#define align_(value) __attribute__((aligned (value))) // for easy alignment #define align_(value) __attribute__((aligned (value))) // for easy alignment
#define C_(type,data) ((type)(data)) // for enforced precedence #define C_(type,data) ((type)(data)) // for enforced precedence
@@ -45,7 +45,8 @@
#define R_ restrict #define R_ restrict
#define V_ volatile #define V_ volatile
#pragma region Fictional //, used for intiution #pragma region Fictional
//, used for intiution
#define EUB_ restrict // Execute Unit Bound: Data is siloed in the ALU Register File. The Load/Store Unit is bypassed. (Route to Execution Unit. Keep in registers) #define EUB_ restrict // Execute Unit Bound: Data is siloed in the ALU Register File. The Load/Store Unit is bypassed. (Route to Execution Unit. Keep in registers)
#define ISO_ restrict // Isolated Provenance: Alternative to Exu_. Guarantees electrical memory isolation, #define ISO_ restrict // Isolated Provenance: Alternative to Exu_. Guarantees electrical memory isolation,
@@ -83,8 +84,8 @@
#define r_(ptr) C_(T_(ptr[0])*R_, ptr) // Constrain pointer to restrict #define r_(ptr) C_(T_(ptr[0])*R_, ptr) // Constrain pointer to restrict
#define v_(ptr) C_(T_(ptr[0])V_*, ptr) // #define v_(ptr) C_(T_(ptr[0])V_*, ptr) //
#define tr_(type, ptr) C_(type *R_, ptr) #define rt_(type, ptr) C_(type *R_, ptr)
#define tv_(type, ptr) C_(type V_*, ptr) #define vt_(type, ptr) C_(type V_*, ptr)
#define TypeR_(type) type *R_ type ## _R // type *restrict type_R #define TypeR_(type) type *R_ type ## _R // type *restrict type_R
#define TypeV_(type) type V_* type ## _V // type volatile* type_V #define TypeV_(type) type V_* type ## _V // type volatile* type_V
-8
View File
@@ -79,14 +79,6 @@
* Why bundle the `__asm__()` wrapper? * Why bundle the `__asm__()` wrapper?
* - The integer R_T4 (= 12, via R_T4_Code) already indicates the register. * - The integer R_T4 (= 12, via R_T4_Code) already indicates the register.
* - The string "$12" is derived from it via reg_str, so they cannot drift apart. * - The string "$12" is derived from it via reg_str, so they cannot drift apart.
* - Spelling `__asm__(reg_str(R_T4_Code))` at every call site is noise.
*
* tmpl defined in dsl.h (token-paste glue).
* rgcc define here (gcc_asm.h) because the `__asm__` keyword is GCC-specific.
* Anyone porting to a different compiler's asm dialect overrides rgcc,
* and the integer→string derivation in rlit can be retargeted in one place.
*
* For clobber lists and asm-template strings, use the bare `rlit(R_T4_Code)`.
* ------------------------------------------------------------------------ */ * ------------------------------------------------------------------------ */
#define rgcc(n) __asm__(rlit(n)) #define rgcc(n) __asm__(rlit(n))
+11 -11
View File
@@ -19,7 +19,7 @@
// source: C:\projects\Pikuma\ps1\code\duffle\pad.c // source: C:\projects\Pikuma\ps1\code\duffle\pad.c
// source: C:\projects\Pikuma\ps1\code\duffle\math.atom.h // source: C:\projects\Pikuma\ps1\code\duffle\math.atom.h
// source: C:\projects\Pikuma\ps1\code\duffle\mips.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\mips.atom.c
// source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.h
// source: C:\projects\Pikuma\ps1\code\duffle\gp.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\gp.atom.c
// source: C:\projects\Pikuma\ps1\code\duffle\pad.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\pad.atom.c
// source: C:\projects\Pikuma\ps1\code\duffle\psyq.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\psyq.atom.c
@@ -270,10 +270,10 @@ WORD_COUNT(mac_gte_store_g4_p3, 1)
WORD_COUNT(mac_gte_sqr_v3, 8) WORD_COUNT(mac_gte_sqr_v3, 8)
/* atom_dbg_skip */ /* atom_dbg_skip */
#define mac_gte_sqr_v3s4(r_sx, r_sy, r_sz, delay_slot) \ #define mac_gte_sqr_v3s4(sx, sy, sz, delay_slot) \
gte_mv_to_data_r(r_sx, C2_IR1) \ gte_mv_to_data_r(sx, C2_IR1) \
, gte_mv_to_data_r(r_sy, C2_IR2) \ , gte_mv_to_data_r(sy, C2_IR2) \
, gte_mv_to_data_r(r_sz, C2_IR3) \ , gte_mv_to_data_r(sz, C2_IR3) \
, delay_slot \ , delay_slot \
, gte_cmdw_sqr , gte_cmdw_sqr
WORD_COUNT(mac_gte_sqr_v3s4, 5) WORD_COUNT(mac_gte_sqr_v3s4, 5)
@@ -304,12 +304,12 @@ WORD_COUNT(mac_gte_gpf_scale, 13)
WORD_COUNT(mac_trans_mt3s3s4, 6) WORD_COUNT(mac_trans_mt3s3s4, 6)
/* atom_dbg_skip */ /* atom_dbg_skip */
#define mac_lzcr_round_even_half_shift(r_shift, r_mag_sq, r_mag_sq_copy) \ #define mac_lzcr_round_even_half_shift(shift, mag_sq, mag_sq_copy) \
and_i(r_shift, r_shift, gte_lzcr_even_mask) \ and_i(shift, shift, gte_lzcr_even_mask) \
, or_u(r_mag_sq_copy, r_mag_sq, 0) \ , or_u(mag_sq_copy, mag_sq, 0) \
, li_s( r_mag_sq, 31) \ , li_s( mag_sq, 31) \
, sub_s( r_mag_sq, r_mag_sq, r_shift) \ , sub_s( mag_sq, mag_sq, shift) \
, shift_aright(r_mag_sq, r_mag_sq, 1) , shift_aright(mag_sq, mag_sq, 1)
WORD_COUNT(mac_lzcr_round_even_half_shift, 5) WORD_COUNT(mac_lzcr_round_even_half_shift, 5)
#define mac_gte_general_purpose_interopolation(to_ir0, to_ir1, to_ir2, to_ir3, fr_mac1, fr_mac2, fr_mac3, nop_slot1, nop_slot2) \ #define mac_gte_general_purpose_interopolation(to_ir0, to_ir1, to_ir2, to_ir3, fr_mac1, fr_mac2, fr_mac3, nop_slot1, nop_slot2) \
+1 -1
View File
@@ -16,7 +16,7 @@
// source: C:\projects\Pikuma\ps1\code\duffle\pad.c // source: C:\projects\Pikuma\ps1\code\duffle\pad.c
// source: C:\projects\Pikuma\ps1\code\duffle\math.atom.h // source: C:\projects\Pikuma\ps1\code\duffle\math.atom.h
// source: C:\projects\Pikuma\ps1\code\duffle\mips.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\mips.atom.c
// source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.h
// source: C:\projects\Pikuma\ps1\code\duffle\gp.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\gp.atom.c
// source: C:\projects\Pikuma\ps1\code\duffle\pad.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\pad.atom.c
// source: C:\projects\Pikuma\ps1\code\duffle\psyq.atom.c // source: C:\projects\Pikuma\ps1\code\duffle\psyq.atom.c
+1 -16
View File
@@ -6,16 +6,6 @@
* Primitive commands: gp0_cmd_poly_f3 = 0x20 (byte opcode) * Primitive commands: gp0_cmd_poly_f3 = 0x20 (byte opcode)
* Packed 32-bit cmd: gp0_word_poly_f3(r, g, b) (32-bit, shifted) * Packed 32-bit cmd: gp0_word_poly_f3(r, g, b) (32-bit, shifted)
* *
* Type ordering: domain?_(direction)?_action_target_modifier_type?
* Examples: add_ui (add + unsigned + immediate)
* add_s (add + signed, R-type implicit)
* shift_lleft (shift + logical + left)
* shift_aright (shift + arithmetic + right)
* call_reg(rs) (call + register, $ra implicit)
* gte_mv_to_data_r (gte + mv + to + data + register)
* gte_lw_v0_xy(base) (gte + lw + v0 + xy)
* load_upper_i (load-upper + immediate, unique verb)
*
* --- GPU-domain layer cake --- * --- GPU-domain layer cake ---
* Every gp.h macro follows the same 4-layer composition as mips.h and gte.h: * Every gp.h macro follows the same 4-layer composition as mips.h and gte.h:
* 4. Semantic encoders gp0_word_poly_f3(r,g,b) * 4. Semantic encoders gp0_word_poly_f3(r,g,b)
@@ -23,9 +13,6 @@
* 2. Per-field encoders enc_gp0_color_r(r), enc_gp0_color_g(g), ... * 2. Per-field encoders enc_gp0_color_r(r), enc_gp0_color_g(g), ...
* 1. Bitfield layout consts gp0_color_red_pos = 0, gp0_color_red_width = 8 * 1. Bitfield layout consts gp0_color_red_pos = 0, gp0_color_red_width = 8
* 0. Opcode IDs gp0_cmd_poly_f3 = 0x20 * 0. Opcode IDs gp0_cmd_poly_f3 = 0x20
*
* Vendor mnemonics (gte_mtc2, gte_mfc2, etc.) are NOT in this header.
* They live in the opt-in `gp_vendor_sym.h` for users who prefer the PSYQ-style names.
* ============================================================================ */ * ============================================================================ */
#ifdef INTELLISENSE_DIRECTIVES #ifdef INTELLISENSE_DIRECTIVES
@@ -391,10 +378,8 @@ enum {
* Primitive structs (8 polygon variants + tag) * Primitive structs (8 polygon variants + tag)
* ============================================================================ * ============================================================================
* Each struct follows the GPU-documented memory layout for the corresponding primitive command. * Each struct follows the GPU-documented memory layout for the corresponding primitive command.
* The PolyTag is the OT-link header; the rest of the struct is the primitive's body. * PolyTag is an OT-link header. Rest of the struct is the primitive's body.
* *
* The current working layouts match the existing demo
* (floor_tri uses Poly_F3; cube_tri uses Poly_G4).
* They are NOT necessarily byte-identical to the PSX-SPX reference layout. * They are NOT necessarily byte-identical to the PSX-SPX reference layout.
* The demo layout uses color+vertex interleaving that doesn't match the standard PSX SDK file format. * The demo layout uses color+vertex interleaving that doesn't match the standard PSX SDK file format.
* For PSX-SDK file compatibility, the textured variants (FT*, GT*) would need layout adjustments. * For PSX-SDK file compatibility, the textured variants (FT*, GT*) would need layout adjustments.
@@ -96,11 +96,11 @@ FI_ Slice_MipsCode ac_gte_sqr_v3(AtomBuilder_R ab, U4 r_sx, U4 r_sy, U4 r_sz, U4
}) })
/* ─── SQR FIRE — mtc2 3 GPRs into IR1/IR2/IR3, then fire SQR. ─── */ /* ─── SQR FIRE — mtc2 3 GPRs into IR1/IR2/IR3, then fire SQR. ─── */
FI_ Slice_MipsCode ac_gte_sqr_v3s4(AtomBuilder_R ab, Reg r_sx, Reg r_sy, Reg r_sz, MipsCode delay_slot) FI_ Slice_MipsCode ac_gte_sqr_v3s4(AtomBuilder_R ab, Reg sx, Reg sy, Reg sz, MipsCode delay_slot)
atom_dbg_skip MipsAtomComp_Proc_(ab, { atom_dbg_skip MipsAtomComp_Proc_(ab, {
gte_mv_to_data_r(r_sx, C2_IR1), gte_mv_to_data_r(sx, C2_IR1),
gte_mv_to_data_r(r_sy, C2_IR2), gte_mv_to_data_r(sy, C2_IR2),
gte_mv_to_data_r(r_sz, C2_IR3), gte_mv_to_data_r(sz, C2_IR3),
delay_slot, gte_cmdw_sqr, delay_slot, gte_cmdw_sqr,
}) })
@@ -157,16 +157,13 @@ FI_ Slice_MipsCode ac_trans_mt3s3s4(AtomBuilder_R ab
* *
* Note: C2_LZCR (cop2r31) is a fixed read-only C2 data register the caller must read it via mfc2 from C2_LZCR; * Note: C2_LZCR (cop2r31) is a fixed read-only C2 data register the caller must read it via mfc2 from C2_LZCR;
* there is no register choice at the hardware level. Only the GPR that holds the result is caller-determined. */ * there is no register choice at the hardware level. Only the GPR that holds the result is caller-determined. */
FI_ Slice_MipsCode ac_lzcr_round_even_half_shift(AtomBuilder_R ab, FI_ Slice_MipsCode ac_lzcr_round_even_half_shift(AtomBuilder_R ab, Reg shift, Reg mag_sq, Reg mag_sq_copy)
U4 r_shift,
U4 r_mag_sq,
U4 r_mag_sq_copy)
atom_dbg_skip MipsAtomComp_Proc_(ab, { atom_dbg_skip MipsAtomComp_Proc_(ab, {
and_i(r_shift, r_shift, gte_lzcr_even_mask), and_i(shift, shift, gte_lzcr_even_mask),
or_u(r_mag_sq_copy, r_mag_sq, 0), or_u(mag_sq_copy, mag_sq, 0),
li_s( r_mag_sq, 31), li_s( mag_sq, 31),
sub_s( r_mag_sq, r_mag_sq, r_shift), sub_s( mag_sq, mag_sq, shift),
shift_aright(r_mag_sq, r_mag_sq, 1), shift_aright(mag_sq, mag_sq, 1),
}) })
FI_ Slice_MipsCode ac_gte_general_purpose_interopolation(AtomBuilder_R ab FI_ Slice_MipsCode ac_gte_general_purpose_interopolation(AtomBuilder_R ab
@@ -339,21 +336,21 @@ typedef Struct_(Binds_gte_cross_v3s4) { V3_S4* src_a; V3_S4* src_b; V3_S4* out;
typedef Struct_(RegUse_gte_cross_v3s4) { typedef Struct_(RegUse_gte_cross_v3s4) {
Reg_(V3_S4) a; Reg_(V3_S4) a;
Reg_(V3_S4) b; Reg_(V3_S4) b;
union { Reg out, t0; } x; Reg out;
union { Reg src_a, t1, rt11; } y; Reg src_a;
union { Reg src_b, t2, rt22; } z; Reg src_b;
}; };
internal MipsAtom* gte_cross_v3s4(AtomArena_R aa, RegUse_gte_cross_v3s4 r) internal MipsAtom* gte_cross_v3s4(AtomArena_R aa, RegUse_gte_cross_v3s4 r)
atom_info(atom_bind(Binds_gte_cross_v3s4)) MipsAtom_Proc_(aa, { atom_info(atom_bind(Binds_gte_cross_v3s4)) MipsAtom_Proc_(aa, {
load_word(r.y.src_a, R_TapePtr, O_(Binds_gte_cross_v3s4,src_a)), load_word(r.src_a, R_TapePtr, O_(Binds_gte_cross_v3s4,src_a)),
load_word(r.z.src_b, R_TapePtr, O_(Binds_gte_cross_v3s4,src_b)), load_word(r.src_b, R_TapePtr, O_(Binds_gte_cross_v3s4,src_b)),
load_word(r.x.out, R_TapePtr, O_(Binds_gte_cross_v3s4,out)), load_word(r.out, R_TapePtr, O_(Binds_gte_cross_v3s4,out)),
LdSlot_ add_ui_self( R_TapePtr, S_(Binds_gte_cross_v3s4)), LdSlot_ add_ui_self(R_TapePtr, S_(Binds_gte_cross_v3s4)),
mac_load_v3s4(r.a, r.y.src_a, 0), LdSlot_ mac_load_v3s4(r.a, r.src_a, 0), LdSlot_
mac_load_v3s4(r.b, r.z.src_b, 0), LdSlot_ mac_load_v3s4(r.b, r.src_b, 0), LdSlot_
mac_gte_op_cross_v3s4(r.a, r.b), /* RT diagonal + IR + OP + MAC read + shift */ mac_gte_op_cross_v3s4(r.a, r.b), /* RT diagonal + IR + OP + MAC read + shift */
mac_store_v3s4(r.a, r.x.out, 0), mac_store_v3s4(r.a, r.out, 0),
mac_yield() mac_yield()
}) })
+1 -26
View File
@@ -1,21 +1,10 @@
/* ============================================================================ /* ============================================================================
* duffle DSL Suffix Conventions * duffle DSL Suffix Conventions
* ============================================================================ * ============================================================================
*
* Every mnemonic in this header follows the same suffix grammar: * Every mnemonic in this header follows the same suffix grammar:
* *
* Primitive commands: gp0_cmd_poly_f3 = 0x20 (byte opcode) * Primitive commands: gp0_cmd_poly_f3 = 0x20 (byte opcode)
* Packed 32-bit cmd: gp0_word_poly_f3(r, g, b) (32-bit, shifted) * Packed 32-bit cmd: gp0_word_poly_f3(r, g, b) (32-bit, shifted)
*
* Type ordering: domain?_(direction)?_action_target_modifier_type?
* Examples: add_ui (add + unsigned + immediate)
* add_s (add + signed, R-type implicit)
* shift_lleft (shift + logical + left)
* shift_aright (shift + arithmetic + right)
* call_reg(rs) (call + register, $ra implicit)
* gte_mv_to_data_r (gte + mv + to + data + register)
* gte_lw_v0_xy(base) (gte + lw + v0 + xy)
* load_upper_i (load-upper + immediate, unique verb)
* ============================================================================ */ * ============================================================================ */
#ifdef INTELLISENSE_DIRECTIVES #ifdef INTELLISENSE_DIRECTIVES
@@ -29,21 +18,7 @@
/* ============================================================================ /* ============================================================================
* gte.h — Geometry Transformation Engine (COP2) for the PS1 * gte.h — Geometry Transformation Engine (COP2) for the PS1
* ============================================================================ * ============================================================================
* * DSL for emitting GTE/MIPS instruction words from C.
* Hand-rolled DSL for emitting GTE/MIPS instruction words from C.
* No GCC inline-assembly string syntax in the code body.
*
* STYLE NOTES
* -----------
* - Per-field encoders are named `enc_gte_<field>(value)` and each one self-masks its argument before shifting.
* Mirrors the `enc_op / enc_rs / enc_rt / ...` family in mips.h.
* - The composite `enc_gte_cmdw(sf, mx, v, cv, lm, cmd)` is a flat OR of the per-field encoders, plus the COP2/CO base.
* - Pre-baked shortcuts (`gte_cmd_rtpt`, `gte_cmd_rtps`, …) are defined for the common cases so call sites read like assembly source.
* - All register/field values are enums (not `#define`s) so they show up in debugger symbol tables and IDE autocomplete.
*
* SEE ALSO
* --------
* - mips.h: The MIPS encoder layer this builds on.
*/ */
/* C2 data registers */ /* C2 data registers */
+3 -4
View File
@@ -58,13 +58,13 @@ typedef Struct_(Str8) { UTF8* ptr; U4 len; };
typedef Struct_(Slice_Str8) { Str8* ptr; U4 len; }; typedef Struct_(Slice_Str8) { Str8* ptr; U4 len; };
#define slit(string_literal) (Str8){ (UTF8*) string_literal, S_(string_literal) - 1 } #define slit(string_literal) (Str8){ (UTF8*) string_literal, S_(string_literal) - 1 }
typedef Struct_(Slice) { B1* ptr; U4 len; }; // Untyped Slice (byte-addressable; .len in elements) typedef Struct_(Slice) { B1* ptr; U4 len; };
FI_ Slice slice_ut_(U4 ptr, U4 len) { return (Slice){(B1*)ptr, len}; } FI_ Slice slice_ut_(U4 ptr, U4 len) { return (Slice){(B1*)ptr, len}; }
#define Slice_(type) Struct_(tmpl(Slice,type)) { type* ptr; U4 len; } #define Slice_(type) Struct_(tmpl(Slice,type)) { type* ptr; U4 len; }
typedef Slice_(B1); typedef Slice_(B1);
#define slice_assert(s) do { assert((s).ptr != 0); assert((s).len > 0); } while(0) #define slice_assert(s) do { assert((s).ptr != 0); assert((s).len > 0); } while(0)
#define slice_end(slice) ((slice).ptr + S_slice(slice) / S_(B1)) /* byte-ptr arithmetic; .len is in elements per slice convention */ #define slice_end(slice) ((slice).ptr + S_slice(slice) / S_(B1))
#define S_slice(s) ((s).len * S_((s).ptr[0])) #define S_slice(s) ((s).len * S_((s).ptr[0]))
#define slice_ut(ptr,len) slice_ut_(u4_(ptr), u4_(len)) #define slice_ut(ptr,len) slice_ut_(u4_(ptr), u4_(len))
@@ -134,8 +134,7 @@ FI_ U4 farena_unused_start(FArena arena) { return arena.start + arena.used; }
#pragma region BIOS Scratchpad #pragma region BIOS Scratchpad
/* BIOS scratchpad location. 1 KB at 0x1F800000. /* BIOS scratchpad location. 1 KB at 0x1F800000.
* TapeHostFrame occupies the final 44 bytes while tape code executes. * TapeHostFrame occupies the final 44 bytes while tape code executes. */
* Atom scratch is bounded by the TapeHostFrame_Loc declaration in lottes_tape.h. */
enum { enum {
Scratchpad_Loc = 0x1F800000, Scratchpad_Loc = 0x1F800000,
Scratchpad_Len = 0x400, /* 1 KB */ Scratchpad_Len = 0x400, /* 1 KB */
+1 -6
View File
@@ -81,13 +81,8 @@ enum {
* (e.g. for asm clobber lists and register-variable declarations via `rgcc(R_X)`). * (e.g. for asm clobber lists and register-variable declarations via `rgcc(R_X)`).
* The enum value is bound to the `#define` so the two forms cannot drift apart. * The enum value is bound to the `#define` so the two forms cannot drift apart.
* *
* Only registers that get stringified need a `_Code` form; the rest are plain enum values.
* If you need to add a new one, follow the pattern:
* #define R_T7_Code 15
* R_T7 = R_T7_Code, // in the enum
*
* User code should always reference the enum form (`R_T4`) at arithmetic sites and let * User code should always reference the enum form (`R_T4`) at arithmetic sites and let
* `rlit(R_T4_Code)` / `rgcc(R_T4)` handle the stringify cases — never write the bare number `12`. * `rlit(R_T4_Code)` / `rgcc(R_T4)` handle the stringify cases
* ============================================================================ */ * ============================================================================ */
#define R_0_Code 0 #define R_0_Code 0
#define R_AT_Code 1 #define R_AT_Code 1
+2 -11
View File
@@ -6,16 +6,10 @@
# include "pad.h" # include "pad.h"
#endif #endif
/* Uses ONE 8-byte frame allocated via the compiler's standard prologue. /* Uses an 8-byte frame allocated via the compiler's standard prologue.
* 4 wasted-arg words for B(12h) InitPAD2 are at [SP+0..15] but are not explicitly allocated. * 4 wasted-arg words for B(12h) InitPAD2 are at [SP+0..15] but are not explicitly allocated.
* Compiler handles the MIPS O32 "wasted stack" convention for us by treating the B-call as a 4-arg call. * Compiler handles the MIPS O32 "wasted stack" convention for us by treating the B-call as a 4-arg call.
* */
* The buffer pointers are passed as arguments so the compiler keeps them in callee-saved registers;
* The B(12h) asm volatile block does NOT clobber those registers (it clobbers only the volatile GPRs + B-table arg registers explicitly).
* The C-level writes after the call re-load the pointers from their callee-saved homes.
*
* The clobber list for both B-calls names the full BIOS destroy set documented in kernelbios.md:167-174 (R1..R15, R24..R25, R31, HI/LO).
* The kernel-ABI "volatile GPRs" subset is clb_mem_drain; the rest of the destroy set is enumerated explicitly here. */
NI_ void pad_bios_init_start(PadBiosRaw* raw0, PadBiosRaw* raw1) NI_ void pad_bios_init_start(PadBiosRaw* raw0, PadBiosRaw* raw1)
{ {
/* Pin raw0 + raw1 to $a0 + $a1 via rgcc; the B(12h) call uses these directly. /* Pin raw0 + raw1 to $a0 + $a1 via rgcc; the B(12h) call uses these directly.
@@ -24,9 +18,6 @@ NI_ void pad_bios_init_start(PadBiosRaw* raw0, PadBiosRaw* raw1)
register PadBiosRaw* p1 rgcc(R_A1) = raw1; register PadBiosRaw* p1 rgcc(R_A1) = raw1;
(void)p0; (void)p1; (void)p0; (void)p1;
// TODO(Ed): Properly annotate the raw values in the inline asm instructions.
// Use enums.
/* B(12h) InitPAD2(raw0, 0x22, raw1, 0x22) /* B(12h) InitPAD2(raw0, 0x22, raw1, 0x22)
* $a0 = raw0 (rgcc-bound; survives the sequence below) * $a0 = raw0 (rgcc-bound; survives the sequence below)
* $a1 = raw1 (preserved into $a2 before $a1 is overwritten) * $a1 = raw1 (preserved into $a2 before $a1 is overwritten)
+2 -2
View File
@@ -11,8 +11,8 @@
# include "duffle/word_count.metadata.h" # include "duffle/word_count.metadata.h"
# include "duffle/psyq.h" # include "duffle/psyq.h"
# include "duffle/math.atom.h" # include "duffle/math.atom.h"
# include "duffle/gte.atom.h"
# include "duffle/mips.atom.c" # include "duffle/mips.atom.c"
# include "duffle/gte.atom.c"
# include "duffle/gp.atom.c" # include "duffle/gp.atom.c"
# include "duffle/psyq.atom.c" # include "duffle/psyq.atom.c"
# include "gen/offsets.h" # include "gen/offsets.h"
@@ -21,7 +21,7 @@
# include "hello_camera.h" # include "hello_camera.h"
#endif #endif
ATOM_FILE_DEBUGGER_LINE_MARKER(hello_joypad_atom_c); ATOM_FILE_DEBUGGER_LINE_MARKER(hello_camera_atom_c);
#pragma region MACs (Mips Atom components) #pragma region MACs (Mips Atom components)
+4 -4
View File
@@ -34,7 +34,7 @@
#include "duffle/pad.c" #include "duffle/pad.c"
#include "duffle/math.atom.h" #include "duffle/math.atom.h"
#include "duffle/mips.atom.c" #include "duffle/mips.atom.c"
#include "duffle/gte.atom.c" #include "duffle/gte.atom.h"
#include "duffle/gp.atom.c" #include "duffle/gp.atom.c"
#include "duffle/pad.atom.c" #include "duffle/pad.atom.c"
#include "duffle/psyq.atom.c" #include "duffle/psyq.atom.c"
@@ -140,9 +140,9 @@ internal void compile_init_atoms(void) {
RegUse_(gte_cross_v3s4) { RegUse_(gte_cross_v3s4) {
.a = ralloc_v3(), .a = ralloc_v3(),
.b = ralloc_v3(), .b = ralloc_v3(),
.x = ralloc(), .out = ralloc(),
.y = ralloc(), .src_a = ralloc(),
.z = ralloc(), .src_b = ralloc(),
}); });
regfile_reset(& rf); regfile_reset(& rf);
+3 -3
View File
@@ -61,7 +61,7 @@ I_ void ent_cube128_init(A8_V3_S2* verts, A6_V4_S2* faces) {
typedef Struct_(Ent_Cube) { typedef Struct_(Ent_Cube) {
V3_S4 accel; V3_S4 accel;
V3_S4 vel; V3_S4 vel;
V3_S4 pos; // RGA(Lengyel): affine point with implicit weight one. Storage alias of V3_S4. V3_S4 pos;
V3_S4 scale; V3_S4 scale;
V3_S2 rot; V3_S2 rot;
A8_V3_S2 verts; A8_V3_S2 verts;
@@ -88,7 +88,7 @@ I_ void ent_floor_init(A4_V3_S2* verts, A2_V3_S2* faces) {
}; };
typedef Struct_(Ent_Floor) { typedef Struct_(Ent_Floor) {
V3_S4 accel; V3_S4 accel;
V3_S4 pos; // RGA(Lengyel): affine point with implicit weight one. Storage alias of V3_S4. V3_S4 pos;
V3_S4 scale; V3_S4 scale;
V3_S2 rot; V3_S2 rot;
A4_V3_S2 verts; A4_V3_S2 verts;
@@ -96,7 +96,7 @@ typedef Struct_(Ent_Floor) {
}; };
typedef Struct_(Camera) { typedef Struct_(Camera) {
P3_S4 pos; // RGA(Lengyel): affine point with implicit weight one. Storage alias of V3_S4. P3_S4 pos;
V3_S2 rot; V3_S2 rot;
MT3_S2S4 look_at; MT3_S2S4 look_at;
}; };