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