mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-07-12 20:31:25 -07:00
improving dsl: gte.
This commit is contained in:
+112
-25
@@ -1,3 +1,90 @@
|
||||
/* ============================================================================
|
||||
* duffle DSL Suffix Conventions (Style B)
|
||||
* ============================================================================
|
||||
*
|
||||
* Every mnemonic in this header follows the same suffix grammar:
|
||||
*
|
||||
* _i Immediate value (16-bit constant operand). Combine with
|
||||
* _u or _s (single-letter modifier + type combined): add_ui,
|
||||
* add_si. Examples: add_ui, add_si, and_i, or_i, xor_i,
|
||||
* load_upper_i. and_i is sign-agnostic (andi zero-extends).
|
||||
* load_upper_i is a unique verb; _i is the immediate marker,
|
||||
* not a modifier+type combination.
|
||||
*
|
||||
* _u Unsigned (no-overflow, no-sign-extension). R-type
|
||||
* arithmetic examples: add_u, sub_u, mult_u, div_u. I-type
|
||||
* (combined with _i): add_ui.
|
||||
*
|
||||
* _s Signed (overflow-traps, sign-extends). R-type: add_s,
|
||||
* sub_s, mult_s, div_s, set_lt_s. I-type (combined with _i):
|
||||
* add_si.
|
||||
*
|
||||
* --- Shift family (R-type): verb-modifier-direction ---
|
||||
* The shift macros use `shift_<modifier><direction>`. Modifier is
|
||||
* the single letter `l` (logical) or `a` (arithmetic). Direction
|
||||
* is the word `left` or `right`. Combined: `_lleft`, `_lright`,
|
||||
* `_aright`. Examples: shift_lleft(rd, rt, shamt) (= sll)
|
||||
* shift_lright(rd, rt, shamt) (= srl)
|
||||
* shift_aright(rd, rt, shamt) (= sra)
|
||||
* (no `_aleft`; MIPS has no `sla` — arithmetic-left is bit-identical
|
||||
* to logical-left, so use shift_lleft for that case)
|
||||
*
|
||||
* --- Jump/Call family ---
|
||||
* Simple jumps keep the original short names: jump (j), jump_reg
|
||||
* (jr), jump_link (jalr rs, rd). The jump-and-link-to variants
|
||||
* (jal, jalr rs with default $ra) get the `call_` verb instead:
|
||||
* call_addr (jal), call_reg (jalr rs, default $ra).
|
||||
* Examples: jump(off) (= j)
|
||||
* jump_reg(rs) (= jr)
|
||||
* jump_link(rs, rd) (= jalr rs, rd)
|
||||
* call_reg(rs) (= jalr rs, default $ra)
|
||||
* call_addr(off) (= jal)
|
||||
*
|
||||
* _r Register marker — used only when the register type needs
|
||||
* disambiguation (e.g., GTE data register vs control
|
||||
* register). NOT used in plain R-type arithmetic (the
|
||||
* R-type is implicit). Examples: gte_mv_to_data_r,
|
||||
* gte_mv_to_ctrl_r.
|
||||
*
|
||||
* _self Destination equals one source operand.
|
||||
* Examples: add_ui_self (I-type, to self),
|
||||
* add_u_self (R-type, to self).
|
||||
*
|
||||
* _mv_to_ Direction: data flows into X.
|
||||
* Example: gte_mv_to_data_r, gte_mv_to_ctrl_r.
|
||||
*
|
||||
* _mv_from_ Direction: data flows out of X.
|
||||
* Example: gte_mv_from_data_r, gte_mv_from_ctrl_r.
|
||||
*
|
||||
* _str String-form — emits inline-asm string instead of `.word`.
|
||||
* Example: gte_rtpt_asm_str.
|
||||
*
|
||||
* _1w / _2w Emitted word count of the sequence.
|
||||
* Example: load_imm_2w.
|
||||
*
|
||||
* _cop2 RESERVED — DO NOT USE in macro names. The `gte_` namespace
|
||||
* prefix already implies coprocessor 2. Use `c2` only in:
|
||||
* (a) integer opcode enums (op_lwc2 = 0x32, op_swc2 = 0x3A)
|
||||
* (b) vendor-mnemonic aliases (gte_mtc2, gte_mfc2)
|
||||
*
|
||||
* Primitive commands: gp0_cmd_poly_f3 = 0x20 (byte opcode)
|
||||
* Packed 32-bit cmd: gp0_word_poly_f3(r, g, b) (32-bit, shifted)
|
||||
*
|
||||
* Type ordering: domain?_(direction)?_action_target_modifier_type?
|
||||
* Examples: add_ui (add + unsigned + immediate)
|
||||
* add_s (add + signed, R-type implicit)
|
||||
* shift_lleft (shift + logical + left)
|
||||
* shift_aright (shift + arithmetic + right)
|
||||
* call_reg(rs) (call + register, $ra implicit)
|
||||
* gte_mv_to_data_r (gte + mv + to + data + register)
|
||||
* gte_lw_v0_xy(base) (gte + lw + v0 + xy)
|
||||
* load_upper_i (load-upper + immediate, unique verb)
|
||||
*
|
||||
* Vendor mnemonics (gte_mtc2, gte_mfc2, gte_lwc2, gte_swc2, etc.) are
|
||||
* NOT in this header. They live in the opt-in `gte_vendor_sym.h` for
|
||||
* users who prefer the textbook MIPS assembly mnemonics.
|
||||
* ============================================================================ */
|
||||
|
||||
#ifdef INTELLISENSE_DIRECTIVES
|
||||
# pragma once
|
||||
# include "dsl.h"
|
||||
@@ -272,14 +359,14 @@ enum { _C2_OPS_ = 0
|
||||
* - rd: COP2 control register index (0..31) */
|
||||
#define enc_gte_tx(sub, rt, rd) (enc_op(op_cop2) | enc_rs(sub) | enc_rt(rt) | enc_rd(rd))
|
||||
|
||||
// #define gte_mt(rt, rd) enc_gte_tx(cop_mt, (rt), (rd)) /* Move GPR (rt) to GTE Control Register (rd) */
|
||||
// #define gte_mf(rt, rd) enc_gte_tx(cop_mf, (rt), (rd)) /* Move GTE Control Register (rd) to GPR (rt) */
|
||||
// #define gte_mv_to_data_r(rt, rd) enc_gte_tx(cop_mt, (rt), (rd)) /* Move GPR (rt) to GTE Control Register (rd) */
|
||||
// #define gte_mv_from_data_r(rt, rd) enc_gte_tx(cop_mf, (rt), (rd)) /* Move GTE Control Register (rd) to GPR (rt) */
|
||||
|
||||
/* Explicit GTE Data vs Control Register Transfers */
|
||||
#define gte_mf(rt, rd) enc_gte_tx(0x00, (rt), (rd)) /* Move from GTE Data Reg (e.g. MAC0, OTZ) */
|
||||
#define gte_cf(rt, rd) enc_gte_tx(0x02, (rt), (rd)) /* Move from GTE Control Reg */
|
||||
#define gte_mt(rt, rd) enc_gte_tx(0x04, (rt), (rd)) /* Move to GTE Data Reg (e.g. VXY0) */
|
||||
#define gte_ct(rt, rd) enc_gte_tx(0x06, (rt), (rd)) /* Move to GTE Control Reg (e.g. Matrices) */
|
||||
#define gte_mv_from_data_r(rt, rd) enc_gte_tx(0x00, (rt), (rd)) /* Move from GTE Data Reg (e.g. MAC0, OTZ) */
|
||||
#define gte_mv_from_ctrl_r(rt, rd) enc_gte_tx(0x02, (rt), (rd)) /* Move from GTE Control Reg */
|
||||
#define gte_mv_to_data_r(rt, rd) enc_gte_tx(0x04, (rt), (rd)) /* Move to GTE Data Reg (e.g. VXY0) */
|
||||
#define gte_mv_to_ctrl_r(rt, rd) enc_gte_tx(0x06, (rt), (rd)) /* Move to GTE Control Reg (e.g. Matrices) */
|
||||
|
||||
/* COP2 Data Load (lwc2): `lwc2 rt, off(rs)`
|
||||
* Layout: [op_lwc2:6][rs:5][rt:5][imm:16]
|
||||
@@ -411,12 +498,12 @@ enum { _C2_OPS_ = 0
|
||||
|
||||
/* lwc2 encoding helpers parameterized on the base GPR.
|
||||
*
|
||||
* gte_lwc2_v0(base) → lwc2 $0, 0(base) ; C2_VXY0
|
||||
* gte_lwc2_v0z(base) → lwc2 $1, 4(base) ; C2_VZ0
|
||||
* gte_lwc2_v1(base) → lwc2 $2, 0(base) ; C2_VXY1
|
||||
* gte_lwc2_v1z(base) → lwc2 $3, 4(base) ; C2_VZ1
|
||||
* gte_lwc2_v2(base) → lwc2 $4, 0(base) ; C2_VXY2
|
||||
* gte_lwc2_v2z(base) → lwc2 $5, 4(base) ; C2_VZ2
|
||||
* gte_lw_v0_xy(base) → lwc2 $0, 0(base) ; C2_VXY0
|
||||
* gte_lw_v0_z(base) → lwc2 $1, 4(base) ; C2_VZ0
|
||||
* gte_lw_v1_xy(base) → lwc2 $2, 0(base) ; C2_VXY1
|
||||
* gte_lw_v1_z(base) → lwc2 $3, 4(base) ; C2_VZ1
|
||||
* gte_lw_v2_xy(base) → lwc2 $4, 0(base) ; C2_VXY2
|
||||
* gte_lw_v2_z(base) → lwc2 $5, 4(base) ; C2_VZ2
|
||||
*
|
||||
* `base` is the GPR number to bake into the .word constant's `rs` field.
|
||||
* These are pure compile-time integers; the C compiler constant-folds
|
||||
@@ -426,12 +513,12 @@ enum {
|
||||
GTE_Z_Offset = 4
|
||||
};
|
||||
|
||||
#define gte_lw_v0(base) enc_gte_lw(gte_in_v0_xy, (base), 0)
|
||||
#define gte_lw_v0z(base) enc_gte_lw(gte_in_v0_z, (base), GTE_Z_Offset)
|
||||
#define gte_lw_v1(base) enc_gte_lw(gte_in_v1_xy, (base), 0)
|
||||
#define gte_lw_v1z(base) enc_gte_lw(gte_in_v1_z, (base), GTE_Z_Offset)
|
||||
#define gte_lw_v2(base) enc_gte_lw(gte_in_v2_xy, (base), 0)
|
||||
#define gte_lw_v2z(base) enc_gte_lw(gte_in_v2_z, (base), GTE_Z_Offset)
|
||||
#define gte_lw_v0_xy(base) enc_gte_lw(gte_in_v0_xy, (base), 0)
|
||||
#define gte_lw_v0_z(base) enc_gte_lw(gte_in_v0_z, (base), GTE_Z_Offset)
|
||||
#define gte_lw_v1_xy(base) enc_gte_lw(gte_in_v1_xy, (base), 0)
|
||||
#define gte_lw_v1_z(base) enc_gte_lw(gte_in_v1_z, (base), GTE_Z_Offset)
|
||||
#define gte_lw_v2_xy(base) enc_gte_lw(gte_in_v2_xy, (base), 0)
|
||||
#define gte_lw_v2_z(base) enc_gte_lw(gte_in_v2_z, (base), GTE_Z_Offset)
|
||||
|
||||
/* gte_load_vN(r_ptr, base) — placeholder-punned lwc2 loaders
|
||||
*
|
||||
@@ -471,19 +558,19 @@ enum {
|
||||
* The `asm_clobber(...)` helper from gcc_asm.h prepends the colon that
|
||||
* starts the clobbers section. */
|
||||
#define gte_load_v0(r_ptr, base) asm volatile( \
|
||||
asm_words( gte_lw_v0(base), gte_lw_v0z(base) ) \
|
||||
asm_words( gte_lw_v0_xy(base), gte_lw_v0_z(base) ) \
|
||||
asm_rpins, r_use(r_ptr) \
|
||||
asm_clobber: rlit(R_V0), rlit(R_T0), rlit(R_T1), rlit(R_RA), clb_mem_drain \
|
||||
)
|
||||
|
||||
#define gte_load_v1(r_ptr, base) asm volatile( \
|
||||
asm_words( gte_lw_v1(base), gte_lw_v1z(base) ) \
|
||||
asm_words( gte_lw_v1_xy(base), gte_lw_v1_z(base) ) \
|
||||
asm_rpins, r_use(r_ptr) \
|
||||
asm_clobber: rlit(R_V0), rlit(R_T0), rlit(R_T1), rlit(R_RA), clb_mem_drain \
|
||||
)
|
||||
|
||||
#define gte_load_v2(r_ptr, base) asm volatile( \
|
||||
asm_words( gte_lw_v2(base), gte_lw_v2z(base) ) \
|
||||
asm_words( gte_lw_v2_xy(base), gte_lw_v2_z(base) ) \
|
||||
asm_rpins, r_use(r_ptr) \
|
||||
asm_clobber: rlit(R_V0), rlit(R_T0), rlit(R_T1), rlit(R_RA), clb_mem_drain \
|
||||
)
|
||||
@@ -502,9 +589,9 @@ enum {
|
||||
*/
|
||||
#define gte_load_v0v1v2(p0, p1, p2, b0, b1, b2) asm volatile( \
|
||||
asm_words( \
|
||||
gte_lw_v0(b0), gte_lw_v0z(b0), \
|
||||
gte_lw_v1(b1), gte_lw_v1z(b1), \
|
||||
gte_lw_v2(b2), gte_lw_v2z(b2) ) \
|
||||
gte_lw_v0_xy(b0), gte_lw_v0_z(b0), \
|
||||
gte_lw_v1_xy(b1), gte_lw_v1_z(b1), \
|
||||
gte_lw_v2_xy(b2), gte_lw_v2_z(b2) ) \
|
||||
asm_rpins \
|
||||
, r_use(p0), r_use(p1), r_use(p2) \
|
||||
asm_clobber: rlit(R_V0), rlit(R_T0), rlit(R_T1), rlit(R_RA), clb_mem_drain \
|
||||
@@ -542,7 +629,7 @@ enum {
|
||||
asm_clobber: clbr_volatile_gprs \
|
||||
)
|
||||
|
||||
#define gte_rtpt_ori() \
|
||||
#define gte_rtpt_asm_str() \
|
||||
__asm__ volatile( \
|
||||
"nop;" \
|
||||
"nop;" \
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/* ============================================================================
|
||||
* duffle DSL — GTE Vendor Mnemonics (opt-in)
|
||||
* ============================================================================
|
||||
*
|
||||
* Provides the textbook MIPS assembly mnemonics for the GTE/COP2
|
||||
* instructions as thin aliases to the canonical duffle macros in gte.h.
|
||||
* The duffle names are primary; this header is for users who prefer
|
||||
* the textbook mnemonics.
|
||||
*
|
||||
* USAGE: #include "duffle/gte_vendor_sym.h" // after gte.h
|
||||
*
|
||||
* Mapping (vendor -> duffle):
|
||||
* Transfers (move GPR <-> GTE control/data register):
|
||||
* gte_mfc2 -> gte_mv_from_data_r (move from coprocessor 2 data reg)
|
||||
* gte_mtc2 -> gte_mv_to_data_r (move to coprocessor 2 data reg)
|
||||
* gte_cfc2 -> gte_mv_from_ctrl_r (move from coprocessor 2 control reg)
|
||||
* gte_ctc2 -> gte_mv_to_ctrl_r (move to coprocessor 2 control reg)
|
||||
*
|
||||
* Data load/store (load/store word to coprocessor 2 data register):
|
||||
* gte_lwc2(rt, base, off) -> gte_lw(rt, base, off)
|
||||
* gte_swc2(rt, base, off) -> gte_sw(rt, base, off)
|
||||
* (the lower-level vector variants gte_lw_v0_xy etc. don't have
|
||||
* vendor mnemonics; they're already gte_-prefixed and short)
|
||||
*
|
||||
* The vendor mnemonics are NOT registered with the duffle word-count
|
||||
* metadata (tape_atom.metadata.h). They expand to the duffle canonical
|
||||
* macros which DO have word-count entries. Verification: V3 (objdump
|
||||
* byte-identical) holds.
|
||||
*
|
||||
* ============================================================================ */
|
||||
|
||||
#ifdef INTELLISENSE_DIRECTIVES
|
||||
# pragma once
|
||||
# include "gte.h"
|
||||
#endif
|
||||
|
||||
#ifndef DUFFLE_GTE_VENDOR_SYM_H
|
||||
#define DUFFLE_GTE_VENDOR_SYM_H
|
||||
|
||||
/* Transfers (move GPR <-> GTE control/data register) */
|
||||
#define gte_mfc2(rt, rd) gte_mv_from_data_r((rt), (rd))
|
||||
#define gte_mtc2(rt, rd) gte_mv_to_data_r((rt), (rd))
|
||||
#define gte_cfc2(rt, rd) gte_mv_from_ctrl_r((rt), (rd))
|
||||
#define gte_ctc2(rt, rd) gte_mv_to_ctrl_r((rt), (rd))
|
||||
|
||||
/* Data load/store (load/store word to coprocessor 2 data register) */
|
||||
#define gte_lwc2(rt, base, off) gte_lw((rt), (base), (off))
|
||||
#define gte_swc2(rt, base, off) gte_sw((rt), (base), (off))
|
||||
|
||||
#endif
|
||||
@@ -102,9 +102,9 @@ FI_ Slice_U4 tb_slice(TapeBuilder tb) { return (Sli
|
||||
|
||||
/* Words: 18; Translates indices to vertex addresses and pushes them to GTE */
|
||||
#define mac_load_tri_verts(rId_0, rId_1, rId_2) \
|
||||
shift_lleft(R_AT, rId_0, v3s2_byteoff), add_u_self(R_AT, R_VertBase), load_word(R_V0, R_AT, O_(V3_S2,x)), load_word(R_V1, R_AT, O_(V3_S2,z)), gte_mt(R_V0, C2_VXY0), gte_mt(R_V1, C2_VZ0) \
|
||||
, shift_lleft(R_AT, rId_1, v3s2_byteoff), add_u_self(R_AT, R_VertBase), load_word(R_V0, R_AT, O_(V3_S2,x)), load_word(R_V1, R_AT, O_(V3_S2,z)), gte_mt(R_V0, C2_VXY1), gte_mt(R_V1, C2_VZ1) \
|
||||
, shift_lleft(R_AT, rId_2, v3s2_byteoff), add_u_self(R_AT, R_VertBase), load_word(R_V0, R_AT, O_(V3_S2,x)), load_word(R_V1, R_AT, O_(V3_S2,z)), gte_mt(R_V0, C2_VXY2), gte_mt(R_V1, C2_VZ2)
|
||||
shift_lleft(R_AT, rId_0, v3s2_byteoff), add_u_self(R_AT, R_VertBase), 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, rId_1, v3s2_byteoff), add_u_self(R_AT, R_VertBase), 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, rId_2, v3s2_byteoff), add_u_self(R_AT, R_VertBase), 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)
|
||||
|
||||
/* Words: 11; Correctly inserts a primitive into the Ordering Table linked list */
|
||||
#define mac_insert_ot_tag(r_otz, prim_length) \
|
||||
@@ -194,11 +194,11 @@ internal MipsAtom_(set_gte_world) {
|
||||
// TODO(Ed): Annotate magic offsets.
|
||||
/* Load 3x3 Rotation + 3x1 Translation from R_T3 into GTE CONTROL Regs (ctc2) */
|
||||
load_word(R_T0, R_T3, 0), load_word(R_T1, R_T3, 4),
|
||||
gte_ct( R_T0, gte_cr_RT11), gte_ct( R_T1, gte_cr_RT12),
|
||||
gte_mv_to_ctrl_r( R_T0, gte_cr_RT11), gte_mv_to_ctrl_r( R_T1, gte_cr_RT12),
|
||||
load_word(R_T0, R_T3, 8), load_word(R_T1, R_T3, 12), load_word(R_T2, R_T3, 16),
|
||||
gte_ct( R_T0, gte_cr_RT13), gte_ct( R_T1, gte_cr_RT21), gte_ct( R_T2, gte_cr_RT22),
|
||||
gte_mv_to_ctrl_r( R_T0, gte_cr_RT13), gte_mv_to_ctrl_r( R_T1, gte_cr_RT21), gte_mv_to_ctrl_r( R_T2, gte_cr_RT22),
|
||||
load_word(R_T0, R_T3, 20), load_word(R_T1, R_T3, 24), load_word(R_T2, R_T3, 28),
|
||||
gte_ct( R_T0, gte_cr_TRX), gte_ct( R_T1, gte_cr_TRY), gte_ct( R_T2, gte_cr_TRZ),
|
||||
gte_mv_to_ctrl_r( R_T0, gte_cr_TRX), gte_mv_to_ctrl_r( R_T1, gte_cr_TRY), gte_mv_to_ctrl_r( R_T2, gte_cr_TRZ),
|
||||
|
||||
mac_yield()
|
||||
};
|
||||
@@ -249,15 +249,15 @@ internal MipsAtom_(diag_gte) {
|
||||
/* Load Vertices into GTE */
|
||||
shift_lleft( R_AT, R_T0, 3), add_u( R_AT, R_AT, R_T5),
|
||||
load_word(R_V0, R_AT, 0), load_word(R_V1, R_AT, 4),
|
||||
gte_mt( R_V0, C2_VXY0), gte_mt( R_V1, C2_VZ0),
|
||||
gte_mv_to_data_r( R_V0, C2_VXY0), gte_mv_to_data_r( R_V1, C2_VZ0),
|
||||
|
||||
shift_lleft( R_AT, R_T1, 3), add_u( R_AT, R_AT, R_T5),
|
||||
load_word(R_V0, R_AT, 0), load_word(R_V1, R_AT, 4),
|
||||
gte_mt( R_V0, C2_VXY1), gte_mt( R_V1, C2_VZ1),
|
||||
gte_mv_to_data_r( R_V0, C2_VXY1), gte_mv_to_data_r( R_V1, C2_VZ1),
|
||||
|
||||
shift_lleft( R_AT, R_T2, 3), add_u( R_AT, R_AT, R_T5),
|
||||
load_word(R_V0, R_AT, 0), load_word(R_V1, R_AT, 4),
|
||||
gte_mt( R_V0, C2_VXY2), gte_mt( R_V1, C2_VZ2),
|
||||
gte_mv_to_data_r( R_V0, C2_VXY2), gte_mv_to_data_r( R_V1, C2_VZ2),
|
||||
|
||||
/* Run Math */
|
||||
nop, nop, gte_cmdw_rtpt,
|
||||
|
||||
Reference in New Issue
Block a user