reducing cruft (still ideating)

This commit is contained in:
2026-06-14 13:15:25 -04:00
parent 66facd79dd
commit 30e2a84ebf
6 changed files with 38 additions and 87 deletions
+1 -1
View File
@@ -44,7 +44,7 @@
#define V_ volatile
// 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 ISO_ restrict // Sole-access path: Isolated Provenance. Alternative to Exu_. Guarantees electrical memory isolation,
#define ISO_ restrict // Isolated Provenance: Alternative to Exu_. Guarantees electrical memory isolation,
// unlocking the compilers ability to safely pack data across multiple parallel SIMD lanes (vectorization).
#define LSU_ volatile // Load/Store Unit Bound: The compiler is forbidden from caching in registers. Forces physical L1 Cache matrix sampling.
#define LIVE_ volatile // Live External Data: Alternative to Lsu_ emphasizing the memory is tapped by an external electrical actor.
+29 -78
View File
@@ -265,67 +265,39 @@
* ============================================================================
*
* A complete GCC inline-asm statement has up to 4 sections separated by `:`:
*
* asm volatile ( "code" : OUTPUTS : INPUTS : CLOBBERS );
*
* Every section-builder below prepends the `:` separator that GCC requires,
* so you can compose them inline without thinking about punctuation. The
* master `asm_block(...)` then wraps the four sections in `asm volatile (...)`.
*
* asm_block(
* asm_code( "..." ),
* asm_out ( "=r"(x), "+m"(y) ), // optional
* asm_in ( "r"(a), "m"(b) ), // optional
* asm_clb ( "$8", "memory" ) // optional
* );
*
* Common idioms (kept for back-compat / terseness):
*
* asm_blob(asm_inline(...), asm_clobber(...)) // 2-section, no I/O
* asm_block(asm_inline(...), , , ) // 4-section, empty
* give me as better example:
*/
/* `asm_code` is a passthrough — it does NOT prepend a colon, since the code
* section is always the first (no separator needed before it). The format
* string + `"i"(...)` operand list are produced by `asm_inline(...)` and
* just pass through unchanged. */
#define asm_code(...) __VA_ARGS__
/* `asm_out` prepends `:` — separates code/outputs/inputs/clobbers */
#define asm_out(...) : __VA_ARGS__
/* `asm_in` prepends `:` */
#define asm_in(...) : __VA_ARGS__
/* `asm_clb` prepends `:` */
#define asm_clb(...) : __VA_ARGS__
/* `asm_clobber` is the legacy single-section name. Kept for existing
* call-sites that put inputs *before* clobbers and want both as one colon-
* prefixed block (i.e. the user wrote `: "r"(x) ... : "..."` by hand). */
#define asm_clobber(...) : __VA_ARGS__
#define asm_out(...) :
#define asm_in(...) :
#define asm_clobber(...) :
/* `asm_inline(...)` dispatches into `_INL_<count>` to emit up to 99 encoded
* instruction words. This is the "compiled-instruction" form of `asm_code`.
*
* Result is a 2-colon body WITHOUT the final clobber section:
* ".word %c0, %c1, ..." : : "i"(p0), "i"(p1)
* |----- code -----| |--- empty ---| |------- inputs -------|
*
* ".word %c0, %c1, ..." : --- empty --- : "i"(p0), "i"(p1), ...
* |------ code --------| |--- outputs ---| |------- inputs -------|
*
* Use it inside `asm volatile( ... )` like so:
*
* asm volatile(
* asm_inline(w0, w1, w3)
* : clobbers
* )
*
* which expands to:
*
* asm volatile(
* ".word %c0, %c1, %c2" : : "i"(w0), "i"(w1), "i"(w2)
* asm volatile(".word %c0, %c1, %c2"
* : // empty outputs
* : "i"(w0), "i"(w1), "i"(w2)
* : "$2", "$8", ...
* )
*
* 3 colons total. Always valid. */
#define asm_inline(...) m_expand(glue(_INL_, _ASM_COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__))
*/
#define asm_inline(...) m_expand(glue(_INL_, _ASM_COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__))
/* reg_str(n) — Stringify an integer register id into the GCC asm
* string form (e.g. 12 → "$12"). Use this anywhere GCC's parser
@@ -343,53 +315,32 @@
* register V3_S2* p0 rgcc(R_T4) = ...; // bundled
*
* asm volatile("nop" : : : reg_str(R_RA), "memory"); // clobber list */
#define reg_str_(n) "$" #n
#define reg_str(n) reg_str_(n)
#define rlit_impl(n) "$" #n
#define rlit(n) rlit_impl(n)
/* ------------------------------------------------------------------------ *
* rgcc(n) — GCC-specific bundle for register-variable declarations.
*
* Produces `__asm__(reg_str(tmpl(n, Code)))` at expansion time. The
* `tmpl(n, Code)` indirection derives the preprocessor-visible `_Code`
* form from the enum name (which the preprocessor can't expand on
* its own). So a call like
*
* register V3_S2* p rgcc(R_T4) = verts[0].ptr;
*
* expands (via tmpl) to
*
* register V3_S2* p __asm__(reg_str(R_T4_Code))
* = verts[0].ptr;
*
* which (via reg_str) becomes
*
* register V3_S2* p __asm__("$12") = verts[0].ptr;
* Produces `__asm__(reg_str(tmpl(n, Code)))` at expansion time.
* The `tmpl(n, Code)` indirection derives the preprocessor-visible `_Code`
* form from the enum name (which the preprocessor can't expand on its own).
* So a call is: register V3_S2* p rgcc(R_T4) = verts[0].ptr;
* expands (via tmpl) to: register V3_S2* p __asm__(rlit(R_T4_Code)) = verts[0].ptr;
* which (via reg_str) becomes: register V3_S2* p __asm__("$12") = verts[0].ptr;
*
* Why bundle the `__asm__()` wrapper?
* - The integer R_T4 (= 12, via R_T4_Code) is the canonical truth.
* - 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. `rgcc(R_T4)` says what you mean.
* - 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.
* - Spelling `__asm__(reg_str(R_T4_Code))` at every call site is noise.
*
* The two-level form (rgcc_/rgcc) is the standard preprocessor idiom
* for forcing one level of expansion before the bundle's `__asm__`
* token is written; without it, `rgcc(R_T4)` would expand to
* `__asm__(reg_str(tmpl(R_T4, Code)))` but the inner `tmpl(R_T4, Code)`
* would token-paste prematurely.
* tmpl defined in dsl.h (the 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.
*
* Layering: reg_str lives in dsl.h (the integer-to-string primitive,
* compiler-agnostic in name). tmpl lives in dsl.h (the token-paste
* glue). rgcc lives 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
* reg_str can be retargeted in one place.
*
* For clobber lists and asm-template strings, use the bare
* `reg_str(R_T4_Code)` — you don't want __asm__() there, you just
* want the string.
* For clobber lists and asm-template strings, use the bare `rlit(R_T4_Code)`.
* ------------------------------------------------------------------------ */
#define rgcc_(n) __asm__(reg_str(tmpl(n, Code)))
#define rgcc_(n) __asm__(rlit(tmpl(n, Code)))
#define rgcc(n) rgcc_(n)
/* rgcc_ref(n) — GCC operand-reference form "%N". Not currently used
+3 -3
View File
@@ -448,21 +448,21 @@ enum {
asm volatile( \
asm_inline( gte_lwc2_v0(base), gte_lwc2_v0z(base) ) \
, "r"(r_ptr) \
asm_clobber( reg_str(R_V0_Code), reg_str(R_T0_Code), reg_str(R_T1_Code), reg_str(R_RA_Code), "memory" ) \
asm_clobber( rlit(R_V0_Code), rlit(R_T0_Code), rlit(R_T1_Code), rlit(R_RA_Code), "memory" ) \
)
#define gte_load_v1(r_ptr, base) \
asm volatile( \
asm_inline( gte_lwc2_v1(base), gte_lwc2_v1z(base) ) \
, "r"(r_ptr) \
asm_clobber( reg_str(R_V0_Code), reg_str(R_T0_Code), reg_str(R_T1_Code), reg_str(R_RA_Code), "memory" ) \
asm_clobber( rlit(R_V0_Code), rlit(R_T0_Code), rlit(R_T1_Code), rlit(R_RA_Code), "memory" ) \
)
#define gte_load_v2(r_ptr, base) \
asm volatile( \
asm_inline( gte_lwc2_v2(base), gte_lwc2_v2z(base) ) \
, "r"(r_ptr) \
asm_clobber( reg_str(R_V0_Code), reg_str(R_T0_Code), reg_str(R_T1_Code), reg_str(R_RA_Code), "memory" ) \
asm_clobber( rlit(R_V0_Code), rlit(R_T0_Code), rlit(R_T1_Code), rlit(R_RA_Code), "memory" ) \
)
/* gte_load_v0v1v2(p0, p1, p2, b0, b1, b2) — the canonical prelude to gte_cmd_rtpt.
+3 -3
View File
@@ -54,9 +54,9 @@ FI_ B4 mem_zero (U4 dest, U4 len) { if(dest == 0){return fa
#pragma region Slice
typedef unsigned char UTF8;
typedef Struct_(Str8) { UTF8* ptr; U4 len; };
typedef Struct_(Slice_Str8) { Str8* ptr; U4 len; };
#define txt(string_literal) (Str8){ (UTF8*) string_literal, S_(string_literal) - 1 }
typedef Struct_(Str8) { UTF8* ptr; U4 len; };
typedef Struct_(Slice_Str8) { Str8* ptr; U4 len; };
#define slit(string_literal) (Str8){ (UTF8*) string_literal, S_(string_literal) - 1 }
typedef Struct_(Slice) { U4 ptr, len; }; // Untyped Slice
FI_ Slice slice_ut_(U4 ptr, U4 len) { return (Slice){ptr, len}; }
+1 -1
View File
@@ -503,7 +503,7 @@ FI_ void mips_flush_icache(void) { C_(VoidFn*, codeblob_mips_flush_icache)(); }
* "memory" barrier. The register ids are passed through `reg_str` so
* the R_*_Code `#define`s are stringified into "$N" at expansion time. */
#define clb_system \
reg_str(R_V0_Code), reg_str(R_T0_Code), reg_str(R_T1_Code), reg_str(R_RA_Code), "memory"
rlit(R_V0_Code), rlit(R_T0_Code), rlit(R_T1_Code), rlit(R_RA_Code), "memory"
#define asm_mips_flush_icache() asm volatile( asm_inline( \
add_ui(rstack_ptr, rstack_ptr, -8) \
+1 -1
View File
@@ -115,7 +115,7 @@ I_ B1* prim__alloc(U4 type_width, Str8 type_name) {
pa->used += type_width;
return next;
}
#define prim_alloc(type) (type*)prim__alloc(S_(type), txt( stringify(type)))
#define prim_alloc(type) (type*)prim__alloc(S_(type), slit( stringify(type)))
void gp_screen_init_c11(DoubleBuffer* screen_buf, S2* active_buf_id)
{