mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-25 02:20:33 +00:00
build_noramlized_v3s4 mostly reviewed.
This commit is contained in:
+42
-59
@@ -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) ───
|
||||
|
||||
Reference in New Issue
Block a user