reviewed: resolve_look_at__populate_proc

This commit is contained in:
ed
2026-08-15 21:34:55 -04:00
parent d9b9241e2c
commit 3301826f5c
4 changed files with 80 additions and 79 deletions
+24 -2
View File
@@ -58,10 +58,21 @@ WORD_COUNT(mac_yield_load, 1)
, nop , nop
WORD_COUNT(mac_yield_tail, 3) WORD_COUNT(mac_yield_tail, 3)
/* atom_dbg_skip */
#define mac_load_half_v3(tx, ty, tz, base, offset) \
load_half(tx, base, offset + OA_(U2,[0])) \
, load_half(ty, base, offset + OA_(U2,[1])) \
, load_half(tz, base, offset + OA_(U2,[2]))
WORD_COUNT(mac_load_half_v3, 3)
#define mac_load_v3s2(transfer, base, offset) \
mac_load_half_v3(transfer.x, transfer.y, transfer.z, base, offset)
WORD_COUNT(mac_load_v3s2, 3)
/* atom_dbg_skip */ /* atom_dbg_skip */
#define mac_load_v2s2(rs_x, rs_y, r_base, offset) \ #define mac_load_v2s2(rs_x, rs_y, r_base, offset) \
load_half( rs_x, r_base, offset + O_(V3_S2,x)) \ load_half(rs_x, r_base, offset + O_(V3_S2,x)) \
, load_half( rs_y, r_base, offset + O_(V3_S2,y)) , load_half(rs_y, r_base, offset + O_(V3_S2,y))
WORD_COUNT(mac_load_v2s2, 2) WORD_COUNT(mac_load_v2s2, 2)
/* atom_dbg_skip */ /* atom_dbg_skip */
@@ -85,6 +96,17 @@ WORD_COUNT(mac_load_v3s4, 3)
mac_load_word_v3(transfer.x, transfer.y, transfer.z, base, offset) mac_load_word_v3(transfer.x, transfer.y, transfer.z, base, offset)
WORD_COUNT(mac_load_p3s4, 3) WORD_COUNT(mac_load_p3s4, 3)
/* atom_dbg_skip */
#define mac_store_half_v3(tx, ty, tz, base, offset) \
store_half(tx, base, offset + OA_(U2,[0])) \
, store_half(ty, base, offset + OA_(U2,[1])) \
, store_half(tz, base, offset + OA_(U2,[2]))
WORD_COUNT(mac_store_half_v3, 3)
#define mac_store_v3s2(transfer, base, offset) \
mac_store_half_v3(transfer.x, transfer.y, transfer.z, base, offset)
WORD_COUNT(mac_store_v3s2, 3)
/* atom_dbg_skip */ /* atom_dbg_skip */
#define mac_store_word_v3(tx, ty, tz, base, offset) \ #define mac_store_word_v3(tx, ty, tz, base, offset) \
store_word(tx, base, offset + OA_(U4,[0])) \ store_word(tx, base, offset + OA_(U4,[0])) \
+22 -3
View File
@@ -7,14 +7,25 @@
ATOM_FILE_DEBUGGER_LINE_MARKER(math_atom_c); ATOM_FILE_DEBUGGER_LINE_MARKER(math_atom_c);
#define v3s4_R_0() ((Reg_(V3_S4)){R_0,R_0,R_0})
typedef Struct_(Reg_V3_S2) { Reg x, y, z; };
typedef Struct_(Reg_V3_S4) { Reg x, y, z; }; // Register allocation of a V3_S4 typedef Struct_(Reg_V3_S4) { Reg x, y, z; }; // Register allocation of a V3_S4
typedef Struct_(Reg_P3_S4) { Reg x, y, z; }; // Register allocation of a P3_S4 typedef Struct_(Reg_P3_S4) { Reg x, y, z; }; // Register allocation of a P3_S4
#pragma region MACs (Mips Atom Component) #pragma region MACs (Mips Atom Component)
FI_ Slice_MipsCode ac_load_half_v3(AtomBuilder_R ab, Reg tx, Reg ty, Reg tz, Reg base, U2 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, {
load_half(tx, base, offset + OA_(U2,[0])),
load_half(ty, base, offset + OA_(U2,[1])),
load_half(tz, base, offset + OA_(U2,[2])),
})
FI_ Slice_MipsCode ac_load_v3s2(AtomBuilder_R ab, Reg_(V3_S2) transfer, Reg base, U2 offset) MipsAtomComp_ProcMap_(ab, mac_load_half_v3(transfer.x, transfer.y, transfer.z, base, offset))
FI_ Slice_MipsCode ac_load_v2s2(AtomBuilder_R ab, U4 rs_x, U4 rs_y, U4 r_base, U4 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, { FI_ Slice_MipsCode ac_load_v2s2(AtomBuilder_R ab, U4 rs_x, U4 rs_y, U4 r_base, U4 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, {
load_half( rs_x, r_base, offset + O_(V3_S2,x)), load_half(rs_x, r_base, offset + O_(V3_S2,x)),
load_half( rs_y, r_base, offset + O_(V3_S2,y)), load_half(rs_y, r_base, offset + O_(V3_S2,y)),
}) })
FI_ Slice_MipsCode ac_store_v2s2(AtomBuilder_R ab, U4 rt_x, U4 rt_y, U4 base, U4 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, { FI_ Slice_MipsCode ac_store_v2s2(AtomBuilder_R ab, U4 rt_x, U4 rt_y, U4 base, U4 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, {
@@ -31,7 +42,15 @@ FI_ Slice_MipsCode ac_load_word_v3(AtomBuilder_R ab, Reg tx, Reg ty, Reg tz, Reg
FI_ Slice_MipsCode ac_load_v3s4(AtomBuilder_R ab, Reg_(V3_S4) transfer, Reg base, U2 offset) MipsAtomComp_ProcMap_(ab, mac_load_word_v3(transfer.x, transfer.y, transfer.z, base, offset)) FI_ Slice_MipsCode ac_load_v3s4(AtomBuilder_R ab, Reg_(V3_S4) transfer, Reg base, U2 offset) MipsAtomComp_ProcMap_(ab, mac_load_word_v3(transfer.x, transfer.y, transfer.z, base, offset))
FI_ Slice_MipsCode ac_load_p3s4(AtomBuilder_R ab, Reg_(P3_S4) transfer, Reg base, U2 offset) MipsAtomComp_ProcMap_(ab, mac_load_word_v3(transfer.x, transfer.y, transfer.z, base, offset)) FI_ Slice_MipsCode ac_load_p3s4(AtomBuilder_R ab, Reg_(P3_S4) transfer, Reg base, U2 offset) MipsAtomComp_ProcMap_(ab, mac_load_word_v3(transfer.x, transfer.y, transfer.z, base, offset))
FI_ Slice_MipsCode ac_store_word_v3(AtomBuilder_R ab, U4 tx, U4 ty, U4 tz, U4 base, U4 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, { FI_ Slice_MipsCode ac_store_half_v3(AtomBuilder_R ab, Reg tx, Reg ty, Reg tz, Reg base, U2 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, {
store_half(tx, base, offset + OA_(U2,[0])),
store_half(ty, base, offset + OA_(U2,[1])),
store_half(tz, base, offset + OA_(U2,[2])),
})
FI_ Slice_MipsCode ac_store_v3s2(AtomBuilder_R ab, Reg_(V3_S2) transfer, Reg base, U2 offset) MipsAtomComp_ProcMap_(ab, mac_store_half_v3(transfer.x, transfer.y, transfer.z, base, offset))
FI_ Slice_MipsCode ac_store_word_v3(AtomBuilder_R ab, Reg tx, Reg ty, Reg tz, Reg base, U2 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, {
store_word(tx, base, offset + OA_(U4,[0])), store_word(tx, base, offset + OA_(U4,[0])),
store_word(ty, base, offset + OA_(U4,[1])), store_word(ty, base, offset + OA_(U4,[1])),
store_word(tz, base, offset + OA_(U4,[2])), store_word(tz, base, offset + OA_(U4,[2])),
+25 -63
View File
@@ -273,7 +273,6 @@ internal MipsAtom* resolve_look_at__cross_uz_ux_to_up_proc(AtomArena_R aa,
/* Load a (uz).x/y/z into r.a. */ /* Load a (uz).x/y/z into r.a. */
mac_load_v3s4(r.a, r.uz, 0), LdSlot_ nop, mac_load_v3s4(r.a, r.uz, 0), LdSlot_ nop,
/* Load b (ux).x/y/z into r.b. */ /* 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 */ mac_load_v3s4(r.b, r.ux, 0), LdSlot_ /* taken by gte_mv_from_ctrl_r */
@@ -321,76 +320,39 @@ internal MipsAtom* resolve_look_at__cross_uz_ux_to_up_proc(AtomArena_R aa,
typedef Struct_(Binds_ResolveLookAtPopAndTrans) { typedef Struct_(Binds_ResolveLookAtPopAndTrans) {
U4 look_at; /* U4 (MT3_S2S4* — destination matrix address) */ U4 look_at; /* U4 (MT3_S2S4* — destination matrix address) */
}; };
/* Atom 6 in the bundle: write look_at->m[][] from ux/uy/uz, then compute the translation column t[] = R * (-eye). typedef Struct_(RegUse_resolve_look_at__populate_proc) {
Reg const scratch;
Reg look_at;
Reg_(V3_S4) row; /* one matrix row, reused */
Reg ux;
Reg uy;
Reg uz;
};
/* Atom 6a: write look_at->m[][] from ux/uy/uz as S2. Zero t[].
* MT3_S2S4 { A3x3_S2 m; A3_S4 t; }
* m[][] is S2 packed (9 × 2 = 18 bytes at offset 0)
* t[0/1/2] is S4 (3 × 4 = 12 bytes at offset 18)
* *
* GPR codes (assigned by resolve_look_at_init): * ux/uy/uz stay dedicated address regs for the whole body.
* r_look_at : MT3_S2S4* (popped from tape; output matrix destination) * row is the S4 load / S2 store transfer, reused per matrix row.
* r_pux : pointer to ux (offset O_(ResolveLookAtScratch,ux)) * Eye is not read here — atom 6b reads it.
* r_puy : pointer to uy (offset O_(ResolveLookAtScratch,uy))
* r_puz : pointer to uz (offset O_(ResolveLookAtScratch,uz))
* r_peye : pointer to eye (offset O_(ResolveLookAtScratch,eye))
* r_tmp0/1/2 : atom-local scratch (load + MVMVA + store temps)
*
* 4 pointer regs (r_pux/r_puy/r_puz/r_peye) are DEDICATED — they hold the scratch addresses for the entire body.
* They are computed in-body via `add_si(r_px, r_scratch, O_(ResolveLookAtScratch, field))` so no tape-data pointer is needed.
*
* Struct layout (per duffle/math.h):
* MT3_S2S4 { A3x3_S2 m; A3_S4 t; } → m[][] is S2 packed (9 × 2 = 18 bytes at offset 0)
* t[0/1/2] is S4 (3 × 4 = 12 bytes at offset 18)
*
* Translation column: GTE MVMVA with the world rotation matrix pre-set
* (helper emits set_gte_world before the bundle, per the bundle design).
* MVMVA computes R * pos (with cv=0/mx=0/sf=0/v=0); MAC1/2/3 = R * (-eye).
* Pool cost: r_look_at (1) + r_scratch (R_T4 carrier) + 4 ptr regs + 3 tmp regs = 9 GPRs.
*/ */
internal MipsAtom* resolve_look_at__populate_proc(AtomArena_R aa internal MipsAtom* resolve_look_at__populate_proc(AtomArena_R aa,
, U4 r_look_at RegUse_resolve_look_at__populate_proc r
, U4 r_scratch
, U4 r_pux, U4 r_puy, U4 r_puz
, U4 r_tmp0, U4 r_tmp1, U4 r_tmp2
) MipsAtom_Proc_(aa, { ) MipsAtom_Proc_(aa, {
/* Pop look_at* (the matrix output) — advance R_TapePtr by 4 bytes. */ load_word(r.look_at, R_TapePtr, O_(Binds_ResolveLookAtPopAndTrans,look_at)),
load_word(r_look_at, R_TapePtr, O_(Binds_ResolveLookAtPopAndTrans,look_at)),
add_ui_self( R_TapePtr, S_(Binds_ResolveLookAtPopAndTrans)), add_ui_self( R_TapePtr, S_(Binds_ResolveLookAtPopAndTrans)),
/* Compute the 3 scratch pointers in their dedicated GPRs (eye isn't needed by 6a — 6b reads it). */ add_si(r.ux, r.scratch, O_(ResolveLookAtScratch,ux)), /* r.ux = &ux */
add_si(r_pux, r_scratch, O_(ResolveLookAtScratch,ux)), /* r_pux = &ux */ add_si(r.uy, r.scratch, O_(ResolveLookAtScratch,uy)), /* r.uy = &uy */
add_si(r_puy, r_scratch, O_(ResolveLookAtScratch,uy)), /* r_puy = &uy */ add_si(r.uz, r.scratch, O_(ResolveLookAtScratch,uz)), /* r.uz = &uz */
add_si(r_puz, r_scratch, O_(ResolveLookAtScratch,uz)), /* r_puz = &uz */
nop,
/* ── m[0] = (S2)ux ── */ mac_load_v3s4(r.row, r.ux, 0), LdSlot_ mac_store_v3s2(r.row, r.look_at, O_(MT3_S2S4,m[0])),
load_word(r_tmp0, r_pux, O_(V3_S4,x)), mac_load_v3s4(r.row, r.uy, 0), LdSlot_ mac_store_v3s2(r.row, r.look_at, O_(MT3_S2S4,m[1])),
load_word(r_tmp1, r_pux, O_(V3_S4,y)), mac_load_v3s4(r.row, r.uz, 0), LdSlot_ mac_store_v3s2(r.row, r.look_at, O_(MT3_S2S4,m[2])),
load_word(r_tmp2, r_pux, O_(V3_S4,z)),
nop,
store_half(r_tmp0, r_look_at, O_(MT3_S2S4,m[0][0])),
store_half(r_tmp1, r_look_at, O_(MT3_S2S4,m[0][1])),
store_half(r_tmp2, r_look_at, O_(MT3_S2S4,m[0][2])),
/* ── m[1] = (S2)uy ── */
load_word(r_tmp0, r_puy, O_(V3_S4,x)),
load_word(r_tmp1, r_puy, O_(V3_S4,y)),
load_word(r_tmp2, r_puy, O_(V3_S4,z)),
nop,
store_half(r_tmp0, r_look_at, O_(MT3_S2S4,m[1][0])),
store_half(r_tmp1, r_look_at, O_(MT3_S2S4,m[1][1])),
store_half(r_tmp2, r_look_at, O_(MT3_S2S4,m[1][2])),
/* ── m[2] = (S2)uz ── */
load_word(r_tmp0, r_puz, O_(V3_S4,x)),
load_word(r_tmp1, r_puz, O_(V3_S4,y)),
load_word(r_tmp2, r_puz, O_(V3_S4,z)),
nop,
store_half(r_tmp0, r_look_at, O_(MT3_S2S4,m[2][0])),
store_half(r_tmp1, r_look_at, O_(MT3_S2S4,m[2][1])),
store_half(r_tmp2, r_look_at, O_(MT3_S2S4,m[2][2])),
/* Zero t[0..2] — atom 6c writes the final values here. */ /* Zero t[0..2] — atom 6c writes the final values here. */
store_word(R_0, r_look_at, O_(MT3_S2S4,t[0])), mac_store_v3s4(v3s4_R_0(), r.look_at, O_(MT3_S2S4,t)),
store_word(R_0, r_look_at, O_(MT3_S2S4,t[1])),
store_word(R_0, r_look_at, O_(MT3_S2S4,t[2])),
mac_yield() mac_yield()
}) })
+9 -11
View File
@@ -247,18 +247,16 @@ internal void resolve_look_at_init(void) {
}); });
/* === ATOM 6a: populate (m[][] from ux/uy/uz, t[]=0) === */ /* === ATOM 6a: populate (m[][] from ux/uy/uz, t[]=0) === */
U4 r_look_at_6a = R_T0; /* tape pop → look_at* */ regfile_reset_to_mask(& rf, pin_mask);
U4 r_scratch_6a = R_ResolveScratch;
U4 r_pux_6a = R_T1;
U4 r_puy_6a = R_T3;
U4 r_puz_6a = R_T5;
U4 r_tmp0_6a = R_T2;
U4 r_tmp1_6a = R_T6;
U4 r_tmp2_6a = R_V0;
smem.resolve_look_at_atom_addrs[6] = resolve_look_at__populate_proc(& ab, smem.resolve_look_at_atom_addrs[6] = resolve_look_at__populate_proc(& ab,
r_look_at_6a, r_scratch_6a, RegUse_(resolve_look_at__populate_proc){
r_pux_6a, r_puy_6a, r_puz_6a, .scratch = R_ResolveScratch,
r_tmp0_6a, r_tmp1_6a, r_tmp2_6a); .look_at = ralloc(), /* T0 */
.row = ralloc_v3(), /* T1 T2 T3 */
.ux = ralloc(), /* T5 = ux */
.uy = ralloc(), /* T6 = uy */
.uz = ralloc(), /* T7 = uz */
});
/* === ATOM 6a.5: set_gte_mt3s2s4 (BAKED — ctc2 RT matrix) === /* === ATOM 6a.5: set_gte_mt3s2s4 (BAKED — ctc2 RT matrix) ===
* This is a BAKED atom from gte.atom.c. Its body hardcodes R_T3 as * This is a BAKED atom from gte.atom.c. Its body hardcodes R_T3 as