build_noramlized_v3s4 mostly reviewed.

This commit is contained in:
ed
2026-08-18 16:10:29 -04:00
parent 290bb0e07a
commit bbda5efaea
12 changed files with 382 additions and 170 deletions
+3 -2
View File
@@ -37,6 +37,7 @@
// The 'Yield' sequence for Tape Atoms (mac_yield).
#define mac_yield(...) \
load_word(R_AtomJmp, R_TapePtr, 0) \
LdSlot_ \
, add_ui_self( R_TapePtr, S_(MipsCode)) \
, jump_reg( R_AtomJmp) \
, BdSlot_ nop
@@ -217,7 +218,7 @@ WORD_COUNT(mac_gte_ld_ir123_v3s4, 3)
, mac_gte_mv_from_mac123_v3s4(a) \
GteDelay_ /* Read MAC1/2/3 → a.xyz (overwrites source-A's load targets) */ \
, mac_shift_aright_v3s4_self(a, 12) /* Right-shift MAC by 12 (S12.20 → S12.0 OuterProduct12) */
WORD_COUNT(mac_gte_op_cross_v3s4, 16)
WORD_COUNT(mac_gte_op_cross_v3s4, 13)
/* atom_dbg_skip */
#define mac_gte_store_f3(r_primitive_cursor) \
@@ -291,7 +292,7 @@ WORD_COUNT(mac_gte_sqr_v3s4, 5)
, shift_aright_var(r_dx, r_dx, r_shift) \
, shift_aright_var(r_dy, r_dy, r_shift) \
, shift_aright_var(r_dz, r_dz, r_shift)
WORD_COUNT(mac_gte_gpf_scale, 12)
WORD_COUNT(mac_gte_gpf_scale, 13)
#define mac_trans_mt3s3s4(r_mtx, r_off, r_t0, r_t1, r_t2) \
load_word( r_t0, r_off, O_(V3_S4,x)) \
+1 -1
View File
@@ -33,7 +33,7 @@ enum {
atom_offset_example_atom_proc_skip = _atom_offset_example_atom_proc_skip,
};
// --- atom: build_normalize_v3s4 (65 words) ---
// --- atom: build_normalize_v3s4 (63 words) ---
#define _atom_offset_aligned_done_srav_path 3
#define _atom_offset_srav_path_aligned_done 4
+42 -59
View File
@@ -272,82 +272,65 @@ typedef Struct_(Binds_NormalizeV3S4) {
U2 dst_offset; /* offset of dst V3_S4 within the BIOS scratchpad */
};
typedef Struct_(RegUse_build_normalize_v3s4) {
Reg src_ptr;
Reg dst_ptr;
Reg src_x;
Reg src_z;
Reg recip_est;
Reg norm;
Reg shift;
union {
Reg v_sqr_aligned, dst_offset;
} t3;
union { Reg mac2; } t4;
union { Reg btarget, shift_count, sqrtbl_index, src_offset; } t5;
union { Reg_(V3_S4) res, src; };
union { Reg t0, src_ptr, mac2; };
union { Reg t1, dst_ptr; };
union { Reg t2, dst_offset, mac1, v_sqr_aligned; };
union { Reg t3, src_offset, btarget, shift_count, sqrtbl_index; };
union { Reg t4, mac3, v_sqr_sum, half_shift_tmp, inv_len; };
union { Reg t5, lzcr, half_shift; };
};
/* ─── Full normalize (all 4 stages inline) ───
* Generic 4-stage GTE normalize (SQR → sum+LZCR → align+sqrtbl → GPF+srav). */
internal MipsAtom* build_normalize_v3s4(AtomArena_R aa, RegUse_build_normalize_v3s4 r)
MipsAtom_Proc_(aa, {
load_half(r.t5.src_offset, R_TapePtr, O_(Binds_NormalizeV3S4, src_offset)),
load_half(r.t3.dst_offset, R_TapePtr, O_(Binds_NormalizeV3S4, dst_offset)),
LdSlot_ add_u(r.src_ptr, R_ScratchBase, r.t5.src_offset),
LdSlot_ add_u(r.dst_ptr, R_ScratchBase, r.t3.dst_offset),
load_half(r.src_offset, R_TapePtr, O_(Binds_NormalizeV3S4, src_offset)),
load_half(r.dst_offset, R_TapePtr, O_(Binds_NormalizeV3S4, dst_offset)),
LdSlot_ add_u(r.src_ptr, R_ScratchBase, r.src_offset),
LdSlot_ add_u(r.dst_ptr, R_ScratchBase, r.dst_offset),
LdSlot_ add_ui_self(R_TapePtr, S_(Binds_NormalizeV3S4)),
/* Load src.x/y/z from r_src_ptr (caller-determined address) into r_src_x / r_recip_est / r_src_z.
* r_src_x holds src.x throughout stages 1-2; r_recip_est (which is src.y during this phase) is reused as MAC2 in stage 4. */
mac_load_word_v3(r.src_x, r.recip_est, r.src_z, r.src_ptr, 0),
mac_load_v3s4(r.src, r.src_ptr, 0),
/* Stage 1: mtc2 src → IR1/2/3, SQR fires. */
LdSlot_ mac_gte_sqr_v3s4(r.src_x, r.recip_est, r.src_z, LdSlot_ nop),
LdSlot_ mac_gte_sqr_v3s4(r.src.x, r.src.y, r.src.z, LdSlot_ nop),
/* Stage 2: mfc2 MAC1/2/3, sum, mtc2 LZCS. */
mac_gte_mv_from_data_r_mac123(r.t3.v_sqr_aligned, r.t4.mac2, r.norm), LdSlot_ nop,
add_u_self( r.norm, r.t3.v_sqr_aligned),
add_u_self( r.norm, r.t4.mac2),
gte_mv_to_data_r( r.norm, C2_LZCS), GteDelay_ nop2,
gte_mv_from_data_r(r.shift, C2_LZCR), GteDelay_ nop,
/* Stage 2: mfc2 MAC1/2/3, sum, mtc2 LZCS. src_ptr is dead; reuse as mac2. */
mac_gte_mv_from_data_r_mac123(r.mac1, r.mac2, r.mac3), LdSlot_ nop,
add_u_self( r.v_sqr_sum, r.mac1),
add_u_self( r.v_sqr_sum, r.mac2),
gte_mv_to_data_r( r.v_sqr_sum, C2_LZCS), GteDelay_ nop2,
gte_mv_from_data_r(r.lzcr, C2_LZCR), GteDelay_ nop,
/* Stage 3: round LZCR to even, compute half-shift, align |v|² to bit 24.
* r_norm holds |v|² sum; r_shift holds the LZCR count from mfc2.
* After the component: r_shift = even(LZCR), r_norm = half-shift, r_t3.v_sqr_aligned = |v|². */
mac_lzcr_round_even_half_shift(r.shift, r.norm, r.t3.v_sqr_aligned),
add_si( r.t5.btarget, r.shift, -24),
branch_lt_zero(r.t5.btarget, atom_offset(aligned_done, srav_path)), BdSlot_ nop, /* bltz → srav_path (LZCR < 24 path) */
jump_rel(atom_offset(srav_path, aligned_done)), /* b → aligned_done (LZCR >= 24 path) */
BdSlot_ shift_lleft_var(r.t3.v_sqr_aligned, r.t3.v_sqr_aligned, r.t5.btarget),
/* Stage 3: even(LZCR), half-shift, align |v|² to bit 24. */
mac_lzcr_round_even_half_shift(r.lzcr, r.v_sqr_sum, r.v_sqr_aligned),
add_si( r.btarget, r.lzcr, -24),
branch_lt_zero(r.btarget, atom_offset(aligned_done, srav_path)), BdSlot_ nop, /* bltz → srav_path (LZCR < 24 path) */
jump_rel(atom_offset(srav_path, aligned_done)), /* b → aligned_done (LZCR >= 24 path) */
BdSlot_ shift_lleft_var(r.v_sqr_aligned, r.v_sqr_aligned, r.btarget),
atom_label(srav_path)
li_s( r.t5.shift_count, 24),
sub_s(r.t5.shift_count, r.t5.shift_count, r.shift),
shift_aright_var(r.t3.v_sqr_aligned, r.t3.v_sqr_aligned, r.t5.shift_count),
li_s( r.shift_count, 24),
sub_s(r.shift_count, r.shift_count, r.lzcr),
shift_aright_var(r.v_sqr_aligned, r.v_sqr_aligned, r.shift_count),
atom_label(aligned_done)
// Save the shift count to r_shift before the next 5 instructions overwrite r_norm (the sqrtbl lookup loads 1/|v| into r_norm, which becomes IR0 in stage 4).
or_u(r.shift, r.norm, 0), /* r_shift ← shift count (preserved through stage 4) */
add_si( r.t3.v_sqr_aligned, r.t3.v_sqr_aligned, -64), /* r_t3.v_sqr_aligned holds |v|² aligned (top bit at bit 7). */
shift_lleft(r.t3.v_sqr_aligned, r.t3.v_sqr_aligned, 1),
mac_load_word_imm(r.t5.sqrtbl_index, & gte_normalize_sqr_tbl), add_u_self(r.t5.sqrtbl_index, r.t3.v_sqr_aligned),
load_half(r.norm, r.t5.sqrtbl_index, 0), /* r_norm = sqrtbl[aligned-64] = 1/|v| (IR0 in stage 4) */
or_u(r.half_shift, r.half_shift_tmp, 0),
add_si( r.v_sqr_aligned, r.v_sqr_aligned, -64),
shift_lleft(r.v_sqr_aligned, r.v_sqr_aligned, 1),
mac_load_word_imm(r.sqrtbl_index, & gte_normalize_sqr_tbl), add_u_self(r.sqrtbl_index, r.v_sqr_aligned),
load_half(r.inv_len, r.sqrtbl_index, 0),
LdSlot_ nop,
/* r.src_z holds src.z from the initial load (r.src_z is a dedicated slot,
* never clobbered between the load at body start and the stage-4 GPF use below).
* Stage 4: GPF + srav finalize (r_shift = shift count, r_norm = 1/|v|). */
mac_gte_general_purpose_interopolation(
r.norm,
r.src_x, /* IR1 = src.x (preserved in r_tmp — r_mac2_scratch was clobbered to MAC2 in stage 1.5) */
r.recip_est,
r.src_z, /* IR3 = src.z (reloaded) */
r.t4.mac2, r.recip_est, r.src_z,
GteDelay_ nop,
GteDelay_ nop
mac_gte_general_purpose_interopolation(r.inv_len,
r.src.x, r.src.y, r.src.z,
r.res.x, r.res.y, r.res.z,
GteDelay_ load_word(R_AtomJmp, R_TapePtr, 0), LdSlot_ // ac_yield: word 1
GteDelay_ add_ui_self( R_TapePtr, S_(MipsCode)) // ac_yield: word 2
),
/* sra by r_shift = (31-LZCR)/2 (saved before sqrtbl lookup) */
mac_shift_aright_var_v3_self(r.t4.mac2, r.recip_est, r.src_z, r.shift),
/* Store result.x/y/z to r_dst_ptr (caller-determined dst address). */
mac_store_word_v3(r.t4.mac2, r.recip_est, r.src_z, r.dst_ptr, 0),
mac_shift_aright_var_v3s4_self(r.res, r.half_shift),
mac_store_v3s4(r.res, r.dst_ptr, 0),
mac_yield()
jump_reg(R_AtomJmp), BdSlot_ nop // ac_yield: word 3-4
// mac_yield()
})
/* ─── GTE OP cross product (a × b → out) ───
+1 -1
View File
@@ -263,7 +263,7 @@ FI_ void tb_scope_run_end(TapeBuilder* tb) { tb_emit(tb,tape_exit); tape_run(tb_
// The 'Yield' sequence for Tape Atoms (mac_yield).
atom_dbg_skip MipsAtomComp_(ac_yield) {
load_word(R_AtomJmp, R_TapePtr, 0),
load_word(R_AtomJmp, R_TapePtr, 0), LdSlot_
add_ui_self( R_TapePtr, S_(MipsCode)),
jump_reg( R_AtomJmp), BdSlot_ nop,
};
+7 -11
View File
@@ -151,17 +151,13 @@ internal void compile_init_atoms(void) {
smem.normalize_v3s4 = build_normalize_v3s4(& ab,
RegUse_(build_normalize_v3s4) {
.src_ptr = ralloc(),
.dst_ptr = ralloc(),
.recip_est = ralloc(),
.norm = ralloc(),
.shift = ralloc(),
.src_x = ralloc(),
.src_z = ralloc(),
// .shift_count = ralloc(), /* dedicated slot for stage-3 → stage-4 shift count */
.t3 = ralloc(),
.t4 = ralloc(),
.t5 = ralloc(),
.res = ralloc_v3(),
.t0 = ralloc(),
.t1 = ralloc(),
.t2 = ralloc(),
.t3 = ralloc(),
.t4 = ralloc(),
.t5 = ralloc(),
});
regfile_reset(& rf);