mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-25 02:20:33 +00:00
resolve_look_at__cross_uz_ux_to_up_proc reviewed
This commit is contained in:
@@ -26,7 +26,7 @@ enum {
|
||||
atom_offset_end_low_exit_stick = _atom_offset_end_low_exit_stick,
|
||||
};
|
||||
|
||||
// --- atom: pad_input_cam (42 words) ---
|
||||
// --- atom: pad_input_cam (40 words) ---
|
||||
|
||||
#define _atom_offset_left_x_exit_left_x 3
|
||||
#define _atom_offset_right_x_exit_right_x 3
|
||||
|
||||
@@ -220,13 +220,13 @@ internal MipsAtom* resolve_look_at__cross_uz_up_into_right_proc(AtomArena_R aa,
|
||||
|
||||
/* Load uz into the RT diagonal. */
|
||||
gte_mv_to_ctrl_r(r.a, gte_cr_RT11), /* D1 = RT11 = uz.x (low 16 of $0, sign-extended by OP). */
|
||||
DmaSlot_ nop2, /* CTC2 retirement (CPU→COP2 2-slot delay) */
|
||||
GteDelay_ nop2, /* CTC2 retirement (CPU→COP2 2-slot delay) */
|
||||
|
||||
/* Load up_in into IR (the second operand for OP). */
|
||||
gte_mv_to_data_r(r.d, C2_IR1), /* IR1 = up_in.x */
|
||||
gte_mv_to_data_r(R_AT, C2_IR2), /* IR2 = up_in.y */
|
||||
gte_mv_to_data_r(r.t0, C2_IR3), /* IR3 = up_in.z */
|
||||
DmaSlot_ nop2, /* MTC2 retirement (CPU→COP2 2-slot delay) */
|
||||
GteDelay_ nop2, /* MTC2 retirement (CPU→COP2 2-slot delay) */
|
||||
|
||||
gte_cmdw_cross, /* OP: MAC1/2/3 = uz × up_in
|
||||
* MAC1 = IR3*D2 - IR2*D3 = up_in.z*uz.y.high - up_in.y*uz.z.high
|
||||
@@ -243,7 +243,7 @@ internal MipsAtom* resolve_look_at__cross_uz_up_into_right_proc(AtomArena_R aa,
|
||||
|
||||
/* mfc2 MAC1/2/3 → r_a/r_b/r_c (out.x/y/z). */
|
||||
mac_gte_mv_from_data_r_mac123(r.a, r.b, r.c),
|
||||
DmaSlot_ nop, /* MFC2 retirement */
|
||||
GteDelay_ nop, /* MFC2 retirement */
|
||||
|
||||
/* Right-shift MAC by 12 to convert from GTE's S12.20 fixed-point scale back to libpsyx OuterProduct12 convention (S12.0, fp_one=4096=1<<12).
|
||||
* Without this, MAC values (~16M for unit-vector cross products) overflow the GTE's 16-bit IR registers when atom 3 normalizes via mtc2. */
|
||||
@@ -254,74 +254,66 @@ internal MipsAtom* resolve_look_at__cross_uz_up_into_right_proc(AtomArena_R aa,
|
||||
mac_yield()
|
||||
})
|
||||
|
||||
typedef Struct_(RegUse_resolve_look_at__cross_uz_ux_to_up_proc) {
|
||||
Reg const scratch; /* pinned T4 */
|
||||
Reg_(V3_S4) a; /* uz components, then MAC / out */
|
||||
Reg_(V3_S4) b; /* ux components */
|
||||
union { Reg t0, up; }; /* &up, dedicated */
|
||||
union { Reg t1, uz, rt11; }; /* &uz, then RT11 save */
|
||||
union { Reg t2, ux, rt22; }; /* &ux, then RT22 save */
|
||||
};
|
||||
/* Atom 4: cross uz × ux → up. */
|
||||
internal MipsAtom* resolve_look_at__cross_uz_ux_to_up_proc(AtomArena_R aa, U4 r_scratch
|
||||
, U4 r_a, U4 r_b, U4 r_c /* load a.x/y/z; result out.x/y/z */
|
||||
, U4 r_d /* load b.x */
|
||||
, U4 r_f, U4 r_g, U4 r_h /* r_f = &up (out ptr), r_g = &uz, r_h = &ux */
|
||||
internal MipsAtom* resolve_look_at__cross_uz_ux_to_up_proc(AtomArena_R aa,
|
||||
RegUse_resolve_look_at__cross_uz_ux_to_up_proc r
|
||||
) MipsAtom_Proc_(aa, {
|
||||
/* Compute the three scratch pointers from r_scratch. */
|
||||
add_si(r_g, r_scratch, O_(ResolveLookAtScratch,uz)), /* r_g = &uz */
|
||||
add_si(r_h, r_scratch, O_(ResolveLookAtScratch,ux)), /* r_h = &ux */
|
||||
add_si(r_f, r_scratch, O_(ResolveLookAtScratch,up)), /* r_f = &up (out) */
|
||||
add_si(r.uz, r.scratch, O_(ResolveLookAtScratch,uz)), /* r.uz = &uz */
|
||||
add_si(r.ux, r.scratch, O_(ResolveLookAtScratch,ux)), /* r.ux = &ux */
|
||||
add_si(r.up, r.scratch, O_(ResolveLookAtScratch,up)), /* r.up = &up (out) */
|
||||
nop,
|
||||
|
||||
/* Load a (uz).x/y/z into r_a/r_b/r_c. */
|
||||
load_word(r_a, r_g, O_(V3_S4,x)),
|
||||
load_word(r_b, r_g, O_(V3_S4,y)),
|
||||
load_word(r_c, r_g, O_(V3_S4,z)),
|
||||
nop,
|
||||
/* Load a (uz).x/y/z into r.a. */
|
||||
mac_load_v3s4(r.a, r.uz, 0), LdSlot_ nop,
|
||||
|
||||
/* Load b (ux).x/y/z into r_d + R_AT/R_V0. */
|
||||
load_word(r_d, r_h, O_(V3_S4,x)),
|
||||
load_word(R_AT, r_h, O_(V3_S4,y)),
|
||||
load_word(R_V0, r_h, O_(V3_S4,z)),
|
||||
nop,
|
||||
/* Load b (ux).x/y/z into r.b. */
|
||||
mac_load_v3s4(r.b, r.ux, 0), LdSlot_ /* taken by gte_mv_from_ctrl_r */
|
||||
|
||||
/* OP reads D1/D2/D3 from RT11/RT22/RT33 ($0/$2/$4), not V0/V1/V2.
|
||||
* Mirror atom 1: cfc2 RT save, ctc2 RT diagonal from uz, mtc2 IR from ux,
|
||||
* ctc2 RT restore. */
|
||||
* Mirror atom 1: cfc2 RT save, ctc2 RT diagonal from uz, mtc2 IR from ux, ctc2 RT restore. */
|
||||
|
||||
/* Save the two RT control-register slots OP will clobber (reusing
|
||||
* r_g/r_h — they're no longer needed as scratch pointers). */
|
||||
gte_mv_from_ctrl_r(r_g, gte_cr_RT11), /* r_g = C2 $0 (RT11|RT12) */
|
||||
gte_mv_from_ctrl_r(r_h, gte_cr_RT22), /* r_h = C2 $4 (RT22|RT33) */
|
||||
/* Save the two RT control-register slots OP will clobber (reusing r.uz/r.ux — they're no longer needed as scratch pointers). */
|
||||
gte_mv_from_ctrl_r(r.rt11, gte_cr_RT11), /* r.rt11 = C2 $0 (RT11|RT12) */
|
||||
gte_mv_from_ctrl_r(r.rt22, gte_cr_RT22), /* r.rt22 = C2 $4 (RT22|RT33) */
|
||||
|
||||
/* Load uz into the RT diagonal — same packing as atom 1.
|
||||
* OP reads D1 = RT11 from $0.low, D2 = RT22 from $2.high, D3 = RT33 from $4.high.
|
||||
* RT22 is shared between $2.high and $4.low — the ctc2 sequence to $2 then $4
|
||||
* sets RT22 to uz.y.high (via $2), then to uz.z.low (via $4). OP reads
|
||||
* RT22 from $2.high which the second ctc2 doesn't touch, so D2 stays uz.y.high.
|
||||
* sets RT22 to uz.y.high (via $2), then to uz.z.low (via $4).
|
||||
* OP reads RT22 from $2.high which the second ctc2 doesn't touch, so D2 stays uz.y.high.
|
||||
* (This is libpsyx OuterProduct12 convention EXACTLY.) */
|
||||
gte_mv_to_ctrl_r(r_b, gte_cr_RT13), /* $2 = uz.y. RT13=uz.y.low, RT22=uz.y.high. */
|
||||
gte_mv_to_ctrl_r(r_c, gte_cr_RT22), /* $4 = uz.z. RT22=uz.z.low, RT33=uz.z.high. */
|
||||
gte_mv_to_ctrl_r(r_a, gte_cr_RT11), /* $0 = uz.x. RT11=uz.x. */
|
||||
nop2, /* CTC2 retirement (CPU→COP2 2-slot delay) */
|
||||
gte_mv_to_ctrl_r(r.a.y, gte_cr_RT13), /* $2 = uz.y. RT13=uz.y.low, RT22=uz.y.high. */
|
||||
gte_mv_to_ctrl_r(r.a.z, gte_cr_RT22), /* $4 = uz.z. RT22=uz.z.low, RT33=uz.z.high. */
|
||||
gte_mv_to_ctrl_r(r.a.x, gte_cr_RT11), /* $0 = uz.x. RT11=uz.x. */
|
||||
GteDelay_ nop2, /* CTC2 retirement (CPU→COP2 2-slot delay) */
|
||||
|
||||
/* Load ux into the IR registers (the second operand for OP). */
|
||||
gte_mv_to_data_r(r_d, C2_IR1), /* IR1 = ux.x */
|
||||
gte_mv_to_data_r(R_AT, C2_IR2), /* IR2 = ux.y */
|
||||
gte_mv_to_data_r(R_V0, C2_IR3), /* IR3 = ux.z */
|
||||
nop2, /* MTC2 retirement (CPU→COP2 2-slot delay) */
|
||||
gte_mv_to_data_r(r.b.x, C2_IR1), /* IR1 = ux.x */
|
||||
gte_mv_to_data_r(r.b.y, C2_IR2), /* IR2 = ux.y */
|
||||
gte_mv_to_data_r(r.b.z, C2_IR3), /* IR3 = ux.z */
|
||||
GteDelay_ nop2, /* MTC2 retirement (CPU→COP2 2-slot delay) */
|
||||
|
||||
gte_cmdw_outer_product,
|
||||
|
||||
/* Restore the RT slots we clobbered. */
|
||||
gte_mv_to_ctrl_r(r_g, gte_cr_RT11), /* restore C2 $0 (RT11|RT12) */
|
||||
gte_mv_to_ctrl_r(r_h, gte_cr_RT22), /* restore C2 $4 (RT22|RT33) */
|
||||
gte_mv_to_ctrl_r(r.rt11, gte_cr_RT11), /* restore C2 $0 (RT11|RT12) */
|
||||
gte_mv_to_ctrl_r(r.rt22, gte_cr_RT22), /* restore C2 $4 (RT22|RT33) */
|
||||
|
||||
mac_gte_mv_from_data_r_mac123(r.a.x, r.a.y, r.a.z),
|
||||
GteDelay_ nop,
|
||||
|
||||
gte_mv_from_data_r(r_a, C2_MAC1),
|
||||
gte_mv_from_data_r(r_b, C2_MAC2),
|
||||
gte_mv_from_data_r(r_c, C2_MAC3),
|
||||
nop,
|
||||
/* Right-shift MAC by 12 to convert from GTE's S12.20 scale back to libpsyx
|
||||
* OuterProduct12 convention (S12.0, fp_one=4096). See atom 1 for rationale. */
|
||||
shift_aright(r_a, r_a, 12),
|
||||
shift_aright(r_b, r_b, 12),
|
||||
shift_aright(r_c, r_c, 12),
|
||||
store_word(r_a, r_f, O_(V3_S4,x)),
|
||||
store_word(r_b, r_f, O_(V3_S4,y)),
|
||||
store_word(r_c, r_f, O_(V3_S4,z)),
|
||||
mac_shift_aright_v3_self(r.a.x, r.a.y, r.a.z, 12),
|
||||
mac_store_v3s4(r.a, r.up, 0),
|
||||
|
||||
mac_yield()
|
||||
})
|
||||
|
||||
@@ -150,6 +150,7 @@ internal void resolve_look_at_init(void) {
|
||||
U4 pin_mask = regfile_abi_mask | (1 << R_ResolveScratch);
|
||||
RegFile rf = regfile(pin_mask);
|
||||
#define ralloc() regfile_alloc(& rf)
|
||||
#define ralloc_v3() { ralloc(), ralloc(), ralloc() }
|
||||
|
||||
smem.resolve_look_at_atom_addrs[0] = resolve_look_at__input_and_sub_proc(& ab,
|
||||
RegUse_(resolve_look_at__input_and_sub_proc) {
|
||||
@@ -216,16 +217,16 @@ internal void resolve_look_at_init(void) {
|
||||
});
|
||||
|
||||
/* === ATOM 4: cross uz×ux→up === */
|
||||
U4 r_a_4 = R_T0;
|
||||
U4 r_b_4 = R_T1;
|
||||
U4 r_c_4 = R_T2;
|
||||
U4 r_d_4 = R_T3;
|
||||
U4 r_f_4 = R_T5; /* out ptr (HARDCODED: scratch+64) */
|
||||
U4 r_g_4 = R_T6; /* a ptr = scratch+16 */
|
||||
U4 r_h_4 = R_T7; /* b ptr = scratch+48 */
|
||||
regfile_reset_to_mask(& rf, pin_mask);
|
||||
smem.resolve_look_at_atom_addrs[4] = resolve_look_at__cross_uz_ux_to_up_proc(& ab,
|
||||
R_ResolveScratch,
|
||||
r_a_4, r_b_4, r_c_4, r_d_4, r_f_4, r_g_4, r_h_4);
|
||||
RegUse_(resolve_look_at__cross_uz_ux_to_up_proc){
|
||||
.scratch = R_ResolveScratch,
|
||||
.a = ralloc_v3(), /* T0 T1 T2 */
|
||||
.b = ralloc_v3(), /* T3 T5 T6 */
|
||||
.t0 = ralloc(), /* T7 = up */
|
||||
.t1 = ralloc(), /* V0 = uz / rt11 */
|
||||
.t2 = ralloc(), /* V1 = ux / rt22 */
|
||||
});
|
||||
|
||||
/* === ATOM 5: normalize up→uy === */
|
||||
src_offset = O_(ResolveLookAtScratch, up);
|
||||
|
||||
Reference in New Issue
Block a user