Nugget
Loading...
Searching...
No Matches
cop2.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#pragma once
28
29// COP2 (GTE) instruction encoder and register access helpers.
30//
31// GTE command encoding (25-bit immediate for cop2 instruction):
32//
33// 24 20 19 18-17 16-15 14-13 12-11 10 9-6 5-0
34// [fake ] [pad][sf][ mx ][ v ][ cv ][ pad ][lm][pad][cmd]
35//
36// sf: shift flag (0 = no shift, 1 = shift right 12)
37// mx: matrix select (0=RT, 1=LL, 2=LC, 3=garbage)
38// v: vector select (0=V0, 1=V1, 2=V2, 3=IR)
39// cv: control vector select (0=TR, 1=BK, 2=FC/bugged, 3=zero)
40// lm: limit flag (0=clamp -0x8000..0x7fff, 1=clamp 0..0x7fff)
41// cmd: function code (6 bits)
42//
43// The upper bits (20-24) contain a "fake" opcode number that Sony's
44// documentation uses for instruction naming. Hardware ignores these
45// bits for dispatch - only the 6-bit function code matters.
46
47#include <stdint.h>
48
49// ==========================================================================
50// Bitfield encoding
51// ==========================================================================
52
53#define COP2_SF_SHIFT 19
54#define COP2_MX_SHIFT 17
55#define COP2_V_SHIFT 15
56#define COP2_CV_SHIFT 13
57#define COP2_LM_SHIFT 10
58
59// Shift factor
60#define COP2_SF0 0 // No shift
61#define COP2_SF1 1 // Shift right 12
62
63// Matrix select
64#define COP2_MX_RT 0 // Rotation matrix
65#define COP2_MX_LL 1 // Light matrix
66#define COP2_MX_LC 2 // Light color matrix
67#define COP2_MX_BAD 3 // Garbage matrix (undocumented)
68
69// Vector select
70#define COP2_V_V0 0
71#define COP2_V_V1 1
72#define COP2_V_V2 2
73#define COP2_V_IR 3 // IR1/IR2/IR3
74
75// Control vector select
76#define COP2_CV_TR 0 // Translation vector
77#define COP2_CV_BK 1 // Background color
78#define COP2_CV_FC 2 // Far color (bugged)
79#define COP2_CV_NONE 3 // Zero / no translation
80
81// Limit mode
82#define COP2_LM_SIGNED 0 // Clamp IR to [-0x8000, 0x7FFF]
83#define COP2_LM_UNSIGNED 1 // Clamp IR to [0, 0x7FFF]
84
85// Function codes (bits 5-0)
86#define COP2_FN_RTPS 0x01
87#define COP2_FN_NCLIP 0x06
88#define COP2_FN_OP 0x0c
89#define COP2_FN_DPCS 0x10
90#define COP2_FN_INTPL 0x11
91#define COP2_FN_MVMVA 0x12
92#define COP2_FN_NCDS 0x13
93#define COP2_FN_CDP 0x14
94#define COP2_FN_NCDT 0x16
95#define COP2_FN_NCCS 0x1b
96#define COP2_FN_CC 0x1c
97#define COP2_FN_NCS 0x1e
98#define COP2_FN_NCT 0x20
99#define COP2_FN_SQR 0x28
100#define COP2_FN_DCPL 0x29
101#define COP2_FN_DPCT 0x2a
102#define COP2_FN_AVSZ3 0x2d
103#define COP2_FN_AVSZ4 0x2e
104#define COP2_FN_RTPT 0x30
105#define COP2_FN_GPF 0x3d
106#define COP2_FN_GPL 0x3e
107#define COP2_FN_NCCT 0x3f
108
109// ==========================================================================
110// Generic encoder: build a cop2 opcode from individual fields
111// ==========================================================================
112
113// Generic encoder: build a cop2 opcode from individual fields.
114// The fake field (bits 24-20) is Sony's instruction number. Hardware
115// ignores it, but conventional encodings include it.
116#define COP2_OP(fake, sf, mx, v, cv, lm, fn) \
117 (((fake) << 20) | ((sf) << COP2_SF_SHIFT) | ((mx) << COP2_MX_SHIFT) | \
118 ((v) << COP2_V_SHIFT) | ((cv) << COP2_CV_SHIFT) | \
119 ((lm) << COP2_LM_SHIFT) | (fn))
120
121// ==========================================================================
122// Named instruction encoders
123// ==========================================================================
124// Each macro embeds the conventional fake field value from Sony's docs.
125// The sf and lm parameters are user-selectable. Other fields (mx, v, cv)
126// are fixed per instruction - only MVMVA exposes them.
127
128// Perspective transform (single / triple)
129#define COP2_RTPS(sf, lm) COP2_OP( 1, sf, 0, 0, 0, lm, COP2_FN_RTPS)
130#define COP2_RTPT(sf, lm) COP2_OP( 2, sf, 0, 0, 0, lm, COP2_FN_RTPT)
131
132// Normal clipping
133#define COP2_NCLIP COP2_OP(20, 0, 0, 0, 0, 0, COP2_FN_NCLIP)
134
135// Cross product (rotation diagonal x IR)
136#define COP2_OP_CP(sf, lm) COP2_OP(23, sf, 0, 0, 0, lm, COP2_FN_OP)
137
138// Depth cue
139#define COP2_DPCS(sf, lm) COP2_OP( 7, sf, 0, 0, 0, lm, COP2_FN_DPCS)
140#define COP2_DPCT(sf, lm) COP2_OP(15, sf, 0, 0, 0, lm, COP2_FN_DPCT)
141#define COP2_DCPL(sf, lm) COP2_OP( 6, sf, 0, 0, 0, lm, COP2_FN_DCPL)
142#define COP2_INTPL(sf, lm) COP2_OP( 9, sf, 0, 0, 0, lm, COP2_FN_INTPL)
143
144// Matrix-vector multiply and add (fully parameterized)
145#define COP2_MVMVA(sf, mx, v, cv, lm) \
146 COP2_OP(4, sf, mx, v, cv, lm, COP2_FN_MVMVA)
147
148// Lighting: normal color (single / triple)
149#define COP2_NCS(sf, lm) COP2_OP(12, sf, 0, 0, 0, lm, COP2_FN_NCS)
150#define COP2_NCT(sf, lm) COP2_OP(13, sf, 0, 0, 0, lm, COP2_FN_NCT)
151#define COP2_NCCS(sf, lm) COP2_OP(16, sf, 0, 0, 0, lm, COP2_FN_NCCS)
152#define COP2_NCCT(sf, lm) COP2_OP(17, sf, 0, 0, 0, lm, COP2_FN_NCCT)
153#define COP2_NCDS(sf, lm) COP2_OP(14, sf, 0, 0, 0, lm, COP2_FN_NCDS)
154#define COP2_NCDT(sf, lm) COP2_OP(15, sf, 0, 0, 0, lm, COP2_FN_NCDT)
155
156// Color
157#define COP2_CC(sf, lm) COP2_OP(19, sf, 0, 0, 0, lm, COP2_FN_CC)
158#define COP2_CDP(sf, lm) COP2_OP(18, sf, 0, 0, 0, lm, COP2_FN_CDP)
159
160// Square
161#define COP2_SQR(sf, lm) COP2_OP(10, sf, 0, 0, 0, lm, COP2_FN_SQR)
162
163// Average Z
164#define COP2_AVSZ3 COP2_OP(21, 1, 0, 0, 0, 0, COP2_FN_AVSZ3)
165#define COP2_AVSZ4 COP2_OP(22, 1, 0, 0, 0, 0, COP2_FN_AVSZ4)
166
167// General purpose interpolation
168#define COP2_GPF(sf, lm) COP2_OP(25, sf, 0, 0, 0, lm, COP2_FN_GPF)
169#define COP2_GPL(sf, lm) COP2_OP(26, sf, 0, 0, 0, lm, COP2_FN_GPL)
170
171// ==========================================================================
172// Execution macro
173// ==========================================================================
174
175#define cop2_cmd(op) __asm__ volatile("cop2 %0" : : "i"(op))
176
177// ==========================================================================
178// Register access
179// ==========================================================================
180
181// GTE data registers (MTC2/MFC2, $0-$31)
182#define cop2_put(reg, val) do { \
183 uint32_t _v = (val); \
184 __asm__ volatile("mtc2 %0, $" #reg \
185 "\n\tnop\n\tnop" \
186 : : "r"(_v)); \
187} while (0)
188
189#define cop2_get(reg, dest) do { \
190 __asm__ volatile("mfc2 %0, $" #reg \
191 "\n\tnop\n\tnop" \
192 : "=r"(dest)); \
193} while (0)
194
195// GTE control registers (CTC2/CFC2, $0-$31)
196#define cop2_putc(reg, val) do { \
197 uint32_t _v = (val); \
198 __asm__ volatile("ctc2 %0, $" #reg \
199 "\n\tnop\n\tnop" \
200 : : "r"(_v)); \
201} while (0)
202
203#define cop2_getc(reg, dest) do { \
204 __asm__ volatile("cfc2 %0, $" #reg \
205 "\n\tnop\n\tnop" \
206 : "=r"(dest)); \
207} while (0)
208
209// ==========================================================================
210// Data register indices
211// ==========================================================================
212
213#define COP2_VXY0 0 // VX0 (low16), VY0 (high16)
214#define COP2_VZ0 1
215#define COP2_VXY1 2
216#define COP2_VZ1 3
217#define COP2_VXY2 4
218#define COP2_VZ2 5
219#define COP2_RGBC 6 // R (low8), G, B, CODE (high8)
220#define COP2_OTZ 7 // 16-bit unsigned, zero-extended on read
221#define COP2_IR0 8 // 16-bit signed, sign-extended on read
222#define COP2_IR1 9
223#define COP2_IR2 10
224#define COP2_IR3 11
225#define COP2_SXY0 12
226#define COP2_SXY1 13
227#define COP2_SXY2 14
228#define COP2_SXYP 15 // Write pushes SXY FIFO, read returns SXY2
229#define COP2_SZ0 16 // 16-bit unsigned, zero-extended on read
230#define COP2_SZ1 17
231#define COP2_SZ2 18
232#define COP2_SZ3 19
233#define COP2_RGB0 20 // Color FIFO entry 0 (oldest)
234#define COP2_RGB1 21
235#define COP2_RGB2 22 // Color FIFO entry 2 (newest, written by instructions)
236#define COP2_RES1 23 // Reserved (but read/write works)
237#define COP2_MAC0 24 // 32-bit signed
238#define COP2_MAC1 25
239#define COP2_MAC2 26
240#define COP2_MAC3 27
241#define COP2_IRGB 28 // Write expands 5-bit fields to IR1-3. Read packs IR1-3.
242#define COP2_ORGB 29 // Read-only: packs IR1-3 with saturation
243#define COP2_LZCS 30 // Write triggers LZCR computation
244#define COP2_LZCR 31 // Read-only: leading bit count result
245
246// ==========================================================================
247// Control register indices
248// ==========================================================================
249
250#define COP2_R11R12 0
251#define COP2_R13R21 1
252#define COP2_R22R23 2
253#define COP2_R31R32 3
254#define COP2_R33 4 // 16-bit, sign-extended on read/write
255#define COP2_TRX 5 // 32-bit
256#define COP2_TRY 6
257#define COP2_TRZ 7
258#define COP2_L11L12 8
259#define COP2_L13L21 9
260#define COP2_L22L23 10
261#define COP2_L31L32 11
262#define COP2_L33 12 // 16-bit, sign-extended
263#define COP2_RBK 13 // 32-bit
264#define COP2_GBK 14
265#define COP2_BBK 15
266#define COP2_LR1LR2 16
267#define COP2_LR3LG1 17
268#define COP2_LG2LG3 18
269#define COP2_LB1LB2 19
270#define COP2_LB3 20 // 16-bit, sign-extended
271#define COP2_RFC 21 // 32-bit
272#define COP2_GFC 22
273#define COP2_BFC 23
274#define COP2_OFX 24 // 32-bit (16.16 fixed)
275#define COP2_OFY 25
276#define COP2_H 26 // 16-bit unsigned (but sign-extends on CFC2 read)
277#define COP2_DQA 27 // 16-bit, sign-extended
278#define COP2_DQB 28 // 32-bit
279#define COP2_ZSF3 29 // 16-bit, sign-extended
280#define COP2_ZSF4 30 // 16-bit, sign-extended
281#define COP2_FLAG 31 // FLAG register (write mask 0x7FFFF000, bit 31 recomputed)
282
283// ==========================================================================
284// FLAG register bit definitions
285// ==========================================================================
286
287#define COP2_FLAG_MAC1_OVER_POS (1u << 30) // MAC1 result > +0x7FFFFFFFFFF
288#define COP2_FLAG_MAC2_OVER_POS (1u << 29)
289#define COP2_FLAG_MAC3_OVER_POS (1u << 28)
290#define COP2_FLAG_MAC1_OVER_NEG (1u << 27) // MAC1 result < -0x80000000000
291#define COP2_FLAG_MAC2_OVER_NEG (1u << 26)
292#define COP2_FLAG_MAC3_OVER_NEG (1u << 25)
293#define COP2_FLAG_IR1_SAT (1u << 24) // IR1 saturated (sets summary)
294#define COP2_FLAG_IR2_SAT (1u << 23) // IR2 saturated (sets summary)
295#define COP2_FLAG_IR3_SAT (1u << 22) // IR3 saturated (NO summary)
296#define COP2_FLAG_COLOR_R_SAT (1u << 21) // Color R saturated to [0,255] (NO summary)
297#define COP2_FLAG_COLOR_G_SAT (1u << 20) // Color G saturated (NO summary)
298#define COP2_FLAG_COLOR_B_SAT (1u << 19) // Color B saturated (NO summary)
299#define COP2_FLAG_SZ3_OTZ_SAT (1u << 18) // SZ3/OTZ saturated to [0,0xFFFF] (sets summary)
300#define COP2_FLAG_DIV_OVERFLOW (1u << 17) // Division overflow H >= 2*SZ3 (sets summary)
301#define COP2_FLAG_MAC0_OVER_POS (1u << 16) // MAC0 > 0x7FFFFFFF (sets summary)
302#define COP2_FLAG_MAC0_OVER_NEG (1u << 15) // MAC0 < -0x80000000 (sets summary)
303#define COP2_FLAG_SX2_SAT (1u << 14) // SX2 saturated to [-0x400,0x3FF] (sets summary)
304#define COP2_FLAG_SY2_SAT (1u << 13) // SY2 saturated (sets summary)
305#define COP2_FLAG_IR0_SAT (1u << 12) // IR0 saturated to [0,0x1000] (NO summary)
306#define COP2_FLAG_ERROR (1u << 31) // Error summary (OR of bits that set summary)
307
308// Bits that set the error summary (bit 31):
309// 30-23 (MAC overflow, IR1/IR2 sat) and 18-13 (SZ3, div, MAC0, SX2, SY2)
310// Bits that do NOT set summary: 22 (IR3), 21-19 (color RGB), 12 (IR0)