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