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