Nugget
Loading...
Searching...
No Matches
gte-latency-common.h
Go to the documentation of this file.
1/*
2
3MIT License
4
5Copyright (c) 2026 PCSX-Redux authors
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26
27// Shared probe macros and helpers for the GTE input-register latency tests.
28//
29// For each (instruction, input register), the smallest N such that an
30// MTC2 (data) or CTC2 (control) to that register N nops after the GTE op
31// does not affect the GTE's output is the practical "instruction slots
32// required between the GTE op and the next write to this register".
33//
34// Each test file (lighting / perspective / color / math / misc) is its
35// own ps-exe, includes this header, and emits one CESTER_TEST per
36// (instruction, register) probe.
37
38#pragma once
39
42
43// clang-format off
44
45// Maximum number of nops to sweep between cop2 op and perturbation.
46// All NCCT boundaries observed so far are <= 13; longer instructions
47// (NCDT at 44 cycles) push later but inputs are typically read in the
48// first half of execution. 32 has comfortable margin and keeps the
49// per-test code size manageable so multiple instructions fit in one
50// 2 MB ps-exe.
51#define MAX_N 32
52
53// A captured GTE output snapshot. We compare the perturbed output's full
54// state against the unperturbed baseline; any field changing means the
55// perturbation reached the GTE before the latch.
56//
57// All FIFO entries are captured because triple-vertex instructions
58// (RTPT/NCDT/etc.) push three results - perturbing V0 only changes the
59// V0 slot (oldest), so comparing only the newest slot misses it.
68
69// Enable COP2 by setting CU2 in CP0 SR.
70static inline void gte_enable(void) {
71 uint32_t sr;
72 __asm__ volatile("mfc0 %0, $12" : "=r"(sr));
73 sr |= 0x40000000;
74 __asm__ volatile("mtc0 %0, $12; nop; nop" : : "r"(sr));
75}
76
77// Disable / restore CP0.SR.IE (bit 0).
78static inline uint32_t irq_disable(void) {
79 uint32_t sr_orig, sr_new;
80 __asm__ volatile("mfc0 %0, $12" : "=r"(sr_orig));
81 sr_new = sr_orig & ~1u;
82 __asm__ volatile("mtc0 %0, $12; nop; nop" : : "r"(sr_new));
83 return sr_orig;
84}
85
86static inline void irq_restore(uint32_t sr) {
87 __asm__ volatile("mtc0 %0, $12; nop; nop" : : "r"(sr));
88}
89
90// Read the full GTE output state into r. Each cop2_get already pads
91// the COP2 read hazard; calling them in sequence is safe.
92static inline void read_full_state(probe_result_t* r) {
93 cop2_get(20, r->rgb0);
94 cop2_get(21, r->rgb1);
95 cop2_get(22, r->rgb2);
96 int32_t v;
97 cop2_get(24, v); r->mac0 = v;
98 cop2_get(25, v); r->mac1 = v;
99 cop2_get(26, v); r->mac2 = v;
100 cop2_get(27, v); r->mac3 = v;
101 cop2_get( 8, v); r->ir0 = v;
102 cop2_get( 9, v); r->ir1 = v;
103 cop2_get(10, v); r->ir2 = v;
104 cop2_get(11, v); r->ir3 = v;
105 cop2_get(12, r->sxy0);
106 cop2_get(13, r->sxy1);
107 cop2_get(14, r->sxy2);
108 cop2_get(16, r->sz0);
109 cop2_get(17, r->sz1);
110 cop2_get(18, r->sz2);
111 cop2_get(19, r->sz3);
112 cop2_getc(31, r->flag);
113}
114
115static inline int results_equal(const probe_result_t* a, const probe_result_t* b) {
116 return a->rgb0 == b->rgb0 && a->rgb1 == b->rgb1 && a->rgb2 == b->rgb2
117 && a->mac0 == b->mac0 && a->mac1 == b->mac1
118 && a->mac2 == b->mac2 && a->mac3 == b->mac3
119 && a->ir0 == b->ir0 && a->ir1 == b->ir1
120 && a->ir2 == b->ir2 && a->ir3 == b->ir3
121 && a->sxy0 == b->sxy0 && a->sxy1 == b->sxy1 && a->sxy2 == b->sxy2
122 && a->sz0 == b->sz0 && a->sz1 == b->sz1
123 && a->sz2 == b->sz2 && a->sz3 == b->sz3
124 && a->flag == b->flag;
125}
126
127// ==========================================================================
128// Probe macros (data-register variant: MTC2)
129// ==========================================================================
130//
131// PROBE_DATA_AT_OFFSET(N, op_imm, dst_reg, canary)
132// cop2 op_imm; <N nops>; mtc2 canary, $dst_reg; <60 nop drain>
133//
134// PROBE_DATA_BASELINE(op_imm, dst_reg, canary)
135// cop2 op_imm; <80 nop drain>; mtc2 canary, $dst_reg; <4 nops>
136// Canary lands long after the GTE op completes - shape baseline.
137//
138// PROBE_DATA_SANITY_PRE(op_imm, dst_reg, canary)
139// mtc2 canary, $dst_reg; nop;nop; cop2 op_imm; <80 nop drain>
140// Canary lands BEFORE the GTE op - confirms the canary value would
141// change the result if it landed in time during execution.
142//
143// op_imm must be a compile-time constant ("i" constraint).
144
145#define PROBE_DATA_AT_OFFSET(N, op_imm, dst_reg, canary) do { \
146 __asm__ volatile( \
147 "cop2 %0\n\t" \
148 ".rept " #N "\n\t" \
149 "nop\n\t" \
150 ".endr\n\t" \
151 "mtc2 %1, $" #dst_reg "\n\t" \
152 ".rept 60\n\t" \
153 "nop\n\t" \
154 ".endr\n\t" \
155 : \
156 : "i"(op_imm), "r"((uint32_t)(canary)) \
157 : "memory"); \
158} while (0)
159
160#define PROBE_DATA_BASELINE(op_imm, dst_reg, canary) do { \
161 __asm__ volatile( \
162 "cop2 %0\n\t" \
163 ".rept 80\n\t" \
164 "nop\n\t" \
165 ".endr\n\t" \
166 "mtc2 %1, $" #dst_reg "\n\t" \
167 ".rept 4\n\t" \
168 "nop\n\t" \
169 ".endr\n\t" \
170 : \
171 : "i"(op_imm), "r"((uint32_t)(canary)) \
172 : "memory"); \
173} while (0)
174
175#define PROBE_DATA_SANITY_PRE(op_imm, dst_reg, canary) do { \
176 __asm__ volatile( \
177 "mtc2 %1, $" #dst_reg "\n\t" \
178 "nop\n\tnop\n\t" \
179 "cop2 %0\n\t" \
180 ".rept 80\n\t" \
181 "nop\n\t" \
182 ".endr\n\t" \
183 : \
184 : "i"(op_imm), "r"((uint32_t)(canary)) \
185 : "memory"); \
186} while (0)
187
188// ==========================================================================
189// Probe macros (control-register variant: CTC2)
190// ==========================================================================
191
192#define PROBE_CTRL_AT_OFFSET(N, op_imm, dst_reg, canary) do { \
193 __asm__ volatile( \
194 "cop2 %0\n\t" \
195 ".rept " #N "\n\t" \
196 "nop\n\t" \
197 ".endr\n\t" \
198 "ctc2 %1, $" #dst_reg "\n\t" \
199 ".rept 60\n\t" \
200 "nop\n\t" \
201 ".endr\n\t" \
202 : \
203 : "i"(op_imm), "r"((uint32_t)(canary)) \
204 : "memory"); \
205} while (0)
206
207#define PROBE_CTRL_BASELINE(op_imm, dst_reg, canary) do { \
208 __asm__ volatile( \
209 "cop2 %0\n\t" \
210 ".rept 80\n\t" \
211 "nop\n\t" \
212 ".endr\n\t" \
213 "ctc2 %1, $" #dst_reg "\n\t" \
214 ".rept 4\n\t" \
215 "nop\n\t" \
216 ".endr\n\t" \
217 : \
218 : "i"(op_imm), "r"((uint32_t)(canary)) \
219 : "memory"); \
220} while (0)
221
222#define PROBE_CTRL_SANITY_PRE(op_imm, dst_reg, canary) do { \
223 __asm__ volatile( \
224 "ctc2 %1, $" #dst_reg "\n\t" \
225 "nop\n\tnop\n\t" \
226 "cop2 %0\n\t" \
227 ".rept 80\n\t" \
228 "nop\n\t" \
229 ".endr\n\t" \
230 : \
231 : "i"(op_imm), "r"((uint32_t)(canary)) \
232 : "memory"); \
233} while (0)
234
235// ==========================================================================
236// Sweep macros - emit MAX_N+1 probes for a single (op, target) pair.
237// ==========================================================================
238//
239// DO_SWEEP_DATA(setup_fn, op_imm, dst_reg, canary, results)
240// For N in 0..MAX_N: setup_fn(); PROBE_DATA_AT_OFFSET(N, ...); record result.
241// DO_SWEEP_CTRL: same but with CTC2.
242//
243// MAX_N must match the iterator below. Increasing MAX_N requires
244// extending the unrolled list.
245
246#define DO_SWEEP_DATA(setup_fn, op_imm, dst_reg, canary, results) \
247 do { \
248 setup_fn(); PROBE_DATA_AT_OFFSET( 0, op_imm, dst_reg, canary); read_full_state(&(results)[ 0]); \
249 setup_fn(); PROBE_DATA_AT_OFFSET( 1, op_imm, dst_reg, canary); read_full_state(&(results)[ 1]); \
250 setup_fn(); PROBE_DATA_AT_OFFSET( 2, op_imm, dst_reg, canary); read_full_state(&(results)[ 2]); \
251 setup_fn(); PROBE_DATA_AT_OFFSET( 3, op_imm, dst_reg, canary); read_full_state(&(results)[ 3]); \
252 setup_fn(); PROBE_DATA_AT_OFFSET( 4, op_imm, dst_reg, canary); read_full_state(&(results)[ 4]); \
253 setup_fn(); PROBE_DATA_AT_OFFSET( 5, op_imm, dst_reg, canary); read_full_state(&(results)[ 5]); \
254 setup_fn(); PROBE_DATA_AT_OFFSET( 6, op_imm, dst_reg, canary); read_full_state(&(results)[ 6]); \
255 setup_fn(); PROBE_DATA_AT_OFFSET( 7, op_imm, dst_reg, canary); read_full_state(&(results)[ 7]); \
256 setup_fn(); PROBE_DATA_AT_OFFSET( 8, op_imm, dst_reg, canary); read_full_state(&(results)[ 8]); \
257 setup_fn(); PROBE_DATA_AT_OFFSET( 9, op_imm, dst_reg, canary); read_full_state(&(results)[ 9]); \
258 setup_fn(); PROBE_DATA_AT_OFFSET(10, op_imm, dst_reg, canary); read_full_state(&(results)[10]); \
259 setup_fn(); PROBE_DATA_AT_OFFSET(11, op_imm, dst_reg, canary); read_full_state(&(results)[11]); \
260 setup_fn(); PROBE_DATA_AT_OFFSET(12, op_imm, dst_reg, canary); read_full_state(&(results)[12]); \
261 setup_fn(); PROBE_DATA_AT_OFFSET(13, op_imm, dst_reg, canary); read_full_state(&(results)[13]); \
262 setup_fn(); PROBE_DATA_AT_OFFSET(14, op_imm, dst_reg, canary); read_full_state(&(results)[14]); \
263 setup_fn(); PROBE_DATA_AT_OFFSET(15, op_imm, dst_reg, canary); read_full_state(&(results)[15]); \
264 setup_fn(); PROBE_DATA_AT_OFFSET(16, op_imm, dst_reg, canary); read_full_state(&(results)[16]); \
265 setup_fn(); PROBE_DATA_AT_OFFSET(17, op_imm, dst_reg, canary); read_full_state(&(results)[17]); \
266 setup_fn(); PROBE_DATA_AT_OFFSET(18, op_imm, dst_reg, canary); read_full_state(&(results)[18]); \
267 setup_fn(); PROBE_DATA_AT_OFFSET(19, op_imm, dst_reg, canary); read_full_state(&(results)[19]); \
268 setup_fn(); PROBE_DATA_AT_OFFSET(20, op_imm, dst_reg, canary); read_full_state(&(results)[20]); \
269 setup_fn(); PROBE_DATA_AT_OFFSET(21, op_imm, dst_reg, canary); read_full_state(&(results)[21]); \
270 setup_fn(); PROBE_DATA_AT_OFFSET(22, op_imm, dst_reg, canary); read_full_state(&(results)[22]); \
271 setup_fn(); PROBE_DATA_AT_OFFSET(23, op_imm, dst_reg, canary); read_full_state(&(results)[23]); \
272 setup_fn(); PROBE_DATA_AT_OFFSET(24, op_imm, dst_reg, canary); read_full_state(&(results)[24]); \
273 setup_fn(); PROBE_DATA_AT_OFFSET(25, op_imm, dst_reg, canary); read_full_state(&(results)[25]); \
274 setup_fn(); PROBE_DATA_AT_OFFSET(26, op_imm, dst_reg, canary); read_full_state(&(results)[26]); \
275 setup_fn(); PROBE_DATA_AT_OFFSET(27, op_imm, dst_reg, canary); read_full_state(&(results)[27]); \
276 setup_fn(); PROBE_DATA_AT_OFFSET(28, op_imm, dst_reg, canary); read_full_state(&(results)[28]); \
277 setup_fn(); PROBE_DATA_AT_OFFSET(29, op_imm, dst_reg, canary); read_full_state(&(results)[29]); \
278 setup_fn(); PROBE_DATA_AT_OFFSET(30, op_imm, dst_reg, canary); read_full_state(&(results)[30]); \
279 setup_fn(); PROBE_DATA_AT_OFFSET(31, op_imm, dst_reg, canary); read_full_state(&(results)[31]); \
280 setup_fn(); PROBE_DATA_AT_OFFSET(32, op_imm, dst_reg, canary); read_full_state(&(results)[32]); \
281 } while (0)
282
283#define DO_SWEEP_CTRL(setup_fn, op_imm, dst_reg, canary, results) \
284 do { \
285 setup_fn(); PROBE_CTRL_AT_OFFSET( 0, op_imm, dst_reg, canary); read_full_state(&(results)[ 0]); \
286 setup_fn(); PROBE_CTRL_AT_OFFSET( 1, op_imm, dst_reg, canary); read_full_state(&(results)[ 1]); \
287 setup_fn(); PROBE_CTRL_AT_OFFSET( 2, op_imm, dst_reg, canary); read_full_state(&(results)[ 2]); \
288 setup_fn(); PROBE_CTRL_AT_OFFSET( 3, op_imm, dst_reg, canary); read_full_state(&(results)[ 3]); \
289 setup_fn(); PROBE_CTRL_AT_OFFSET( 4, op_imm, dst_reg, canary); read_full_state(&(results)[ 4]); \
290 setup_fn(); PROBE_CTRL_AT_OFFSET( 5, op_imm, dst_reg, canary); read_full_state(&(results)[ 5]); \
291 setup_fn(); PROBE_CTRL_AT_OFFSET( 6, op_imm, dst_reg, canary); read_full_state(&(results)[ 6]); \
292 setup_fn(); PROBE_CTRL_AT_OFFSET( 7, op_imm, dst_reg, canary); read_full_state(&(results)[ 7]); \
293 setup_fn(); PROBE_CTRL_AT_OFFSET( 8, op_imm, dst_reg, canary); read_full_state(&(results)[ 8]); \
294 setup_fn(); PROBE_CTRL_AT_OFFSET( 9, op_imm, dst_reg, canary); read_full_state(&(results)[ 9]); \
295 setup_fn(); PROBE_CTRL_AT_OFFSET(10, op_imm, dst_reg, canary); read_full_state(&(results)[10]); \
296 setup_fn(); PROBE_CTRL_AT_OFFSET(11, op_imm, dst_reg, canary); read_full_state(&(results)[11]); \
297 setup_fn(); PROBE_CTRL_AT_OFFSET(12, op_imm, dst_reg, canary); read_full_state(&(results)[12]); \
298 setup_fn(); PROBE_CTRL_AT_OFFSET(13, op_imm, dst_reg, canary); read_full_state(&(results)[13]); \
299 setup_fn(); PROBE_CTRL_AT_OFFSET(14, op_imm, dst_reg, canary); read_full_state(&(results)[14]); \
300 setup_fn(); PROBE_CTRL_AT_OFFSET(15, op_imm, dst_reg, canary); read_full_state(&(results)[15]); \
301 setup_fn(); PROBE_CTRL_AT_OFFSET(16, op_imm, dst_reg, canary); read_full_state(&(results)[16]); \
302 setup_fn(); PROBE_CTRL_AT_OFFSET(17, op_imm, dst_reg, canary); read_full_state(&(results)[17]); \
303 setup_fn(); PROBE_CTRL_AT_OFFSET(18, op_imm, dst_reg, canary); read_full_state(&(results)[18]); \
304 setup_fn(); PROBE_CTRL_AT_OFFSET(19, op_imm, dst_reg, canary); read_full_state(&(results)[19]); \
305 setup_fn(); PROBE_CTRL_AT_OFFSET(20, op_imm, dst_reg, canary); read_full_state(&(results)[20]); \
306 setup_fn(); PROBE_CTRL_AT_OFFSET(21, op_imm, dst_reg, canary); read_full_state(&(results)[21]); \
307 setup_fn(); PROBE_CTRL_AT_OFFSET(22, op_imm, dst_reg, canary); read_full_state(&(results)[22]); \
308 setup_fn(); PROBE_CTRL_AT_OFFSET(23, op_imm, dst_reg, canary); read_full_state(&(results)[23]); \
309 setup_fn(); PROBE_CTRL_AT_OFFSET(24, op_imm, dst_reg, canary); read_full_state(&(results)[24]); \
310 setup_fn(); PROBE_CTRL_AT_OFFSET(25, op_imm, dst_reg, canary); read_full_state(&(results)[25]); \
311 setup_fn(); PROBE_CTRL_AT_OFFSET(26, op_imm, dst_reg, canary); read_full_state(&(results)[26]); \
312 setup_fn(); PROBE_CTRL_AT_OFFSET(27, op_imm, dst_reg, canary); read_full_state(&(results)[27]); \
313 setup_fn(); PROBE_CTRL_AT_OFFSET(28, op_imm, dst_reg, canary); read_full_state(&(results)[28]); \
314 setup_fn(); PROBE_CTRL_AT_OFFSET(29, op_imm, dst_reg, canary); read_full_state(&(results)[29]); \
315 setup_fn(); PROBE_CTRL_AT_OFFSET(30, op_imm, dst_reg, canary); read_full_state(&(results)[30]); \
316 setup_fn(); PROBE_CTRL_AT_OFFSET(31, op_imm, dst_reg, canary); read_full_state(&(results)[31]); \
317 setup_fn(); PROBE_CTRL_AT_OFFSET(32, op_imm, dst_reg, canary); read_full_state(&(results)[32]); \
318 } while (0)
319
320// ==========================================================================
321// Reporting
322// ==========================================================================
323// Print sweep results in a fixed format that downstream scripts can parse:
324//
325// === <name> ===
326// baseline RGB=(...) MAC0=... MAC=(...) IR0=... IR=(...) FLAG=...
327// sanity-pre ... DIFFERS_OK | *** SAME_AS_BASELINE_BUG ***
328// N=NN ...
329// === <name> boundary: N=NN ===
330
331static void report_sweep(const char* name,
332 const probe_result_t* baseline,
333 const probe_result_t* sanity_pre,
334 const probe_result_t results[MAX_N + 1]) {
335 ramsyscall_printf("=== %s ===\n", name);
336 ramsyscall_printf("baseline RGB=(0x%08x,0x%08x,0x%08x) MAC0=%d MAC=(%d,%d,%d) IR0=%d IR=(%d,%d,%d) FLAG=0x%08x\n",
337 baseline->rgb0, baseline->rgb1, baseline->rgb2,
338 baseline->mac0, baseline->mac1, baseline->mac2, baseline->mac3,
339 baseline->ir0, baseline->ir1, baseline->ir2, baseline->ir3,
340 baseline->flag);
341 int sanity_differs = !results_equal(baseline, sanity_pre);
342 ramsyscall_printf("sanity-pre RGB=(0x%08x,0x%08x,0x%08x) MAC0=%d MAC=(%d,%d,%d) IR0=%d IR=(%d,%d,%d) FLAG=0x%08x %s\n",
343 sanity_pre->rgb0, sanity_pre->rgb1, sanity_pre->rgb2,
344 sanity_pre->mac0, sanity_pre->mac1, sanity_pre->mac2, sanity_pre->mac3,
345 sanity_pre->ir0, sanity_pre->ir1, sanity_pre->ir2, sanity_pre->ir3,
346 sanity_pre->flag,
347 sanity_differs ? "DIFFERS_OK" : "*** SAME_AS_BASELINE_BUG ***");
348 int boundary = -1;
349 for (int n = 0; n <= MAX_N; n++) {
350 int matches = results_equal(baseline, &results[n]);
351 ramsyscall_printf("N=%2d RGB=(0x%08x,0x%08x,0x%08x) MAC=(%d,%d,%d) IR=(%d,%d,%d) FLAG=0x%08x %s\n",
352 n,
353 results[n].rgb0, results[n].rgb1, results[n].rgb2,
354 results[n].mac1, results[n].mac2, results[n].mac3,
355 results[n].ir1, results[n].ir2, results[n].ir3,
356 results[n].flag,
357 matches ? "MATCH" : "diff");
358 if (matches && boundary < 0) boundary = n;
359 }
360 ramsyscall_printf("=== %s boundary: N=%d ===\n", name, boundary);
361}
362
363// ==========================================================================
364// Test-body helpers (each probe is a single CESTER_TEST that calls these)
365// ==========================================================================
366//
367// MAKE_DATA_TEST(test_name, scene_setup, op_imm, dst_reg, canary, label)
368// Emits a CESTER_TEST that runs baseline + sanity_pre + warmup +
369// measurement sweeps for an MTC2 (data) probe.
370
371#define MAKE_DATA_TEST(test_name, scene_setup, op_imm, dst_reg, canary, label) \
372CESTER_TEST(test_name, gte_latency_tests, \
373 static probe_result_t baseline, sanity_pre; \
374 static probe_result_t warmup[MAX_N + 1]; \
375 static probe_result_t results[MAX_N + 1]; \
376 scene_setup(); \
377 PROBE_DATA_BASELINE(op_imm, dst_reg, canary); \
378 read_full_state(&baseline); \
379 scene_setup(); \
380 PROBE_DATA_SANITY_PRE(op_imm, dst_reg, canary); \
381 read_full_state(&sanity_pre); \
382 uint32_t saved_sr = irq_disable(); \
383 DO_SWEEP_DATA(scene_setup, op_imm, dst_reg, canary, warmup); \
384 DO_SWEEP_DATA(scene_setup, op_imm, dst_reg, canary, results); \
385 irq_restore(saved_sr); \
386 report_sweep(label, &baseline, &sanity_pre, results); \
387 cester_assert_true(!results_equal(&baseline, &sanity_pre)); \
388)
389
390#define MAKE_CTRL_TEST(test_name, scene_setup, op_imm, dst_reg, canary, label) \
391CESTER_TEST(test_name, gte_latency_tests, \
392 static probe_result_t baseline, sanity_pre; \
393 static probe_result_t warmup[MAX_N + 1]; \
394 static probe_result_t results[MAX_N + 1]; \
395 scene_setup(); \
396 PROBE_CTRL_BASELINE(op_imm, dst_reg, canary); \
397 read_full_state(&baseline); \
398 scene_setup(); \
399 PROBE_CTRL_SANITY_PRE(op_imm, dst_reg, canary); \
400 read_full_state(&sanity_pre); \
401 uint32_t saved_sr = irq_disable(); \
402 DO_SWEEP_CTRL(scene_setup, op_imm, dst_reg, canary, warmup); \
403 DO_SWEEP_CTRL(scene_setup, op_imm, dst_reg, canary, results); \
404 irq_restore(saved_sr); \
405 report_sweep(label, &baseline, &sanity_pre, results); \
406 cester_assert_true(!results_equal(&baseline, &sanity_pre)); \
407)
#define cop2_getc(reg, dest)
Definition cop2.h:203
#define cop2_get(reg, dest)
Definition cop2.h:189
uint32_t r
Definition cpu.c:222
int matches
Definition dcache.c:706
int n
Definition dcache.c:225
ramsyscall_printf("=== e01_kseg1_reads_no_fill ===\n")
int32_t mac1
Definition gte-depthcue.c:116
uint8_t b
Definition gte-depthcue.c:39
int32_t mac2
Definition gte-depthcue.c:116
int32_t mac3
Definition gte-depthcue.c:116
uint32_t rgb2
Definition gte-depthcue.c:35
uint32_t ir1
Definition gte-edgecase.c:108
uint32_t sz3
Definition gte-edgecase.c:375
uint32_t sxy2
Definition gte-edgecase.c:36
uint32_t flag
Definition gte-edgecase.c:36
#define MAX_N
Definition gte-latency-common.h:51
uint32_t rgb1
Definition gte-lighting.c:205
uint32_t rgb0
Definition gte-lighting.c:205
uint32_t ir3
Definition gte-precision.c:320
uint32_t sz1
Definition gte-rtps.c:217
uint32_t sz2
Definition gte-rtps.c:217
uint32_t sxy1
Definition gte-rtps.c:164
uint32_t ir2
Definition gte-sqr.c:24
Definition gte-latency-common.h:60
int32_t mac3
Definition gte-latency-common.h:62
uint32_t rgb1
Definition gte-latency-common.h:61
uint32_t sz0
Definition gte-latency-common.h:65
int32_t ir1
Definition gte-latency-common.h:63
uint32_t sz2
Definition gte-latency-common.h:65
int32_t ir0
Definition gte-latency-common.h:63
uint32_t rgb2
Definition gte-latency-common.h:61
int32_t mac2
Definition gte-latency-common.h:62
uint32_t sxy0
Definition gte-latency-common.h:64
int32_t ir2
Definition gte-latency-common.h:63
uint32_t sz1
Definition gte-latency-common.h:65
int32_t ir3
Definition gte-latency-common.h:63
int32_t mac1
Definition gte-latency-common.h:62
uint32_t sxy1
Definition gte-latency-common.h:64
uint32_t rgb0
Definition gte-latency-common.h:61
uint32_t sz3
Definition gte-latency-common.h:65
uint32_t flag
Definition gte-latency-common.h:66
int32_t mac0
Definition gte-latency-common.h:62
uint32_t sxy2
Definition gte-latency-common.h:64
void uint32_t(classId, spec)