Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
gwu.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 * Write-to-use delay, per cop2 command and per input register.
28 *
29 * Every cell is one (command, input register) pair of the gte-latency tests,
30 * with that test's scene and canary. A cell function writes the register's
31 * scene value, waits 4 nops, writes a second value, waits N nops, runs the
32 * command:
33 *
34 * mtc2/ctc2 a, reg; nop x4; mtc2/ctc2 b, reg; nop x N; cop2 CMD
35 *
36 * and the command's outputs are compared against two references run through
37 * the same function: a = b = scene value (old), a = b = canary (new).
38 * The written register itself is left out of the comparison.
39 *
40 * Varied: N = 0..3; A = 0..3, the word within a 16-byte cache line the
41 * sequence starts at (A0..A3, cached); and cached vs uncached fetch (U,
42 * at A = 0). Held: interrupts off, nop as the filler and as the
43 * instruction before the second write, mtc2/ctc2 as the writer, the
44 * measured pass is the second of two back to back.
45 *
46 * The last column of each cell is the cached result from SCPH-1000, -1001,
47 * -5501 (two) -7001 and -9002 (see RESULTS.md). A letter that is the same
48 * at every A is checked against it, and the program returns 1 on any
49 * difference; '?' marks a letter that moves with A or between consoles,
50 * which is printed and not checked. The uncached pass is printed only.
51 */
52
53#pragma once
54
55#include <stdint.h>
56
57#include "gte-latency-common.h"
58
59#define GWU_NMAX 4
60#define GWU_AMAX 4
61
62typedef void (*GwuFn)(uint32_t, uint32_t);
63
64typedef struct {
65 const char* label;
66 void (*scene)(void);
67 uint32_t (*read)(void);
69 uint32_t canary;
70 uint8_t ctrl;
71 uint8_t reg;
72 const char* expect;
73} GwuCell;
74
75#define GWU_W_D "mtc2"
76#define GWU_W_C "ctc2"
77#define GWU_GET_D cop2_get
78#define GWU_GET_C cop2_getc
79#define GWU_ISC_D 0
80#define GWU_ISC_C 1
81
82// A = how many words past a 16-byte cache line boundary the sequence starts.
83#define GWU_FN(W, name, op, reg, N, A) \
84 static void name##_##N##_##A(uint32_t a, uint32_t b) { \
85 __asm__ volatile(".set push\n.set noreorder\n.balign 16\n.rept " #A "\nnop\n.endr\n" W " %0, $" #reg \
86 "\nnop\nnop\nnop\nnop\n" W " %1, $" #reg "\n.rept " #N \
87 "\nnop\n.endr\ncop2 %2\nnop\nnop\n.set pop\n" \
88 : \
89 : "r"(a), "r"(b), "i"(op)); \
90 }
91
92#define GWU_FN_A(W, name, op, reg, N) \
93 GWU_FN(W, name, op, reg, N, 0) \
94 GWU_FN(W, name, op, reg, N, 1) \
95 GWU_FN(W, name, op, reg, N, 2) \
96 GWU_FN(W, name, op, reg, N, 3)
97
98#define GWU_FUNCS(K, name, scene, op, reg, canary, label, expect) \
99 GWU_FN_A(GWU_W_##K, name, op, reg, 0) \
100 GWU_FN_A(GWU_W_##K, name, op, reg, 1) \
101 GWU_FN_A(GWU_W_##K, name, op, reg, 2) \
102 GWU_FN_A(GWU_W_##K, name, op, reg, 3) \
103 static uint32_t name##_rd(void) { \
104 uint32_t v; \
105 GWU_GET_##K(reg, v); \
106 return v; \
107 }
108
109#define GWU_ROW(name, N) {name##_##N##_0, name##_##N##_1, name##_##N##_2, name##_##N##_3}
110#define GWU_ENTRY(K, name, scene, op, reg, canary, label, expect) \
111 {label, scene, name##_rd, {GWU_ROW(name, 0), GWU_ROW(name, 1), GWU_ROW(name, 2), GWU_ROW(name, 3)}, \
112 canary, GWU_ISC_##K, reg, expect},
#define GWU_AMAX
Definition gwu.h:60
void(* GwuFn)(uint32_t, uint32_t)
Definition gwu.h:62
#define GWU_NMAX
Definition gwu.h:59
Definition gwu.h:64
uint32_t canary
Definition gwu.h:69
uint8_t reg
Definition gwu.h:71
uint8_t ctrl
Definition gwu.h:70
const char * expect
Definition gwu.h:72
const char * label
Definition gwu.h:65