shithub: psxe

Download patch

ref: c0e38d3d2f856a498a3bfea51062273f38f40090
parent: 2edfc7dd2902b1867d7e2fb2a62f8cc27223d771
author: allkern <lisandroaalarcon@gmail.com>
date: Mon Jul 10 18:11:06 EDT 2023

Start implementing RTPS

Cleanup

--- a/psx/cpu.c
+++ b/psx/cpu.c
@@ -5,7 +5,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-psx_cpu_instruction_t g_psx_cpu_secondary_table[] = {
+static const psx_cpu_instruction_t g_psx_cpu_secondary_table[] = {
     psx_cpu_i_sll    , psx_cpu_i_invalid, psx_cpu_i_srl    , psx_cpu_i_sra    ,
     psx_cpu_i_sllv   , psx_cpu_i_invalid, psx_cpu_i_srlv   , psx_cpu_i_srav   ,
     psx_cpu_i_jr     , psx_cpu_i_jalr   , psx_cpu_i_invalid, psx_cpu_i_invalid,
@@ -24,7 +24,7 @@
     psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid
 };
 
-psx_cpu_instruction_t g_psx_cpu_primary_table[] = {
+static const psx_cpu_instruction_t g_psx_cpu_primary_table[] = {
     psx_cpu_i_special, psx_cpu_i_bxx    , psx_cpu_i_j      , psx_cpu_i_jal    ,
     psx_cpu_i_beq    , psx_cpu_i_bne    , psx_cpu_i_blez   , psx_cpu_i_bgtz   ,
     psx_cpu_i_addi   , psx_cpu_i_addiu  , psx_cpu_i_slti   , psx_cpu_i_sltiu  ,
@@ -43,7 +43,7 @@
     psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid
 };
 
-psx_cpu_instruction_t g_psx_cpu_cop0_table[] = {
+static const psx_cpu_instruction_t g_psx_cpu_cop0_table[] = {
     psx_cpu_i_mfc0   , psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
     psx_cpu_i_mtc0   , psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
     psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
@@ -54,7 +54,7 @@
     psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid
 };
 
-psx_cpu_instruction_t g_psx_cpu_cop2_table[] = {
+static const psx_cpu_instruction_t g_psx_cpu_cop2_table[] = {
     psx_cpu_i_mfc2   , psx_cpu_i_invalid, psx_cpu_i_cfc2   , psx_cpu_i_invalid,
     psx_cpu_i_mtc2   , psx_cpu_i_invalid, psx_cpu_i_ctc2   , psx_cpu_i_invalid,
     psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid, psx_cpu_i_invalid,
@@ -65,7 +65,7 @@
     psx_cpu_i_gte    , psx_cpu_i_gte    , psx_cpu_i_gte    , psx_cpu_i_gte
 };
 
-psx_cpu_instruction_t g_psx_cpu_bxx_table[] = {
+static const psx_cpu_instruction_t g_psx_cpu_bxx_table[] = {
     psx_cpu_i_bltz   , psx_cpu_i_bgez   , psx_cpu_i_bltz   , psx_cpu_i_bgez   ,
     psx_cpu_i_bltz   , psx_cpu_i_bgez   , psx_cpu_i_bltz   , psx_cpu_i_bgez   ,
     psx_cpu_i_bltz   , psx_cpu_i_bgez   , psx_cpu_i_bltz   , psx_cpu_i_bgez   ,
@@ -76,7 +76,7 @@
     psx_cpu_i_bltz   , psx_cpu_i_bgez   , psx_cpu_i_bltz   , psx_cpu_i_bgez
 };
 
-psx_cpu_instruction_t g_psx_gte_table[] = {
+static const psx_cpu_instruction_t g_psx_gte_table[] = {
     psx_gte_i_invalid, psx_gte_i_rtps   , psx_gte_i_invalid, psx_gte_i_invalid,
     psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_nclip  , psx_gte_i_invalid,
     psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid, psx_gte_i_invalid,
@@ -95,25 +95,61 @@
     psx_gte_i_invalid, psx_gte_i_gpf    , psx_gte_i_gpl    , psx_gte_i_ncct
 };
 
-uint32_t g_psx_cpu_cop0_write_mask_table[] = {
-    0x00000000, // cop0r0-r2   - N/A
-    0x00000000, // cop0r0-r2   - N/A
-    0x00000000, // cop0r0-r2   - N/A
-    0xffffffff, // cop0r3      - BPC - Breakpoint on execute (R/W)
-    0x00000000, // cop0r4      - N/A
-    0xffffffff, // cop0r5      - BDA - Breakpoint on data access (R/W)
-    0x00000000, // cop0r6      - JUMPDEST - Randomly memorized jump address (R)
-    0xffc0f03f, // cop0r7      - DCIC - Breakpoint control (R/W)
-    0x00000000, // cop0r8      - BadVaddr - Bad Virtual Address (R)
-    0xffffffff, // cop0r9      - BDAM - Data Access breakpoint mask (R/W)
-    0x00000000, // cop0r10     - N/A
-    0xffffffff, // cop0r11     - BPCM - Execute breakpoint mask (R/W)
-    0xffffffff, // cop0r12     - SR - System status register (R/W)
-    0x00000300, // cop0r13     - CAUSE - (R)  Describes the most recently recognised exception
-    0x00000000, // cop0r14     - EPC - Return Address from Trap (R)
-    0x00000000  // cop0r15     - PRID - Processor ID (R)
+static const uint32_t g_psx_cpu_cop0_write_mask_table[] = {
+    0x00000000, // cop0r0   - N/A
+    0x00000000, // cop0r1   - N/A
+    0x00000000, // cop0r2   - N/A
+    0xffffffff, // BPC      - Breakpoint on execute (R/W)
+    0x00000000, // cop0r4   - N/A
+    0xffffffff, // BDA      - Breakpoint on data access (R/W)
+    0x00000000, // JUMPDEST - Randomly memorized jump address (R)
+    0xffc0f03f, // DCIC     - Breakpoint control (R/W)
+    0x00000000, // BadVaddr - Bad Virtual Address (R)
+    0xffffffff, // BDAM     - Data Access breakpoint mask (R/W)
+    0x00000000, // cop0r10  - N/A
+    0xffffffff, // BPCM     - Execute breakpoint mask (R/W)
+    0xffffffff, // SR       - System status register (R/W)
+    0x00000300, // CAUSE    - Describes the most recently recognised exception (R)
+    0x00000000, // EPC      - Return Address from Trap (R)
+    0x00000000  // PRID     - Processor ID (R)
 };
 
+static const uint8_t g_psx_gte_unr_table[] = {
+    0xff, 0xfd, 0xfb, 0xf9, 0xf7, 0xf5, 0xf3, 0xf1,
+    0xef, 0xee, 0xec, 0xea, 0xe8, 0xe6, 0xe4, 0xe3,
+    0xe1, 0xdf, 0xdd, 0xdc, 0xda, 0xd8, 0xd6, 0xd5,
+    0xd3, 0xd1, 0xd0, 0xce, 0xcd, 0xcb, 0xc9, 0xc8,
+    0xc6, 0xc5, 0xc3, 0xc1, 0xc0, 0xbe, 0xbd, 0xbb,
+    0xba, 0xb8, 0xb7, 0xb5, 0xb4, 0xb2, 0xb1, 0xb0,
+    0xae, 0xad, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa4,
+    0xa3, 0xa2, 0xa0, 0x9f, 0x9e, 0x9c, 0x9b, 0x9a,
+    0x99, 0x97, 0x96, 0x95, 0x94, 0x92, 0x91, 0x90,
+    0x8f, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x87, 0x86,
+    0x85, 0x84, 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7d,
+    0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x75, 0x74,
+    0x73, 0x72, 0x71, 0x70, 0x6f, 0x6e, 0x6d, 0x6c,
+    0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64,
+    0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5d,
+    0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55,
+    0x54, 0x53, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e,
+    0x4d, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x48,
+    0x47, 0x46, 0x45, 0x44, 0x43, 0x43, 0x42, 0x41,
+    0x40, 0x3f, 0x3f, 0x3e, 0x3d, 0x3c, 0x3c, 0x3b,
+    0x3a, 0x39, 0x39, 0x38, 0x37, 0x36, 0x36, 0x35,
+    0x34, 0x33, 0x33, 0x32, 0x31, 0x31, 0x30, 0x2f,
+    0x2e, 0x2e, 0x2d, 0x2c, 0x2c, 0x2b, 0x2a, 0x2a,
+    0x29, 0x28, 0x28, 0x27, 0x26, 0x26, 0x25, 0x24,
+    0x24, 0x23, 0x22, 0x22, 0x21, 0x20, 0x20, 0x1f,
+    0x1e, 0x1e, 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
+    0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15,
+    0x15, 0x14, 0x14, 0x13, 0x12, 0x12, 0x11, 0x11,
+    0x10, 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c,
+    0x0c, 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08,
+    0x07, 0x07, 0x06, 0x06, 0x05, 0x05, 0x04, 0x04,
+    0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00,
+    0x00
+};
+
 #define OP ((cpu->opcode >> 26) & 0x3f)
 #define S ((cpu->opcode >> 21) & 0x1f)
 #define T ((cpu->opcode >> 16) & 0x1f)
@@ -126,39 +162,10 @@
 #define IMM16S ((int32_t)((int16_t)IMM16))
 
 #define R_R0 (cpu->r[0])
-#define R_AT (cpu->r[1])
-#define R_V0 (cpu->r[2])
-#define R_V1 (cpu->r[3])
 #define R_A0 (cpu->r[4])
-#define R_A1 (cpu->r[5])
-#define R_A2 (cpu->r[6])
-#define R_A3 (cpu->r[7])
-#define R_T0 (cpu->r[8])
-#define R_T1 (cpu->r[9])
-#define R_T2 (cpu->r[10])
-#define R_T3 (cpu->r[11])
-#define R_T4 (cpu->r[12])
-#define R_T5 (cpu->r[13])
-#define R_T6 (cpu->r[14])
-#define R_T7 (cpu->r[15])
-#define R_S0 (cpu->r[16])
-#define R_S1 (cpu->r[17])
-#define R_S2 (cpu->r[18])
-#define R_S3 (cpu->r[19])
-#define R_S4 (cpu->r[20])
-#define R_S5 (cpu->r[21])
-#define R_S6 (cpu->r[22])
-#define R_S7 (cpu->r[23])
-#define R_T8 (cpu->r[24])
-#define R_T9 (cpu->r[25])
-#define R_K0 (cpu->r[26])
-#define R_K1 (cpu->r[27])
-#define R_GP (cpu->r[28])
-#define R_SP (cpu->r[29])
-#define R_FP (cpu->r[30])
 #define R_RA (cpu->r[31])
 
-#define CPU_TRACE
+//#define CPU_TRACE
 
 #ifdef CPU_TRACE
 #define TRACE_M(m) \
@@ -216,6 +223,8 @@
 #define TRACE_I26(m)
 #define TRACE_RT(m)
 #define TRACE_C0M(m)
+#define TRACE_C2M(m)
+#define TRACE_C2MC(m)
 #define TRACE_B(m)
 #define TRACE_RS(m)
 #define TRACE_MTF(m)
@@ -231,27 +240,19 @@
     cpu->load_v = 0xffffffff; \
     cpu->load_d = 0;
 
+#ifdef CPU_TRACE
 #define DEBUG_ALL \
-    log_fatal("r0=%08x at=%08x v0=%08x v1=%08x", R_R0, R_AT, R_V0, R_V1); \
-    log_fatal("a0=%08x a1=%08x a2=%08x a3=%08x", R_A0, R_A1, R_A2, R_A3); \
-    log_fatal("t0=%08x t1=%08x t2=%08x t3=%08x", R_T0, R_T1, R_T2, R_T3); \
-    log_fatal("t4=%08x t5=%08x t6=%08x t7=%08x", R_T4, R_T5, R_T6, R_T7); \
-    log_fatal("s0=%08x s1=%08x s2=%08x s3=%08x", R_S0, R_S1, R_S2, R_S3); \
-    log_fatal("s4=%08x s5=%08x s6=%08x s7=%08x", R_S4, R_S5, R_S6, R_S7); \
-    log_fatal("t8=%08x t9=%08x k0=%08x k1=%08x", R_T8, R_T9, R_K0, R_K1); \
-    log_fatal("gp=%08x sp=%08x fp=%08x ra=%08x", R_GP, R_SP, R_FP, R_RA); \
+    log_fatal("r0=%08x at=%08x v0=%08x v1=%08x", cpu->r[0] , cpu->r[1] , cpu->r[2] , cpu->r[3] ); \
+    log_fatal("a0=%08x a1=%08x a2=%08x a3=%08x", cpu->r[4] , cpu->r[5] , cpu->r[6] , cpu->r[7] ); \
+    log_fatal("t0=%08x t1=%08x t2=%08x t3=%08x", cpu->r[8] , cpu->r[9] , cpu->r[10], cpu->r[11]); \
+    log_fatal("t4=%08x t5=%08x t6=%08x t7=%08x", cpu->r[12], cpu->r[13], cpu->r[14], cpu->r[15]); \
+    log_fatal("s0=%08x s1=%08x s2=%08x s3=%08x", cpu->r[16], cpu->r[17], cpu->r[18], cpu->r[19]); \
+    log_fatal("s4=%08x s5=%08x s6=%08x s7=%08x", cpu->r[20], cpu->r[21], cpu->r[22], cpu->r[23]); \
+    log_fatal("t8=%08x t9=%08x k0=%08x k1=%08x", cpu->r[24], cpu->r[25], cpu->r[26], cpu->r[27]); \
+    log_fatal("gp=%08x sp=%08x fp=%08x ra=%08x", cpu->r[28], cpu->r[29], cpu->r[30], cpu->r[31]); \
     log_fatal("pc=%08x hi=%08x lo=%08x l:%s=%08x", cpu->pc, cpu->hi, cpu->lo, g_mips_cc_register_names[cpu->load_d], cpu->load_v); \
     exit(1)
 
-#define SE8(v) ((int32_t)((int8_t)v))
-#define SE16(v) ((int32_t)((int16_t)v))
-
-#define BRANCH(offset) \
-    cpu->next_pc = cpu->next_pc + (offset); \
-    cpu->next_pc = cpu->next_pc - 4; \
-    cpu->branch = 1; \
-    cpu->branch_taken = 1;
-
 const char* g_mips_cop0_register_names[] = {
     "cop0_r0",
     "cop0_r1",
@@ -271,7 +272,7 @@
     "cop0_prid"
 };
 
-const char* g_mips_cc_register_names[] = {
+static const char* g_mips_cc_register_names[] = {
     "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
     "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
     "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
@@ -278,7 +279,7 @@
     "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
 };
 
-const char* g_psx_cpu_syscall_function_symbol_table[] = {
+static const char* g_psx_cpu_syscall_function_symbol_table[] = {
     "NoFunction",
     "EnterCriticalSection",
     "ExitCriticalSection",
@@ -285,7 +286,17 @@
     "ChangeThreadSubFunction"
     // DeliverEvent (invalid)
 };
+#endif
 
+#define SE8(v) ((int32_t)((int8_t)v))
+#define SE16(v) ((int32_t)((int16_t)v))
+
+#define BRANCH(offset) \
+    cpu->next_pc = cpu->next_pc + (offset); \
+    cpu->next_pc = cpu->next_pc - 4; \
+    cpu->branch = 1; \
+    cpu->branch_taken = 1;
+
 void cpu_a_kcall_hook(psx_cpu_t* cpu) {
     switch (cpu->r[9]) {
         case 0x09: putc(R_A0, stdout); break;
@@ -692,6 +703,8 @@
 }
 
 void psx_cpu_i_cop2(psx_cpu_t* cpu) {
+    cpu->cop2_flag = 0;
+
     g_psx_cpu_cop2_table[S](cpu);
 }
 
@@ -1336,7 +1349,7 @@
 
     DO_PENDING_LOAD;
 
-    ((uint32_t*)(&cpu->cop2_dr))[D] = t & g_psx_cpu_cop0_write_mask_table[D];
+    ((uint32_t*)(&cpu->cop2_dr))[D] = t;
 }
 
 void psx_cpu_i_ctc2(psx_cpu_t* cpu) {
@@ -1346,9 +1359,39 @@
 
     DO_PENDING_LOAD;
 
-    ((uint32_t*)(&cpu->cop2_cr))[D] = t & g_psx_cpu_cop0_write_mask_table[D];
+    ((uint32_t*)(&cpu->cop2_cr))[D] = t;
 }
 
+#define R_IR1 cpu->cop2_dr.ir1
+#define R_IR2 cpu->cop2_dr.ir2
+#define R_IR3 cpu->cop2_dr.ir3
+#define R_MAC0 cpu->cop2_dr.mac0
+#define R_MAC1 cpu->cop2_dr.mac1
+#define R_MAC2 cpu->cop2_dr.mac2
+#define R_MAC3 cpu->cop2_dr.mac3
+#define R_RT11 cpu->cop2_cr.rt[0]
+#define R_RT12 cpu->cop2_cr.rt[1]
+#define R_RT13 cpu->cop2_cr.rt[2]
+#define R_RT21 cpu->cop2_cr.rt[3]
+#define R_RT22 cpu->cop2_cr.rt[4]
+#define R_RT23 cpu->cop2_cr.rt[5]
+#define R_RT31 cpu->cop2_cr.rt[6]
+#define R_RT32 cpu->cop2_cr.rt[7]
+#define R_RT33 cpu->cop2_cr.rt[8]
+#define R_VX0 cpu->cop2_dr.v0[0]
+#define R_VY0 cpu->cop2_dr.v0[1]
+#define R_VZ0 cpu->cop2_dr.v0[2]
+#define R_VX1 cpu->cop2_dr.v1[0]
+#define R_VY1 cpu->cop2_dr.v1[1]
+#define R_VZ1 cpu->cop2_dr.v1[2]
+#define R_VX2 cpu->cop2_dr.v2[0]
+#define R_VY2 cpu->cop2_dr.v2[1]
+#define R_VZ2 cpu->cop2_dr.v2[2]
+#define R_TRX cpu->cop2_cr.trx
+#define R_TRY cpu->cop2_cr.try
+#define R_TRZ cpu->cop2_cr.trz
+#define R_SZ3 cpu->cop2_dr.sz3
+
 void psx_cpu_i_gte(psx_cpu_t* cpu) {
     DO_PENDING_LOAD;
 
@@ -1360,7 +1403,20 @@
 }
 
 void psx_gte_i_rtps(psx_cpu_t* cpu) {
-    log_fatal("rtps: Unimplemented GTE instruction");
+    int sf = (cpu->opcode >> 19) & 1;
+
+    R_MAC1 = (R_TRX * 0x1000) + (R_RT11 * R_VX0 + R_RT12 * R_VY0 + R_RT13 * R_VZ0);
+    R_MAC2 = (R_TRY * 0x1000) + (R_RT21 * R_VX0 + R_RT22 * R_VY0 + R_RT23 * R_VZ0);
+    R_MAC3 = (R_TRZ * 0x1000) + (R_RT31 * R_VX0 + R_RT32 * R_VY0 + R_RT33 * R_VZ0);
+
+    R_IR1 = R_MAC1;
+    R_IR2 = R_MAC2;
+    R_IR3 = R_MAC3;
+    
+    // R_SZ3 = R_MAC3 << ((1 - sf) * 12)
+    // R_MAC0 = (((H*20000h/SZ3)+1)/2)*IR1+OFX, SX2=MAC0/10000h
+    // R_MAC0 = (((H*20000h/SZ3)+1)/2)*IR2+OFY, SY2=MAC0/10000h
+    // R_MAC0 = (((H*20000h/SZ3)+1)/2)*DQA+DQB, IR0=MAC0/1000h
 }
 
 void psx_gte_i_nclip(psx_cpu_t* cpu) {
@@ -1432,7 +1488,7 @@
 }
 
 void psx_gte_i_rtpt(psx_cpu_t* cpu) {
-    log_fatal("rtpt: Unimplemented GTE instruction");
+    log_fatal("rtpt: Unimplemented GTE instruction");   
 }
 
 void psx_gte_i_gpf(psx_cpu_t* cpu) {
@@ -1448,36 +1504,7 @@
 }
 
 #undef R_R0
-#undef R_AT
-#undef R_V0
-#undef R_V1
 #undef R_A0
-#undef R_A1
-#undef R_A2
-#undef R_A3
-#undef R_T0
-#undef R_T1
-#undef R_T2
-#undef R_T3
-#undef R_T4
-#undef R_T5
-#undef R_T6
-#undef R_T7
-#undef R_S0
-#undef R_S1
-#undef R_S2
-#undef R_S3
-#undef R_S4
-#undef R_S5
-#undef R_S6
-#undef R_S7
-#undef R_T8
-#undef R_T9
-#undef R_K0
-#undef R_K1
-#undef R_GP
-#undef R_SP
-#undef R_FP
 #undef R_RA
 
 #undef OP
@@ -1498,6 +1525,8 @@
 #undef TRACE_I26
 #undef TRACE_RT
 #undef TRACE_C0M
+#undef TRACE_C2M
+#undef TRACE_C2MC
 #undef TRACE_B
 #undef TRACE_RS
 #undef TRACE_MTF
--- a/psx/cpu.h
+++ b/psx/cpu.h
@@ -104,6 +104,8 @@
         uint32_t flag;
     } cop2_cr;
 
+    uint32_t cop2_flag;
+
     psx_bus_t* bus;
 
     psx_cpu_kcall_hook_t a_function_hook;
@@ -223,6 +225,48 @@
 #define CAUSE_RI        (0x0a << 2)
 #define CAUSE_CPU       (0x0b << 2)
 #define CAUSE_OV        (0x0c << 2)
+
+/*
+  31   Error Flag (Bit30..23, and 18..13 ORed together) (Read only)
+  30   MAC1 Result positive 44bit overflow (max +7FFFFFFFFFFh) ;\triggered
+  29   MAC2 Result positive 44bit overflow (max +7FFFFFFFFFFh) ; during
+  28   MAC3 Result positive 44bit overflow (max +7FFFFFFFFFFh) ; calculations
+  27   MAC1 Result negative 44bit overflow (min -80000000000h) ;
+  26   MAC2 Result negative 44bit overflow (min -80000000000h) ;
+  25   MAC3 Result negative 44bit overflow (min -80000000000h) ;/
+  24   IR1 saturated to +0000h..+7FFFh (lm=1) or to -8000h..+7FFFh (lm=0)
+  23   IR2 saturated to +0000h..+7FFFh (lm=1) or to -8000h..+7FFFh (lm=0)
+  22   IR3 saturated to +0000h..+7FFFh (lm=1) or to -8000h..+7FFFh (lm=0)
+  21   Color-FIFO-R saturated to +00h..+FFh
+  20   Color-FIFO-G saturated to +00h..+FFh
+  19   Color-FIFO-B saturated to +00h..+FFh
+  18   SZ3 or OTZ saturated to +0000h..+FFFFh
+  17   Divide overflow. RTPS/RTPT division result saturated to max=1FFFFh
+  16   MAC0 Result positive 32bit overflow (max +7FFFFFFFh)    ;\triggered on
+  15   MAC0 Result negative 32bit overflow (min -80000000h)    ;/final result
+  14   SX2 saturated to -0400h..+03FFh
+  13   SY2 saturated to -0400h..+03FFh
+*/
+
+#define GTEF_SY2SAT 0x00002000
+#define GTEF_SX2SAT 0x00004000
+#define GTEF_M0POVF 0x00008000
+#define GTEF_M0NOVF 0x00010000
+#define GTEF_DIVOVF 0x00020000
+#define GTEF_SZ3SAT 0x00040000
+#define GTEF_CFRSAT 0x00080000
+#define GTEF_CFGSAT 0x00100000
+#define GTEF_CFBSAT 0x00200000
+#define GTEF_IR3SAT 0x00400000
+#define GTEF_IR2SAT 0x00800000
+#define GTEF_IR1SAT 0x01000000
+#define GTEF_M3NOVF 0x02000000
+#define GTEF_M2NOVF 0x04000000
+#define GTEF_M1NOVF 0x08000000
+#define GTEF_M3POVF 0x10000000
+#define GTEF_M2POVF 0x20000000
+#define GTEF_M1POVF 0x40000000
+#define GTEF_ERRORF 0x80000000
 
 void psx_cpu_i_invalid(psx_cpu_t*);
 
--