#ifdef INTELLISENSE_DIRECTIVES
#pragma once
#endif
// Auto-generated by ps1_meta.lua — DO NOT EDIT
// Directory: C:\projects\Pikuma\ps1\code\duffle/
//   source: C:\projects\Pikuma\ps1\code\duffle\word_count.metadata.h
//   source: C:\projects\Pikuma\ps1\code\duffle\dsl.h
//   source: C:\projects\Pikuma\ps1\code\duffle\memory.h
//   source: C:\projects\Pikuma\ps1\code\duffle\math.h
//   source: C:\projects\Pikuma\ps1\code\duffle\gcc_asm.h
//   source: C:\projects\Pikuma\ps1\code\duffle\mips.h
//   source: C:\projects\Pikuma\ps1\code\duffle\gp.h
//   source: C:\projects\Pikuma\ps1\code\duffle\gte.h
//   source: C:\projects\Pikuma\ps1\code\duffle\pad.h
//   source: C:\projects\Pikuma\ps1\code\duffle\dsl.atom.h
//   source: C:\projects\Pikuma\ps1\code\duffle\lottes_tape.h
//   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\mips.atom.c
//   source: C:\projects\Pikuma\ps1\code\duffle\gte.atom.c
//   source: C:\projects\Pikuma\ps1\code\duffle\gp.atom.c
//   source: C:\projects\Pikuma\ps1\code\duffle\pad.atom.c
//   source: C:\projects\Pikuma\ps1\code\duffle\psyq.atom.c
// Component atoms (MipsAtomComp_(ac_*)) -> macro variants (mac_*)

#ifndef WORD_COUNT
#define WORD_COUNT(name, count)  enum { words_##name = (count) };
#endif

/* atom_dbg_skip */
/* ---------------------------------------------------------------------------
 *  MACRO ATOM Components (Reusable Assembly Components)
 *  These do NOT yield. They are expanded inline inside Tape Atoms.
 * ---------------------------------------------------------------------------*/
// The 'Yield' sequence for Tape Atoms (mac_yield).
//   - mac_yield() is the safe default for atom-endings: 4 words, BD-slot of jr is mandatory nop.
//   - mac_yield_load() + mac_yield_tail():
//     - unconditional branch: mac_yield_load fills the branch's BD-slot (replaces a nop);
//     - mac_yield_tail runs at the branch target (does NOT re-load R_AtomJmp).
#define mac_yield(...) \
	load_word(R_AtomJmp, R_TapePtr, 0) \
,	add_ui_self(         R_TapePtr, S_(MipsCode)) \
,	jump_reg( R_AtomJmp) \
,	nop
WORD_COUNT(mac_yield, 4)

/* atom_dbg_skip */
#define mac_yield_load(...) \
	load_word(R_AtomJmp, R_TapePtr, 0)
WORD_COUNT(mac_yield_load, 1)

/* atom_dbg_skip */
#define mac_yield_tail(...) \
	add_ui_self(R_TapePtr, S_(MipsCode)) \
,	jump_reg(  R_AtomJmp) \
,	nop
WORD_COUNT(mac_yield_tail, 3)

/* atom_dbg_skip */
#define mac_load_v2s2(rs_x, rs_y, r_base, offset) \
	load_half( rs_x, r_base, O_(V3_S2,x)) \
,	load_half( rs_y, r_base, O_(V3_S2,y))
WORD_COUNT(mac_load_v2s2, 2)

/* atom_dbg_skip */
#define mac_store_v2s2(rt_x, rt_y, base, offset) \
	store_half(rt_x, base, offset + O_(V2_S2,x)) \
,	store_half(rt_y, base, offset + O_(V2_S2,y))
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, O_(V3_S4,x)) \
,	load_word( rs_y, r_base, O_(V3_S4,y)) \
,	load_word( rs_z, r_base, O_(V3_S4,z))
WORD_COUNT(mac_load_v3s4, 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))
WORD_COUNT(mac_store_v3s4, 3)

/* atom_dbg_skip */
#define mac_sub_v3s4(rds_x, rds_y, rds_z, rt_x, rt_y, rt_z) \
	sub_s(rds_x, rds_x, rt_x) \
,	sub_s(rds_y, rds_y, rt_y) \
,	sub_s(rds_z, rds_z, rt_z)
WORD_COUNT(mac_sub_v3s4, 3)

/* atom_dbg_skip */
#define mac_store_rects2(rt_x, rt_y, rt_width, rt_height, base, offset) \
	store_half(rt_x,      base, offset + O_(Rect_S2,x)) \
,	store_half(rt_y,      base, offset + O_(Rect_S2,y)) \
,	store_half(rt_width,  base, offset + O_(Rect_S2,width)) \
,	store_half(rt_height, base, offset + O_(Rect_S2,height))
WORD_COUNT(mac_store_rects2, 4)

/* atom_dbg_skip */
#define mac_load_tri_indices(r_face_cusor, r_i0, r_i1, r_i2) \
	load_half_u(r_i0, r_face_cusor, 0 * S_(S2)) \
,	load_half_u(r_i1, r_face_cusor, 1 * S_(S2)) \
,	load_half_u(r_i2, r_face_cusor, 2 * S_(S2))
WORD_COUNT(mac_load_tri_indices, 3)

/* atom_dbg_skip */
#define mac_gte_store_f3(r_primitive_cursor) \
	gte_sw(C2_SXY0, r_primitive_cursor, O_(Poly_F3,p0)) \
,	gte_sw(C2_SXY1, r_primitive_cursor, O_(Poly_F3,p1)) \
,	gte_sw(C2_SXY2, r_primitive_cursor, O_(Poly_F3,p2))
WORD_COUNT(mac_gte_store_f3, 3)

/* atom_dbg_skip */
#define mac_gte_load_tri_verts(r_vert_base, r_v0, r_v1, r_v2) \
	shift_lleft(R_AT, r_v0, v3s2_byteoff) \
,	add_u_self(R_AT, r_vert_base) \
,	load_word(R_V0, R_AT, O_(V3_S2,x)) \
,	load_word(R_V1, R_AT, O_(V3_S2,z)) \
,	gte_mv_to_data_r(R_V0, C2_VXY0) \
,	gte_mv_to_data_r(R_V1, C2_VZ0) \
,	shift_lleft(R_AT, r_v1, v3s2_byteoff) \
,	add_u_self(R_AT, r_vert_base) \
,	load_word(R_V0, R_AT, O_(V3_S2,x)) \
,	load_word(R_V1, R_AT, O_(V3_S2,z)) \
,	gte_mv_to_data_r(R_V0, C2_VXY1) \
,	gte_mv_to_data_r(R_V1, C2_VZ1) \
,	shift_lleft(R_AT, r_v2, v3s2_byteoff) \
,	add_u_self(R_AT, r_vert_base) \
,	load_word(R_V0, R_AT, O_(V3_S2,x)) \
,	load_word(R_V1, R_AT, O_(V3_S2,z)) \
,	gte_mv_to_data_r(R_V0, C2_VXY2) \
,	gte_mv_to_data_r(R_V1, C2_VZ2)
WORD_COUNT(mac_gte_load_tri_verts, 18)

/* atom_dbg_skip */
#define mac_gte_store_g4_p012(r_primitive_cursor) \
	gte_sw(C2_SXY0, r_primitive_cursor, O_(Poly_G4,p0)) \
,	gte_sw(C2_SXY1, r_primitive_cursor, O_(Poly_G4,p1)) \
,	gte_sw(C2_SXY2, r_primitive_cursor, O_(Poly_G4,p2))
WORD_COUNT(mac_gte_store_g4_p012, 3)

/* atom_dbg_skip */
#define mac_gte_store_g4_p3(r_primitive_cursor) \
	gte_sw(C2_SXY2, r_primitive_cursor, O_(Poly_G4,p3))
WORD_COUNT(mac_gte_store_g4_p3, 1)

/* atom_dbg_skip */
#define mac_gte_sqr_v3(r_sx, r_sy, r_sz, r_sq_x, r_sq_y, r_sq_z) \
	gte_mv_to_data_r(r_sx, C2_IR1) \
,	gte_mv_to_data_r(r_sy, C2_IR2) \
,	gte_mv_to_data_r(r_sz, C2_IR3) \
,	nop \
,	gte_cmdw_sqr \
,	gte_mv_from_data_r(r_sq_x, C2_MAC1) \
,	gte_mv_from_data_r(r_sq_y, C2_MAC2) \
,	gte_mv_from_data_r(r_sq_z, C2_MAC3)
WORD_COUNT(mac_gte_sqr_v3, 8)

/* atom_dbg_skip */
#define mac_gte_gpf_scale(r_sx, r_sy, r_sz, r_recip_est, r_shift, r_dx, r_dy, r_dz) \
	gte_mv_to_data_r(r_recip_est, C2_IR0) \
,	gte_mv_to_data_r(r_sx,        C2_IR1) \
,	gte_mv_to_data_r(r_sy,        C2_IR2) \
,	gte_mv_to_data_r(r_sz,        C2_IR3) \
,	nop2 /* retire IR0..IR3 → GPF input pre-fill (matches libgte 0x80016134..0x80016138) */ \
,	gte_cmdw_gpf \
,	gte_mv_from_data_r(r_dx, C2_MAC1) \
,	gte_mv_from_data_r(r_dy, C2_MAC2) \
,	gte_mv_from_data_r(r_dz, C2_MAC3) \
,	shift_aright_var(r_dx, r_dx, r_shift) \
,	shift_aright_var(r_dy, r_dy, r_shift) \
,	shift_aright_var(r_dz, r_dz, r_shift)
WORD_COUNT(mac_gte_gpf_scale, 13)

#define mac_gcmd_push(cmd, reg_transfer, reg_base, port) \
	load_upper_i(reg_transfer, u4_hi(cmd)) \
,	or_i_self(   reg_transfer, u4_lo(cmd))	/* load_upper_i(reg_transfer, cmd >> 16),	// or_i_self(   reg_transfer, cmd & 0xFFFF), */ \
,	store_word(  reg_transfer, reg_base, port)
WORD_COUNT(mac_gcmd_push, 3)

/* atom_dbg_skip */
#define mac_store_rgb8(rr, rg, rb, base, offset) \
	store_byte(rr, base, offset + O_(RGB8,r)) \
,	store_byte(rg, base, offset + O_(RGB8,g)) \
,	store_byte(rb, base, offset + O_(RGB8,b))
WORD_COUNT(mac_store_rgb8, 3)

/* atom_dbg_skip */
#define mac_pack_color_word(r_base, off, cmd, r, g, b) \
	load_upper_i(R_AT, (cmd) << 8  | (b)) \
,	or_i_self(   R_AT, ((g)  << 8) | (r)) \
,	store_word(  R_AT, r_base, (off))
WORD_COUNT(mac_pack_color_word, 3)

/* atom_dbg_skip */
#define mac_format_f3_color(r_base, r, g, b) \
	mac_pack_color_word(r_base, O_(Poly_F3,color), gp0_cmd_poly_f3, r, g, b)
WORD_COUNT(mac_format_f3_color, 3)

#define mac_format_g4_color(r_prim_cursor, r0, g0, b0, r1, g1, b1, r2, g2, b2, r3, g3, b3) \
	mac_pack_color_word(r_prim_cursor, O_(Poly_G4,c0), gp0_cmd_poly_g4, r0,g0,b0) \
,	mac_pack_color_word(r_prim_cursor, O_(Poly_G4,c1), 0,               r1,g1,b1) \
,	mac_pack_color_word(r_prim_cursor, O_(Poly_G4,c2), 0,               r2,g2,b2) \
,	mac_pack_color_word(r_prim_cursor, O_(Poly_G4,c3), 0,               r3,g3,b3)
WORD_COUNT(mac_format_g4_color, 12)

#define mac_insert_ot_tag(r_ot_base, r_prim_cursor, poly_size) \
	shift_lleft( R_T1, R_T1, S_(U4)/2)                        /* T1 = otz * S_(U4) (otz arg is implicit R_T1) */ \
,	add_u_self(  R_T1, r_ot_base)                             /* T1 = & OrderingTable[OTZ] */ \
,	load_word(   R_AT, R_T1,          O_(PolyTag,code))       /* AT = old_ot_head */ \
,	load_upper_i(R_V0, (poly_size/S_(U4) - S_(PolyTag)/S_(U4)) << PolyTag_len_bits) \
,	mask_upper(  R_AT, R_AT,          S_(PolyTag_len_bits))   /* Strip upper 8 bits (length from prev cell) → keep only low 24 */ \
,	or_u(        R_AT, R_AT, R_V0)                            /* Merge length */ \
,	store_word(  R_AT, r_prim_cursor, O_(PolyTag,code))       /* prim->tag = packed(prim_length, old_addr) */ \
,	shift_lleft( R_AT, r_prim_cursor, S_(PolyTag_len_bits))   /* AT = (prim_length << 24) | old_addr */ \
,	shift_lright(R_AT, R_AT,          S_(PolyTag_len_bits)) \
,	store_word(  R_AT, R_T1,          O_(PolyTag,code))       /* OrderingTable[OTZ] = PrimCursor */
WORD_COUNT(mac_insert_ot_tag, 11)

/* atom_dbg_skip */
#define mac_pad_set_centered_axes(r_state, r_scratch) \
	load_upper_i(r_scratch, (PadAxis_Centered_Word >> 16) & 0xFFFF) \
,	or_i_self(   r_scratch,  PadAxis_Centered_Word        & 0xFFFF) \
,	store_word(  r_scratch, r_state, O_(PadState,axes))
WORD_COUNT(mac_pad_set_centered_axes, 3)

/* atom_dbg_skip */
#define mac_pad_set_id_byte(r_state, r_id, id_value) \
	add_ui(    r_id, R_0, id_value) \
,	store_byte(r_id, r_state, O_(PadState,id))
WORD_COUNT(mac_pad_set_id_byte, 2)

/* atom_dbg_skip */
#define mac_pad_set_status(r_tmp, r_state, pad_status) \
	add_ui(    r_tmp, R_0, pad_status) \
,	store_word(r_tmp, r_state, O_(PadState,status))
WORD_COUNT(mac_pad_set_status, 2)

/* atom_dbg_skip */
#define mac_pad_store_inverted_buttons(r_buttons, r_pad_state) \
	nor_u(       r_buttons, r_buttons, R_0) \
,	store_half(  r_buttons, r_pad_state, O_(PadState,   buttons))
WORD_COUNT(mac_pad_store_inverted_buttons, 2)

