@@ -32,16 +32,13 @@ enum : u32
32
32
PGXP_MEM_SCRATCH_OFFSET = Bus::RAM_8MB_SIZE / 4
33
33
};
34
34
35
- #define NONE 0
36
35
#define ALL 0xFFFFFFFF
37
- #define VALID 1
38
- #define VALID_0 (VALID << 0 )
39
- #define VALID_1 (VALID << 8 )
40
- #define VALID_2 (VALID << 16 )
41
- #define VALID_3 (VALID << 24 )
36
+ #define VALID_0 (1 << 0 )
37
+ #define VALID_1 (1 << 1 )
38
+ #define VALID_2 (1 << 2 )
42
39
#define VALID_01 (VALID_0 | VALID_1)
43
40
#define VALID_012 (VALID_0 | VALID_1 | VALID_2)
44
- #define VALID_ALL (VALID_0 | VALID_1 | VALID_2 | VALID_3 )
41
+ #define VALID_ALL (VALID_0 | VALID_1 | VALID_2)
45
42
#define INV_VALID_ALL (ALL ^ VALID_ALL)
46
43
47
44
union psx_value
@@ -85,6 +82,9 @@ static void CPU_BITWISE(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal);
85
82
static void WriteMem (const PGXP_value* value, u32 addr);
86
83
static void WriteMem16 (const PGXP_value* src, u32 addr);
87
84
85
+ static void CopyZIfMissing (PGXP_value& dst, const PGXP_value& src);
86
+ static void SelectZ (PGXP_value& dst, const PGXP_value& src1, const PGXP_value& src2);
87
+
88
88
#ifdef LOG_VALUES
89
89
static void LogInstruction (u32 pc, u32 instr);
90
90
static void LogValue (const char * name, u32 rval, const PGXP_value* val);
@@ -107,8 +107,8 @@ static void LogValueStr(SmallStringBase& str, const char* name, u32 rval, const
107
107
#endif
108
108
// clang-format on
109
109
110
- static const PGXP_value PGXP_value_invalid = {0 .f , 0 .f , 0 .f , 0 , { 0 } };
111
- static const PGXP_value PGXP_value_zero = {0 .f , 0 .f , 0 .f , 0 , { VALID_ALL} };
110
+ static const PGXP_value PGXP_value_invalid = {0 .f , 0 .f , 0 .f , 0 , 0 };
111
+ static const PGXP_value PGXP_value_zero = {0 .f , 0 .f , 0 .f , 0 , VALID_ALL};
112
112
113
113
static PGXP_value* s_mem = nullptr ;
114
114
static PGXP_value* s_vertex_cache = nullptr ;
@@ -303,19 +303,19 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::ValidateAndCopyMem16(PGXP_value* dest, u32
303
303
if (hiword)
304
304
{
305
305
dest->x = dest->y ;
306
- dest->compFlags [ 0 ] = dest->compFlags [ 1 ] ;
306
+ dest->SetValidComp ( 0 , dest->GetValidComp ( 1 )) ;
307
307
}
308
308
309
309
// only set y as valid if x is also valid.. don't want to make fake values
310
- if (dest->compFlags [ 0 ] == VALID )
310
+ if (dest->GetValidComp ( 0 ) )
311
311
{
312
312
dest->y = (dest->x < 0 ) ? -1 .f * sign : 0 .f ;
313
- dest->compFlags [ 1 ] = VALID ;
313
+ dest->SetValidComp ( 1 , true ) ;
314
314
}
315
315
else
316
316
{
317
317
dest->y = 0 .0f ;
318
- dest->compFlags [ 1 ] = 0 ;
318
+ dest->SetValidComp ( 1 , false ) ;
319
319
}
320
320
321
321
dest->value = value;
@@ -340,24 +340,39 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::WriteMem16(const PGXP_value* src, u32 addr
340
340
if (hiword)
341
341
{
342
342
dest->y = src->x ;
343
- dest->compFlags [ 1 ] = src->compFlags [ 0 ] ;
343
+ dest->SetValidComp ( 1 , src->GetValidComp ( 0 )) ;
344
344
dest->value = (dest->value & UINT32_C (0x0000FFFF )) | (src->value << 16 );
345
345
}
346
346
else
347
347
{
348
348
dest->x = src->x ;
349
- dest->compFlags [ 0 ] = src->compFlags [ 0 ] ;
349
+ dest->SetValidComp ( 0 , src->GetValidComp ( 0 )) ;
350
350
dest->value = (dest->value & UINT32_C (0xFFFF0000 )) | (src->value & UINT32_C (0x0000FFFF ));
351
351
}
352
352
353
353
// overwrite z/w if valid
354
- if (src->compFlags [ 2 ] == VALID )
354
+ if (src->GetValidComp ( 2 ) )
355
355
{
356
356
dest->z = src->z ;
357
- dest->compFlags [ 2 ] = src-> compFlags [ 2 ] ;
357
+ dest->SetValidComp ( 2 , true ) ;
358
358
}
359
359
}
360
360
361
+ ALWAYS_INLINE_RELEASE void CPU::PGXP::CopyZIfMissing (PGXP_value& dst, const PGXP_value& src)
362
+ {
363
+ if (dst.GetValidComp (2 ))
364
+ return ;
365
+
366
+ dst.z = src.z ;
367
+ dst.flags |= (src.flags & VALID_2);
368
+ }
369
+
370
+ ALWAYS_INLINE_RELEASE void CPU::PGXP::SelectZ (PGXP_value& dst, const PGXP_value& src1, const PGXP_value& src2)
371
+ {
372
+ dst.z = src1.GetValidComp (2 ) ? src1.z : src2.z ;
373
+ dst.flags |= ((src1.flags | src2.flags ) & VALID_2);
374
+ }
375
+
361
376
#ifdef LOG_VALUES
362
377
void CPU::PGXP::LogInstruction (u32 pc, u32 instr)
363
378
{
@@ -929,13 +944,13 @@ void CPU::PGXP::CPU_ADD(u32 instr, u32 rsVal, u32 rtVal)
929
944
930
945
// TODO: decide which "z/w" component to use
931
946
932
- ret.halfFlags [ 0 ] &= g_state.pgxp_gpr [rt (instr)].halfFlags [ 0 ] ;
947
+ ret.flags &= ( g_state.pgxp_gpr [rt (instr)].flags & VALID_01) ;
933
948
}
934
949
935
950
if (!(ret.flags & VALID_2) && (g_state.pgxp_gpr [rt (instr)].flags & VALID_2))
936
951
{
937
952
ret.z = g_state.pgxp_gpr [rt (instr)].z ;
938
- ret.flags |= VALID_2 ;
953
+ ret.SetValidComp ( 2 , true ) ;
939
954
}
940
955
941
956
ret.value = rsVal + rtVal;
@@ -974,7 +989,7 @@ void CPU::PGXP::CPU_SUB(u32 instr, u32 rsVal, u32 rtVal)
974
989
// truncate on overflow/underflow
975
990
ret.y += (ret.y > SHRT_MAX) ? -(USHRT_MAX + 1 ) : (ret.y < SHRT_MIN) ? USHRT_MAX + 1 : 0 .f ;
976
991
977
- ret.halfFlags [ 0 ] &= g_state.pgxp_gpr [rt (instr)].halfFlags [ 0 ] ;
992
+ ret.flags &= ( g_state.pgxp_gpr [rt (instr)].flags & VALID_01) ;
978
993
979
994
ret.value = rsVal - rtVal;
980
995
@@ -1020,17 +1035,17 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_BITWISE(u32 instr, u32 rdVal, u32 rsVa
1020
1035
else if (vald.w .l == vals.w .l )
1021
1036
{
1022
1037
ret.x = g_state.pgxp_gpr [rs (instr)].x ;
1023
- ret.compFlags [ 0 ] = g_state.pgxp_gpr [rs (instr)].compFlags [ 0 ] ;
1038
+ ret.SetValidComp ( 0 , g_state.pgxp_gpr [rs (instr)].GetValidComp ( 0 )) ;
1024
1039
}
1025
1040
else if (vald.w .l == valt.w .l )
1026
1041
{
1027
1042
ret.x = g_state.pgxp_gpr [rt (instr)].x ;
1028
- ret.compFlags [ 0 ] = g_state.pgxp_gpr [rt (instr)].compFlags [ 0 ] ;
1043
+ ret.SetValidComp ( 0 , g_state.pgxp_gpr [rt (instr)].GetValidComp ( 0 )) ;
1029
1044
}
1030
1045
else
1031
1046
{
1032
1047
ret.x = (float )vald.sw .l ;
1033
- ret.compFlags [ 0 ] = VALID ;
1048
+ ret.SetValidComp ( 0 , true ) ;
1034
1049
}
1035
1050
1036
1051
if (vald.w .h == 0 )
@@ -1040,17 +1055,17 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_BITWISE(u32 instr, u32 rdVal, u32 rsVa
1040
1055
else if (vald.w .h == vals.w .h )
1041
1056
{
1042
1057
ret.y = g_state.pgxp_gpr [rs (instr)].y ;
1043
- ret.compFlags [ 1 ] &= g_state.pgxp_gpr [rs (instr)].compFlags [ 1 ] ;
1058
+ ret.SetValidComp ( 1 , g_state.pgxp_gpr [rs (instr)].GetValidComp ( 1 )) ;
1044
1059
}
1045
1060
else if (vald.w .h == valt.w .h )
1046
1061
{
1047
1062
ret.y = g_state.pgxp_gpr [rt (instr)].y ;
1048
- ret.compFlags [ 1 ] &= g_state.pgxp_gpr [rt (instr)].compFlags [ 1 ] ;
1063
+ ret.SetValidComp ( 1 , g_state.pgxp_gpr [rt (instr)].GetValidComp ( 1 )) ;
1049
1064
}
1050
1065
else
1051
1066
{
1052
1067
ret.y = (float )vald.sw .h ;
1053
- ret.compFlags [ 1 ] = VALID ;
1068
+ ret.SetValidComp ( 1 , true ) ;
1054
1069
}
1055
1070
1056
1071
// iCB Hack: Force validity if even one half is valid
@@ -1059,20 +1074,20 @@ ALWAYS_INLINE_RELEASE void CPU::PGXP::CPU_BITWISE(u32 instr, u32 rdVal, u32 rsVa
1059
1074
// /iCB Hack
1060
1075
1061
1076
// Get a valid W
1062
- if (( g_state.pgxp_gpr [rs (instr)].flags & VALID_2) == VALID_2 )
1077
+ if (g_state.pgxp_gpr [rs (instr)].GetValidComp ( 2 ) )
1063
1078
{
1064
1079
ret.z = g_state.pgxp_gpr [rs (instr)].z ;
1065
- ret.compFlags [ 2 ] = g_state. pgxp_gpr [ rs (instr)]. compFlags [ 2 ] ;
1080
+ ret.SetValidComp ( 2 , true ) ;
1066
1081
}
1067
- else if (( g_state.pgxp_gpr [rt (instr)].flags & VALID_2) == VALID_2 )
1082
+ else if (g_state.pgxp_gpr [rt (instr)].GetValidComp ( 2 ) )
1068
1083
{
1069
1084
ret.z = g_state.pgxp_gpr [rt (instr)].z ;
1070
- ret.compFlags [ 2 ] = g_state. pgxp_gpr [ rt (instr)]. compFlags [ 2 ] ;
1085
+ ret.SetValidComp ( 2 , true ) ;
1071
1086
}
1072
1087
else
1073
1088
{
1074
1089
ret.z = 0 .0f ;
1075
- ret.compFlags [ 2 ] = 0 ;
1090
+ ret.SetValidComp ( 2 , false ) ;
1076
1091
}
1077
1092
1078
1093
ret.value = rdVal;
@@ -1134,7 +1149,7 @@ void CPU::PGXP::CPU_SLT(u32 instr, u32 rsVal, u32 rtVal)
1134
1149
1135
1150
ret = g_state.pgxp_gpr [rs (instr)];
1136
1151
ret.y = 0 .f ;
1137
- ret.compFlags [ 1 ] = VALID ;
1152
+ ret.SetValidComp ( 1 , true ) ;
1138
1153
1139
1154
ret.x = (g_state.pgxp_gpr [rs (instr)].y < g_state.pgxp_gpr [rt (instr)].y ) ? 1 .f :
1140
1155
(f16Unsign (g_state.pgxp_gpr [rs (instr)].x ) < f16Unsign (g_state.pgxp_gpr [rt (instr)].x )) ? 1 .f :
@@ -1163,7 +1178,7 @@ void CPU::PGXP::CPU_SLTU(u32 instr, u32 rsVal, u32 rtVal)
1163
1178
1164
1179
ret = g_state.pgxp_gpr [rs (instr)];
1165
1180
ret.y = 0 .f ;
1166
- ret.compFlags [ 1 ] = VALID ;
1181
+ ret.SetValidComp ( 1 , true ) ;
1167
1182
1168
1183
ret.x = (f16Unsign (g_state.pgxp_gpr [rs (instr)].y ) < f16Unsign (g_state.pgxp_gpr [rt (instr)].y )) ? 1 .f :
1169
1184
(f16Unsign (g_state.pgxp_gpr [rs (instr)].x ) < f16Unsign (g_state.pgxp_gpr [rt (instr)].x )) ? 1 .f :
@@ -1193,10 +1208,11 @@ void CPU::PGXP::CPU_MULT(u32 instr, u32 rsVal, u32 rtVal)
1193
1208
MakeValid (&g_state.pgxp_gpr [rt (instr)], rtVal);
1194
1209
}
1195
1210
1196
- g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)] = g_state.pgxp_gpr [static_cast <u8 >(Reg::hi)] = g_state.pgxp_gpr [rs (instr)];
1211
+ g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)] = g_state.pgxp_gpr [rs (instr)];
1212
+ CopyZIfMissing (g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)], g_state.pgxp_gpr [rs (instr)]);
1197
1213
1198
- g_state. pgxp_gpr [ static_cast < u8 >(Reg::lo)]. halfFlags [ 0 ] = g_state. pgxp_gpr [ static_cast < u8 >(Reg::hi)]. halfFlags [ 0 ] =
1199
- ( g_state.pgxp_gpr [rs (instr)]. halfFlags [ 0 ] & g_state.pgxp_gpr [rt (instr)]. halfFlags [ 0 ]) ;
1214
+ // Z/valid is the same
1215
+ g_state.pgxp_gpr [static_cast < u8 >(Reg::hi)] = g_state.pgxp_gpr [static_cast < u8 >(Reg::lo)] ;
1200
1216
1201
1217
double xx, xy, yx, yy;
1202
1218
double lx = 0 , ly = 0 , hx = 0 , hy = 0 ;
@@ -1245,10 +1261,11 @@ void CPU::PGXP::CPU_MULTU(u32 instr, u32 rsVal, u32 rtVal)
1245
1261
MakeValid (&g_state.pgxp_gpr [rt (instr)], rtVal);
1246
1262
}
1247
1263
1248
- g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)] = g_state.pgxp_gpr [static_cast <u8 >(Reg::hi)] = g_state.pgxp_gpr [rs (instr)];
1264
+ g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)] = g_state.pgxp_gpr [rs (instr)];
1265
+ CopyZIfMissing (g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)], g_state.pgxp_gpr [rs (instr)]);
1249
1266
1250
- g_state. pgxp_gpr [ static_cast < u8 >(Reg::lo)]. halfFlags [ 0 ] = g_state. pgxp_gpr [ static_cast < u8 >(Reg::hi)]. halfFlags [ 0 ] =
1251
- ( g_state.pgxp_gpr [rs (instr)]. halfFlags [ 0 ] & g_state.pgxp_gpr [rt (instr)]. halfFlags [ 0 ]) ;
1267
+ // Z/valid is the same
1268
+ g_state.pgxp_gpr [static_cast < u8 >(Reg::hi)] = g_state.pgxp_gpr [static_cast < u8 >(Reg::lo)] ;
1252
1269
1253
1270
double xx, xy, yx, yy;
1254
1271
double lx = 0 , ly = 0 , hx = 0 , hy = 0 ;
@@ -1298,10 +1315,11 @@ void CPU::PGXP::CPU_DIV(u32 instr, u32 rsVal, u32 rtVal)
1298
1315
MakeValid (&g_state.pgxp_gpr [rt (instr)], rtVal);
1299
1316
}
1300
1317
1301
- g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)] = g_state.pgxp_gpr [static_cast <u8 >(Reg::hi)] = g_state.pgxp_gpr [rs (instr)];
1318
+ g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)] = g_state.pgxp_gpr [rs (instr)];
1319
+ CopyZIfMissing (g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)], g_state.pgxp_gpr [rs (instr)]);
1302
1320
1303
- g_state. pgxp_gpr [ static_cast < u8 >(Reg::lo)]. halfFlags [ 0 ] = g_state. pgxp_gpr [ static_cast < u8 >(Reg::hi)]. halfFlags [ 0 ] =
1304
- ( g_state.pgxp_gpr [rs (instr)]. halfFlags [ 0 ] & g_state.pgxp_gpr [rt (instr)]. halfFlags [ 0 ]) ;
1321
+ // Z/valid is the same
1322
+ g_state.pgxp_gpr [static_cast < u8 >(Reg::hi)] = g_state.pgxp_gpr [static_cast < u8 >(Reg::lo)] ;
1305
1323
1306
1324
double vs = f16Unsign (g_state.pgxp_gpr [rs (instr)].x ) + (g_state.pgxp_gpr [rs (instr)].y ) * (double )(1 << 16 );
1307
1325
double vt = f16Unsign (g_state.pgxp_gpr [rt (instr)].x ) + (g_state.pgxp_gpr [rt (instr)].y ) * (double )(1 << 16 );
@@ -1354,10 +1372,11 @@ void CPU::PGXP::CPU_DIVU(u32 instr, u32 rsVal, u32 rtVal)
1354
1372
MakeValid (&g_state.pgxp_gpr [rt (instr)], rtVal);
1355
1373
}
1356
1374
1357
- g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)] = g_state.pgxp_gpr [static_cast <u8 >(Reg::hi)] = g_state.pgxp_gpr [rs (instr)];
1375
+ g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)] = g_state.pgxp_gpr [rs (instr)];
1376
+ CopyZIfMissing (g_state.pgxp_gpr [static_cast <u8 >(Reg::lo)], g_state.pgxp_gpr [rs (instr)]);
1358
1377
1359
- g_state. pgxp_gpr [ static_cast < u8 >(Reg::lo)]. halfFlags [ 0 ] = g_state. pgxp_gpr [ static_cast < u8 >(Reg::hi)]. halfFlags [ 0 ] =
1360
- ( g_state.pgxp_gpr [rs (instr)]. halfFlags [ 0 ] & g_state.pgxp_gpr [rt (instr)]. halfFlags [ 0 ]) ;
1378
+ // Z/valid is the same
1379
+ g_state.pgxp_gpr [static_cast < u8 >(Reg::hi)] = g_state.pgxp_gpr [static_cast < u8 >(Reg::lo)] ;
1361
1380
1362
1381
double vs = f16Unsign (g_state.pgxp_gpr [rs (instr)].x ) + f16Unsign (g_state.pgxp_gpr [rs (instr)].y ) * (double )(1 << 16 );
1363
1382
double vt = f16Unsign (g_state.pgxp_gpr [rt (instr)].x ) + f16Unsign (g_state.pgxp_gpr [rt (instr)].y ) * (double )(1 << 16 );
0 commit comments