diff --git a/code/duffle/gcc_asm.h b/code/duffle/gcc_asm.h index e533c5c..2f3fe0a 100644 --- a/code/duffle/gcc_asm.h +++ b/code/duffle/gcc_asm.h @@ -307,7 +307,8 @@ * to `".word %c0, ..." : : "i"(...)` already including the empty output * and input sections via their trailing `:`, so clobbers just tacks on the * end. */ -#define asm_blob(inlines, clobbers) asm volatile ( inlines clobbers ) +// #define asm_blob(inlines, clobbers) asm volatile ( inlines clobbers ) +// Not a fan rather just do asm volatile ( ... ) /* `asm_block(code, outs, ins, clb)` — the full 4-section shell. Each * argument is expected to already include its own leading `:` (via the diff --git a/code/duffle/gte.h b/code/duffle/gte.h index 85a2f55..052c9ce 100644 --- a/code/duffle/gte.h +++ b/code/duffle/gte.h @@ -119,6 +119,12 @@ enum { gte_cr_OFX = 30, gte_cr_OFY = 31, }; +enum { _C2_OPS_ = 0 + + , op_lwc2 = 0x32 /* Load Word to Coprocessor 2 (GTE) */ + , op_swc2 = 0x3A /* Store Word from Coprocessor 2 (GTE) */ +}; + /* COP2 (GTE) Transfer Format: ctc2 rt, rd or cfc2 rt, rd * Layout: [op_cop2:6][sub:5][rt:5][rd:5][0:11] * - sub: cop_mf (0x00) for cfc2, cop_mt (0x04) for ctc2 @@ -182,19 +188,54 @@ enum { * asm_gte_load_v0(svector_ptr); */ -/* Pre-baked constant: lwc2 $0, 0($12) — a plain integer the C compiler - * constant-folds into a .word directive */ -#define gte_lwc2_v0_RT4 enc_cop2_lwc2(gte_in_v0_xy, R_T4, 0) -#define gte_lwc2_v0z_RT4 enc_cop2_lwc2(gte_in_v0_z, R_T4, 4) +/* Pre-baked constants: lwc2 $N, off($12) — plain integers the C compiler + * constant-folds into .word directives. The R_T4 in the name reminds you + * that the `rs` field is baked to R_T4 ($12), forcing the placeholder-pun + * pattern below. */ +#define gte_lwc2_v0_RT4 enc_cop2_lwc2(gte_in_v0_xy, R_T4, 0) +#define gte_lwc2_v0z_RT4 enc_cop2_lwc2(gte_in_v0_z, R_T4, 4) +#define gte_lwc2_v1_RT4 enc_cop2_lwc2(gte_in_v1_xy, R_T4, 0) +#define gte_lwc2_v1z_RT4 enc_cop2_lwc2(gte_in_v1_z, R_T4, 4) +#define gte_lwc2_v2_RT4 enc_cop2_lwc2(gte_in_v2_xy, R_T4, 0) +#define gte_lwc2_v2z_RT4 enc_cop2_lwc2(gte_in_v2_z, R_T4, 4) -/* The actual call-site macro — zero string syntax */ +/* The actual call-site macros — zero string syntax. The asm_blob wrapper + * (defined in gcc_asm.h) handles the asm volatile (...) envelope, and the + * colon-prefixed clobber/input sections slot in cleanly: + * + * asm_blob( , ) + * + * The placeholder-pun: the .word constants have rs=R_T4 ($12) hardwired, + * and the "$12" clobber + "r"(r_ptr) input forces GCC to bind the pointer + * to $12, which is exactly the register the constants expect. */ #define gte_load_v0(r_ptr) \ - asm V_( \ - asm_inline( gte_lwc2_v0_RT4 , gte_lwc2_v0z_RT4 ) \ - asm_clobber( clb_system , "$12" ) \ - : \ - : "r"(r_ptr) \ - ) + asm volatile( \ + asm_inline( gte_lwc2_v0_RT4, gte_lwc2_v0z_RT4 ), \ + asm_clobber( clb_system, "$12" ) \ + : : "r"(r_ptr) ) + +#define gte_load_v1(r_ptr) \ + asm volatile( \ + asm_inline( gte_lwc2_v1_RT4, gte_lwc2_v1z_RT4 ), \ + asm_clobber( clb_system, "$12" ) \ + : : "r"(r_ptr) ) + +#define gte_load_v2(r_ptr) \ + asm volatile( \ + asm_inline( gte_lwc2_v2_RT4, gte_lwc2_v2z_RT4 ), \ + asm_clobber( clb_system, "$12" ) \ + : : "r"(r_ptr) ) + +/* All three at once — the canonical prelude to gte_cmd_rtpt. */ +#define gte_load_v0v1v2(r_ptr) \ + asm volatile( \ + asm_inline( \ + gte_lwc2_v0_RT4, gte_lwc2_v0z_RT4, \ + gte_lwc2_v1_RT4, gte_lwc2_v1z_RT4, \ + gte_lwc2_v2_RT4, gte_lwc2_v2z_RT4 \ + ), \ + asm_clobber( clb_system, "$12" ) \ + : : "r"(r_ptr) ) /** * @brief Loads a single SVECTOR to GTE vector register V1 @@ -202,12 +243,12 @@ enum { * @details Loads values from an SVECTOR struct to GTE data registers C2_VXY1 * and C2_VZ1. */ -#define gte_load_v1( r0 ) __asm__ volatile ( \ - "lwc2 $2, 0( %0 );" \ - "lwc2 $3, 4( %0 );" \ - : \ - : "r"( r0 ) \ - : "$t0" ) +// #define gte_load_v1( r0 ) __asm__ volatile ( \ +// "lwc2 $2, 0( %0 );" \ +// "lwc2 $3, 4( %0 );" \ +// : \ +// : "r"( r0 ) \ +// : "$t0" ) /** * @brief Loads a single SVECTOR to GTE vector register V2 @@ -215,12 +256,12 @@ enum { * @details Loads values from an SVECTOR struct to GTE data registers C2_VXY2 * and C2_VZ2. */ -#define gte_load_v2( r0 ) __asm__ volatile ( \ - "lwc2 $4, 0( %0 );" \ - "lwc2 $5, 4( %0 );" \ - : \ - : "r"( r0 ) \ - : "$t0" ) +// #define gte_load_v2( r0 ) __asm__ volatile ( \ +// "lwc2 $4, 0( %0 );" \ +// "lwc2 $5, 4( %0 );" \ +// : \ +// : "r"( r0 ) \ +// : "$t0" ) #define gte_ldv0(r0) \ __asm__ volatile( \ diff --git a/code/duffle/mips.h b/code/duffle/mips.h index 7b43f64..6210df9 100644 --- a/code/duffle/mips.h +++ b/code/duffle/mips.h @@ -59,11 +59,10 @@ enum { , op_lw = 0x23 /* Load Word */ , op_lbu = 0x24 /* Load Byte Unsigned */ , op_lhu = 0x25 /* Load Halfword Unsigned */ - , op_lwc2 = 0x32 /* Load Word to Coprocessor 2 (GTE) */ , op_sb = 0x28 /* Store Byte */ , op_sh = 0x29 /* Store Halfword */ , op_sw = 0x2B /* Store Word */ - , op_swc2 = 0x3A /* Store Word from Coprocessor 2 (GTE) */ + , op_load_addr = op_la , op_load_imm = op_li @@ -225,17 +224,17 @@ enum { * 5. lw $ra, 4($sp); jr $ra ; restore & return * 6. sp += 8 */ -I_ +internal Code CodeBlob_(mips_flush_icache) { - add_ui(rstack_ptr, rstack_ptr, -8), /* sp -= 8 */ - store_word(rret_addr, rstack_ptr, 4), /* sw $ra, 4($sp) */ - add_ui(rret_0, rdiscard, bios_flushcache), /* addiu $a0, $0, 0x44 */ - add_ui(rtmp_0, rdiscard, bios_table_addr), /* addiu $t0, $0, 0xA0 */ - jump_link(rtmp_0, rret_addr), /* jalr $t0, $ra */ - nop(), /* BD slot */ - load_word(rret_addr, rstack_ptr, 4), /* lw $ra, 4($sp) */ - jump_reg(rret_addr), /* jr $ra */ - add_ui(rstack_ptr, rstack_ptr, 8) /* sp += 8 (BD) */ + add_ui(rstack_ptr, rstack_ptr, -8), /* sp -= 8 */ + store_word(rret_addr, rstack_ptr, 4), /* sw $ra, 4($sp) */ + add_ui(rret_0, rdiscard, bios_flushcache), /* addiu $a0, $0, 0x44 */ + add_ui(rtmp_0, rdiscard, bios_table_addr), /* addiu $t0, $0, 0xA0 */ + jump_link(rtmp_0, rret_addr), /* jalr $t0, $ra */ + nop(), /* BD slot */ + load_word(rret_addr, rstack_ptr, 4), /* lw $ra, 4($sp) */ + jump_reg(rret_addr), /* jr $ra */ + add_ui(rstack_ptr, rstack_ptr, 8) /* sp += 8 (BD) */ }; FI_ void mips_flush_icache(void) { C_(VoidFn*, codeblob_mips_flush_icache)(); } @@ -243,15 +242,15 @@ FI_ void mips_flush_icache(void) { C_(VoidFn*, codeblob_mips_flush_icache)(); } #define asm_mips_flush_icache() asm volatile( \ asm_inline( \ - add_ui(rstack_ptr, rstack_ptr, -8) \ - , store_word(rret_addr, rstack_ptr, 4) \ - , add_ui(rret_0, rdiscard, bios_flushcache) \ - , add_ui(rtmp_0, rdiscard, bios_table_addr) \ - , jump_link(rtmp_0, rret_addr) \ - , nop() \ - , load_word(rret_addr, rstack_ptr, 4) \ - , jump_reg(rret_addr) \ - , add_ui(rstack_ptr, rstack_ptr, 8) \ + add_ui(rstack_ptr, rstack_ptr, -8) \ + , store_word(rret_addr, rstack_ptr, 4) \ + , add_ui(rret_0, rdiscard, bios_flushcache) \ + , add_ui(rtmp_0, rdiscard, bios_table_addr) \ + , jump_link(rtmp_0, rret_addr) \ + , nop() \ + , load_word(rret_addr, rstack_ptr, 4) \ + , jump_reg(rret_addr) \ + , add_ui(rstack_ptr, rstack_ptr, 8) \ ) \ asm_clobber( clb_system ) \ ) diff --git a/code/gte_hello/hello_gte.c b/code/gte_hello/hello_gte.c index a330edf..aa3487e 100644 --- a/code/gte_hello/hello_gte.c +++ b/code/gte_hello/hello_gte.c @@ -8,6 +8,8 @@ #include "duffle/dsl.h" #include "duffle/memory.h" #include "duffle/math.h" +#include "duffle/gcc_asm.h" +#include "duffle/mips.h" #include "duffle/gp.h" #include "duffle/gte.h" #include "hello_gte.h" @@ -243,7 +245,8 @@ void update(PrimitiveArena* pa, U4* ordering_buf) V3_S2* p1 = & static_mem.floor.verts[face->y]; V3_S2* p2 = & static_mem.floor.verts[face->z]; - gte_ldv0(p0); + // gte_ldv0(p0); + gte_load_v0(p0); gte_ldv1(p1); gte_ldv2(p2);