improving dsl: gte.

This commit is contained in:
2026-07-08 00:37:27 -04:00
parent d0b1bae896
commit 10c8dcdc07
5 changed files with 183 additions and 45 deletions
+112 -25
View File
@@ -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;" \
+50
View File
@@ -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
+9 -9
View File
@@ -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,
+8 -8
View File
@@ -75,17 +75,17 @@ MipsAtom_(cube_tri) {
/* V0 = verts[face->x] */
shift_lleft(R_AT, R_T0, 3), add_u(R_AT, R_AT, R_VertBase),
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),
/* V1 = verts[face->y] */
shift_lleft(R_AT, R_T1, 3), add_u(R_AT, R_AT, R_VertBase),
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),
/* V2 = verts[face->z] */
shift_lleft(R_AT, R_T2, 3), add_u(R_AT, R_AT, R_VertBase),
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),
/* ── 3. RTPT — transforms V0/V1/V2 → SXY0/SXY1/SXY2 + SZ1/SZ2/SZ3 ─── */
nop, nop, gte_cmdw_rtpt,
@@ -96,7 +96,7 @@ MipsAtom_(cube_tri) {
nop, nop,
/* ── 5. Cull check: skip format/insert if MAC0 ≤ 0 (backface) ───────── */
gte_mf(R_T0, C2_MAC0),
gte_mv_from_data_r(R_T0, C2_MAC0),
nop,
branch_le_zero(R_T0, 49), /* Skip 49 if MAC0 ≤ 0 (backface) → cull */
nop, /* BD slot */
@@ -132,7 +132,7 @@ MipsAtom_(cube_tri) {
/* ── 7. Load V3 = verts[face->w] into V0 ─────────────────────────────── */
shift_lleft(R_AT, R_T3, 3), add_u(R_AT, R_AT, R_VertBase),
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),
/* ── 8. RTPS — transforms V0 (now V3) → SXY0 (p3) + SZ0 ─────────────── */
nop, nop, gte_cmdw_rtps,
@@ -143,7 +143,7 @@ MipsAtom_(cube_tri) {
/* ── 9. AVSZ4 — average Z from SZ0/SZ1/SZ2/SZ3 ────────────── */
nop, nop, gte_cmdw_avsz4,
nop, nop,
gte_mf(R_T1, C2_OTZ),
gte_mv_from_data_r(R_T1, C2_OTZ),
/* ── 10. Bounds check OTZ < 2048 ─────────────────────────────────────── */
add_ui( R_AT, R_0, 2048),
@@ -197,7 +197,7 @@ MipsAtom_(floor_tri) {
nop, nop, gte_cmdw_nclip,
nop, nop,
/* Culling (Branch forward if Backface) */
gte_mf(R_T0, C2_MAC0),
gte_mv_from_data_r(R_T0, C2_MAC0),
nop, branch_le_zero(R_T0, atom_offset(culling, floor_tri_exit)),
nop,
/* Format Primitive */
@@ -206,7 +206,7 @@ MipsAtom_(floor_tri) {
mac_gte_store_f3(),
/* Calculate Depth */
nop, nop, gte_avg_sort_z3,
nop, nop, gte_mf(R_T1, C2_OTZ),
nop, nop, gte_mv_from_data_r(R_T1, C2_OTZ),
/* Bounds Check OTZ < 2048 (Branch forward to skip insertion) */
add_ui( R_AT, R_0, OrderingTbl_Len),
set_lt_u( R_AT, R_T1, R_AT),
+4 -3
View File
@@ -35,9 +35,10 @@ WORD_COUNT(shift_lleft, 1)
WORD_COUNT(shift_lright, 1)
WORD_COUNT(shift_aright, 1)
WORD_COUNT(mask_upper, 2)
WORD_COUNT(gte_mf, 1)
WORD_COUNT(gte_mt, 1)
WORD_COUNT(gte_ct, 1)
WORD_COUNT(gte_mv_from_data_r, 1)
WORD_COUNT(gte_mv_from_ctrl_r, 1)
WORD_COUNT(gte_mv_to_data_r, 1)
WORD_COUNT(gte_mv_to_ctrl_r, 1)
WORD_COUNT(gte_sw, 1)
WORD_COUNT(gte_cmdw_rtpt, 1)
WORD_COUNT(gte_cmdw_nclip, 1)