~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to cpu-exec.c

Tags: upstream-0.9.0+20070816
ImportĀ upstreamĀ versionĀ 0.9.0+20070816

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
//#define DEBUG_EXEC
41
41
//#define DEBUG_SIGNAL
42
42
 
43
 
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K)
44
 
/* XXX: unify with i386 target */
45
43
void cpu_loop_exit(void)
46
44
{
 
45
    /* NOTE: the register at this point must be saved by hand because
 
46
       longjmp restore them */
 
47
    regs_to_env();
47
48
    longjmp(env->jmp_env, 1);
48
49
}
49
 
#endif
 
50
 
50
51
#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
51
52
#define reg_T2
52
53
#endif
195
196
    cs_base = 0;
196
197
    pc = env->PC;
197
198
#elif defined(TARGET_M68K)
198
 
    flags = env->fpcr & M68K_FPCR_PREC;
 
199
    flags = (env->fpcr & M68K_FPCR_PREC)  /* Bit  6 */
 
200
            | (env->sr & SR_S)            /* Bit  13 */
 
201
            | ((env->macsr >> 4) & 0xf);  /* Bits 0-3 */
199
202
    cs_base = 0;
200
203
    pc = env->pc;
201
204
#elif defined(TARGET_SH4)
202
205
    flags = env->sr & (SR_MD | SR_RB);
203
206
    cs_base = 0;         /* XXXXX */
204
207
    pc = env->pc;
 
208
#elif defined(TARGET_ALPHA)
 
209
    flags = env->ps;
 
210
    cs_base = 0;
 
211
    pc = env->pc;
205
212
#else
206
213
#error unsupported CPU
207
214
#endif
242
249
    TranslationBlock *tb;
243
250
    uint8_t *tc_ptr;
244
251
 
245
 
#if defined(TARGET_I386)
246
 
    /* handle exit of HALTED state */
247
 
    if (env1->hflags & HF_HALTED_MASK) {
248
 
        /* disable halt condition */
249
 
        if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
250
 
            (env1->eflags & IF_MASK)) {
251
 
            env1->hflags &= ~HF_HALTED_MASK;
252
 
        } else {
253
 
            return EXCP_HALTED;
254
 
        }
255
 
    }
256
 
#elif defined(TARGET_PPC)
257
 
    if (env1->halted) {
258
 
        if (env1->msr[MSR_EE] && 
259
 
            (env1->interrupt_request & 
260
 
             (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) {
261
 
            env1->halted = 0;
262
 
        } else {
263
 
            return EXCP_HALTED;
264
 
        }
265
 
    }
266
 
#elif defined(TARGET_SPARC)
267
 
    if (env1->halted) {
268
 
        if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
269
 
            (env1->psret != 0)) {
270
 
            env1->halted = 0;
271
 
        } else {
272
 
            return EXCP_HALTED;
273
 
        }
274
 
    }
275
 
#elif defined(TARGET_ARM)
276
 
    if (env1->halted) {
277
 
        /* An interrupt wakes the CPU even if the I and F CPSR bits are
278
 
           set.  */
279
 
        if (env1->interrupt_request
280
 
            & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) {
281
 
            env1->halted = 0;
282
 
        } else {
283
 
            return EXCP_HALTED;
284
 
        }
285
 
    }
286
 
#elif defined(TARGET_MIPS)
287
 
    if (env1->halted) {
288
 
        if (env1->interrupt_request &
289
 
            (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) {
290
 
            env1->halted = 0;
291
 
        } else {
292
 
            return EXCP_HALTED;
293
 
        }
294
 
    }
295
 
#endif
 
252
    if (cpu_halted(env1) == EXCP_HALTED)
 
253
        return EXCP_HALTED;
296
254
 
297
255
    cpu_single_env = env1; 
298
256
 
305
263
    asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
306
264
#endif
307
265
 
308
 
#if defined(TARGET_I386)
309
266
    env_to_regs();
 
267
#if defined(TARGET_I386)
310
268
    /* put eflags in CPU temporary format */
311
269
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
312
270
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
313
271
    CC_OP = CC_OP_EFLAGS;
314
272
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
315
 
#elif defined(TARGET_ARM)
316
273
#elif defined(TARGET_SPARC)
317
274
#if defined(reg_REGWPTR)
318
275
    saved_regwptr = REGWPTR;
319
276
#endif
320
 
#elif defined(TARGET_PPC)
321
277
#elif defined(TARGET_M68K)
322
278
    env->cc_op = CC_OP_FLAGS;
323
279
    env->cc_dest = env->sr & 0xf;
324
280
    env->cc_x = (env->sr >> 4) & 1;
 
281
#elif defined(TARGET_ALPHA)
 
282
#elif defined(TARGET_ARM)
 
283
#elif defined(TARGET_PPC)
325
284
#elif defined(TARGET_MIPS)
326
285
#elif defined(TARGET_SH4)
327
286
    /* XXXXX */
361
320
                                 env->exception_is_int, 
362
321
                                 env->error_code, 
363
322
                                 env->exception_next_eip, 0);
 
323
                    /* successfully delivered */
 
324
                    env->old_exception = -1;
364
325
#elif defined(TARGET_PPC)
365
326
                    do_interrupt(env);
366
327
#elif defined(TARGET_MIPS)
371
332
                    do_interrupt(env);
372
333
#elif defined(TARGET_SH4)
373
334
                    do_interrupt(env);
 
335
#elif defined(TARGET_ALPHA)
 
336
                    do_interrupt(env);
 
337
#elif defined(TARGET_M68K)
 
338
                    do_interrupt(0);
374
339
#endif
375
340
                }
376
341
                env->exception_index = -1;
409
374
#endif      
410
375
                interrupt_request = env->interrupt_request;
411
376
                if (__builtin_expect(interrupt_request, 0)) {
 
377
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
 
378
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
 
379
                        env->exception_index = EXCP_DEBUG;
 
380
                        cpu_loop_exit();
 
381
                    }
 
382
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
 
383
    defined(TARGET_PPC) || defined(TARGET_ALPHA)
 
384
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
 
385
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
 
386
                        env->halted = 1;
 
387
                        env->exception_index = EXCP_HLT;
 
388
                        cpu_loop_exit();
 
389
                    }
 
390
#endif
412
391
#if defined(TARGET_I386)
413
392
                    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
414
393
                        !(env->hflags & HF_SMM_MASK)) {
443
422
                        cpu_ppc_reset(env);
444
423
                    }
445
424
#endif
446
 
                    if (msr_ee != 0) {
447
 
                        if ((interrupt_request & CPU_INTERRUPT_HARD)) {
448
 
                            /* Raise it */
449
 
                            env->exception_index = EXCP_EXTERNAL;
450
 
                            env->error_code = 0;
451
 
                            do_interrupt(env);
 
425
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
 
426
                        ppc_hw_interrupt(env);
 
427
                        if (env->pending_interrupts == 0)
452
428
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
453
429
#if defined(__sparc__) && !defined(HOST_SOLARIS)
454
 
                            tmp_T0 = 0;
455
 
#else
456
 
                            T0 = 0;
457
 
#endif
458
 
                        } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
459
 
                            /* Raise it */
460
 
                            env->exception_index = EXCP_DECR;
461
 
                            env->error_code = 0;
462
 
                            do_interrupt(env);
463
 
                            env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
464
 
#if defined(__sparc__) && !defined(HOST_SOLARIS)
465
 
                            tmp_T0 = 0;
466
 
#else
467
 
                            T0 = 0;
468
 
#endif
469
 
                        }
 
430
                        tmp_T0 = 0;
 
431
#else
 
432
                        T0 = 0;
 
433
#endif
470
434
                    }
471
435
#elif defined(TARGET_MIPS)
472
436
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
 
437
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
473
438
                        (env->CP0_Status & (1 << CP0St_IE)) &&
474
 
                        (env->CP0_Status & env->CP0_Cause & 0x0000FF00) &&
475
 
                        !(env->hflags & MIPS_HFLAG_EXL) &&
476
 
                        !(env->hflags & MIPS_HFLAG_ERL) &&
 
439
                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
 
440
                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
477
441
                        !(env->hflags & MIPS_HFLAG_DM)) {
478
442
                        /* Raise it */
479
443
                        env->exception_index = EXCP_EXT_INTERRUPT;
497
461
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
498
462
                            do_interrupt(env->interrupt_index);
499
463
                            env->interrupt_index = 0;
 
464
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
 
465
                            cpu_check_irqs(env);
 
466
#endif
500
467
#if defined(__sparc__) && !defined(HOST_SOLARIS)
501
468
                            tmp_T0 = 0;
502
469
#else
506
473
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
507
474
                        //do_interrupt(0, 0, 0, 0, 0);
508
475
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
509
 
                    } else if (interrupt_request & CPU_INTERRUPT_HALT) {
510
 
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
511
 
                        env->halted = 1;
512
 
                        env->exception_index = EXCP_HLT;
513
 
                        cpu_loop_exit();
514
 
                    }
 
476
                    }
515
477
#elif defined(TARGET_ARM)
516
478
                    if (interrupt_request & CPU_INTERRUPT_FIQ
517
479
                        && !(env->uncached_cpsr & CPSR_F)) {
525
487
                    }
526
488
#elif defined(TARGET_SH4)
527
489
                    /* XXXXX */
 
490
#elif defined(TARGET_ALPHA)
 
491
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
 
492
                        do_interrupt(env);
 
493
                    }
 
494
#elif defined(TARGET_M68K)
 
495
                    if (interrupt_request & CPU_INTERRUPT_HARD
 
496
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
 
497
                            < env->pending_level) {
 
498
                        /* Real hardware gets the interrupt vector via an
 
499
                           IACK cycle at this point.  Current emulated
 
500
                           hardware doesn't rely on this, so we
 
501
                           provide/save the vector when the interrupt is
 
502
                           first signalled.  */
 
503
                        env->exception_index = env->pending_vector;
 
504
                        do_interrupt(1);
 
505
                    }
528
506
#endif
529
507
                   /* Don't use the cached interupt_request value,
530
508
                      do_interrupt may have updated the EXITTB flag. */
546
524
                }
547
525
#ifdef DEBUG_EXEC
548
526
                if ((loglevel & CPU_LOG_TB_CPU)) {
549
 
#if defined(TARGET_I386)
550
527
                    /* restore flags in standard format */
551
 
#ifdef reg_EAX
552
 
                    env->regs[R_EAX] = EAX;
553
 
#endif
554
 
#ifdef reg_EBX
555
 
                    env->regs[R_EBX] = EBX;
556
 
#endif
557
 
#ifdef reg_ECX
558
 
                    env->regs[R_ECX] = ECX;
559
 
#endif
560
 
#ifdef reg_EDX
561
 
                    env->regs[R_EDX] = EDX;
562
 
#endif
563
 
#ifdef reg_ESI
564
 
                    env->regs[R_ESI] = ESI;
565
 
#endif
566
 
#ifdef reg_EDI
567
 
                    env->regs[R_EDI] = EDI;
568
 
#endif
569
 
#ifdef reg_EBP
570
 
                    env->regs[R_EBP] = EBP;
571
 
#endif
572
 
#ifdef reg_ESP
573
 
                    env->regs[R_ESP] = ESP;
574
 
#endif
 
528
                    regs_to_env();
 
529
#if defined(TARGET_I386)
575
530
                    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
576
531
                    cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
577
532
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
593
548
                    cpu_dump_state(env, logfile, fprintf, 0);
594
549
#elif defined(TARGET_SH4)
595
550
                    cpu_dump_state(env, logfile, fprintf, 0);
 
551
#elif defined(TARGET_ALPHA)
 
552
                    cpu_dump_state(env, logfile, fprintf, 0);
596
553
#else
597
554
#error unsupported target CPU 
598
555
#endif
643
600
                                     : /* no outputs */
644
601
                                     : "r" (gen_func) 
645
602
                                     : "i0", "i1", "i2", "i3", "i4", "i5",
 
603
                                       "o0", "o1", "o2", "o3", "o4", "o5",
646
604
                                       "l0", "l1", "l2", "l3", "l4", "l5",
647
605
                                       "l6", "l7");
648
606
#elif defined(__arm__)
755
713
                    cpu_loop_exit();
756
714
                }
757
715
#endif
758
 
            }
 
716
            } /* for(;;) */
759
717
        } else {
760
718
            env_to_regs();
761
719
        }
784
742
              | env->cc_dest | (env->cc_x << 4);
785
743
#elif defined(TARGET_MIPS)
786
744
#elif defined(TARGET_SH4)
 
745
#elif defined(TARGET_ALPHA)
787
746
    /* XXXXX */
788
747
#else
789
748
#error unsupported target CPU
1111
1070
    }
1112
1071
    if (ret == 1) {
1113
1072
#if 0
1114
 
        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
1115
 
               env->nip, env->error_code, tb);
 
1073
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n", 
 
1074
               env->PC, env->error_code, tb);
1116
1075
#endif
1117
1076
    /* we restore the process signal mask as the sigreturn should
1118
1077
       do it (XXX: use sigsetjmp) */
1170
1129
    /* never comes here */
1171
1130
    return 1;
1172
1131
}
 
1132
 
 
1133
#elif defined (TARGET_ALPHA)
 
1134
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
 
1135
                                    int is_write, sigset_t *old_set,
 
1136
                                    void *puc)
 
1137
{
 
1138
    TranslationBlock *tb;
 
1139
    int ret;
 
1140
    
 
1141
    if (cpu_single_env)
 
1142
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
 
1143
#if defined(DEBUG_SIGNAL)
 
1144
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
 
1145
           pc, address, is_write, *(unsigned long *)old_set);
 
1146
#endif
 
1147
    /* XXX: locking issue */
 
1148
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
 
1149
        return 1;
 
1150
    }
 
1151
 
 
1152
    /* see if it is an MMU fault */
 
1153
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, 1, 0);
 
1154
    if (ret < 0)
 
1155
        return 0; /* not an MMU fault */
 
1156
    if (ret == 0)
 
1157
        return 1; /* the MMU fault was handled without causing real CPU fault */
 
1158
 
 
1159
    /* now we have a real cpu fault */
 
1160
    tb = tb_find_pc(pc);
 
1161
    if (tb) {
 
1162
        /* the PC is inside the translated code. It means that we have
 
1163
           a virtual CPU fault */
 
1164
        cpu_restore_state(tb, env, pc, puc);
 
1165
    }
 
1166
#if 0
 
1167
        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
 
1168
               env->nip, env->error_code, tb);
 
1169
#endif
 
1170
    /* we restore the process signal mask as the sigreturn should
 
1171
       do it (XXX: use sigsetjmp) */
 
1172
    sigprocmask(SIG_SETMASK, old_set, NULL);
 
1173
    cpu_loop_exit();
 
1174
    /* never comes here */
 
1175
    return 1;
 
1176
}
1173
1177
#else
1174
1178
#error unsupported target CPU
1175
1179
#endif
1474
1478
    /* XXX: compute is_write */
1475
1479
    is_write = 0;
1476
1480
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1477
 
                             is_write,
1478
 
                             &uc->uc_sigmask, puc);
 
1481
                             is_write, &uc->uc_sigmask, puc);
 
1482
}
 
1483
 
 
1484
#elif defined(__mips__)
 
1485
 
 
1486
int cpu_signal_handler(int host_signum, void *pinfo, 
 
1487
                       void *puc)
 
1488
{
 
1489
    siginfo_t *info = pinfo;
 
1490
    struct ucontext *uc = puc;
 
1491
    greg_t pc = uc->uc_mcontext.pc;
 
1492
    int is_write;
 
1493
    
 
1494
    /* XXX: compute is_write */
 
1495
    is_write = 0;
 
1496
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
 
1497
                             is_write, &uc->uc_sigmask, puc);
1479
1498
}
1480
1499
 
1481
1500
#else