char: remove watch callback on chardev detach from frontend
[qemu/ar7.git] / cpu-exec.c
blob5a4399509e686b7c499295146f32cb39de31266a
1 /*
2 * emulator main execution loop
4 * Copyright (c) 2003-2005 Fabrice Bellard
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.
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.
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/>.
19 #include "config.h"
20 #include "cpu.h"
21 #include "disas/disas.h"
22 #include "tcg.h"
23 #include "qemu/atomic.h"
24 #include "sysemu/qtest.h"
26 bool qemu_cpu_has_work(CPUState *cpu)
28 return cpu_has_work(cpu);
31 void cpu_loop_exit(CPUArchState *env)
33 CPUState *cpu = ENV_GET_CPU(env);
35 cpu->current_tb = NULL;
36 siglongjmp(env->jmp_env, 1);
39 /* exit the current TB from a signal handler. The host registers are
40 restored in a state compatible with the CPU emulator
42 #if defined(CONFIG_SOFTMMU)
43 void cpu_resume_from_signal(CPUArchState *env, void *puc)
45 /* XXX: restore cpu registers saved in host registers */
47 env->exception_index = -1;
48 siglongjmp(env->jmp_env, 1);
50 #endif
52 /* Execute a TB, and fix up the CPU state afterwards if necessary */
53 static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
55 CPUArchState *env = cpu->env_ptr;
56 uintptr_t next_tb = tcg_qemu_tb_exec(env, tb_ptr);
57 if ((next_tb & TB_EXIT_MASK) > TB_EXIT_IDX1) {
58 /* We didn't start executing this TB (eg because the instruction
59 * counter hit zero); we must restore the guest PC to the address
60 * of the start of the TB.
62 CPUClass *cc = CPU_GET_CLASS(cpu);
63 TranslationBlock *tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
64 if (cc->synchronize_from_tb) {
65 cc->synchronize_from_tb(cpu, tb);
66 } else {
67 assert(cc->set_pc);
68 cc->set_pc(cpu, tb->pc);
71 if ((next_tb & TB_EXIT_MASK) == TB_EXIT_REQUESTED) {
72 /* We were asked to stop executing TBs (probably a pending
73 * interrupt. We've now stopped, so clear the flag.
75 cpu->tcg_exit_req = 0;
77 return next_tb;
80 /* Execute the code without caching the generated code. An interpreter
81 could be used if available. */
82 static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
83 TranslationBlock *orig_tb)
85 CPUState *cpu = ENV_GET_CPU(env);
86 TranslationBlock *tb;
88 /* Should never happen.
89 We only end up here when an existing TB is too long. */
90 if (max_cycles > CF_COUNT_MASK)
91 max_cycles = CF_COUNT_MASK;
93 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
94 max_cycles);
95 cpu->current_tb = tb;
96 /* execute the generated code */
97 cpu_tb_exec(cpu, tb->tc_ptr);
98 cpu->current_tb = NULL;
99 tb_phys_invalidate(tb, -1);
100 tb_free(tb);
103 static TranslationBlock *tb_find_slow(CPUArchState *env,
104 target_ulong pc,
105 target_ulong cs_base,
106 uint64_t flags)
108 TranslationBlock *tb, **ptb1;
109 unsigned int h;
110 tb_page_addr_t phys_pc, phys_page1;
111 target_ulong virt_page2;
113 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
115 /* find translated block using physical mappings */
116 phys_pc = get_page_addr_code(env, pc);
117 phys_page1 = phys_pc & TARGET_PAGE_MASK;
118 h = tb_phys_hash_func(phys_pc);
119 ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[h];
120 for(;;) {
121 tb = *ptb1;
122 if (!tb)
123 goto not_found;
124 if (tb->pc == pc &&
125 tb->page_addr[0] == phys_page1 &&
126 tb->cs_base == cs_base &&
127 tb->flags == flags) {
128 /* check next page if needed */
129 if (tb->page_addr[1] != -1) {
130 tb_page_addr_t phys_page2;
132 virt_page2 = (pc & TARGET_PAGE_MASK) +
133 TARGET_PAGE_SIZE;
134 phys_page2 = get_page_addr_code(env, virt_page2);
135 if (tb->page_addr[1] == phys_page2)
136 goto found;
137 } else {
138 goto found;
141 ptb1 = &tb->phys_hash_next;
143 not_found:
144 /* if no translated code available, then translate it now */
145 tb = tb_gen_code(env, pc, cs_base, flags, 0);
147 found:
148 /* Move the last found TB to the head of the list */
149 if (likely(*ptb1)) {
150 *ptb1 = tb->phys_hash_next;
151 tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
152 tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
154 /* we add the TB in the virtual pc hash table */
155 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
156 return tb;
159 static inline TranslationBlock *tb_find_fast(CPUArchState *env)
161 TranslationBlock *tb;
162 target_ulong cs_base, pc;
163 int flags;
165 /* we record a subset of the CPU state. It will
166 always be the same before a given translated block
167 is executed. */
168 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
169 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
170 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
171 tb->flags != flags)) {
172 tb = tb_find_slow(env, pc, cs_base, flags);
174 return tb;
177 static CPUDebugExcpHandler *debug_excp_handler;
179 void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
181 debug_excp_handler = handler;
184 static void cpu_handle_debug_exception(CPUArchState *env)
186 CPUWatchpoint *wp;
188 if (!env->watchpoint_hit) {
189 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
190 wp->flags &= ~BP_WATCHPOINT_HIT;
193 if (debug_excp_handler) {
194 debug_excp_handler(env);
198 /* main execution loop */
200 volatile sig_atomic_t exit_request;
202 int cpu_exec(CPUArchState *env)
204 CPUState *cpu = ENV_GET_CPU(env);
205 #if !(defined(CONFIG_USER_ONLY) && \
206 (defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))
207 CPUClass *cc = CPU_GET_CLASS(cpu);
208 #endif
209 int ret, interrupt_request;
210 TranslationBlock *tb;
211 uint8_t *tc_ptr;
212 uintptr_t next_tb;
214 if (cpu->halted) {
215 if (!cpu_has_work(cpu)) {
216 return EXCP_HALTED;
219 cpu->halted = 0;
222 current_cpu = cpu;
224 /* As long as current_cpu is null, up to the assignment just above,
225 * requests by other threads to exit the execution loop are expected to
226 * be issued using the exit_request global. We must make sure that our
227 * evaluation of the global value is performed past the current_cpu
228 * value transition point, which requires a memory barrier as well as
229 * an instruction scheduling constraint on modern architectures. */
230 smp_mb();
232 if (unlikely(exit_request)) {
233 cpu->exit_request = 1;
236 #if defined(TARGET_I386)
237 /* put eflags in CPU temporary format */
238 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
239 env->df = 1 - (2 * ((env->eflags >> 10) & 1));
240 CC_OP = CC_OP_EFLAGS;
241 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
242 #elif defined(TARGET_SPARC)
243 #elif defined(TARGET_M68K)
244 env->cc_op = CC_OP_FLAGS;
245 env->cc_dest = env->sr & 0xf;
246 env->cc_x = (env->sr >> 4) & 1;
247 #elif defined(TARGET_ALPHA)
248 #elif defined(TARGET_ARM)
249 #elif defined(TARGET_UNICORE32)
250 #elif defined(TARGET_PPC)
251 env->reserve_addr = -1;
252 #elif defined(TARGET_LM32)
253 #elif defined(TARGET_MICROBLAZE)
254 #elif defined(TARGET_MIPS)
255 #elif defined(TARGET_MOXIE)
256 #elif defined(TARGET_OPENRISC)
257 #elif defined(TARGET_SH4)
258 #elif defined(TARGET_CRIS)
259 #elif defined(TARGET_S390X)
260 #elif defined(TARGET_XTENSA)
261 /* XXXXX */
262 #else
263 #error unsupported target CPU
264 #endif
265 env->exception_index = -1;
267 /* prepare setjmp context for exception handling */
268 for(;;) {
269 if (sigsetjmp(env->jmp_env, 0) == 0) {
270 /* if an exception is pending, we execute it here */
271 if (env->exception_index >= 0) {
272 if (env->exception_index >= EXCP_INTERRUPT) {
273 /* exit request from the cpu execution loop */
274 ret = env->exception_index;
275 if (ret == EXCP_DEBUG) {
276 cpu_handle_debug_exception(env);
278 break;
279 } else {
280 #if defined(CONFIG_USER_ONLY)
281 /* if user mode only, we simulate a fake exception
282 which will be handled outside the cpu execution
283 loop */
284 #if defined(TARGET_I386)
285 cc->do_interrupt(cpu);
286 #endif
287 ret = env->exception_index;
288 break;
289 #else
290 cc->do_interrupt(cpu);
291 env->exception_index = -1;
292 #endif
296 next_tb = 0; /* force lookup of first TB */
297 for(;;) {
298 interrupt_request = cpu->interrupt_request;
299 if (unlikely(interrupt_request)) {
300 if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {
301 /* Mask out external interrupts for this step. */
302 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
304 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
305 cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
306 env->exception_index = EXCP_DEBUG;
307 cpu_loop_exit(env);
309 #if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
310 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
311 defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
312 if (interrupt_request & CPU_INTERRUPT_HALT) {
313 cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
314 cpu->halted = 1;
315 env->exception_index = EXCP_HLT;
316 cpu_loop_exit(env);
318 #endif
319 #if defined(TARGET_I386)
320 #if !defined(CONFIG_USER_ONLY)
321 if (interrupt_request & CPU_INTERRUPT_POLL) {
322 cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
323 apic_poll_irq(env->apic_state);
325 #endif
326 if (interrupt_request & CPU_INTERRUPT_INIT) {
327 cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
329 do_cpu_init(x86_env_get_cpu(env));
330 env->exception_index = EXCP_HALTED;
331 cpu_loop_exit(env);
332 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
333 do_cpu_sipi(x86_env_get_cpu(env));
334 } else if (env->hflags2 & HF2_GIF_MASK) {
335 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
336 !(env->hflags & HF_SMM_MASK)) {
337 cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
339 cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
340 do_smm_enter(x86_env_get_cpu(env));
341 next_tb = 0;
342 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
343 !(env->hflags2 & HF2_NMI_MASK)) {
344 cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
345 env->hflags2 |= HF2_NMI_MASK;
346 do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
347 next_tb = 0;
348 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
349 cpu->interrupt_request &= ~CPU_INTERRUPT_MCE;
350 do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
351 next_tb = 0;
352 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
353 (((env->hflags2 & HF2_VINTR_MASK) &&
354 (env->hflags2 & HF2_HIF_MASK)) ||
355 (!(env->hflags2 & HF2_VINTR_MASK) &&
356 (env->eflags & IF_MASK &&
357 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
358 int intno;
359 cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,
361 cpu->interrupt_request &= ~(CPU_INTERRUPT_HARD |
362 CPU_INTERRUPT_VIRQ);
363 intno = cpu_get_pic_interrupt(env);
364 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
365 do_interrupt_x86_hardirq(env, intno, 1);
366 /* ensure that no TB jump will be modified as
367 the program flow was changed */
368 next_tb = 0;
369 #if !defined(CONFIG_USER_ONLY)
370 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
371 (env->eflags & IF_MASK) &&
372 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
373 int intno;
374 /* FIXME: this should respect TPR */
375 cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR,
377 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
378 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
379 do_interrupt_x86_hardirq(env, intno, 1);
380 cpu->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
381 next_tb = 0;
382 #endif
385 #elif defined(TARGET_PPC)
386 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
387 cpu_reset(cpu);
389 if (interrupt_request & CPU_INTERRUPT_HARD) {
390 ppc_hw_interrupt(env);
391 if (env->pending_interrupts == 0) {
392 cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;
394 next_tb = 0;
396 #elif defined(TARGET_LM32)
397 if ((interrupt_request & CPU_INTERRUPT_HARD)
398 && (env->ie & IE_IE)) {
399 env->exception_index = EXCP_IRQ;
400 cc->do_interrupt(cpu);
401 next_tb = 0;
403 #elif defined(TARGET_MICROBLAZE)
404 if ((interrupt_request & CPU_INTERRUPT_HARD)
405 && (env->sregs[SR_MSR] & MSR_IE)
406 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
407 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
408 env->exception_index = EXCP_IRQ;
409 cc->do_interrupt(cpu);
410 next_tb = 0;
412 #elif defined(TARGET_MIPS)
413 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
414 cpu_mips_hw_interrupts_pending(env)) {
415 /* Raise it */
416 env->exception_index = EXCP_EXT_INTERRUPT;
417 env->error_code = 0;
418 cc->do_interrupt(cpu);
419 next_tb = 0;
421 #elif defined(TARGET_OPENRISC)
423 int idx = -1;
424 if ((interrupt_request & CPU_INTERRUPT_HARD)
425 && (env->sr & SR_IEE)) {
426 idx = EXCP_INT;
428 if ((interrupt_request & CPU_INTERRUPT_TIMER)
429 && (env->sr & SR_TEE)) {
430 idx = EXCP_TICK;
432 if (idx >= 0) {
433 env->exception_index = idx;
434 cc->do_interrupt(cpu);
435 next_tb = 0;
438 #elif defined(TARGET_SPARC)
439 if (interrupt_request & CPU_INTERRUPT_HARD) {
440 if (cpu_interrupts_enabled(env) &&
441 env->interrupt_index > 0) {
442 int pil = env->interrupt_index & 0xf;
443 int type = env->interrupt_index & 0xf0;
445 if (((type == TT_EXTINT) &&
446 cpu_pil_allowed(env, pil)) ||
447 type != TT_EXTINT) {
448 env->exception_index = env->interrupt_index;
449 cc->do_interrupt(cpu);
450 next_tb = 0;
454 #elif defined(TARGET_ARM)
455 if (interrupt_request & CPU_INTERRUPT_FIQ
456 && !(env->uncached_cpsr & CPSR_F)) {
457 env->exception_index = EXCP_FIQ;
458 cc->do_interrupt(cpu);
459 next_tb = 0;
461 /* ARMv7-M interrupt return works by loading a magic value
462 into the PC. On real hardware the load causes the
463 return to occur. The qemu implementation performs the
464 jump normally, then does the exception return when the
465 CPU tries to execute code at the magic address.
466 This will cause the magic PC value to be pushed to
467 the stack if an interrupt occurred at the wrong time.
468 We avoid this by disabling interrupts when
469 pc contains a magic address. */
470 if (interrupt_request & CPU_INTERRUPT_HARD
471 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
472 || !(env->uncached_cpsr & CPSR_I))) {
473 env->exception_index = EXCP_IRQ;
474 cc->do_interrupt(cpu);
475 next_tb = 0;
477 #elif defined(TARGET_UNICORE32)
478 if (interrupt_request & CPU_INTERRUPT_HARD
479 && !(env->uncached_asr & ASR_I)) {
480 env->exception_index = UC32_EXCP_INTR;
481 cc->do_interrupt(cpu);
482 next_tb = 0;
484 #elif defined(TARGET_SH4)
485 if (interrupt_request & CPU_INTERRUPT_HARD) {
486 cc->do_interrupt(cpu);
487 next_tb = 0;
489 #elif defined(TARGET_ALPHA)
491 int idx = -1;
492 /* ??? This hard-codes the OSF/1 interrupt levels. */
493 switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
494 case 0 ... 3:
495 if (interrupt_request & CPU_INTERRUPT_HARD) {
496 idx = EXCP_DEV_INTERRUPT;
498 /* FALLTHRU */
499 case 4:
500 if (interrupt_request & CPU_INTERRUPT_TIMER) {
501 idx = EXCP_CLK_INTERRUPT;
503 /* FALLTHRU */
504 case 5:
505 if (interrupt_request & CPU_INTERRUPT_SMP) {
506 idx = EXCP_SMP_INTERRUPT;
508 /* FALLTHRU */
509 case 6:
510 if (interrupt_request & CPU_INTERRUPT_MCHK) {
511 idx = EXCP_MCHK;
514 if (idx >= 0) {
515 env->exception_index = idx;
516 env->error_code = 0;
517 cc->do_interrupt(cpu);
518 next_tb = 0;
521 #elif defined(TARGET_CRIS)
522 if (interrupt_request & CPU_INTERRUPT_HARD
523 && (env->pregs[PR_CCS] & I_FLAG)
524 && !env->locked_irq) {
525 env->exception_index = EXCP_IRQ;
526 cc->do_interrupt(cpu);
527 next_tb = 0;
529 if (interrupt_request & CPU_INTERRUPT_NMI) {
530 unsigned int m_flag_archval;
531 if (env->pregs[PR_VR] < 32) {
532 m_flag_archval = M_FLAG_V10;
533 } else {
534 m_flag_archval = M_FLAG_V32;
536 if ((env->pregs[PR_CCS] & m_flag_archval)) {
537 env->exception_index = EXCP_NMI;
538 cc->do_interrupt(cpu);
539 next_tb = 0;
542 #elif defined(TARGET_M68K)
543 if (interrupt_request & CPU_INTERRUPT_HARD
544 && ((env->sr & SR_I) >> SR_I_SHIFT)
545 < env->pending_level) {
546 /* Real hardware gets the interrupt vector via an
547 IACK cycle at this point. Current emulated
548 hardware doesn't rely on this, so we
549 provide/save the vector when the interrupt is
550 first signalled. */
551 env->exception_index = env->pending_vector;
552 do_interrupt_m68k_hardirq(env);
553 next_tb = 0;
555 #elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
556 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
557 (env->psw.mask & PSW_MASK_EXT)) {
558 cc->do_interrupt(cpu);
559 next_tb = 0;
561 #elif defined(TARGET_XTENSA)
562 if (interrupt_request & CPU_INTERRUPT_HARD) {
563 env->exception_index = EXC_IRQ;
564 cc->do_interrupt(cpu);
565 next_tb = 0;
567 #endif
568 /* Don't use the cached interrupt_request value,
569 do_interrupt may have updated the EXITTB flag. */
570 if (cpu->interrupt_request & CPU_INTERRUPT_EXITTB) {
571 cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
572 /* ensure that no TB jump will be modified as
573 the program flow was changed */
574 next_tb = 0;
577 if (unlikely(cpu->exit_request)) {
578 cpu->exit_request = 0;
579 env->exception_index = EXCP_INTERRUPT;
580 cpu_loop_exit(env);
582 #if defined(DEBUG_DISAS)
583 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
584 /* restore flags in standard format */
585 #if defined(TARGET_I386)
586 log_cpu_state(cpu, CPU_DUMP_CCOP);
587 #elif defined(TARGET_M68K)
588 cpu_m68k_flush_flags(env, env->cc_op);
589 env->cc_op = CC_OP_FLAGS;
590 env->sr = (env->sr & 0xffe0)
591 | env->cc_dest | (env->cc_x << 4);
592 log_cpu_state(cpu, 0);
593 #else
594 log_cpu_state(cpu, 0);
595 #endif
597 #endif /* DEBUG_DISAS */
598 spin_lock(&tcg_ctx.tb_ctx.tb_lock);
599 tb = tb_find_fast(env);
600 /* Note: we do it here to avoid a gcc bug on Mac OS X when
601 doing it in tb_find_slow */
602 if (tcg_ctx.tb_ctx.tb_invalidated_flag) {
603 /* as some TB could have been invalidated because
604 of memory exceptions while generating the code, we
605 must recompute the hash index here */
606 next_tb = 0;
607 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
609 if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
610 qemu_log("Trace %p [" TARGET_FMT_lx "] %s\n",
611 tb->tc_ptr, tb->pc, lookup_symbol(tb->pc));
613 /* see if we can patch the calling TB. When the TB
614 spans two pages, we cannot safely do a direct
615 jump. */
616 if (next_tb != 0 && tb->page_addr[1] == -1) {
617 tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
618 next_tb & TB_EXIT_MASK, tb);
620 spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
622 /* cpu_interrupt might be called while translating the
623 TB, but before it is linked into a potentially
624 infinite loop and becomes env->current_tb. Avoid
625 starting execution if there is a pending interrupt. */
626 cpu->current_tb = tb;
627 barrier();
628 if (likely(!cpu->exit_request)) {
629 tc_ptr = tb->tc_ptr;
630 /* execute the generated code */
631 next_tb = cpu_tb_exec(cpu, tc_ptr);
632 switch (next_tb & TB_EXIT_MASK) {
633 case TB_EXIT_REQUESTED:
634 /* Something asked us to stop executing
635 * chained TBs; just continue round the main
636 * loop. Whatever requested the exit will also
637 * have set something else (eg exit_request or
638 * interrupt_request) which we will handle
639 * next time around the loop.
641 tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
642 next_tb = 0;
643 break;
644 case TB_EXIT_ICOUNT_EXPIRED:
646 /* Instruction counter expired. */
647 int insns_left;
648 tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
649 insns_left = env->icount_decr.u32;
650 if (env->icount_extra && insns_left >= 0) {
651 /* Refill decrementer and continue execution. */
652 env->icount_extra += insns_left;
653 if (env->icount_extra > 0xffff) {
654 insns_left = 0xffff;
655 } else {
656 insns_left = env->icount_extra;
658 env->icount_extra -= insns_left;
659 env->icount_decr.u16.low = insns_left;
660 } else {
661 if (insns_left > 0) {
662 /* Execute remaining instructions. */
663 cpu_exec_nocache(env, insns_left, tb);
665 env->exception_index = EXCP_INTERRUPT;
666 next_tb = 0;
667 cpu_loop_exit(env);
669 break;
671 default:
672 break;
675 cpu->current_tb = NULL;
676 /* reset soft MMU for next block (it can currently
677 only be set by a memory fault) */
678 } /* for(;;) */
679 } else {
680 /* Reload env after longjmp - the compiler may have smashed all
681 * local variables as longjmp is marked 'noreturn'. */
682 cpu = current_cpu;
683 env = cpu->env_ptr;
685 } /* for(;;) */
688 #if defined(TARGET_I386)
689 /* restore flags in standard format */
690 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
691 | (env->df & DF_MASK);
692 #elif defined(TARGET_ARM)
693 /* XXX: Save/restore host fpu exception state?. */
694 #elif defined(TARGET_UNICORE32)
695 #elif defined(TARGET_SPARC)
696 #elif defined(TARGET_PPC)
697 #elif defined(TARGET_LM32)
698 #elif defined(TARGET_M68K)
699 cpu_m68k_flush_flags(env, env->cc_op);
700 env->cc_op = CC_OP_FLAGS;
701 env->sr = (env->sr & 0xffe0)
702 | env->cc_dest | (env->cc_x << 4);
703 #elif defined(TARGET_MICROBLAZE)
704 #elif defined(TARGET_MIPS)
705 #elif defined(TARGET_MOXIE)
706 #elif defined(TARGET_OPENRISC)
707 #elif defined(TARGET_SH4)
708 #elif defined(TARGET_ALPHA)
709 #elif defined(TARGET_CRIS)
710 #elif defined(TARGET_S390X)
711 #elif defined(TARGET_XTENSA)
712 /* XXXXX */
713 #else
714 #error unsupported target CPU
715 #endif
717 /* fail safe : never use current_cpu outside cpu_exec() */
718 current_cpu = NULL;
719 return ret;