Statistics
| Branch: | Revision:

root / cpu-exec.c @ 48ff7a62

History | View | Annotate | Download (24.8 kB)

1
/*
2
 *  i386 emulator main execution loop
3
 *
4
 *  Copyright (c) 2003-2005 Fabrice Bellard
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
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/>.
18
 */
19
#include "config.h"
20
#include "cpu.h"
21
#include "disas.h"
22
#include "tcg.h"
23
#include "qemu-barrier.h"
24

    
25
int tb_invalidated_flag;
26

    
27
//#define CONFIG_DEBUG_EXEC
28

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

    
34
void cpu_loop_exit(CPUState *env)
35
{
36
    env->current_tb = NULL;
37
    longjmp(env->jmp_env, 1);
38
}
39

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

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

    
53
/* Execute the code without caching the generated code. An interpreter
54
   could be used if available. */
55
static void cpu_exec_nocache(CPUState *env, int max_cycles,
56
                             TranslationBlock *orig_tb)
57
{
58
    unsigned long next_tb;
59
    TranslationBlock *tb;
60

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

    
66
    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
67
                     max_cycles);
68
    env->current_tb = tb;
69
    /* execute the generated code */
70
    next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
71
    env->current_tb = NULL;
72

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

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

    
92
    tb_invalidated_flag = 0;
93

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

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

    
137
static inline TranslationBlock *tb_find_fast(CPUState *env)
138
{
139
    TranslationBlock *tb;
140
    target_ulong cs_base, pc;
141
    int flags;
142

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

    
155
static CPUDebugExcpHandler *debug_excp_handler;
156

    
157
CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
158
{
159
    CPUDebugExcpHandler *old_handler = debug_excp_handler;
160

    
161
    debug_excp_handler = handler;
162
    return old_handler;
163
}
164

    
165
static void cpu_handle_debug_exception(CPUState *env)
166
{
167
    CPUWatchpoint *wp;
168

    
169
    if (!env->watchpoint_hit) {
170
        QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
171
            wp->flags &= ~BP_WATCHPOINT_HIT;
172
        }
173
    }
174
    if (debug_excp_handler) {
175
        debug_excp_handler(env);
176
    }
177
}
178

    
179
/* main execution loop */
180

    
181
volatile sig_atomic_t exit_request;
182

    
183
int cpu_exec(CPUState *env)
184
{
185
    int ret, interrupt_request;
186
    TranslationBlock *tb;
187
    uint8_t *tc_ptr;
188
    unsigned long next_tb;
189

    
190
    if (env->halted) {
191
        if (!cpu_has_work(env)) {
192
            return EXCP_HALTED;
193
        }
194

    
195
        env->halted = 0;
196
    }
197

    
198
    cpu_single_env = env;
199

    
200
    if (unlikely(exit_request)) {
201
        env->exit_request = 1;
202
    }
203

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

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

    
260
            next_tb = 0; /* force lookup of first TB */
261
            for(;;) {
262
                interrupt_request = env->interrupt_request;
263
                if (unlikely(interrupt_request)) {
264
                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
265
                        /* Mask out external interrupts for this step. */
266
                        interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
267
                    }
268
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
269
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
270
                        env->exception_index = EXCP_DEBUG;
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
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
277
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
278
                        env->halted = 1;
279
                        env->exception_index = EXCP_HLT;
280
                        cpu_loop_exit(env);
281
                    }
282
#endif
283
#if defined(TARGET_I386)
284
                    if (interrupt_request & CPU_INTERRUPT_INIT) {
285
                            svm_check_intercept(env, SVM_EXIT_INIT);
286
                            do_cpu_init(env);
287
                            env->exception_index = EXCP_HALTED;
288
                            cpu_loop_exit(env);
289
                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
290
                            do_cpu_sipi(env);
291
                    } else if (env->hflags2 & HF2_GIF_MASK) {
292
                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
293
                            !(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
                            next_tb = 0;
298
                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
299
                                   !(env->hflags2 & HF2_NMI_MASK)) {
300
                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
301
                            env->hflags2 |= HF2_NMI_MASK;
302
                            do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
303
                            next_tb = 0;
304
                        } else if (interrupt_request & CPU_INTERRUPT_MCE) {
305
                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
306
                            do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
307
                            next_tb = 0;
308
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
309
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
310
                                     (env->hflags2 & HF2_HIF_MASK)) ||
311
                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
312
                                     (env->eflags & IF_MASK && 
313
                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
314
                            int intno;
315
                            svm_check_intercept(env, SVM_EXIT_INTR);
316
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
317
                            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
                            /* ensure that no TB jump will be modified as
321
                               the program flow was changed */
322
                            next_tb = 0;
323
#if !defined(CONFIG_USER_ONLY)
324
                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
325
                                   (env->eflags & IF_MASK) && 
326
                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
327
                            int intno;
328
                            /* 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;
335
#endif
336
                        }
337
                    }
338
#elif defined(TARGET_PPC)
339
#if 0
340
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
341
                        cpu_reset(env);
342
                    }
343
#endif
344
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
345
                        ppc_hw_interrupt(env);
346
                        if (env->pending_interrupts == 0)
347
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
348
                        next_tb = 0;
349
                    }
350
#elif defined(TARGET_LM32)
351
                    if ((interrupt_request & CPU_INTERRUPT_HARD)
352
                        && (env->ie & IE_IE)) {
353
                        env->exception_index = EXCP_IRQ;
354
                        do_interrupt(env);
355
                        next_tb = 0;
356
                    }
357
#elif defined(TARGET_MICROBLAZE)
358
                    if ((interrupt_request & CPU_INTERRUPT_HARD)
359
                        && (env->sregs[SR_MSR] & MSR_IE)
360
                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
361
                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
362
                        env->exception_index = EXCP_IRQ;
363
                        do_interrupt(env);
364
                        next_tb = 0;
365
                    }
366
#elif defined(TARGET_MIPS)
367
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
368
                        cpu_mips_hw_interrupts_pending(env)) {
369
                        /* Raise it */
370
                        env->exception_index = EXCP_EXT_INTERRUPT;
371
                        env->error_code = 0;
372
                        do_interrupt(env);
373
                        next_tb = 0;
374
                    }
375
#elif defined(TARGET_SPARC)
376
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
377
                        if (cpu_interrupts_enabled(env) &&
378
                            env->interrupt_index > 0) {
379
                            int pil = env->interrupt_index & 0xf;
380
                            int type = env->interrupt_index & 0xf0;
381

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

    
548
                /* cpu_interrupt might be called while translating the
549
                   TB, but before it is linked into a potentially
550
                   infinite loop and becomes env->current_tb. Avoid
551
                   starting execution if there is a pending interrupt. */
552
                env->current_tb = tb;
553
                barrier();
554
                if (likely(!env->exit_request)) {
555
                    tc_ptr = tb->tc_ptr;
556
                /* execute the generated code */
557
                    next_tb = tcg_qemu_tb_exec(env, tc_ptr);
558
                    if ((next_tb & 3) == 2) {
559
                        /* Instruction counter expired.  */
560
                        int insns_left;
561
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
562
                        /* Restore PC.  */
563
                        cpu_pc_from_tb(env, tb);
564
                        insns_left = env->icount_decr.u32;
565
                        if (env->icount_extra && insns_left >= 0) {
566
                            /* Refill decrementer and continue execution.  */
567
                            env->icount_extra += insns_left;
568
                            if (env->icount_extra > 0xffff) {
569
                                insns_left = 0xffff;
570
                            } else {
571
                                insns_left = env->icount_extra;
572
                            }
573
                            env->icount_extra -= insns_left;
574
                            env->icount_decr.u16.low = insns_left;
575
                        } else {
576
                            if (insns_left > 0) {
577
                                /* Execute remaining instructions.  */
578
                                cpu_exec_nocache(env, insns_left, tb);
579
                            }
580
                            env->exception_index = EXCP_INTERRUPT;
581
                            next_tb = 0;
582
                            cpu_loop_exit(env);
583
                        }
584
                    }
585
                }
586
                env->current_tb = NULL;
587
                /* reset soft MMU for next block (it can currently
588
                   only be set by a memory fault) */
589
            } /* for(;;) */
590
        } else {
591
            /* Reload env after longjmp - the compiler may have smashed all
592
             * local variables as longjmp is marked 'noreturn'. */
593
            env = cpu_single_env;
594
        }
595
    } /* for(;;) */
596

    
597

    
598
#if defined(TARGET_I386)
599
    /* restore flags in standard format */
600
    env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
601
        | (DF & DF_MASK);
602
#elif defined(TARGET_ARM)
603
    /* XXX: Save/restore host fpu exception state?.  */
604
#elif defined(TARGET_UNICORE32)
605
#elif defined(TARGET_SPARC)
606
#elif defined(TARGET_PPC)
607
#elif defined(TARGET_LM32)
608
#elif defined(TARGET_M68K)
609
    cpu_m68k_flush_flags(env, env->cc_op);
610
    env->cc_op = CC_OP_FLAGS;
611
    env->sr = (env->sr & 0xffe0)
612
              | env->cc_dest | (env->cc_x << 4);
613
#elif defined(TARGET_MICROBLAZE)
614
#elif defined(TARGET_MIPS)
615
#elif defined(TARGET_SH4)
616
#elif defined(TARGET_ALPHA)
617
#elif defined(TARGET_CRIS)
618
#elif defined(TARGET_S390X)
619
    /* XXXXX */
620
#else
621
#error unsupported target CPU
622
#endif
623

    
624
    /* fail safe : never use cpu_single_env outside cpu_exec() */
625
    cpu_single_env = NULL;
626
    return ret;
627
}