mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-25 02:20:33 +00:00
Add RegUse_ support to the lua metaprogram. Ideated further on type mapping atom comonents to their base component op (math distinctions annotated in the asm).
This commit is contained in:
+10
-9
@@ -140,16 +140,17 @@ enum { false = 0, true = 1, true_overflow, };
|
||||
|
||||
typedef void Proc_(VoidFn) (void);
|
||||
|
||||
#define Kilo_(n) (C_(U4, n) << 10)
|
||||
#define Mega_(n) (C_(U4, n) << 20)
|
||||
#define Giga_(n) (C_(U4, n) << 30)
|
||||
#define Tera_(n) (C_(U4, n) << 40)
|
||||
#define Kilo_(n) (C_(U4, n) << 10)
|
||||
#define Mega_(n) (C_(U4, n) << 20)
|
||||
#define Giga_(n) (C_(U4, n) << 30)
|
||||
#define Tera_(n) (C_(U4, n) << 40)
|
||||
|
||||
#define null C_(U4, 0)
|
||||
#define nullptr C_(void*, 0)
|
||||
#define O_(type, field) C_(U4, & C_(type*,0)->field)
|
||||
#define OT_(field) O_(typeof_ptr(& field), field))
|
||||
#define S_(data) C_(U4, sizeof(data))
|
||||
#define null C_(U4, 0)
|
||||
#define nullptr C_(void*, 0)
|
||||
#define O_(type, field) C_(U4, & C_(type*,0)->field)
|
||||
#define OA_(type, aexpr) C_(U4, & C_(type*,0) aexpr)
|
||||
#define OT_(field) O_(typeof_ptr(& field), field))
|
||||
#define S_(data) C_(U4, sizeof(data))
|
||||
|
||||
#define sop_1(op,a,b) C_(U1, s1_(a) op s1_(b))
|
||||
#define sop_2(op,a,b) C_(U2, s2_(a) op s2_(b))
|
||||
|
||||
+27
-11
@@ -17,7 +17,7 @@
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\bios.h
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\psyq.h
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\pad.c
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\math.atom.c
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\math.atom.h
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\mips.atom.c
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.c
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\gp.atom.c
|
||||
@@ -71,19 +71,35 @@ WORD_COUNT(mac_load_v2s2, 2)
|
||||
WORD_COUNT(mac_store_v2s2, 2)
|
||||
|
||||
/* atom_dbg_skip */
|
||||
#define mac_load_v3s4(rs_x, rs_y, rs_z, r_base, offset) \
|
||||
load_word( rs_x, r_base, offset + O_(V3_S4,x)) \
|
||||
, load_word( rs_y, r_base, offset + O_(V3_S4,y)) \
|
||||
, load_word( rs_z, r_base, offset + O_(V3_S4,z))
|
||||
#define mac_load_word_v3(tx, ty, tz, base, offset) \
|
||||
load_word(tx, base, offset + OA_(U4,[0])) \
|
||||
, load_word(ty, base, offset + OA_(U4,[1])) \
|
||||
, load_word(tz, base, offset + OA_(U4,[2]))
|
||||
WORD_COUNT(mac_load_word_v3, 3)
|
||||
|
||||
#define mac_load_v3s4(transfer, base, offset) \
|
||||
mac_load_word_v3(transfer.x, transfer.y, transfer.z, base, offset)
|
||||
WORD_COUNT(mac_load_v3s4, 3)
|
||||
|
||||
#define mac_load_p3s4(transfer, base, offset) \
|
||||
mac_load_word_v3(transfer.x, transfer.y, transfer.z, base, offset)
|
||||
WORD_COUNT(mac_load_p3s4, 3)
|
||||
|
||||
/* atom_dbg_skip */
|
||||
#define mac_store_v3s4(rt_x, rt_y, rt_z, base, offset) \
|
||||
store_word(rt_x, base, offset + O_(V3_S4,x)) \
|
||||
, store_word(rt_y, base, offset + O_(V3_S4,y)) \
|
||||
, store_word(rt_z, base, offset + O_(V3_S4,z))
|
||||
#define mac_store_word_v3(tx, ty, tz, base, offset) \
|
||||
store_word(tx, base, offset + OA_(U4,[0])) \
|
||||
, store_word(ty, base, offset + OA_(U4,[1])) \
|
||||
, store_word(tz, base, offset + OA_(U4,[2]))
|
||||
WORD_COUNT(mac_store_word_v3, 3)
|
||||
|
||||
#define mac_store_v3s4(transfer, base, offset) \
|
||||
mac_store_word_v3(transfer.x, transfer.y, transfer.z, base, offset)
|
||||
WORD_COUNT(mac_store_v3s4, 3)
|
||||
|
||||
#define mac_store_p3s4(transfer, base, offset) \
|
||||
mac_store_word_v3(transfer.x, transfer.y, transfer.z, base, offset)
|
||||
WORD_COUNT(mac_store_p3s4, 3)
|
||||
|
||||
/* atom_dbg_skip */
|
||||
#define mac_add_si_v3s4(rt_x, rt_y, rt_z, base, offset) \
|
||||
add_si(rt_x, base, O_(V3_S4,x)) \
|
||||
@@ -234,8 +250,8 @@ WORD_COUNT(mac_lzcr_round_even_half_shift, 5)
|
||||
, gte_mv_to_data_r(to_ir1, C2_IR1) /* IR1 = src.x (preserved in r_tmp — r_mac2_scratch was clobbered to MAC2 in stage 1.5) */ \
|
||||
, gte_mv_to_data_r(to_ir2, C2_IR2) \
|
||||
, gte_mv_to_data_r(to_ir3, C2_IR3) /* IR3 = src.z (reloaded) */ \
|
||||
, LdSlot_ nop_slot1 \
|
||||
, LdSlot_ nop_slot2 \
|
||||
, DmaSlot_ nop_slot1 \
|
||||
, DmaSlot_ nop_slot2 \
|
||||
, gte_cmdw_gpf \
|
||||
, gte_mv_from_data_r(fr_mac1, C2_MAC1) \
|
||||
, gte_mv_from_data_r(fr_mac2, C2_MAC2) \
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\bios.h
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\psyq.h
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\pad.c
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\math.atom.c
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\math.atom.h
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\mips.atom.c
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.c
|
||||
// source: C:\projects\Pikuma\ps1\code\duffle\gp.atom.c
|
||||
|
||||
@@ -150,8 +150,8 @@ MipsAtomComp_Proc_(ab, {
|
||||
gte_mv_to_data_r(to_ir1, C2_IR1), /* IR1 = src.x (preserved in r_tmp — r_mac2_scratch was clobbered to MAC2 in stage 1.5) */
|
||||
gte_mv_to_data_r(to_ir2, C2_IR2),
|
||||
gte_mv_to_data_r(to_ir3, C2_IR3), /* IR3 = src.z (reloaded) */
|
||||
LdSlot_ nop_slot1,
|
||||
LdSlot_ nop_slot2,
|
||||
DmaSlot_ nop_slot1,
|
||||
DmaSlot_ nop_slot2,
|
||||
gte_cmdw_gpf,
|
||||
gte_mv_from_data_r(fr_mac1, C2_MAC1),
|
||||
gte_mv_from_data_r(fr_mac2, C2_MAC2),
|
||||
@@ -284,7 +284,7 @@ MipsAtom_Proc_(aa, {
|
||||
|
||||
/* Load src.x/y/z from r_src_ptr (caller-determined address) into r_tmp/r_recip_est/r_branch_tmp.
|
||||
* r.rt1_src_x holds src.x throughout stages 1-2 — r_mac2_scratch is clobbered to MAC2 in stage 1.5 (line below). */
|
||||
mac_load_v3s4(r.src_x, r.recip_est, r.t5.src_z, r.src_ptr, 0),
|
||||
mac_load_word_v3(r.src_x, r.recip_est, r.t5.src_z, 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.t5.src_z, LdSlot_ nop),
|
||||
@@ -293,8 +293,8 @@ MipsAtom_Proc_(aa, {
|
||||
mac_gte_mv_from_data_r_mac123(r.t3.mac1_scratch, r.t4.mac2_scratch, r.norm), LdSlot_ nop,
|
||||
add_u_self( r.norm, r.t3.mac1_scratch),
|
||||
add_u_self( r.norm, r.t4.mac2_scratch),
|
||||
gte_mv_to_data_r( r.norm, C2_LZCS), LdSlot_ nop2,
|
||||
gte_mv_from_data_r(r.shift, C2_LZCR), LdSlot_ nop,
|
||||
gte_mv_to_data_r( r.norm, C2_LZCS), DmaSlot_ nop2,
|
||||
gte_mv_from_data_r(r.shift, C2_LZCR), DmaSlot_ 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.
|
||||
@@ -328,13 +328,13 @@ MipsAtom_Proc_(aa, {
|
||||
r.recip_est,
|
||||
r.t5.src_z, /* IR3 = src.z (reloaded) */
|
||||
r.t4.mac2_scratch, r.recip_est, r.t5.src_z,
|
||||
LdSlot_ add_si(r.dst_ptr, r.scratch, dst_offset), // pre-laoding destination to register here.
|
||||
LdSlot_ nop
|
||||
DmaSlot_ add_si(r.dst_ptr, r.scratch, dst_offset), // pre-laoding destination to register here.
|
||||
DmaSlot_ nop
|
||||
),
|
||||
/* sra by r_shift = (31-LZCR)/2 (saved before sqrtbl lookup) */
|
||||
mac_shift_aright_var_v3_self(r.t4.mac2_scratch, r.recip_est, r.t5.src_z, r.shift),
|
||||
/* Store result.x/y/z to r_dst_ptr (caller-determined dst address). */
|
||||
mac_store_v3s4(r.t4.mac2_scratch, r.recip_est, r.t5.src_z, r.dst_ptr, 0),
|
||||
mac_store_word_v3(r.t4.mac2_scratch, r.recip_est, r.t5.src_z, r.dst_ptr, 0),
|
||||
|
||||
mac_yield()
|
||||
})
|
||||
|
||||
@@ -101,6 +101,7 @@ enum {
|
||||
};
|
||||
|
||||
typedef U2 Reg; // Register parameter used with atom or atom component procedures
|
||||
#define Reg_(type) tmpl(Reg,type) // Just a way to template register allocations of C-struct types.
|
||||
|
||||
typedef U4 const MipsCode; // Underlying type to mips asm words.
|
||||
typedef Slice_(MipsCode);
|
||||
@@ -143,6 +144,8 @@ typedef Slice_(MipsAtom);
|
||||
// Inline-only callers (the generated `mac_<name>` aliases) skip the `ab` arg via metaprogram filtering; escape callers (ac_<name> invoked as a function) pass a long-lived builder.
|
||||
#define MipsAtomComp_Proc_(ab, ...) { MipsCode atom_comp_code[] align_(4) = __VA_ARGS__; atombuilder_push(ab, slice_from_array(MipsCode, atom_comp_code)); }
|
||||
|
||||
#define MipsAtomComp_ProcMap_(ab, base_command) atom_dbg_skip MipsAtomComp_Proc_(ab, {base_command })
|
||||
|
||||
/* Line-table anchor: gcc only adds a file to the .debug_line file table when the contains line-numbered content.
|
||||
Files containing only atoms and atom components.
|
||||
Place `ATOM_FILE_LINE_MARKER();` once at file scope in any `.atom.c` that defines atoms.
|
||||
@@ -372,7 +375,7 @@ FI_ void regfile_reset(RegFile_R rf) {
|
||||
rf->GPR[0] = u4_lo(regfile_abi_mask);
|
||||
rf->GPR[1] = u4_hi(regfile_abi_mask);
|
||||
}
|
||||
FI_ void regfile_reset_mask(RegFile_R rf, U4 mask) {
|
||||
FI_ void regfile_reset_to_mask(RegFile_R rf, U4 mask) {
|
||||
rf->GPR[0] = u4_lo(mask);
|
||||
rf->GPR[1] = u4_hi(mask);
|
||||
}
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
|
||||
ATOM_FILE_DEBUGGER_LINE_MARKER(math_atom_c);
|
||||
|
||||
#pragma region MACs (Mips Atom Component)
|
||||
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
|
||||
|
||||
// FI_ Slice_MipsCode ac_load_imm
|
||||
#pragma region MACs (Mips Atom Component)
|
||||
|
||||
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)),
|
||||
@@ -21,23 +22,23 @@ FI_ Slice_MipsCode ac_store_v2s2(AtomBuilder_R ab, U4 rt_x, U4 rt_y, U4 base, U4
|
||||
store_half(rt_y, base, offset + O_(V2_S2,y)),
|
||||
})
|
||||
|
||||
FI_ Slice_MipsCode ac_load_v3s4(AtomBuilder_R ab, U4 rs_x, U4 rs_y, U4 rs_z, U4 r_base, U4 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, {
|
||||
load_word( rs_x, r_base, offset + O_(V3_S4,x)),
|
||||
load_word( rs_y, r_base, offset + O_(V3_S4,y)),
|
||||
load_word( rs_z, r_base, offset + O_(V3_S4,z)),
|
||||
FI_ Slice_MipsCode ac_load_word_v3(AtomBuilder_R ab, Reg tx, Reg ty, Reg tz, Reg base, U2 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, {
|
||||
load_word(tx, base, offset + OA_(U4,[0])),
|
||||
load_word(ty, base, offset + OA_(U4,[1])),
|
||||
load_word(tz, base, offset + OA_(U4,[2])),
|
||||
})
|
||||
// TODO(Ed): we could generate these mappings properly..
|
||||
#define ac_load_p3s4 ac_load_v3s4
|
||||
#define mac_load_p3s4 mac_load_v3s4
|
||||
|
||||
FI_ Slice_MipsCode ac_store_v3s4(AtomBuilder_R ab, U4 rt_x, U4 rt_y, U4 rt_z, U4 base, U4 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, {
|
||||
store_word(rt_x, base, offset + O_(V3_S4,x)),
|
||||
store_word(rt_y, base, offset + O_(V3_S4,y)),
|
||||
store_word(rt_z, base, offset + O_(V3_S4,z)),
|
||||
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_store_word_v3(AtomBuilder_R ab, U4 tx, U4 ty, U4 tz, U4 base, U4 offset) atom_dbg_skip MipsAtomComp_Proc_(ab, {
|
||||
store_word(tx, base, offset + OA_(U4,[0])),
|
||||
store_word(ty, base, offset + OA_(U4,[1])),
|
||||
store_word(tz, base, offset + OA_(U4,[2])),
|
||||
})
|
||||
// TODO(Ed): we could generate these mappings properly..
|
||||
#define ac_store_p3s4 ac_store_v3s4
|
||||
#define mac_store_p3s4 mac_store_v3s4
|
||||
|
||||
FI_ Slice_MipsCode ac_store_v3s4(AtomBuilder_R ab, Reg_(V3_S4) transfer, Reg base, U2 offset) MipsAtomComp_ProcMap_(ab, mac_store_word_v3(transfer.x, transfer.y, transfer.z, base, offset))
|
||||
FI_ Slice_MipsCode ac_store_p3s4(AtomBuilder_R ab, Reg_(P3_S4) transfer, Reg base, U2 offset) MipsAtomComp_ProcMap_(ab, mac_store_word_v3(transfer.x, transfer.y, transfer.z, base, offset))
|
||||
|
||||
FI_ Slice_MipsCode ac_add_si_v3s4(AtomBuilder_R ab, Reg rt_x, Reg rt_y, Reg rt_z, Reg base, U2 offset)
|
||||
atom_dbg_skip MipsAtomComp_Proc_(ab, {
|
||||
@@ -10,7 +10,7 @@
|
||||
# include "duffle/pad.h"
|
||||
# include "duffle/word_count.metadata.h"
|
||||
# include "duffle/psyq.h"
|
||||
# include "duffle/math.atom.c"
|
||||
# include "duffle/math.atom.h"
|
||||
# include "duffle/mips.atom.c"
|
||||
# include "duffle/gte.atom.c"
|
||||
# include "duffle/gp.atom.c"
|
||||
@@ -129,7 +129,7 @@ typedef Struct_(Binds_ResolveLookAtSub) {
|
||||
};
|
||||
|
||||
typedef Struct_(RegUse_resolve_look_at__input_and_sub_proc) {
|
||||
Reg const scratch;
|
||||
Reg scratch;
|
||||
Reg target; Reg eye; Reg up_in;
|
||||
Reg t0; Reg t1; Reg t2; Reg t3; Reg t4;
|
||||
};
|
||||
@@ -152,7 +152,7 @@ typedef Struct_(RegUse_resolve_look_at__input_and_sub_proc) {
|
||||
* Pool cost: 8 GPRs + R_T4 (carrier) + R_AT + R_V0 (hardcoded) = 11 GPRs.
|
||||
*/
|
||||
internal MipsAtom* resolve_look_at__input_and_sub_proc(AtomArena_R aa, RegUse_resolve_look_at__input_and_sub_proc r)
|
||||
MipsAtom_Proc_(aa, atom_info(atom_bind(Binds_ResolveLookAtSub)){
|
||||
atom_info(atom_bind(Binds_ResolveLookAtSub)) MipsAtom_Proc_(aa, {
|
||||
load_word(r.target, R_TapePtr, O_(Binds_ResolveLookAtSub,target)),
|
||||
load_word(r.eye, R_TapePtr, O_(Binds_ResolveLookAtSub,eye)),
|
||||
load_word(r.up_in, R_TapePtr, O_(Binds_ResolveLookAtSub,up_in)),
|
||||
@@ -160,20 +160,20 @@ MipsAtom_Proc_(aa, atom_info(atom_bind(Binds_ResolveLookAtSub)){
|
||||
add_ui_self( R_TapePtr, S_(Binds_ResolveLookAtSub)),
|
||||
|
||||
/* Stage up_in.x/y/z into the scratchpad. */
|
||||
mac_load_p3s4( r.t0, r.t1, r.t2, r.up_in, 0),
|
||||
mac_store_p3s4(r.t0, r.t1, r.t2, r.scratch, O_(ResolveLookAtScratch,up_in)),
|
||||
mac_load_word_v3( r.t0, r.t1, r.t2, r.up_in, 0),
|
||||
mac_store_word_v3(r.t0, r.t1, r.t2, r.scratch, O_(ResolveLookAtScratch,up_in)),
|
||||
|
||||
// Stage eye.x/y/z into the scratchpad (atom 6 reads these for the translation column).
|
||||
mac_load_p3s4( r.t0, r.t1, r.t2, r.eye, 0),
|
||||
mac_store_p3s4(r.t0, r.t1, r.t2, r.scratch, O_(ResolveLookAtScratch,eye)),
|
||||
mac_load_word_v3( r.t0, r.t1, r.t2, r.eye, 0),
|
||||
mac_store_word_v3(r.t0, r.t1, r.t2, r.scratch, O_(ResolveLookAtScratch,eye)),
|
||||
|
||||
/* Compute fwd = target - eye. */
|
||||
// mac_load_p3s4(t3, R_AT, t4, r.eye, 0),
|
||||
mac_load_p3s4(r.t3, R_AT, r.t4, r.target, 0),
|
||||
mac_load_word_v3(r.t3, R_AT, r.t4, r.target, 0),
|
||||
mac_sub_v3s4(
|
||||
r.t3, R_AT, r.t4,
|
||||
r.t0, r.t1, r.t2),
|
||||
mac_store_v3s4(r.t3, R_AT, r.t4, r.scratch, O_(ResolveLookAtScratch,fwd)),
|
||||
mac_store_word_v3(r.t3, R_AT, r.t4, r.scratch, O_(ResolveLookAtScratch,fwd)),
|
||||
|
||||
mac_yield()
|
||||
})
|
||||
@@ -199,9 +199,9 @@ internal MipsAtom* resolve_look_at__cross_uz_up_into_right_proc(AtomArena_R aa,
|
||||
nop,
|
||||
|
||||
/* Load a (uz).x/y/z into r_a/r_b/r_c. */
|
||||
mac_load_v3s4(r.a, r.b, r.c, r.g, 0),
|
||||
mac_load_word_v3(r.a, r.b, r.c, r.g, 0),
|
||||
/* Load b (up_in).x/y/z into r_d + R_AT/R_V0 (R_AT/R_V0 are hardcoded scratch). */
|
||||
mac_load_v3s4(r.d, R_AT, r.t0, r.h, 0), LdSlot_
|
||||
mac_load_word_v3(r.d, R_AT, r.t0, r.h, 0), LdSlot_ // (taken by gte_mv_from_ctrl_r)
|
||||
|
||||
/* Save the two RT control-register slots OP will clobber. We reuse r_g/r_h (scratch pointers, no longer needed) as the save targets. */
|
||||
gte_mv_from_ctrl_r(r.target0, gte_cr_RT11), /* r_g = C2 r0 (RT11|RT12) */
|
||||
@@ -228,8 +228,7 @@ internal MipsAtom* resolve_look_at__cross_uz_up_into_right_proc(AtomArena_R aa,
|
||||
gte_mv_to_data_r(r.t0, C2_IR3), /* IR3 = up_in.z */
|
||||
DmaSlot_ nop2, /* MTC2 retirement (CPU→COP2 2-slot delay) */
|
||||
|
||||
// gte_cmdw_cross, /* OP: MAC1/2/3 = uz × up_in
|
||||
gte_cmdw_outer_product, /* OP: MAC1/2/3 = uz × up_in
|
||||
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
|
||||
* MAC2 = IR1*D3 - IR3*D1 = up_in.x*uz.z.high - up_in.z*uz.x
|
||||
* MAC3 = IR2*D1 - IR1*D2 = up_in.y*uz.x - up_in.x*uz.y.high
|
||||
@@ -249,9 +248,8 @@ internal MipsAtom* resolve_look_at__cross_uz_up_into_right_proc(AtomArena_R aa,
|
||||
/* 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. */
|
||||
mac_shift_aright_v3_self(r.a, r.b, r.c, 12),
|
||||
|
||||
/* Store out.x/y/z to r_f (out ptr = scratch+32). */
|
||||
mac_store_v3s4(r.a, r.b, r.c, r.f, 0),
|
||||
mac_store_word_v3(r.a, r.b, r.c, r.f, 0),
|
||||
|
||||
mac_yield()
|
||||
})
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#pragma region Duffle TUs
|
||||
#include "duffle/pad.c"
|
||||
#include "duffle/math.atom.c"
|
||||
#include "duffle/math.atom.h"
|
||||
#include "duffle/mips.atom.c"
|
||||
#include "duffle/gte.atom.c"
|
||||
#include "duffle/gp.atom.c"
|
||||
@@ -149,20 +149,22 @@ 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)
|
||||
|
||||
smem.resolve_look_at_atom_addrs[0] = resolve_look_at__input_and_sub_proc(& ab,
|
||||
RegUse_(resolve_look_at__input_and_sub_proc) {
|
||||
.scratch = R_ResolveScratch,
|
||||
.target = regfile_alloc(& rf),
|
||||
.eye = regfile_alloc(& rf),
|
||||
.up_in = regfile_alloc(& rf),
|
||||
.t0 = regfile_alloc(& rf),
|
||||
.t1 = regfile_alloc(& rf),
|
||||
.t2 = regfile_alloc(& rf),
|
||||
.t3 = regfile_alloc(& rf),
|
||||
.t4 = regfile_alloc(& rf),
|
||||
.target = ralloc(),
|
||||
.eye = ralloc(),
|
||||
.up_in = ralloc(),
|
||||
.t0 = ralloc(),
|
||||
.t1 = ralloc(),
|
||||
.t2 = ralloc(),
|
||||
.t3 = ralloc(),
|
||||
.t4 = ralloc(),
|
||||
}
|
||||
);
|
||||
regfile_reset_to_mask(& rf, pin_mask);
|
||||
|
||||
/* === ATOM 1: normalize fwd→uz === */
|
||||
U2 src_offset = O_(ResolveLookAtScratch, fwd);
|
||||
@@ -170,27 +172,30 @@ internal void resolve_look_at_init(void) {
|
||||
smem.resolve_look_at_atom_addrs[1] = normalize_v3s4_proc(& ab,
|
||||
src_offset, dst_offset, RegUse_(normalize_v3s4_proc){
|
||||
.scratch = R_ResolveScratch,
|
||||
.src_ptr = R_T0,
|
||||
.dst_ptr = R_T1,
|
||||
.recip_est = R_T6,
|
||||
.norm = R_T7,
|
||||
.shift = R_V0,
|
||||
.src_x = R_T2,
|
||||
.t3 = R_T3,
|
||||
.t4 = R_T5,
|
||||
.t5 = R_V1,
|
||||
.src_ptr = ralloc(),
|
||||
.dst_ptr = ralloc(),
|
||||
.recip_est = ralloc(),
|
||||
.norm = ralloc(),
|
||||
.shift = ralloc(),
|
||||
.src_x = ralloc(),
|
||||
.t3 = ralloc(),
|
||||
.t4 = ralloc(),
|
||||
.t5 = ralloc(),
|
||||
});
|
||||
regfile_reset_to_mask(& rf, pin_mask);
|
||||
|
||||
/* === ATOM 2: cross uz×up_in→right === */
|
||||
smem.resolve_look_at_atom_addrs[2] = resolve_look_at__cross_uz_up_into_right_proc(& ab,
|
||||
RegUse_(resolve_look_at__cross_uz_up_into_right_proc) {
|
||||
.scratch = R_ResolveScratch,
|
||||
.a = R_T0, .b = R_T1, .c = R_T2,
|
||||
.d = R_T3,
|
||||
.f = R_T5,
|
||||
.t1 = R_T6,
|
||||
.t2 = R_T7,
|
||||
.t0 = R_V0,
|
||||
.a = ralloc(),
|
||||
.b = ralloc(),
|
||||
.c = ralloc(),
|
||||
.d = ralloc(),
|
||||
.f = ralloc(),
|
||||
.t1 = ralloc(),
|
||||
.t2 = ralloc(),
|
||||
.t0 = ralloc(),
|
||||
});
|
||||
|
||||
/* === ATOM 3: normalize right→ux === */
|
||||
@@ -285,6 +290,7 @@ internal void resolve_look_at_init(void) {
|
||||
|
||||
/* Sanity check: arena didn't overflow. */
|
||||
assert(ab.used <= ResolveLookAtArena_Size);
|
||||
#undef ralloc
|
||||
}
|
||||
|
||||
/* Emit the resolve_look_at bundle into the tape. Called once per frame from update().
|
||||
|
||||
Reference in New Issue
Block a user