Revision 24c7b0e3

b/cpu-exec.c
461 461
                    }
462 462
#elif defined(TARGET_MIPS)
463 463
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
464
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
464 465
                        (env->CP0_Status & (1 << CP0St_IE)) &&
465
                        (env->CP0_Status & env->CP0_Cause & 0x0000FF00) &&
466
                        !(env->hflags & MIPS_HFLAG_EXL) &&
467
                        !(env->hflags & MIPS_HFLAG_ERL) &&
466
                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
467
                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
468 468
                        !(env->hflags & MIPS_HFLAG_DM)) {
469 469
                        /* Raise it */
470 470
                        env->exception_index = EXCP_EXT_INTERRUPT;
b/dyngen-exec.h
80 80

  
81 81
typedef struct FILE FILE;
82 82
extern int fprintf(FILE *, const char *, ...);
83
extern int fputs(const char *, FILE *);
83 84
extern int printf(const char *, ...);
84 85
#undef NULL
85 86
#define NULL 0
b/hw/mips_int.c
5 5
   IRQ may change */
6 6
void cpu_mips_update_irq(CPUState *env)
7 7
{
8
    if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
9
        (env->CP0_Status & (1 << CP0St_IE)) &&
10
        !(env->hflags & MIPS_HFLAG_EXL) &&
11
	!(env->hflags & MIPS_HFLAG_ERL) &&
12
	!(env->hflags & MIPS_HFLAG_DM)) {
13
        if (! (env->interrupt_request & CPU_INTERRUPT_HARD)) {
8
    if ((env->CP0_Status & (1 << CP0St_IE)) &&
9
        !(env->CP0_Status & (1 << CP0St_EXL)) &&
10
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
11
        !(env->hflags & MIPS_HFLAG_DM)) {
12
        if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
13
            !(env->interrupt_request & CPU_INTERRUPT_HARD)) {
14 14
            cpu_interrupt(env, CPU_INTERRUPT_HARD);
15 15
	}
16
    } else {
16
    } else
17 17
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
18
    }
19 18
}
20 19

  
21 20
void cpu_mips_irq_request(void *opaque, int irq, int level)
b/target-mips/cpu.h
248 248
#define MIPS_HFLAG_TMASK  0x007F
249 249
#define MIPS_HFLAG_MODE   0x001F /* execution modes                    */
250 250
#define MIPS_HFLAG_UM     0x0001 /* user mode                          */
251
#define MIPS_HFLAG_ERL    0x0002 /* Error mode                         */
252
#define MIPS_HFLAG_EXL    0x0004 /* Exception mode                     */
253 251
#define MIPS_HFLAG_DM     0x0008 /* Debug mode                         */
254 252
#define MIPS_HFLAG_SM     0x0010 /* Supervisor mode                    */
255 253
#define MIPS_HFLAG_RE     0x0040 /* Reversed endianness                */
b/target-mips/helper.c
90 90
    if (user_mode && address > 0x7FFFFFFFUL)
91 91
        return TLBRET_BADADDR;
92 92
    if (address < (int32_t)0x80000000UL) {
93
        if (!(env->hflags & MIPS_HFLAG_ERL)) {
93
        if (!(env->CP0_Status & (1 << CP0St_ERL))) {
94 94
#ifdef MIPS_USES_R4K_TLB
95 95
            ret = map_address(env, physical, prot, address, rw, access_type);
96 96
#else
......
289 289
        goto set_DEPC;
290 290
    case EXCP_DDBL:
291 291
        env->CP0_Debug |= 1 << CP0DB_DDBL;
292
        goto set_DEPC;
293 292
    set_DEPC:
294 293
        if (env->hflags & MIPS_HFLAG_BMASK) {
295 294
            /* If the exception was raised from a delay slot,
296 295
               come back to the jump.  */
297 296
            env->CP0_DEPC = env->PC - 4;
298
            if (!(env->hflags & MIPS_HFLAG_EXL))
299
                env->CP0_Cause |= (1 << CP0Ca_BD);
300 297
            env->hflags &= ~MIPS_HFLAG_BMASK;
301 298
        } else {
302 299
            env->CP0_DEPC = env->PC;
303
            env->CP0_Cause &= ~(1 << CP0Ca_BD);
304 300
        }
305 301
    enter_debug_mode:
306 302
        env->hflags |= MIPS_HFLAG_DM;
303
        env->hflags &= ~MIPS_HFLAG_UM;
307 304
        /* EJTAG probe trap enable is not implemented... */
308 305
        env->PC = (int32_t)0xBFC00480;
309 306
        break;
......
311 308
        cpu_reset(env);
312 309
        break;
313 310
    case EXCP_SRESET:
314
        env->CP0_Status = (1 << CP0St_SR);
311
        env->CP0_Status |= (1 << CP0St_SR);
315 312
        env->CP0_WatchLo = 0;
316 313
        goto set_error_EPC;
317 314
    case EXCP_NMI:
318
        env->CP0_Status = (1 << CP0St_NMI);
315
        env->CP0_Status |= (1 << CP0St_NMI);
319 316
    set_error_EPC:
320 317
        if (env->hflags & MIPS_HFLAG_BMASK) {
321 318
            /* If the exception was raised from a delay slot,
322 319
               come back to the jump.  */
323 320
            env->CP0_ErrorEPC = env->PC - 4;
324
            if (!(env->hflags & MIPS_HFLAG_EXL))
325
                env->CP0_Cause |= (1 << CP0Ca_BD);
326 321
            env->hflags &= ~MIPS_HFLAG_BMASK;
327 322
        } else {
328 323
            env->CP0_ErrorEPC = env->PC;
329
            env->CP0_Cause &= ~(1 << CP0Ca_BD);
330 324
        }
331
        env->hflags |= MIPS_HFLAG_ERL;
332
	env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
325
        env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
326
        env->hflags &= ~MIPS_HFLAG_UM;
333 327
        env->PC = (int32_t)0xBFC00000;
334 328
        break;
335 329
    case EXCP_MCHECK:
......
350 344
        goto set_EPC;
351 345
    case EXCP_TLBL:
352 346
        cause = 2;
353
        if (env->error_code == 1 && !(env->hflags & MIPS_HFLAG_EXL))
347
        if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL)))
354 348
            offset = 0x000;
355 349
        goto set_EPC;
356 350
    case EXCP_IBE:
......
384 378
        goto set_EPC;
385 379
    case EXCP_TLBS:
386 380
        cause = 3;
387
        if (env->error_code == 1 && !(env->hflags & MIPS_HFLAG_EXL))
381
        if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL)))
388 382
            offset = 0x000;
389
        goto set_EPC;
390 383
    set_EPC:
391
        if (env->hflags & MIPS_HFLAG_BMASK) {
392
            /* If the exception was raised from a delay slot,
393
               come back to the jump.  */
394
            env->CP0_EPC = env->PC - 4;
395
            if (!(env->hflags & MIPS_HFLAG_EXL))
384
        if (!(env->CP0_Status & (1 << CP0St_EXL))) {
385
            if (env->hflags & MIPS_HFLAG_BMASK) {
386
                /* If the exception was raised from a delay slot,
387
                   come back to the jump.  */
388
                env->CP0_EPC = env->PC - 4;
396 389
                env->CP0_Cause |= (1 << CP0Ca_BD);
397
            env->hflags &= ~MIPS_HFLAG_BMASK;
390
                env->hflags &= ~MIPS_HFLAG_BMASK;
391
            } else {
392
                env->CP0_EPC = env->PC;
393
                env->CP0_Cause &= ~(1 << CP0Ca_BD);
394
            }
398 395
        } else {
399
            env->CP0_EPC = env->PC;
400
            env->CP0_Cause &= ~(1 << CP0Ca_BD);
396
            env->CP0_Status |= (1 << CP0St_EXL);
397
            env->hflags &= ~MIPS_HFLAG_UM;
401 398
        }
402 399
        if (env->CP0_Status & (1 << CP0St_BEV)) {
403 400
            env->PC = (int32_t)0xBFC00200;
404 401
        } else {
405 402
            env->PC = (int32_t)0x80000000;
406 403
        }
407
        env->hflags |= MIPS_HFLAG_EXL;
408
        env->CP0_Status |= (1 << CP0St_EXL);
409 404
        env->PC += offset;
410 405
        env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2);
411 406
        break;
b/target-mips/op.c
1105 1105
void op_mfc0_status (void)
1106 1106
{
1107 1107
    T0 = env->CP0_Status;
1108
    if (env->hflags & MIPS_HFLAG_UM)
1109
        T0 |= (1 << CP0St_UM);
1110
    if (env->hflags & MIPS_HFLAG_ERL)
1111
        T0 |= (1 << CP0St_ERL);
1112
    if (env->hflags & MIPS_HFLAG_EXL)
1113
        T0 |= (1 << CP0St_EXL);
1114 1108
    RETURN();
1115 1109
}
1116 1110

  
......
1365 1359
{
1366 1360
    uint32_t val, old;
1367 1361

  
1368
    val = (int32_t)T0 & 0xFA78FF01;
1362
    /* No 64bit FPU, no reverse endianness, no MDMX/DSP, no 64bit ops,
1363
       no 64bit addressing implemented. */
1364
    val = (int32_t)T0 & 0xF878FF17;
1369 1365
    old = env->CP0_Status;
1370
    if (T0 & (1 << CP0St_UM))
1371
        env->hflags |= MIPS_HFLAG_UM;
1372
    else
1373
        env->hflags &= ~MIPS_HFLAG_UM;
1374
    if (T0 & (1 << CP0St_ERL))
1375
        env->hflags |= MIPS_HFLAG_ERL;
1376
    else
1377
        env->hflags &= ~MIPS_HFLAG_ERL;
1378
    if (T0 & (1 << CP0St_EXL))
1379
        env->hflags |= MIPS_HFLAG_EXL;
1380
    else
1381
        env->hflags &= ~MIPS_HFLAG_EXL;
1382 1366
    env->CP0_Status = val;
1383 1367
    if (loglevel & CPU_LOG_TB_IN_ASM)
1384 1368
       CALL_FROM_TB2(do_mtc0_status_debug, old, val);
......
1662 1646
# define DEBUG_FPU_STATE() do { } while(0)
1663 1647
#endif
1664 1648

  
1649
void op_cp0_enabled(void)
1650
{
1651
    if (!(env->CP0_Status & (1 << CP0St_CU0)) &&
1652
	(env->hflags & MIPS_HFLAG_UM)) {
1653
        CALL_FROM_TB2(do_raise_exception_direct_err, EXCP_CpU, 0);
1654
    }
1655
    RETURN();
1656
}
1657

  
1665 1658
void op_cp1_enabled(void)
1666 1659
{
1667 1660
    if (!(env->CP0_Status & (1 << CP0St_CU1))) {
......
2091 2084
void op_eret (void)
2092 2085
{
2093 2086
    CALL_FROM_TB0(debug_eret);
2094
    if (env->hflags & MIPS_HFLAG_ERL) {
2087
    if (env->CP0_Status & (1 << CP0St_ERL)) {
2095 2088
        env->PC = env->CP0_ErrorEPC;
2096
        env->hflags &= ~MIPS_HFLAG_ERL;
2097
	env->CP0_Status &= ~(1 << CP0St_ERL);
2089
        env->CP0_Status &= ~(1 << CP0St_ERL);
2098 2090
    } else {
2099 2091
        env->PC = env->CP0_EPC;
2100
        env->hflags &= ~MIPS_HFLAG_EXL;
2101
	env->CP0_Status &= ~(1 << CP0St_EXL);
2092
        env->CP0_Status &= ~(1 << CP0St_EXL);
2102 2093
    }
2094
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2095
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
2096
        !(env->hflags & MIPS_HFLAG_DM) &&
2097
        (env->CP0_Status & (1 << CP0St_UM)))
2098
        env->hflags |= MIPS_HFLAG_UM;
2103 2099
    env->CP0_LLAddr = 1;
2104 2100
    RETURN();
2105 2101
}
......
2108 2104
{
2109 2105
    CALL_FROM_TB0(debug_eret);
2110 2106
    env->PC = env->CP0_DEPC;
2107
    env->hflags |= MIPS_HFLAG_DM;
2108
    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2109
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
2110
        !(env->hflags & MIPS_HFLAG_DM) &&
2111
        (env->CP0_Status & (1 << CP0St_UM)))
2112
        env->hflags |= MIPS_HFLAG_UM;
2113
    env->CP0_LLAddr = 1;
2111 2114
    RETURN();
2112 2115
}
2113 2116

  
b/target-mips/op_helper.c
509 509
void debug_eret (void)
510 510
{
511 511
    if (loglevel) {
512
        fprintf(logfile, "ERET: pc " TARGET_FMT_lx " EPC " TARGET_FMT_lx " ErrorEPC " TARGET_FMT_lx " (%d)\n",
513
                env->PC, env->CP0_EPC, env->CP0_ErrorEPC,
514
                env->hflags & MIPS_HFLAG_ERL ? 1 : 0);
512
        fprintf(logfile, "ERET: pc " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
513
                env->PC, env->CP0_EPC);
514
        if (env->CP0_Status & (1 << CP0St_ERL))
515
            fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
516
        fputs("\n", logfile);
515 517
    }
516 518
}
517 519

  
b/target-mips/translate.c
4022 4022
{
4023 4023
    const char *opn = "unk";
4024 4024

  
4025
    if ((!ctx->CP0_Status & (1 << CP0St_CU0) &&
4026
          (ctx->hflags & MIPS_HFLAG_UM)) &&
4027
        !(ctx->hflags & MIPS_HFLAG_ERL) &&
4028
        !(ctx->hflags & MIPS_HFLAG_EXL)) {
4029
        if (loglevel & CPU_LOG_TB_IN_ASM) {
4030
            fprintf(logfile, "CP0 is not usable\n");
4031
        }
4032
        generate_exception (ctx, EXCP_CpU);
4033
        return;
4034
    }
4035

  
4036 4025
    switch (opc) {
4037 4026
    case OPC_MFC0:
4038 4027
        if (rt == 0) {
......
4809 4798
            gen_trap(ctx, op1, rs, -1, imm);
4810 4799
            break;
4811 4800
        case OPC_SYNCI:
4812
           /* treat as noop */
4801
            /* treat as noop */
4813 4802
            break;
4814 4803
        default:            /* Invalid */
4815 4804
            MIPS_INVAL("REGIMM");
......
4818 4807
        }
4819 4808
        break;
4820 4809
    case OPC_CP0:
4810
        gen_op_cp0_enabled();
4821 4811
        op1 = MASK_CP0(ctx->opcode);
4822 4812
        switch (op1) {
4823 4813
        case OPC_MFC0:
......
5258 5248
    }
5259 5249

  
5260 5250
    c0_status = env->CP0_Status;
5261
    if (env->hflags & MIPS_HFLAG_UM)
5262
        c0_status |= (1 << CP0St_UM);
5263
    if (env->hflags & MIPS_HFLAG_ERL)
5264
        c0_status |= (1 << CP0St_ERL);
5265
    if (env->hflags & MIPS_HFLAG_EXL)
5266
        c0_status |= (1 << CP0St_EXL);
5267 5251

  
5268 5252
    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TARGET_FMT_lx "\n",
5269 5253
                c0_status, env->CP0_Cause, env->CP0_EPC);
......
5304 5288
    } else {
5305 5289
        env->CP0_ErrorEPC = env->PC;
5306 5290
    }
5291
    env->hflags = 0;
5307 5292
    env->PC = (int32_t)0xBFC00000;
5308 5293
#if defined (MIPS_USES_R4K_TLB)
5309 5294
    env->CP0_Random = MIPS_TLB_NB - 1;
......
5314 5299
    env->CP0_EBase = 0x80000000;
5315 5300
    env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
5316 5301
    env->CP0_WatchLo = 0;
5317
    env->hflags = MIPS_HFLAG_ERL;
5318 5302
    /* Count register increments in debug mode, EJTAG version 1 */
5319 5303
    env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
5320 5304
#endif

Also available in: Unified diff