cpu-exec.c 24.6 KB
Newer Older
B
bellard 已提交
1 2
/*
 *  i386 emulator main execution loop
3
 *
B
bellard 已提交
4
 *  Copyright (c) 2003-2005 Fabrice Bellard
B
bellard 已提交
5
 *
B
bellard 已提交
6 7 8 9
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
B
bellard 已提交
10
 *
B
bellard 已提交
11 12 13 14
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
B
bellard 已提交
15
 *
B
bellard 已提交
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
B
bellard 已提交
18
 */
B
bellard 已提交
19
#include "config.h"
B
Blue Swirl 已提交
20
#include "cpu.h"
B
log fix  
bellard 已提交
21
#include "disas.h"
22
#include "tcg.h"
J
Jan Kiszka 已提交
23
#include "qemu-barrier.h"
B
bellard 已提交
24

25 26
int tb_invalidated_flag;

27
//#define CONFIG_DEBUG_EXEC
B
bellard 已提交
28

29
bool qemu_cpu_has_work(CPUState *env)
30 31 32 33
{
    return cpu_has_work(env);
}

B
Blue Swirl 已提交
34
void cpu_loop_exit(CPUState *env)
B
bellard 已提交
35
{
B
Blue Swirl 已提交
36 37
    env->current_tb = NULL;
    longjmp(env->jmp_env, 1);
B
bellard 已提交
38
}
39

40 41 42
/* exit the current TB from a signal handler. The host registers are
   restored in a state compatible with the CPU emulator
 */
43
#if defined(CONFIG_SOFTMMU)
B
Blue Swirl 已提交
44
void cpu_resume_from_signal(CPUState *env, void *puc)
45 46 47 48 49 50 51
{
    /* XXX: restore cpu registers saved in host registers */

    env->exception_index = -1;
    longjmp(env->jmp_env, 1);
}
#endif
52

P
pbrook 已提交
53 54
/* Execute the code without caching the generated code. An interpreter
   could be used if available. */
B
Blue Swirl 已提交
55 56
static void cpu_exec_nocache(CPUState *env, int max_cycles,
                             TranslationBlock *orig_tb)
P
pbrook 已提交
57 58 59 60 61 62 63 64 65 66 67 68 69
{
    unsigned long next_tb;
    TranslationBlock *tb;

    /* Should never happen.
       We only end up here when an existing TB is too long.  */
    if (max_cycles > CF_COUNT_MASK)
        max_cycles = CF_COUNT_MASK;

    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
                     max_cycles);
    env->current_tb = tb;
    /* execute the generated code */
B
Blue Swirl 已提交
70
    next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
P
Paolo Bonzini 已提交
71
    env->current_tb = NULL;
P
pbrook 已提交
72 73 74 75

    if ((next_tb & 3) == 2) {
        /* Restore PC.  This may happen if async event occurs before
           the TB starts executing.  */
76
        cpu_pc_from_tb(env, tb);
P
pbrook 已提交
77 78 79 80 81
    }
    tb_phys_invalidate(tb, -1);
    tb_free(tb);
}

B
Blue Swirl 已提交
82 83
static TranslationBlock *tb_find_slow(CPUState *env,
                                      target_ulong pc,
84
                                      target_ulong cs_base,
85
                                      uint64_t flags)
86 87 88
{
    TranslationBlock *tb, **ptb1;
    unsigned int h;
P
Paul Brook 已提交
89 90
    tb_page_addr_t phys_pc, phys_page1, phys_page2;
    target_ulong virt_page2;
91

92
    tb_invalidated_flag = 0;
93

94
    /* find translated block using physical mappings */
P
Paul Brook 已提交
95
    phys_pc = get_page_addr_code(env, pc);
96 97 98 99 100 101 102 103
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
    phys_page2 = -1;
    h = tb_phys_hash_func(phys_pc);
    ptb1 = &tb_phys_hash[h];
    for(;;) {
        tb = *ptb1;
        if (!tb)
            goto not_found;
104
        if (tb->pc == pc &&
105
            tb->page_addr[0] == phys_page1 &&
106
            tb->cs_base == cs_base &&
107 108 109
            tb->flags == flags) {
            /* check next page if needed */
            if (tb->page_addr[1] != -1) {
110
                virt_page2 = (pc & TARGET_PAGE_MASK) +
111
                    TARGET_PAGE_SIZE;
P
Paul Brook 已提交
112
                phys_page2 = get_page_addr_code(env, virt_page2);
113 114 115 116 117 118 119 120 121
                if (tb->page_addr[1] == phys_page2)
                    goto found;
            } else {
                goto found;
            }
        }
        ptb1 = &tb->phys_hash_next;
    }
 not_found:
P
pbrook 已提交
122 123
   /* if no translated code available, then translate it now */
    tb = tb_gen_code(env, pc, cs_base, flags, 0);
124

125
 found:
126 127 128 129 130 131
    /* Move the last found TB to the head of the list */
    if (likely(*ptb1)) {
        *ptb1 = tb->phys_hash_next;
        tb->phys_hash_next = tb_phys_hash[h];
        tb_phys_hash[h] = tb;
    }
132 133 134 135 136
    /* we add the TB in the virtual pc hash table */
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
    return tb;
}

B
Blue Swirl 已提交
137
static inline TranslationBlock *tb_find_fast(CPUState *env)
138 139 140
{
    TranslationBlock *tb;
    target_ulong cs_base, pc;
141
    int flags;
142 143 144 145

    /* we record a subset of the CPU state. It will
       always be the same before a given translated block
       is executed. */
146
    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
B
bellard 已提交
147
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
148 149
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
                 tb->flags != flags)) {
B
Blue Swirl 已提交
150
        tb = tb_find_slow(env, pc, cs_base, flags);
151 152 153 154
    }
    return tb;
}

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
static CPUDebugExcpHandler *debug_excp_handler;

CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
{
    CPUDebugExcpHandler *old_handler = debug_excp_handler;

    debug_excp_handler = handler;
    return old_handler;
}

static void cpu_handle_debug_exception(CPUState *env)
{
    CPUWatchpoint *wp;

    if (!env->watchpoint_hit) {
        QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
            wp->flags &= ~BP_WATCHPOINT_HIT;
        }
    }
    if (debug_excp_handler) {
        debug_excp_handler(env);
    }
}

B
bellard 已提交
179 180
/* main execution loop */

181 182
volatile sig_atomic_t exit_request;

B
Blue Swirl 已提交
183
int cpu_exec(CPUState *env)
B
bellard 已提交
184
{
185 186
    int ret, interrupt_request;
    TranslationBlock *tb;
B
bellard 已提交
187
    uint8_t *tc_ptr;
P
pbrook 已提交
188
    unsigned long next_tb;
189

B
Blue Swirl 已提交
190 191
    if (env->halted) {
        if (!cpu_has_work(env)) {
192 193 194
            return EXCP_HALTED;
        }

B
Blue Swirl 已提交
195
        env->halted = 0;
196
    }
B
bellard 已提交
197

B
Blue Swirl 已提交
198
    cpu_single_env = env;
B
bellard 已提交
199

J
Jan Kiszka 已提交
200
    if (unlikely(exit_request)) {
201 202 203
        env->exit_request = 1;
    }

204
#if defined(TARGET_I386)
205 206 207 208 209
    /* put eflags in CPU temporary format */
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
    CC_OP = CC_OP_EFLAGS;
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
210
#elif defined(TARGET_SPARC)
P
pbrook 已提交
211 212 213 214
#elif defined(TARGET_M68K)
    env->cc_op = CC_OP_FLAGS;
    env->cc_dest = env->sr & 0xf;
    env->cc_x = (env->sr >> 4) & 1;
215 216
#elif defined(TARGET_ALPHA)
#elif defined(TARGET_ARM)
217
#elif defined(TARGET_UNICORE32)
218
#elif defined(TARGET_PPC)
M
Michael Walle 已提交
219
#elif defined(TARGET_LM32)
220
#elif defined(TARGET_MICROBLAZE)
B
bellard 已提交
221
#elif defined(TARGET_MIPS)
B
bellard 已提交
222
#elif defined(TARGET_SH4)
223
#elif defined(TARGET_CRIS)
A
Alexander Graf 已提交
224
#elif defined(TARGET_S390X)
B
bellard 已提交
225
    /* XXXXX */
B
bellard 已提交
226 227 228
#else
#error unsupported target CPU
#endif
229
    env->exception_index = -1;
230

B
bellard 已提交
231
    /* prepare setjmp context for exception handling */
232 233 234 235 236 237 238
    for(;;) {
        if (setjmp(env->jmp_env) == 0) {
            /* if an exception is pending, we execute it here */
            if (env->exception_index >= 0) {
                if (env->exception_index >= EXCP_INTERRUPT) {
                    /* exit request from the cpu execution loop */
                    ret = env->exception_index;
239 240 241
                    if (ret == EXCP_DEBUG) {
                        cpu_handle_debug_exception(env);
                    }
242
                    break;
A
aurel32 已提交
243 244
                } else {
#if defined(CONFIG_USER_ONLY)
245
                    /* if user mode only, we simulate a fake exception
T
ths 已提交
246
                       which will be handled outside the cpu execution
247
                       loop */
B
bellard 已提交
248
#if defined(TARGET_I386)
249
                    do_interrupt(env);
B
bellard 已提交
250
#endif
251 252
                    ret = env->exception_index;
                    break;
A
aurel32 已提交
253
#else
B
bellard 已提交
254
                    do_interrupt(env);
255
                    env->exception_index = -1;
B
bellard 已提交
256
#endif
257
                }
258
            }
B
bellard 已提交
259

260
            next_tb = 0; /* force lookup of first TB */
261
            for(;;) {
B
bellard 已提交
262
                interrupt_request = env->interrupt_request;
M
malc 已提交
263 264 265
                if (unlikely(interrupt_request)) {
                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
                        /* Mask out external interrupts for this step. */
266
                        interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
M
malc 已提交
267
                    }
268 269 270
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
                        env->exception_index = EXCP_DEBUG;
B
Blue Swirl 已提交
271
                        cpu_loop_exit(env);
272
                    }
273
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
274
    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
275
    defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
276 277 278 279
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
                        env->halted = 1;
                        env->exception_index = EXCP_HLT;
B
Blue Swirl 已提交
280
                        cpu_loop_exit(env);
281 282
                    }
#endif
B
bellard 已提交
283
#if defined(TARGET_I386)
284
                    if (interrupt_request & CPU_INTERRUPT_INIT) {
285
                            svm_check_intercept(env, SVM_EXIT_INIT);
286 287
                            do_cpu_init(env);
                            env->exception_index = EXCP_HALTED;
B
Blue Swirl 已提交
288
                            cpu_loop_exit(env);
289 290 291
                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
                            do_cpu_sipi(env);
                    } else if (env->hflags2 & HF2_GIF_MASK) {
292 293
                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
                            !(env->hflags & HF_SMM_MASK)) {
294
                            svm_check_intercept(env, SVM_EXIT_SMI);
295
                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
296
                            do_smm_enter(env);
297 298 299 300 301
                            next_tb = 0;
                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
                                   !(env->hflags2 & HF2_NMI_MASK)) {
                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
                            env->hflags2 |= HF2_NMI_MASK;
302
                            do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
303
                            next_tb = 0;
304 305
			} else if (interrupt_request & CPU_INTERRUPT_MCE) {
                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
306
                            do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
307
                            next_tb = 0;
308 309 310 311 312 313 314
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
                                     (env->hflags2 & HF2_HIF_MASK)) ||
                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
                                     (env->eflags & IF_MASK && 
                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
                            int intno;
315
                            svm_check_intercept(env, SVM_EXIT_INTR);
316 317
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
                            intno = cpu_get_pic_interrupt(env);
318
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
319
                            do_interrupt_x86_hardirq(env, intno, 1);
320 321 322
                            /* ensure that no TB jump will be modified as
                               the program flow was changed */
                            next_tb = 0;
T
ths 已提交
323
#if !defined(CONFIG_USER_ONLY)
324 325 326 327 328
                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
                                   (env->eflags & IF_MASK) && 
                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
                            int intno;
                            /* FIXME: this should respect TPR */
329
                            svm_check_intercept(env, SVM_EXIT_VINTR);
330
                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
331
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
332
                            do_interrupt_x86_hardirq(env, intno, 1);
333
                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
334
                            next_tb = 0;
B
bellard 已提交
335
#endif
336
                        }
B
bellard 已提交
337
                    }
338
#elif defined(TARGET_PPC)
339 340
#if 0
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
341
                        cpu_reset(env);
342 343
                    }
#endif
344
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
345 346 347
                        ppc_hw_interrupt(env);
                        if (env->pending_interrupts == 0)
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
348
                        next_tb = 0;
349
                    }
M
Michael Walle 已提交
350 351 352 353 354 355 356
#elif defined(TARGET_LM32)
                    if ((interrupt_request & CPU_INTERRUPT_HARD)
                        && (env->ie & IE_IE)) {
                        env->exception_index = EXCP_IRQ;
                        do_interrupt(env);
                        next_tb = 0;
                    }
357 358 359 360 361 362 363 364 365
#elif defined(TARGET_MICROBLAZE)
                    if ((interrupt_request & CPU_INTERRUPT_HARD)
                        && (env->sregs[SR_MSR] & MSR_IE)
                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
                        env->exception_index = EXCP_IRQ;
                        do_interrupt(env);
                        next_tb = 0;
                    }
B
bellard 已提交
366 367
#elif defined(TARGET_MIPS)
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
368
                        cpu_mips_hw_interrupts_pending(env)) {
B
bellard 已提交
369 370 371 372
                        /* Raise it */
                        env->exception_index = EXCP_EXT_INTERRUPT;
                        env->error_code = 0;
                        do_interrupt(env);
373
                        next_tb = 0;
B
bellard 已提交
374
                    }
375
#elif defined(TARGET_SPARC)
376 377 378 379 380 381 382 383 384 385 386 387 388 389
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
                        if (cpu_interrupts_enabled(env) &&
                            env->interrupt_index > 0) {
                            int pil = env->interrupt_index & 0xf;
                            int type = env->interrupt_index & 0xf0;

                            if (((type == TT_EXTINT) &&
                                  cpu_pil_allowed(env, pil)) ||
                                  type != TT_EXTINT) {
                                env->exception_index = env->interrupt_index;
                                do_interrupt(env);
                                next_tb = 0;
                            }
                        }
390
		    }
B
bellard 已提交
391 392 393 394 395
#elif defined(TARGET_ARM)
                    if (interrupt_request & CPU_INTERRUPT_FIQ
                        && !(env->uncached_cpsr & CPSR_F)) {
                        env->exception_index = EXCP_FIQ;
                        do_interrupt(env);
396
                        next_tb = 0;
B
bellard 已提交
397
                    }
P
pbrook 已提交
398 399 400 401 402 403
                    /* ARMv7-M interrupt return works by loading a magic value
                       into the PC.  On real hardware the load causes the
                       return to occur.  The qemu implementation performs the
                       jump normally, then does the exception return when the
                       CPU tries to execute code at the magic address.
                       This will cause the magic PC value to be pushed to
404
                       the stack if an interrupt occurred at the wrong time.
P
pbrook 已提交
405 406
                       We avoid this by disabling interrupts when
                       pc contains a magic address.  */
B
bellard 已提交
407
                    if (interrupt_request & CPU_INTERRUPT_HARD
P
pbrook 已提交
408 409
                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
                            || !(env->uncached_cpsr & CPSR_I))) {
B
bellard 已提交
410 411
                        env->exception_index = EXCP_IRQ;
                        do_interrupt(env);
412
                        next_tb = 0;
B
bellard 已提交
413
                    }
414 415 416 417 418 419
#elif defined(TARGET_UNICORE32)
                    if (interrupt_request & CPU_INTERRUPT_HARD
                        && !(env->uncached_asr & ASR_I)) {
                        do_interrupt(env);
                        next_tb = 0;
                    }
B
bellard 已提交
420
#elif defined(TARGET_SH4)
421 422
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
                        do_interrupt(env);
423
                        next_tb = 0;
424
                    }
J
j_mayer 已提交
425
#elif defined(TARGET_ALPHA)
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
                    {
                        int idx = -1;
                        /* ??? This hard-codes the OSF/1 interrupt levels.  */
		        switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
                        case 0 ... 3:
                            if (interrupt_request & CPU_INTERRUPT_HARD) {
                                idx = EXCP_DEV_INTERRUPT;
                            }
                            /* FALLTHRU */
                        case 4:
                            if (interrupt_request & CPU_INTERRUPT_TIMER) {
                                idx = EXCP_CLK_INTERRUPT;
                            }
                            /* FALLTHRU */
                        case 5:
                            if (interrupt_request & CPU_INTERRUPT_SMP) {
                                idx = EXCP_SMP_INTERRUPT;
                            }
                            /* FALLTHRU */
                        case 6:
                            if (interrupt_request & CPU_INTERRUPT_MCHK) {
                                idx = EXCP_MCHK;
                            }
                        }
                        if (idx >= 0) {
                            env->exception_index = idx;
                            env->error_code = 0;
                            do_interrupt(env);
                            next_tb = 0;
                        }
J
j_mayer 已提交
456
                    }
457
#elif defined(TARGET_CRIS)
E
edgar_igl 已提交
458
                    if (interrupt_request & CPU_INTERRUPT_HARD
E
Edgar E. Iglesias 已提交
459 460
                        && (env->pregs[PR_CCS] & I_FLAG)
                        && !env->locked_irq) {
E
edgar_igl 已提交
461 462 463 464 465 466 467
                        env->exception_index = EXCP_IRQ;
                        do_interrupt(env);
                        next_tb = 0;
                    }
                    if (interrupt_request & CPU_INTERRUPT_NMI
                        && (env->pregs[PR_CCS] & M_FLAG)) {
                        env->exception_index = EXCP_NMI;
468
                        do_interrupt(env);
469
                        next_tb = 0;
470
                    }
P
pbrook 已提交
471 472 473 474 475 476 477 478 479 480
#elif defined(TARGET_M68K)
                    if (interrupt_request & CPU_INTERRUPT_HARD
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
                            < env->pending_level) {
                        /* Real hardware gets the interrupt vector via an
                           IACK cycle at this point.  Current emulated
                           hardware doesn't rely on this, so we
                           provide/save the vector when the interrupt is
                           first signalled.  */
                        env->exception_index = env->pending_vector;
481
                        do_interrupt_m68k_hardirq(env);
482
                        next_tb = 0;
P
pbrook 已提交
483
                    }
484 485 486 487 488 489
#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                        (env->psw.mask & PSW_MASK_EXT)) {
                        do_interrupt(env);
                        next_tb = 0;
                    }
B
bellard 已提交
490
#endif
491
                   /* Don't use the cached interrupt_request value,
B
bellard 已提交
492
                      do_interrupt may have updated the EXITTB flag. */
B
bellard 已提交
493
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
494 495 496
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
                        /* ensure that no TB jump will be modified as
                           the program flow was changed */
497
                        next_tb = 0;
498
                    }
499 500 501 502
                }
                if (unlikely(env->exit_request)) {
                    env->exit_request = 0;
                    env->exception_index = EXCP_INTERRUPT;
B
Blue Swirl 已提交
503
                    cpu_loop_exit(env);
504
                }
505
#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
506
                if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
507
                    /* restore flags in standard format */
508
#if defined(TARGET_I386)
509 510
                    env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
                        | (DF & DF_MASK);
511
                    log_cpu_state(env, X86_DUMP_CCOP);
512
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
P
pbrook 已提交
513 514 515 516 517
#elif defined(TARGET_M68K)
                    cpu_m68k_flush_flags(env, env->cc_op);
                    env->cc_op = CC_OP_FLAGS;
                    env->sr = (env->sr & 0xffe0)
                              | env->cc_dest | (env->cc_x << 4);
518
                    log_cpu_state(env, 0);
B
bellard 已提交
519
#else
520
                    log_cpu_state(env, 0);
B
bellard 已提交
521
#endif
522
                }
523
#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
P
pbrook 已提交
524
                spin_lock(&tb_lock);
B
Blue Swirl 已提交
525
                tb = tb_find_fast(env);
P
pbrook 已提交
526 527 528 529 530 531 532
                /* Note: we do it here to avoid a gcc bug on Mac OS X when
                   doing it in tb_find_slow */
                if (tb_invalidated_flag) {
                    /* as some TB could have been invalidated because
                       of memory exceptions while generating the code, we
                       must recompute the hash index here */
                    next_tb = 0;
P
pbrook 已提交
533
                    tb_invalidated_flag = 0;
P
pbrook 已提交
534
                }
535
#ifdef CONFIG_DEBUG_EXEC
536 537 538
                qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
                             (long)tb->tc_ptr, tb->pc,
                             lookup_symbol(tb->pc));
539
#endif
540 541 542
                /* see if we can patch the calling TB. When the TB
                   spans two pages, we cannot safely do a direct
                   jump. */
P
Paolo Bonzini 已提交
543
                if (next_tb != 0 && tb->page_addr[1] == -1) {
544
                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
545
                }
P
pbrook 已提交
546
                spin_unlock(&tb_lock);
547 548 549 550 551

                /* cpu_interrupt might be called while translating the
                   TB, but before it is linked into a potentially
                   infinite loop and becomes env->current_tb. Avoid
                   starting execution if there is a pending interrupt. */
J
Jan Kiszka 已提交
552 553 554
                env->current_tb = tb;
                barrier();
                if (likely(!env->exit_request)) {
P
pbrook 已提交
555
                    tc_ptr = tb->tc_ptr;
556
                /* execute the generated code */
B
Blue Swirl 已提交
557
                    next_tb = tcg_qemu_tb_exec(env, tc_ptr);
P
pbrook 已提交
558
                    if ((next_tb & 3) == 2) {
T
ths 已提交
559
                        /* Instruction counter expired.  */
P
pbrook 已提交
560 561 562
                        int insns_left;
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
                        /* Restore PC.  */
563
                        cpu_pc_from_tb(env, tb);
P
pbrook 已提交
564 565 566 567 568 569 570 571 572 573 574 575 576 577
                        insns_left = env->icount_decr.u32;
                        if (env->icount_extra && insns_left >= 0) {
                            /* Refill decrementer and continue execution.  */
                            env->icount_extra += insns_left;
                            if (env->icount_extra > 0xffff) {
                                insns_left = 0xffff;
                            } else {
                                insns_left = env->icount_extra;
                            }
                            env->icount_extra -= insns_left;
                            env->icount_decr.u16.low = insns_left;
                        } else {
                            if (insns_left > 0) {
                                /* Execute remaining instructions.  */
B
Blue Swirl 已提交
578
                                cpu_exec_nocache(env, insns_left, tb);
P
pbrook 已提交
579 580 581
                            }
                            env->exception_index = EXCP_INTERRUPT;
                            next_tb = 0;
B
Blue Swirl 已提交
582
                            cpu_loop_exit(env);
P
pbrook 已提交
583 584 585
                        }
                    }
                }
J
Jan Kiszka 已提交
586
                env->current_tb = NULL;
B
bellard 已提交
587 588
                /* reset soft MMU for next block (it can currently
                   only be set by a memory fault) */
T
ths 已提交
589
            } /* for(;;) */
B
bellard 已提交
590
        }
591 592
    } /* for(;;) */

B
bellard 已提交
593

B
bellard 已提交
594
#if defined(TARGET_I386)
B
bellard 已提交
595
    /* restore flags in standard format */
596 597
    env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
        | (DF & DF_MASK);
B
bellard 已提交
598
#elif defined(TARGET_ARM)
B
bellard 已提交
599
    /* XXX: Save/restore host fpu exception state?.  */
600
#elif defined(TARGET_UNICORE32)
601
#elif defined(TARGET_SPARC)
602
#elif defined(TARGET_PPC)
M
Michael Walle 已提交
603
#elif defined(TARGET_LM32)
P
pbrook 已提交
604 605 606 607 608
#elif defined(TARGET_M68K)
    cpu_m68k_flush_flags(env, env->cc_op);
    env->cc_op = CC_OP_FLAGS;
    env->sr = (env->sr & 0xffe0)
              | env->cc_dest | (env->cc_x << 4);
609
#elif defined(TARGET_MICROBLAZE)
B
bellard 已提交
610
#elif defined(TARGET_MIPS)
B
bellard 已提交
611
#elif defined(TARGET_SH4)
J
j_mayer 已提交
612
#elif defined(TARGET_ALPHA)
613
#elif defined(TARGET_CRIS)
A
Alexander Graf 已提交
614
#elif defined(TARGET_S390X)
B
bellard 已提交
615
    /* XXXXX */
B
bellard 已提交
616 617 618
#else
#error unsupported target CPU
#endif
P
pbrook 已提交
619

B
bellard 已提交
620
    /* fail safe : never use cpu_single_env outside cpu_exec() */
621
    cpu_single_env = NULL;
B
bellard 已提交
622 623
    return ret;
}