Nugget
Loading...
Searching...
No Matches
gte-encoding.c
Go to the documentation of this file.
1// GTE instruction encoding tests: systematic sweep of bitfield parameters.
2//
3// Helper macros for unrolled MVMVA sweeps. Defined at file scope so they
4// survive cester's double-include of __BASE_FILE__.
5
6#define MVMVA_T(mx, v, cv) do { \
7 if ((v) == 3) { cop2_put(9, 0x100); cop2_put(10, 0x200); cop2_put(11, 0x300); } \
8 gte_clear_flag(); \
9 cop2_cmd(COP2_MVMVA(1, mx, v, cv, 0)); \
10} while (0)
11
12#define MVMVA_MX3_V(v) do { \
13 if ((v) == 3) { cop2_put(9, 0x400); cop2_put(10, 0x500); cop2_put(11, 0x600); } \
14 gte_clear_flag(); \
15 cop2_cmd(COP2_MVMVA(1, 3, v, 3, 0)); \
16 int32_t _m1, _m2, _m3; \
17 cop2_get(25, _m1); cop2_get(26, _m2); cop2_get(27, _m3); \
18 ramsyscall_printf("MVMVA mx=3 v=%d: MAC=(%d,%d,%d)\n", v, _m1, _m2, _m3); \
19} while (0)
20
21#define MVMVA_CV2_MX(mx) do { \
22 cop2_put(9, 0x100); cop2_put(10, 0x200); cop2_put(11, 0x300); \
23 gte_clear_flag(); \
24 cop2_cmd(COP2_MVMVA(1, mx, 0, 2, 0)); \
25 int32_t _m1, _m2, _m3; uint32_t _fl; \
26 cop2_get(25, _m1); cop2_get(26, _m2); cop2_get(27, _m3); _fl = gte_read_flag(); \
27 ramsyscall_printf("MVMVA mx=%d cv=2: MAC=(%d,%d,%d) FLAG=0x%08x\n", mx, _m1, _m2, _m3, _fl); \
28} while (0)
29//
30// The GTE command word is a 25-bit immediate with fields:
31// [fake:5][sf:1][mx:2][v:2][cv:2][pad:2][lm:1][pad:4][fn:6]
32//
33// These tests verify:
34// 1. The "fake" field (bits 24-20) is ignored by hardware
35// 2. sf=0 vs sf=1 behavior for each function code
36// 3. lm=0 vs lm=1 behavior for each function code
37// 4. All MVMVA mx/v/cv combinations produce results
38// 5. Unused bitfield values don't crash
39
40// ==========================================================================
41// Fake field is ignored by hardware
42// ==========================================================================
43
44// Run RTPS with fake=0 (non-standard) and verify same result as fake=1
45CESTER_TEST(enc_fake_field_ignored_rtps, gte_tests,
47 gte_set_translation(0, 0, 1000);
48 gte_set_screen(160 << 16, 120 << 16, 200);
49 cop2_put(0, 0);
50 cop2_put(1, 0);
51
52 // Standard encoding: fake=1, sf=1
54 cop2_cmd(COP2_RTPS(1, 0));
55 uint32_t sxy2_std;
56 cop2_get(14, sxy2_std);
57
58 // Non-standard: fake=0, same sf/fn
59 cop2_put(0, 0);
60 cop2_put(1, 0);
62 cop2_cmd(COP2_OP(0, 1, 0, 0, 0, 0, COP2_FN_RTPS));
63 uint32_t sxy2_alt;
64 cop2_get(14, sxy2_alt);
65
66 cester_assert_uint_eq(sxy2_std, sxy2_alt);
67)
68
69// Run GPF with fake=31 (max) vs standard fake=25
70CESTER_TEST(enc_fake_field_ignored_gpf, gte_tests,
71 cop2_put(8, 0x1000);
72 cop2_put(9, 100);
73 cop2_put(10, 200);
74 cop2_put(11, 300);
75 cop2_put(6, 0x00808080);
76
78 cop2_cmd(COP2_GPF(1, 0));
79 int32_t mac1_std;
80 cop2_get(25, mac1_std);
81
82 cop2_put(8, 0x1000);
83 cop2_put(9, 100);
84 cop2_put(10, 200);
85 cop2_put(11, 300);
86 cop2_put(6, 0x00808080);
88 cop2_cmd(COP2_OP(31, 1, 0, 0, 0, 0, COP2_FN_GPF));
89 int32_t mac1_alt;
90 cop2_get(25, mac1_alt);
91
92 cester_assert_int_eq(mac1_std, mac1_alt);
93)
94
95// ==========================================================================
96// sf=0 vs sf=1 for each instruction
97// ==========================================================================
98
99// GPF: sf changes shift behavior
100CESTER_TEST(enc_gpf_sf_difference, gte_tests,
101 cop2_put(8, 0x1000);
102 cop2_put(9, 0x1000);
103 cop2_put(10, 0x1000);
104 cop2_put(11, 0x1000);
105 cop2_put(6, 0x00808080);
106
107 // sf=1: MAC = (IR0*IR) >> 12 = (0x1000*0x1000)>>12 = 0x1000
109 cop2_cmd(COP2_GPF(1, 0));
110 int32_t mac1_sf1;
111 cop2_get(25, mac1_sf1);
112
113 cop2_put(8, 0x1000);
114 cop2_put(9, 0x1000);
115 cop2_put(10, 0x1000);
116 cop2_put(11, 0x1000);
117 cop2_put(6, 0x00808080);
118
119 // sf=0: MAC = IR0*IR = 0x1000*0x1000 = 0x1000000
121 cop2_cmd(COP2_GPF(0, 0));
122 int32_t mac1_sf0;
123 cop2_get(25, mac1_sf0);
124
125 cester_assert_int_eq(0x1000, mac1_sf1);
126 cester_assert_int_eq(0x1000000, mac1_sf0);
127)
128
129// SQR: sf changes shift
130CESTER_TEST(enc_sqr_sf_difference, gte_tests,
131 cop2_put(9, 0x100);
132 cop2_put(10, 0x100);
133 cop2_put(11, 0x100);
134
136 cop2_cmd(COP2_SQR(1, 0));
137 int32_t mac1_sf1;
138 cop2_get(25, mac1_sf1);
139
140 cop2_put(9, 0x100);
141 cop2_put(10, 0x100);
142 cop2_put(11, 0x100);
144 cop2_cmd(COP2_SQR(0, 0));
145 int32_t mac1_sf0;
146 cop2_get(25, mac1_sf0);
147
148 // sf=1: (0x100*0x100)>>12 = 0x10000>>12 = 0x10
149 // sf=0: 0x100*0x100 = 0x10000
150 cester_assert_int_eq(0x10, mac1_sf1);
151 cester_assert_int_eq(0x10000, mac1_sf0);
152)
153
154// OP: sf changes shift
155CESTER_TEST(enc_op_sf_difference, gte_tests,
156 cop2_putc(0, 0x00001000);
157 cop2_putc(2, 0x00002000);
158 cop2_putc(4, 0x1000);
159 cop2_put(9, 100);
160 cop2_put(10, 0);
161 cop2_put(11, 0);
162
164 cop2_cmd(COP2_OP_CP(1, 0));
165 int32_t mac2_sf1;
166 cop2_get(26, mac2_sf1);
167
168 cop2_put(9, 100);
169 cop2_put(10, 0);
170 cop2_put(11, 0);
172 cop2_cmd(COP2_OP_CP(0, 0));
173 int32_t mac2_sf0;
174 cop2_get(26, mac2_sf0);
175
176 // sf=1: MAC2 = (R33*IR1 - R11*IR3)>>12 = (0x1000*100 - 0x1000*0)>>12 = 100
177 // sf=0: MAC2 = R33*IR1 - R11*IR3 = 0x1000*100 = 409600
178 cester_assert_int_eq(100, mac2_sf1);
179 cester_assert_int_eq(409600, mac2_sf0);
180)
181
182// ==========================================================================
183// lm=0 vs lm=1 for each instruction
184// ==========================================================================
185
186// SQR: lm=1 clamps IR to [0, 0x7fff]
187CESTER_TEST(enc_sqr_lm_difference, gte_tests,
188 cop2_put(9, 0x2000); // 2.0
189 cop2_put(10, 0x2000);
190 cop2_put(11, 0x2000);
191
192 // sf=1, lm=0: 2.0^2 = 4.0 = 0x4000 (in range for signed)
194 cop2_cmd(COP2_SQR(1, 0));
195 uint32_t ir1_lm0;
196 cop2_get(9, ir1_lm0);
197
198 cop2_put(9, 0x2000);
199 cop2_put(10, 0x2000);
200 cop2_put(11, 0x2000);
201
202 // sf=1, lm=1: same result since 0x4000 > 0 (lm=1 only clamps negative to 0)
204 cop2_cmd(COP2_SQR(1, 1));
205 uint32_t ir1_lm1;
206 cop2_get(9, ir1_lm1);
207
208 // Both should be 0x4000 since result is positive
209 cester_assert_uint_eq(0x4000, ir1_lm0);
210 cester_assert_uint_eq(0x4000, ir1_lm1);
211)
212
213// ==========================================================================
214// MVMVA: all mx/v/cv combinations (4 x 4 x 4 = 64 combos)
215// ==========================================================================
216
217// Sweep all 64 MVMVA parameter combinations and verify no crash.
218// Log MAC results for ground truth capture.
219CESTER_TEST(enc_mvmva_full_sweep, gte_tests,
220 // Set up all matrices and vectors with known non-zero values
221 // RT matrix
222 cop2_putc(0, 0x08001000);
223 cop2_putc(1, 0x02000400);
224 cop2_putc(2, 0x08001000);
225 cop2_putc(3, 0x02000400);
226 cop2_putc(4, 0x1000);
227 // LL matrix
228 cop2_putc(8, 0x04000800);
229 cop2_putc(9, 0x01000200);
230 cop2_putc(10, 0x04000800);
231 cop2_putc(11, 0x01000200);
232 cop2_putc(12, 0x0800);
233 // LC matrix
234 cop2_putc(16, 0x02000400);
235 cop2_putc(17, 0x00800100);
236 cop2_putc(18, 0x02000400);
237 cop2_putc(19, 0x00800100);
238 cop2_putc(20, 0x0400);
239 // Vectors
240 cop2_put(0, (0x200 << 16) | 0x100); // V0
241 cop2_put(1, 0x300);
242 cop2_put(2, (0x500 << 16) | 0x400); // V1
243 cop2_put(3, 0x600);
244 cop2_put(4, (0x800 << 16) | 0x700); // V2
245 cop2_put(5, 0x900);
246 cop2_put(9, 0x100); // IR1
247 cop2_put(10, 0x200); // IR2
248 cop2_put(11, 0x300); // IR3
249 cop2_put(8, 0x0800); // IR0
250 // Control vectors
251 gte_set_translation(100, 200, 300);
252 cop2_putc(13, 400);
253 cop2_putc(14, 500);
254 cop2_putc(15, 600);
255 gte_set_far_color(700, 800, 900);
256
257 // All 64 MVMVA combos unrolled (cop2_cmd requires compile-time constants).
258 MVMVA_T(0,0,0); MVMVA_T(0,0,1); MVMVA_T(0,0,2); MVMVA_T(0,0,3);
259 MVMVA_T(0,1,0); MVMVA_T(0,1,1); MVMVA_T(0,1,2); MVMVA_T(0,1,3);
260 MVMVA_T(0,2,0); MVMVA_T(0,2,1); MVMVA_T(0,2,2); MVMVA_T(0,2,3);
261 MVMVA_T(0,3,0); MVMVA_T(0,3,1); MVMVA_T(0,3,2); MVMVA_T(0,3,3);
262 MVMVA_T(1,0,0); MVMVA_T(1,0,1); MVMVA_T(1,0,2); MVMVA_T(1,0,3);
263 MVMVA_T(1,1,0); MVMVA_T(1,1,1); MVMVA_T(1,1,2); MVMVA_T(1,1,3);
264 MVMVA_T(1,2,0); MVMVA_T(1,2,1); MVMVA_T(1,2,2); MVMVA_T(1,2,3);
265 MVMVA_T(1,3,0); MVMVA_T(1,3,1); MVMVA_T(1,3,2); MVMVA_T(1,3,3);
266 MVMVA_T(2,0,0); MVMVA_T(2,0,1); MVMVA_T(2,0,2); MVMVA_T(2,0,3);
267 MVMVA_T(2,1,0); MVMVA_T(2,1,1); MVMVA_T(2,1,2); MVMVA_T(2,1,3);
268 MVMVA_T(2,2,0); MVMVA_T(2,2,1); MVMVA_T(2,2,2); MVMVA_T(2,2,3);
269 MVMVA_T(2,3,0); MVMVA_T(2,3,1); MVMVA_T(2,3,2); MVMVA_T(2,3,3);
270 MVMVA_T(3,0,0); MVMVA_T(3,0,1); MVMVA_T(3,0,2); MVMVA_T(3,0,3);
271 MVMVA_T(3,1,0); MVMVA_T(3,1,1); MVMVA_T(3,1,2); MVMVA_T(3,1,3);
272 MVMVA_T(3,2,0); MVMVA_T(3,2,1); MVMVA_T(3,2,2); MVMVA_T(3,2,3);
273 MVMVA_T(3,3,0); MVMVA_T(3,3,1); MVMVA_T(3,3,2); MVMVA_T(3,3,3);
274 cester_assert_int_eq(1, 1); // if we got here, none crashed
275)
276
277// ==========================================================================
278// MVMVA mx=3 (garbage matrix) with all vector/cv combinations
279// ==========================================================================
280
281CESTER_TEST(enc_mvmva_mx3_all_vectors, gte_tests,
282 cop2_putc(0, 0x20001000);
283 cop2_putc(1, 0x40003000);
284 cop2_putc(2, 0x60005000);
285 cop2_putc(3, 0x80007000);
286 cop2_putc(4, 0x1000);
287 cop2_put(8, 0x0800);
288 cop2_put(0, (0x100 << 16) | 0x100);
289 cop2_put(1, 0x100);
290 cop2_put(2, (0x200 << 16) | 0x200);
291 cop2_put(3, 0x200);
292 cop2_put(4, (0x300 << 16) | 0x300);
293 cop2_put(5, 0x300);
294 cop2_put(9, 0x400);
295 cop2_put(10, 0x500);
296 cop2_put(11, 0x600);
297
300)
301
302// ==========================================================================
303// MVMVA cv=2 (FC bug) with all matrix/vector combinations
304// ==========================================================================
305
306CESTER_TEST(enc_mvmva_cv2_all_matrices, gte_tests,
310 gte_set_far_color(0x1000, 0x2000, 0x3000);
311 cop2_put(0, (0x200 << 16) | 0x100);
312 cop2_put(1, 0x300);
313 cop2_put(9, 0x100);
314 cop2_put(10, 0x200);
315 cop2_put(11, 0x300);
316
319)
320
321// ==========================================================================
322// Instructions that ignore sf/lm should produce identical results
323// ==========================================================================
324
325// NCLIP ignores sf and lm
326CESTER_TEST(enc_nclip_ignores_sf_lm, gte_tests,
327 cop2_put(12, 0x00000000);
328 cop2_put(13, 0x00000064);
329 cop2_put(14, 0x00640000);
330
332 cop2_cmd(COP2_OP(20, 0, 0, 0, 0, 0, COP2_FN_NCLIP)); // standard
333 int32_t mac0_std;
334 cop2_get(24, mac0_std);
335
336 cop2_put(12, 0x00000000);
337 cop2_put(13, 0x00000064);
338 cop2_put(14, 0x00640000);
340 cop2_cmd(COP2_OP(0, 1, 3, 3, 3, 1, COP2_FN_NCLIP)); // all bits set
341 int32_t mac0_alt;
342 cop2_get(24, mac0_alt);
343
344 cester_assert_int_eq(mac0_std, mac0_alt);
345)
346
347// AVSZ3 ignores sf and lm (uses fixed >>12)
348CESTER_TEST(enc_avsz3_ignores_sf_lm, gte_tests,
349 cop2_put(17, 100);
350 cop2_put(18, 200);
351 cop2_put(19, 300);
352 cop2_putc(29, 0x555);
353
356 int32_t mac0_std;
357 cop2_get(24, mac0_std);
358
359 cop2_put(17, 100);
360 cop2_put(18, 200);
361 cop2_put(19, 300);
362 cop2_putc(29, 0x555);
364 cop2_cmd(COP2_OP(0, 0, 3, 3, 3, 1, COP2_FN_AVSZ3));
365 int32_t mac0_alt;
366 cop2_get(24, mac0_alt);
367
368 cester_assert_int_eq(mac0_std, mac0_alt);
369)
CESTER_TEST(cpu_cop0_basic_write_bp, cpu_tests, uint32_t expectedEPC;uint32_t t;volatile uint32_t *ptr=(volatile uint32_t *) 0x58; *ptr=1;__asm__ volatile("" " lui %0, 0b1100101010000000\n" " mtc0 %0, $7\n" " li %0, 0x58\n" " mtc0 %0, $5\n" " li %0, 0xfffffff0\n" " mtc0 %0, $9\n" :"=r"(t));cester_assert_uint_eq(1, *ptr);__asm__ volatile("la %0, 1f\n1:\nsw $0, 0x58($0)" :"=r"(expectedEPC));__asm__ volatile("mtc0 $0, $7\n");cester_assert_uint_eq(0, *ptr);cester_assert_uint_eq(1, s_got40);cester_assert_uint_eq(0, s_got80);cester_assert_uint_eq(0x40, s_from);cester_assert_uint_eq(expectedEPC, s_epc);) CESTER_TEST(cpu_cop0_kseg_write_bp
cester_assert_uint_eq(1, *ptr)
#define COP2_FN_GPF
Definition cop2.h:105
#define COP2_OP_CP(sf, lm)
Definition cop2.h:136
#define cop2_cmd(op)
Definition cop2.h:175
#define cop2_put(reg, val)
Definition cop2.h:182
#define COP2_SQR(sf, lm)
Definition cop2.h:161
#define COP2_GPF(sf, lm)
Definition cop2.h:168
#define cop2_putc(reg, val)
Definition cop2.h:196
#define COP2_RTPS(sf, lm)
Definition cop2.h:129
#define COP2_AVSZ3
Definition cop2.h:164
#define COP2_FN_RTPS
Definition cop2.h:86
#define cop2_get(reg, dest)
Definition cop2.h:189
#define COP2_FN_NCLIP
Definition cop2.h:87
#define COP2_OP(fake, sf, mx, v, cv, lm, fn)
Definition cop2.h:116
#define COP2_FN_AVSZ3
Definition cop2.h:102
cester_assert_int_eq(0, hi)
gte_set_far_color(0xff00, 0xff00, 0xff00)
gte_tests
Definition gte-depthcue.c:29
gte_clear_flag()
gte_set_identity_rotation()
gte_set_translation(0, 0, 0)
gte_set_screen(0, 0, 0)
#define MVMVA_T(mx, v, cv)
Definition gte-encoding.c:6
#define MVMVA_CV2_MX(mx)
Definition gte-encoding.c:21
#define MVMVA_MX3_V(v)
Definition gte-encoding.c:12
gte_set_white_light_color()
gte_set_simple_light()
void uint32_t(classId, spec)