mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-14 11:38:14 +00:00
389 lines
18 KiB
C
389 lines
18 KiB
C
#ifdef INTELLISENSE_DIRECTIVES
|
||
#pragma once
|
||
#endif
|
||
// Auto-generated by ps1_meta.lua — DO NOT EDIT
|
||
// Directory: C:\projects\Pikuma\ps1\code\hello_camera/
|
||
// source: C:\projects\Pikuma\ps1\code\hello_camera\hello_camera.c
|
||
// source: C:\projects\Pikuma\ps1\code\hello_camera\hello_camera.h
|
||
// source: C:\projects\Pikuma\ps1\code\hello_camera\hello_camera.atom.c
|
||
// Component atoms (MipsAtomComp_(ac_*)) -> macro variants (mac_*)
|
||
|
||
#ifndef WORD_COUNT
|
||
#define WORD_COUNT(name, count) enum { words_##name = (count) };
|
||
#endif
|
||
|
||
#define mac_put_disp_env(reg_transfer, reg_base, port) \
|
||
mac_gcmd_push(gp0_word_draw_area_top_left_origin, reg_transfer, reg_base, port) \
|
||
, mac_gcmd_push(gp0_word_draw_area_bottom_right_320x240, reg_transfer, reg_base, port) \
|
||
, mac_gcmd_push(gp0_word_set_mask_bit(), reg_transfer, reg_base, port) \
|
||
, mac_gcmd_push(gp0_word_draw_area_top_left_origin, reg_transfer, reg_base, port) \
|
||
, mac_gcmd_push(gp0_word_draw_area_bottom_right_320x240, reg_transfer, reg_base, port)
|
||
WORD_COUNT(mac_put_disp_env, 5)
|
||
|
||
#define mac_put_draw_env(reg_transfer, reg_base, port) \
|
||
mac_gcmd_push(gp0_dr_env_tag, reg_transfer, reg_base, port) /* tag (length=15 << 24, addr=0) — packet header for the DR_ENV sequence. The GPU needs this to recognize the next 15 words as a DR_ENV packet and trigger the isbg auto-clear. */ \
|
||
, mac_gcmd_push(gp0_word_draw_mode_drawing_allowed, reg_transfer, reg_base, port) /* code[0] DrawMode (dfe=1, dtd=0, tpage=0) */ \
|
||
, mac_gcmd_push(gp0_word_set_texture_window(), reg_transfer, reg_base, port) /* code[1] TextureWindow (tw=(0,0)) */ \
|
||
, mac_gcmd_push(enc_gp0_draw_area_tl_word(0, ScreenRes_Y), reg_transfer, reg_base, port) /* code[2] DrawArea top-left (clip.x=0, clip.y=ScreenRes_Y=240) */ \
|
||
, mac_gcmd_push(gp0_word_draw_area_bottom_right_320x240, reg_transfer, reg_base, port) /* code[3] DrawArea bottom-right (clip.x+w=320, clip.y+h=480) */ \
|
||
, mac_gcmd_push(gp0_word_set_draw_offset(), reg_transfer, reg_base, port) /* code[4] DrawOffset (ofs=(0,0)) — bare-cmd word; the GPU uses the current state machine. */ \
|
||
, mac_gcmd_push(gp0_word_dr_env_mask(), reg_transfer, reg_base, port) /* code[5] Mask (dtd=0, dfe=1, isbg=1) — 0xE6 cmd + isbg bit. */ \
|
||
, mac_gcmd_push(gp0_word_dr_env_bg_color_cmd(1, 7, 7, 7), reg_transfer, reg_base, port) /* code[6] Initial-bg-color + auto-clear (isbg=1, r=7, g=7, b=7). */ \
|
||
, mac_gcmd_push(gp0_word_dr_env_draw_mode(1), reg_transfer, reg_base, port) /* code[7] Re-assert DrawMode with isbg=1 (isbg-flag set; the 0xE1 cmd byte plus isbg only). */ /* code[8..10] Padding (NOP — GPU discards; the DR_ENV requires 16 words total). */ \
|
||
, mac_gcmd_push(gp0_word_nop(), reg_transfer, reg_base, port) \
|
||
, mac_gcmd_push(gp0_word_nop(), reg_transfer, reg_base, port) \
|
||
, mac_gcmd_push(gp0_word_nop(), reg_transfer, reg_base, port) /* code[11..12] TextureWindow bottom-right (tw.x+tw.w=0, tw.y+tw.h=0) — libpsyx emits twice. */ \
|
||
, mac_gcmd_push(gp0_word_set_texture_window(), reg_transfer, reg_base, port) \
|
||
, mac_gcmd_push(gp0_word_set_texture_window(), reg_transfer, reg_base, port) /* code[13..14] Padding (NOP) — completes the 16-word packet. */ \
|
||
, mac_gcmd_push(gp0_word_nop(), reg_transfer, reg_base, port) \
|
||
, mac_gcmd_push(gp0_word_nop(), reg_transfer, reg_base, port)
|
||
WORD_COUNT(mac_put_draw_env, 16)
|
||
|
||
#define mac_resolve_look_at__input_and_sub(...) \
|
||
load_word(r_target_ptr, R_TapePtr, O_(Binds_ResolveLookAtSub,target)) \
|
||
, load_word(r_eye_ptr, R_TapePtr, O_(Binds_ResolveLookAtSub,eye)) \
|
||
, load_word(r_up_in_ptr, R_TapePtr, O_(Binds_ResolveLookAtSub,up_in)) \
|
||
, add_ui_self( R_TapePtr, S_(Binds_ResolveLookAtSub)) \
|
||
, load_word(r_scratch, R_TapePtr, O_(Binds_ResolveLookAtScratch,scratch_base)) \
|
||
, add_ui_self( R_TapePtr, S_(Binds_ResolveLookAtScratch)) /* Stage eye.x/y/z into the scratchpad (atom 6 reads these for the translation
|
||
* column). Reuse r_tmp0/r_tmp1/r_tmp2. Offsets via O_(ResolveLookAtScratch,*). */ \
|
||
, load_word(r_tmp0, r_eye_ptr, O_(P3_S4,x)) \
|
||
, load_word(r_tmp1, r_eye_ptr, O_(P3_S4,y)) \
|
||
, load_word(r_tmp2, r_eye_ptr, O_(P3_S4,z)) \
|
||
, nop /* load-delay */ \
|
||
, store_word(r_tmp0, r_scratch, O_(ResolveLookAtScratch,eye.x)) \
|
||
, store_word(r_tmp1, r_scratch, O_(ResolveLookAtScratch,eye.y)) \
|
||
, store_word(r_tmp2, r_scratch, O_(ResolveLookAtScratch,eye.z)) /* Stage up_in.x/y/z into the scratchpad (atom 2 reads these for the outer
|
||
* product with uz). Reuse r_tmp0/r_tmp1/r_tmp2. */ \
|
||
, load_word(r_tmp0, r_up_in_ptr, O_(V3_S4,x)) \
|
||
, load_word(r_tmp1, r_up_in_ptr, O_(V3_S4,y)) \
|
||
, load_word(r_tmp2, r_up_in_ptr, O_(V3_S4,z)) \
|
||
, nop /* load-delay */ \
|
||
, store_word(r_tmp0, r_scratch, O_(ResolveLookAtScratch,up_in.x)) \
|
||
, store_word(r_tmp1, r_scratch, O_(ResolveLookAtScratch,up_in.y)) \
|
||
, store_word(r_tmp2, r_scratch, O_(ResolveLookAtScratch,up_in.z)) /* Compute fwd = target - eye. */ \
|
||
, load_word(r_tmp0, r_target_ptr, O_(P3_S4,x)) \
|
||
, load_word(r_tmp1, r_target_ptr, O_(P3_S4,y)) \
|
||
, load_word(r_tmp2, r_target_ptr, O_(P3_S4,z)) \
|
||
, load_word(r_tmp3, r_eye_ptr, O_(P3_S4,x)) \
|
||
, load_word(R_AT, r_eye_ptr, O_(P3_S4,y)) \
|
||
, load_word(R_V0, r_eye_ptr, O_(P3_S4,z)) \
|
||
, nop /* load-delay */ \
|
||
, sub_u(r_tmp0, r_tmp0, r_tmp3) \
|
||
, sub_u(r_tmp1, r_tmp1, R_AT) \
|
||
, sub_u(r_tmp2, r_tmp2, R_V0) /* Store fwd.x/y/z (atom 1 reads these as the normalize src). */ \
|
||
, store_word(r_tmp0, r_scratch, O_(ResolveLookAtScratch,fwd.x)) \
|
||
, store_word(r_tmp1, r_scratch, O_(ResolveLookAtScratch,fwd.y)) \
|
||
, store_word(r_tmp2, r_scratch, O_(ResolveLookAtScratch,fwd.z)) \
|
||
, mac_yield()
|
||
WORD_COUNT(mac_resolve_look_at__input_and_sub, 34)
|
||
|
||
#define mac_resolve_look_at__cross_uz_up_in_to_right(...) \
|
||
add_si(r_g, r_scratch, O_(ResolveLookAtScratch,uz)) /* r_g = &uz */ \
|
||
, add_si(r_h, r_scratch, O_(ResolveLookAtScratch,up_in)) /* r_h = &up_in */ \
|
||
, add_si(r_f, r_scratch, O_(ResolveLookAtScratch,right)) /* r_f = &right (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 b (up_in).x/y/z into r_d + R_AT/R_V0 (hardcoded; reusing the
|
||
* body's last two loads is fine because the load-delay slot is the nop
|
||
* after the third load, and mtc2 below doesn't read these regs). */ \
|
||
, 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 /* mtc2 a → IR1/2/3, b → D1/2/3 (VXY0/VZ0/VXY1). */ \
|
||
, gte_mv_to_data_r(r_a, C2_IR1) \
|
||
, gte_mv_to_data_r(r_b, C2_IR2) \
|
||
, gte_mv_to_data_r(r_c, C2_IR3) \
|
||
, gte_mv_to_data_r(r_d, C2_VXY0) /* D1 = b.x */ \
|
||
, gte_mv_to_data_r(R_AT, C2_VZ0) /* D2 = b.y */ \
|
||
, gte_mv_to_data_r(R_V0, C2_VXY1) /* D3 = b.z */ \
|
||
, nop2 /* MTC2 retirement (CPU→COP2 2-slot delay) */ \
|
||
, gte_cmdw_outer_product /* OP fires; MAC1/2/3 = a × b */ /* mfc2 MAC1/2/3 → r_a/r_b/r_c (out.x/y/z). */ \
|
||
, 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 /* MFC2 retirement */ /* Store out.x/y/z to r_f (out ptr = scratch+32). */ \
|
||
, 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_yield()
|
||
WORD_COUNT(mac_resolve_look_at__cross_uz_up_in_to_right, 29)
|
||
|
||
#define mac_resolve_look_at__cross_uz_ux_to_up(...) \
|
||
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) */ \
|
||
, 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 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 /* mtc2 a → IR1/2/3, b → D1/2/3 (VXY0/VZ0/VXY1). */ \
|
||
, gte_mv_to_data_r(r_a, C2_IR1) \
|
||
, gte_mv_to_data_r(r_b, C2_IR2) \
|
||
, gte_mv_to_data_r(r_c, C2_IR3) \
|
||
, gte_mv_to_data_r(r_d, C2_VXY0) \
|
||
, gte_mv_to_data_r(R_AT, C2_VZ0) \
|
||
, gte_mv_to_data_r(R_V0, C2_VXY1) \
|
||
, nop2 \
|
||
, gte_cmdw_outer_product \
|
||
, 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 \
|
||
, 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_yield()
|
||
WORD_COUNT(mac_resolve_look_at__cross_uz_ux_to_up, 29)
|
||
|
||
#define mac_resolve_look_at__normalize_fwd_to_uz(...) \
|
||
add_si(r_a, r_scratch, O_(ResolveLookAtScratch,fwd)) /* r_a = &fwd */ \
|
||
, add_si(r_b, r_scratch, O_(ResolveLookAtScratch,uz)) /* r_b = &uz */ \
|
||
, nop /* Load src.x/y/z from r_a into r_e/r_f/r_i. */ \
|
||
, load_word(r_e, r_a, O_(V3_S4,x)) \
|
||
, load_word(r_f, r_a, O_(V3_S4,y)) \
|
||
, load_word(r_i, r_a, O_(V3_S4,z)) \
|
||
, nop /* load-delay */ /* Stage 1: mtc2 src → IR1/2/3, SQR fires. */ \
|
||
, gte_mv_to_data_r(r_e, C2_IR1) \
|
||
, gte_mv_to_data_r(r_f, C2_IR2) \
|
||
, gte_mv_to_data_r(r_i, C2_IR3) \
|
||
, nop \
|
||
, gte_cmdw_sqr /* Stage 2: mfc2 MAC1/2/3, sum, mtc2 LZCS. */ \
|
||
, gte_mv_from_data_r(r_d, C2_MAC1) \
|
||
, gte_mv_from_data_r(r_g, C2_MAC2) \
|
||
, gte_mv_from_data_r(r_recip_est, C2_MAC3) \
|
||
, nop \
|
||
, add_u(r_recip_est, r_recip_est, r_g) \
|
||
, add_u(r_recip_est, r_recip_est, r_d) \
|
||
, gte_mv_to_data_r(r_recip_est, C2_LZCS) \
|
||
, nop2 \
|
||
, gte_mv_from_data_r(r_h, C2_LZCR) \
|
||
, nop /* Stage 3: compute shift amount, align |v|² to bit 24. */ \
|
||
, and_i( r_h, r_h, -2) \
|
||
, li_s( r_shift, 31) \
|
||
, sub_s( r_shift, r_shift, r_h) \
|
||
, shift_aright(r_shift, r_shift, 1) \
|
||
, add_si( r_a, r_h, -24) /* r_a = LZCR - 24 (overlapping with r_recip_est; src ptr no longer needed) */ \
|
||
, branch_lt_zero(r_a, atom_offset(srav_path_fwd_to_uz, aligned_done_fwd_to_uz)) \
|
||
, nop \
|
||
, jump_rel(atom_offset(aligned_done_fwd_to_uz, srav_path_fwd_to_uz)) \
|
||
, shift_lleft_var(r_recip_est, r_recip_est, r_a) \
|
||
, atom_label(srav_path_fwd_to_uz) \
|
||
, li_s( r_a, 24) \
|
||
, sub_s( r_a, r_a, r_h) \
|
||
, shift_aright_var(r_recip_est, r_recip_est, r_a) \
|
||
, atom_label(aligned_done_fwd_to_uz) /* r_recip_est holds |v|² aligned to bit 24. */ \
|
||
, add_si( r_recip_est, r_recip_est, -64) \
|
||
, shift_lleft(r_recip_est, r_recip_est, 1) \
|
||
, load_upper_i(r_a, u4_hi(& gte_normalize_sqr_tbl)) \
|
||
, or_i_self(r_a, u4_lo(& gte_normalize_sqr_tbl)) \
|
||
, add_u(r_a, r_a, r_recip_est) \
|
||
, load_half(r_recip_est, r_a, 0) \
|
||
, nop /* Stage 4: GPF + srav finalize. */ \
|
||
, gte_mv_to_data_r(r_recip_est, C2_IR0) \
|
||
, gte_mv_to_data_r(r_e, C2_IR1) \
|
||
, gte_mv_to_data_r(r_f, C2_IR2) \
|
||
, gte_mv_to_data_r(r_i, C2_IR3) \
|
||
, nop2 \
|
||
, gte_cmdw_gpf \
|
||
, gte_mv_from_data_r(r_e, C2_MAC1) \
|
||
, gte_mv_from_data_r(r_f, C2_MAC2) \
|
||
, gte_mv_from_data_r(r_i, C2_MAC3) \
|
||
, shift_aright_var(r_e, r_e, r_shift) \
|
||
, shift_aright_var(r_f, r_f, r_shift) \
|
||
, shift_aright_var(r_i, r_i, r_shift) /* Store result.x/y/z to r_b (dst ptr = scratch+16). */ \
|
||
, store_word(r_e, r_b, O_(V3_S4,x)) \
|
||
, store_word(r_f, r_b, O_(V3_S4,y)) \
|
||
, store_word(r_i, r_b, O_(V3_S4,z)) \
|
||
, mac_yield()
|
||
WORD_COUNT(mac_resolve_look_at__normalize_fwd_to_uz, 59)
|
||
|
||
#define mac_resolve_look_at__normalize_right_to_ux(...) \
|
||
add_si(r_a, r_scratch, O_(ResolveLookAtScratch,right)) /* r_a = &right */ \
|
||
, add_si(r_b, r_scratch, O_(ResolveLookAtScratch,ux)) /* r_b = &ux */ \
|
||
, nop \
|
||
, load_word(r_e, r_a, O_(V3_S4,x)) \
|
||
, load_word(r_f, r_a, O_(V3_S4,y)) \
|
||
, load_word(r_i, r_a, O_(V3_S4,z)) \
|
||
, nop \
|
||
, gte_mv_to_data_r(r_e, C2_IR1) \
|
||
, gte_mv_to_data_r(r_f, C2_IR2) \
|
||
, gte_mv_to_data_r(r_i, C2_IR3) \
|
||
, nop \
|
||
, gte_cmdw_sqr \
|
||
, gte_mv_from_data_r(r_d, C2_MAC1) \
|
||
, gte_mv_from_data_r(r_g, C2_MAC2) \
|
||
, gte_mv_from_data_r(r_recip_est, C2_MAC3) \
|
||
, nop \
|
||
, add_u(r_recip_est, r_recip_est, r_g) \
|
||
, add_u(r_recip_est, r_recip_est, r_d) \
|
||
, gte_mv_to_data_r(r_recip_est, C2_LZCS) \
|
||
, nop2 \
|
||
, gte_mv_from_data_r(r_h, C2_LZCR) \
|
||
, nop \
|
||
, and_i( r_h, r_h, -2) \
|
||
, li_s( r_shift, 31) \
|
||
, sub_s( r_shift, r_shift, r_h) \
|
||
, shift_aright(r_shift, r_shift, 1) \
|
||
, add_si( r_a, r_h, -24) \
|
||
, branch_lt_zero(r_a, atom_offset(srav_path_right_to_ux, aligned_done_right_to_ux)) \
|
||
, nop \
|
||
, jump_rel(atom_offset(aligned_done_right_to_ux, srav_path_right_to_ux)) \
|
||
, shift_lleft_var(r_recip_est, r_recip_est, r_a) \
|
||
, atom_label(srav_path_right_to_ux) \
|
||
, li_s( r_a, 24) \
|
||
, sub_s( r_a, r_a, r_h) \
|
||
, shift_aright_var(r_recip_est, r_recip_est, r_a) \
|
||
, atom_label(aligned_done_right_to_ux) \
|
||
, add_si( r_recip_est, r_recip_est, -64) \
|
||
, shift_lleft(r_recip_est, r_recip_est, 1) \
|
||
, load_upper_i(r_a, u4_hi(& gte_normalize_sqr_tbl)) \
|
||
, or_i_self(r_a, u4_lo(& gte_normalize_sqr_tbl)) \
|
||
, add_u(r_a, r_a, r_recip_est) \
|
||
, load_half(r_recip_est, r_a, 0) \
|
||
, nop \
|
||
, gte_mv_to_data_r(r_recip_est, C2_IR0) \
|
||
, gte_mv_to_data_r(r_e, C2_IR1) \
|
||
, gte_mv_to_data_r(r_f, C2_IR2) \
|
||
, gte_mv_to_data_r(r_i, C2_IR3) \
|
||
, nop2 \
|
||
, gte_cmdw_gpf \
|
||
, gte_mv_from_data_r(r_e, C2_MAC1) \
|
||
, gte_mv_from_data_r(r_f, C2_MAC2) \
|
||
, gte_mv_from_data_r(r_i, C2_MAC3) \
|
||
, shift_aright_var(r_e, r_e, r_shift) \
|
||
, shift_aright_var(r_f, r_f, r_shift) \
|
||
, shift_aright_var(r_i, r_i, r_shift) \
|
||
, store_word(r_e, r_b, O_(V3_S4,x)) \
|
||
, store_word(r_f, r_b, O_(V3_S4,y)) \
|
||
, store_word(r_i, r_b, O_(V3_S4,z)) \
|
||
, mac_yield()
|
||
WORD_COUNT(mac_resolve_look_at__normalize_right_to_ux, 59)
|
||
|
||
#define mac_resolve_look_at__normalize_up_to_uy(...) \
|
||
add_si(r_a, r_scratch, O_(ResolveLookAtScratch,up)) /* r_a = &up */ \
|
||
, add_si(r_b, r_scratch, O_(ResolveLookAtScratch,uy)) /* r_b = &uy */ \
|
||
, nop \
|
||
, load_word(r_e, r_a, O_(V3_S4,x)) \
|
||
, load_word(r_f, r_a, O_(V3_S4,y)) \
|
||
, load_word(r_i, r_a, O_(V3_S4,z)) \
|
||
, nop \
|
||
, gte_mv_to_data_r(r_e, C2_IR1) \
|
||
, gte_mv_to_data_r(r_f, C2_IR2) \
|
||
, gte_mv_to_data_r(r_i, C2_IR3) \
|
||
, nop \
|
||
, gte_cmdw_sqr \
|
||
, gte_mv_from_data_r(r_d, C2_MAC1) \
|
||
, gte_mv_from_data_r(r_g, C2_MAC2) \
|
||
, gte_mv_from_data_r(r_recip_est, C2_MAC3) \
|
||
, nop \
|
||
, add_u(r_recip_est, r_recip_est, r_g) \
|
||
, add_u(r_recip_est, r_recip_est, r_d) \
|
||
, gte_mv_to_data_r(r_recip_est, C2_LZCS) \
|
||
, nop2 \
|
||
, gte_mv_from_data_r(r_h, C2_LZCR) \
|
||
, nop \
|
||
, and_i( r_h, r_h, -2) \
|
||
, li_s( r_shift, 31) \
|
||
, sub_s( r_shift, r_shift, r_h) \
|
||
, shift_aright(r_shift, r_shift, 1) \
|
||
, add_si( r_a, r_h, -24) \
|
||
, branch_lt_zero(r_a, atom_offset(srav_path_up_to_uy, aligned_done_up_to_uy)) \
|
||
, nop \
|
||
, jump_rel(atom_offset(aligned_done_up_to_uy, srav_path_up_to_uy)) \
|
||
, shift_lleft_var(r_recip_est, r_recip_est, r_a) \
|
||
, atom_label(srav_path_up_to_uy) \
|
||
, li_s( r_a, 24) \
|
||
, sub_s( r_a, r_a, r_h) \
|
||
, shift_aright_var(r_recip_est, r_recip_est, r_a) \
|
||
, atom_label(aligned_done_up_to_uy) \
|
||
, add_si( r_recip_est, r_recip_est, -64) \
|
||
, shift_lleft(r_recip_est, r_recip_est, 1) \
|
||
, load_upper_i(r_a, u4_hi(& gte_normalize_sqr_tbl)) \
|
||
, or_i_self(r_a, u4_lo(& gte_normalize_sqr_tbl)) \
|
||
, add_u(r_a, r_a, r_recip_est) \
|
||
, load_half(r_recip_est, r_a, 0) \
|
||
, nop \
|
||
, gte_mv_to_data_r(r_recip_est, C2_IR0) \
|
||
, gte_mv_to_data_r(r_e, C2_IR1) \
|
||
, gte_mv_to_data_r(r_f, C2_IR2) \
|
||
, gte_mv_to_data_r(r_i, C2_IR3) \
|
||
, nop2 \
|
||
, gte_cmdw_gpf \
|
||
, gte_mv_from_data_r(r_e, C2_MAC1) \
|
||
, gte_mv_from_data_r(r_f, C2_MAC2) \
|
||
, gte_mv_from_data_r(r_i, C2_MAC3) \
|
||
, shift_aright_var(r_e, r_e, r_shift) \
|
||
, shift_aright_var(r_f, r_f, r_shift) \
|
||
, shift_aright_var(r_i, r_i, r_shift) \
|
||
, store_word(r_e, r_b, O_(V3_S4,x)) \
|
||
, store_word(r_f, r_b, O_(V3_S4,y)) \
|
||
, store_word(r_i, r_b, O_(V3_S4,z)) \
|
||
, mac_yield()
|
||
WORD_COUNT(mac_resolve_look_at__normalize_up_to_uy, 59)
|
||
|
||
#define mac_resolve_look_at__populate_and_translate(...) \
|
||
load_word(r_look_at, R_TapePtr, O_(Binds_ResolveLookAtPopAndTrans,look_at)) \
|
||
, add_ui_self( R_TapePtr, S_(Binds_ResolveLookAtPopAndTrans)) /* Compute the 4 scratch pointers in their dedicated GPRs. */ \
|
||
, add_si(r_pux, r_scratch, O_(ResolveLookAtScratch,ux)) /* r_pux = &ux */ \
|
||
, add_si(r_puy, r_scratch, O_(ResolveLookAtScratch,uy)) /* r_puy = &uy */ \
|
||
, add_si(r_puz, r_scratch, O_(ResolveLookAtScratch,uz)) /* r_puz = &uz */ \
|
||
, add_si(r_peye, r_scratch, O_(ResolveLookAtScratch,eye)) /* r_peye = &eye */ \
|
||
, nop /* ── m[0] = (S2)ux ── */ \
|
||
, load_word(r_tmp0, r_pux, O_(V3_S4,x)) \
|
||
, load_word(r_tmp1, r_pux, O_(V3_S4,y)) \
|
||
, 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])) /* ── Translation column t[i] = R * (-eye) ─────────────────────────────
|
||
* pos = -eye: load eye.x/y/z from r_peye, negate via sub_u from R_0. */ \
|
||
, load_word(r_tmp0, r_peye, O_(P3_S4,x)) \
|
||
, load_word(r_tmp1, r_peye, O_(P3_S4,y)) \
|
||
, load_word(r_tmp2, r_peye, O_(P3_S4,z)) \
|
||
, nop \
|
||
, sub_u(r_tmp0, R_0, r_tmp0) /* pos.x = -eye.x */ \
|
||
, sub_u(r_tmp1, R_0, r_tmp1) \
|
||
, sub_u(r_tmp2, R_0, r_tmp2) /* mtc2 IR1/2/3 = pos (for MVMVA — input vector registers). */ \
|
||
, gte_mv_to_data_r(r_tmp0, C2_IR1) \
|
||
, gte_mv_to_data_r(r_tmp1, C2_IR2) \
|
||
, gte_mv_to_data_r(r_tmp2, C2_IR3) \
|
||
, nop2 /* MVMVA: MAC1/2/3 = R * IR with cv=0 (no TR vector), mx=0 (rotation matrix),
|
||
* sf=0 (no shift), v=0 (V0 = IR1/2/3, no far-plane clipping). The pre-set
|
||
* rotation matrix is the one set by the preceding set_gte_world atom.
|
||
* gte_cmdw_mvmva is parameterless and defaults to cv=0/mx=0/sf=0/v=0. */ \
|
||
, gte_cmdw_mvmva \
|
||
, nop /* GTE interlock */ /* mfc2 MAC1/2/3 → r_tmp0/r_tmp1/r_tmp2 (sign-extended into 32-bit GPRs).
|
||
* MAC1/2/3 hold R*v with no TR add and no perspective divide — exactly the
|
||
* 3 distinct world-space translation values we need for t[0..2]. */ \
|
||
, gte_mv_from_data_r(r_tmp0, C2_MAC1) \
|
||
, gte_mv_from_data_r(r_tmp1, C2_MAC2) \
|
||
, gte_mv_from_data_r(r_tmp2, C2_MAC3) \
|
||
, nop \
|
||
, store_word(r_tmp0, r_look_at, O_(MT3_S2S4,t[0])) \
|
||
, store_word(r_tmp1, r_look_at, O_(MT3_S2S4,t[1])) \
|
||
, store_word(r_tmp2, r_look_at, O_(MT3_S2S4,t[2])) \
|
||
, mac_yield()
|
||
WORD_COUNT(mac_resolve_look_at__populate_and_translate, 50)
|
||
|