Nugget
Loading...
Searching...
No Matches
gte-mvmva.c
Go to the documentation of this file.
1// MVMVA: parameterized matrix-vector multiply and add
2
3// mx=RT, v=V0, cv=TR (standard transform)
4CESTER_TEST(mvmva_rt_v0_tr, gte_tests,
5 // 90-degree Z rotation
6 cop2_putc(0, 0xf0000000); // R11=0, R12=-0x1000
7 cop2_putc(1, 0x10000000); // R13=0, R21=0x1000
8 cop2_putc(2, 0x00000000);
9 cop2_putc(3, 0x00000000);
10 cop2_putc(4, 0x1000);
11 gte_set_translation(10, 20, 30);
12 cop2_put(0, (200 << 16) | 100);
13 cop2_put(1, 300);
15 cop2_cmd(COP2_MVMVA(1, 0, 0, 0, 0));
16 int32_t mac1, mac2, mac3;
17 cop2_get(25, mac1);
18 cop2_get(26, mac2);
19 cop2_get(27, mac3);
23)
24
25// mx=RT, v=V1, cv=Zero
26CESTER_TEST(mvmva_rt_v1_zero, gte_tests,
28 cop2_put(2, (40 << 16) | 30); // V1 = (30, 40)
29 cop2_put(3, 50); // V1.Z = 50
31 cop2_cmd(COP2_MVMVA(1, 0, 1, 3, 0));
32 int32_t mac1, mac2, mac3;
39)
40
41// mx=RT, v=V2, cv=BK
42CESTER_TEST(mvmva_rt_v2_bk, gte_tests,
44 cop2_putc(13, 1000); // RBK
45 cop2_putc(14, 2000); // GBK
46 cop2_putc(15, 3000); // BBK
47 cop2_put(4, (200 << 16) | 100); // V2
48 cop2_put(5, 300);
50 cop2_cmd(COP2_MVMVA(1, 0, 2, 1, 0));
51 int32_t mac1, mac2, mac3;
52 cop2_get(25, mac1);
53 cop2_get(26, mac2);
54 cop2_get(27, mac3);
58)
59
60// mx=RT, v=IR, cv=Zero
61CESTER_TEST(mvmva_rt_ir_zero, gte_tests,
63 cop2_put(9, 500);
64 cop2_put(10, 600);
65 cop2_put(11, 700);
67 cop2_cmd(COP2_MVMVA(1, 0, 3, 3, 0));
68 int32_t mac1, mac2, mac3;
69 cop2_get(25, mac1);
70 cop2_get(26, mac2);
71 cop2_get(27, mac3);
75)
76
77// mx=LL (light matrix), v=V0, cv=Zero
78CESTER_TEST(mvmva_ll_v0_zero, gte_tests,
79 gte_set_simple_light(); // L33=0x1000, rest zero
80 cop2_put(0, (200 << 16) | 100);
81 cop2_put(1, 0x1000);
83 cop2_cmd(COP2_MVMVA(1, 1, 0, 3, 0));
84 int32_t mac1, mac2, mac3;
85 cop2_get(25, mac1);
86 cop2_get(26, mac2);
87 cop2_get(27, mac3);
88 // Only L33 is non-zero, so MAC3 = L33*VZ0 >> 12 = 0x1000 * 0x1000 >> 12 = 0x1000
92)
93
94// mx=LC (light color), v=IR, cv=BK
95CESTER_TEST(mvmva_lc_ir_bk, gte_tests,
97 cop2_putc(13, 100); // RBK
98 cop2_putc(14, 200); // GBK
99 cop2_putc(15, 300); // BBK
100 cop2_put(9, 0x1000);
101 cop2_put(10, 0x1000);
102 cop2_put(11, 0x1000);
104 cop2_cmd(COP2_MVMVA(1, 2, 3, 1, 0));
105 int32_t mac1, mac2, mac3;
106 cop2_get(25, mac1);
107 cop2_get(26, mac2);
108 cop2_get(27, mac3);
109 // White LC identity: MAC = (BK<<12 + LR1*IR1) >> 12 = BK + IR
110 // BK = (100, 200, 300), IR = (0x1000, 0x1000, 0x1000) = (4096, 4096, 4096)
111 // MAC1 = 100 + 4096 = 4196, etc.
115)
116
117// cv=2 (far color) bug
118CESTER_TEST(mvmva_cv2_fc_bug, gte_tests,
120 gte_set_far_color(0x1000, 0x2000, 0x3000);
121 cop2_put(0, (0x200 << 16) | 0x100);
122 cop2_put(1, 0x300);
124 cop2_cmd(COP2_MVMVA(1, 0, 0, 2, 0));
125 int32_t mac1, mac2, mac3;
127 cop2_get(25, mac1);
128 cop2_get(26, mac2);
129 cop2_get(27, mac3);
130 flag = gte_read_flag();
131 // Buggy: result is partial - only last column (R13*VZ, R23*VZ, R33*VZ)
132 // With identity: R13=0, R23=0, R33=0x1000
133 // MAC1 = R13*VZ >> 12 = 0
134 // MAC2 = R23*VZ >> 12 = 0 (but VY contribution leaks? Let's check)
135 // MAC3 = R33*VZ >> 12 = 0x300
136 ramsyscall_printf("MVMVA cv=2: MAC=(%d,%d,%d) FLAG=0x%08x\n", mac1, mac2, mac3, flag);
140 cester_assert_uint_eq(0x00000000, flag);
141)
142
143// mx=3 (garbage matrix)
144CESTER_TEST(mvmva_mx3_garbage, gte_tests,
145 cop2_putc(0, 0x20001000); // R11=0x1000, R12=0x2000
146 cop2_putc(1, 0x40003000); // R13=0x3000, R21=0x4000
147 cop2_putc(2, 0x60005000); // R22=0x5000, R23=0x6000
148 cop2_putc(3, 0x80007000); // R31=0x7000, R32=-0x8000
149 cop2_putc(4, 0x1000);
150 cop2_put(8, 0x0800); // IR0
151 cop2_put(0, (0x100 << 16) | 0x100);
152 cop2_put(1, 0x100);
154 cop2_cmd(COP2_MVMVA(1, 3, 0, 3, 0));
155 int32_t mac1, mac2, mac3;
157 cop2_get(25, mac1);
158 cop2_get(26, mac2);
159 cop2_get(27, mac3);
160 flag = gte_read_flag();
161 ramsyscall_printf("MVMVA mx=3: MAC=(%d,%d,%d) FLAG=0x%08x\n", mac1, mac2, mac3, flag);
166)
167
168// MVMVA with lm=1
169CESTER_TEST(mvmva_lm1, gte_tests,
171 gte_set_translation(-500, -600, -700);
172 cop2_put(0, (100 << 16) | 100);
173 cop2_put(1, 100);
175 // sf=1, mx=RT, v=V0, cv=TR, lm=1
176 cop2_cmd(COP2_MVMVA(1, 0, 0, 0, 1));
177 int32_t mac1;
179 cop2_get(25, mac1);
180 cop2_get(9, ir1);
181 // MAC1 = 100 + (-500) = -400
183 // IR1 with lm=1: clamped to [0, 0x7fff], so -400 -> 0
185)
186
187// MVMVA sf=0 (no shift)
188CESTER_TEST(mvmva_sf0, gte_tests,
190 gte_set_translation(0, 0, 0);
191 cop2_put(0, (10 << 16) | 10);
192 cop2_put(1, 10);
194 cop2_cmd(COP2_MVMVA(0, 0, 0, 3, 0));
195 int32_t mac1, mac2, mac3;
196 cop2_get(25, mac1);
197 cop2_get(26, mac2);
198 cop2_get(27, mac3);
199 // sf=0: no >>12 shift. MAC = R * V = 0x1000 * 10 = 40960
203)
#define cop2_cmd(op)
Definition cop2.h:175
#define cop2_put(reg, val)
Definition cop2.h:182
#define cop2_putc(reg, val)
Definition cop2.h:196
#define COP2_MVMVA(sf, mx, v, cv, lm)
Definition cop2.h:145
#define cop2_get(reg, dest)
Definition cop2.h:189
gte_set_far_color(0xff00, 0xff00, 0xff00)
uint32_t ir1
Definition gte-edgecase.c:108
gte_set_translation(0, 0, 0)
gte_set_simple_light()
int32_t mac1
Definition gte-mvmva.c:32
gte_set_identity_rotation()
gte_set_white_light_color()
cester_assert_int_eq(30, mac1)
ramsyscall_printf("MVMVA mx=3: MAC=(%d,%d,%d) FLAG=0x%08x\n", mac1, mac2, mac3, flag)
gte_tests
Definition gte-mvmva.c:26
CESTER_TEST(mvmva_rt_v0_tr, gte_tests, cop2_putc(0, 0xf0000000);cop2_putc(1, 0x10000000);cop2_putc(2, 0x00000000);cop2_putc(3, 0x00000000);cop2_putc(4, 0x1000);gte_set_translation(10, 20, 30);cop2_put(0,(200<< 16)|100);cop2_put(1, 300);gte_clear_flag();cop2_cmd(COP2_MVMVA(1, 0, 0, 0, 0));int32_t mac1, mac2, mac3;cop2_get(25, mac1);cop2_get(26, mac2);cop2_get(27, mac3);cester_assert_int_eq(-190, mac1);cester_assert_int_eq(120, mac2);cester_assert_int_eq(330, mac3);) CESTER_TEST(mvmva_rt_v1_zero
uint32_t flag
Definition gte-mvmva.c:156
cester_assert_uint_eq(0x00000000, flag)
int32_t mac2
Definition gte-mvmva.c:32
gte_clear_flag()
int32_t mac3
Definition gte-mvmva.c:32
void uint32_t(classId, spec)