@@ -959,14 +959,14 @@ target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel)
959
959
960
960
void helper_mtc0_index (CPUMIPSState * env , target_ulong arg1 )
961
961
{
962
- int num = 1 ;
963
- unsigned int tmp = env -> tlb -> nb_tlb ;
964
-
965
- do {
966
- tmp >>= 1 ;
967
- num <<= 1 ;
968
- } while ( tmp ) ;
969
- env -> CP0_Index = ( env -> CP0_Index & 0x80000000 ) | ( arg1 & ( num - 1 ));
962
+ uint32_t index_p = env -> CP0_Index & 0x80000000 ;
963
+ uint32_t tlb_index = arg1 & 0x7fffffff ;
964
+ if ( tlb_index < env -> tlb -> nb_tlb ) {
965
+ if ( env -> insn_flags & ISA_MIPS32R6 ) {
966
+ index_p |= arg1 & 0x80000000 ;
967
+ }
968
+ env -> CP0_Index = index_p | tlb_index ;
969
+ }
970
970
}
971
971
972
972
void helper_mtc0_mvpcontrol (CPUMIPSState * env , target_ulong arg1 )
@@ -1294,8 +1294,13 @@ void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
1294
1294
1295
1295
void helper_mtc0_pagemask (CPUMIPSState * env , target_ulong arg1 )
1296
1296
{
1297
- /* 1k pages not implemented */
1298
- env -> CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1 ));
1297
+ uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1 );
1298
+ if (!(env -> insn_flags & ISA_MIPS32R6 ) || (arg1 == ~0 ) ||
1299
+ (mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
1300
+ mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
1301
+ mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF )) {
1302
+ env -> CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1 ));
1303
+ }
1299
1304
}
1300
1305
1301
1306
void helper_mtc0_pagegrain (CPUMIPSState * env , target_ulong arg1 )
@@ -1309,7 +1314,13 @@ void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
1309
1314
1310
1315
void helper_mtc0_wired (CPUMIPSState * env , target_ulong arg1 )
1311
1316
{
1312
- env -> CP0_Wired = arg1 % env -> tlb -> nb_tlb ;
1317
+ if (env -> insn_flags & ISA_MIPS32R6 ) {
1318
+ if (arg1 < env -> tlb -> nb_tlb ) {
1319
+ env -> CP0_Wired = arg1 ;
1320
+ }
1321
+ } else {
1322
+ env -> CP0_Wired = arg1 % env -> tlb -> nb_tlb ;
1323
+ }
1313
1324
}
1314
1325
1315
1326
void helper_mtc0_srsconf0 (CPUMIPSState * env , target_ulong arg1 )
@@ -1368,11 +1379,21 @@ void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
1368
1379
}
1369
1380
1370
1381
/* 1k pages not implemented */
1371
- val = arg1 & mask ;
1372
1382
#if defined(TARGET_MIPS64 )
1373
- val &= env -> SEGMask ;
1383
+ if (env -> insn_flags & ISA_MIPS32R6 ) {
1384
+ int entryhi_r = extract64 (arg1 , 62 , 2 );
1385
+ int config0_at = extract32 (env -> CP0_Config0 , 13 , 2 );
1386
+ bool no_supervisor = (env -> CP0_Status_rw_bitmask & 0x8 ) == 0 ;
1387
+ if ((entryhi_r == 2 ) ||
1388
+ (entryhi_r == 1 && (no_supervisor || config0_at == 1 ))) {
1389
+ /* skip EntryHi.R field if new value is reserved */
1390
+ mask &= ~(0x3ull << 62 );
1391
+ }
1392
+ }
1393
+ mask &= env -> SEGMask ;
1374
1394
#endif
1375
1395
old = env -> CP0_EntryHi ;
1396
+ val = (arg1 & mask ) | (old & ~mask );
1376
1397
env -> CP0_EntryHi = val ;
1377
1398
if (env -> CP0_Config3 & (1 << CP0C3_MT )) {
1378
1399
sync_c0_entryhi (env , env -> current_tc );
@@ -1402,6 +1423,13 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
1402
1423
uint32_t val , old ;
1403
1424
uint32_t mask = env -> CP0_Status_rw_bitmask ;
1404
1425
1426
+ if (env -> insn_flags & ISA_MIPS32R6 ) {
1427
+ if (extract32 (env -> CP0_Status , CP0St_KSU , 2 ) == 0x3 ) {
1428
+ mask &= ~(3 << CP0St_KSU );
1429
+ }
1430
+ mask &= ~(0x00180000 & arg1 );
1431
+ }
1432
+
1405
1433
val = arg1 & mask ;
1406
1434
old = env -> CP0_Status ;
1407
1435
env -> CP0_Status = (env -> CP0_Status & ~mask ) | val ;
@@ -1457,6 +1485,9 @@ static void mtc0_cause(CPUMIPSState *cpu, target_ulong arg1)
1457
1485
if (cpu -> insn_flags & ISA_MIPS32R2 ) {
1458
1486
mask |= 1 << CP0Ca_DC ;
1459
1487
}
1488
+ if (cpu -> insn_flags & ISA_MIPS32R6 ) {
1489
+ mask &= ~((1 << CP0Ca_WP ) & arg1 );
1490
+ }
1460
1491
1461
1492
cpu -> CP0_Cause = (cpu -> CP0_Cause & ~mask ) | (arg1 & mask );
1462
1493
@@ -2391,8 +2422,9 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
2391
2422
}
2392
2423
break ;
2393
2424
case 25 :
2394
- if (arg1 & 0xffffff00 )
2425
+ if (( env -> insn_flags & ISA_MIPS32R6 ) || ( arg1 & 0xffffff00 )) {
2395
2426
return ;
2427
+ }
2396
2428
env -> active_fpu .fcr31 = (env -> active_fpu .fcr31 & 0x017fffff ) | ((arg1 & 0xfe ) << 24 ) |
2397
2429
((arg1 & 0x1 ) << 23 );
2398
2430
break ;
@@ -2408,9 +2440,13 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
2408
2440
((arg1 & 0x4 ) << 22 );
2409
2441
break ;
2410
2442
case 31 :
2411
- if (arg1 & 0x007c0000 )
2412
- return ;
2413
- env -> active_fpu .fcr31 = arg1 ;
2443
+ if (env -> insn_flags & ISA_MIPS32R6 ) {
2444
+ uint32_t mask = 0xfefc0000 ;
2445
+ env -> active_fpu .fcr31 = (arg1 & ~mask ) |
2446
+ (env -> active_fpu .fcr31 & mask );
2447
+ } else if (!(arg1 & 0x007c0000 )) {
2448
+ env -> active_fpu .fcr31 = arg1 ;
2449
+ }
2414
2450
break ;
2415
2451
default :
2416
2452
return ;
0 commit comments