blob: f9ea080e31df57d291d4b06d78b92092fb3aaf2d [file] [log] [blame]
bellard7d132992003-03-06 23:23:54 +00001/*
陳韋任e965fc32012-02-06 14:02:55 +08002 * emulator main execution loop
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard66321a12005-04-06 20:47:48 +00004 * Copyright (c) 2003-2005 Fabrice Bellard
bellard7d132992003-03-06 23:23:54 +00005 *
bellard3ef693a2003-03-23 20:17:16 +00006 * 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.
bellard7d132992003-03-06 23:23:54 +000010 *
bellard3ef693a2003-03-23 20:17:16 +000011 * 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.
bellard7d132992003-03-06 23:23:54 +000015 *
bellard3ef693a2003-03-23 20:17:16 +000016 * You should have received a copy of the GNU Lesser General Public
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellard7d132992003-03-06 23:23:54 +000018 */
bellarde4533c72003-06-15 19:51:39 +000019#include "config.h"
Blue Swirlcea5f9a2011-05-15 16:03:25 +000020#include "cpu.h"
Paolo Bonzini76cad712012-10-24 11:12:21 +020021#include "disas/disas.h"
bellard7cb69ca2008-05-10 10:55:51 +000022#include "tcg.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010023#include "qemu/atomic.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010024#include "sysemu/qtest.h"
bellard7d132992003-03-06 23:23:54 +000025
Juan Quintelaf0667e62009-07-27 16:13:05 +020026//#define CONFIG_DEBUG_EXEC
bellard7d132992003-03-06 23:23:54 +000027
Andreas Färber3993c6b2012-05-03 06:43:49 +020028bool qemu_cpu_has_work(CPUState *cpu)
aliguori6a4955a2009-04-24 18:03:20 +000029{
Andreas Färber3993c6b2012-05-03 06:43:49 +020030 return cpu_has_work(cpu);
aliguori6a4955a2009-04-24 18:03:20 +000031}
32
Andreas Färber9349b4f2012-03-14 01:38:32 +010033void cpu_loop_exit(CPUArchState *env)
bellarde4533c72003-06-15 19:51:39 +000034{
Andreas Färberd77953b2013-01-16 19:29:31 +010035 CPUState *cpu = ENV_GET_CPU(env);
36
37 cpu->current_tb = NULL;
Peter Maydell6ab7e542013-02-20 15:21:09 +000038 siglongjmp(env->jmp_env, 1);
bellarde4533c72003-06-15 19:51:39 +000039}
thsbfed01f2007-06-03 17:44:37 +000040
bellardfbf9eeb2004-04-25 21:21:33 +000041/* exit the current TB from a signal handler. The host registers are
42 restored in a state compatible with the CPU emulator
43 */
Blue Swirl9eff14f2011-05-21 08:42:35 +000044#if defined(CONFIG_SOFTMMU)
Andreas Färber9349b4f2012-03-14 01:38:32 +010045void cpu_resume_from_signal(CPUArchState *env, void *puc)
bellardfbf9eeb2004-04-25 21:21:33 +000046{
Blue Swirl9eff14f2011-05-21 08:42:35 +000047 /* XXX: restore cpu registers saved in host registers */
48
49 env->exception_index = -1;
Peter Maydell6ab7e542013-02-20 15:21:09 +000050 siglongjmp(env->jmp_env, 1);
Blue Swirl9eff14f2011-05-21 08:42:35 +000051}
Blue Swirl9eff14f2011-05-21 08:42:35 +000052#endif
bellardfbf9eeb2004-04-25 21:21:33 +000053
Peter Maydell77211372013-02-22 18:10:02 +000054/* 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 }
67 return next_tb;
68}
69
pbrook2e70f6e2008-06-29 01:03:05 +000070/* Execute the code without caching the generated code. An interpreter
71 could be used if available. */
Andreas Färber9349b4f2012-03-14 01:38:32 +010072static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
Blue Swirlcea5f9a2011-05-15 16:03:25 +000073 TranslationBlock *orig_tb)
pbrook2e70f6e2008-06-29 01:03:05 +000074{
Andreas Färberd77953b2013-01-16 19:29:31 +010075 CPUState *cpu = ENV_GET_CPU(env);
pbrook2e70f6e2008-06-29 01:03:05 +000076 TranslationBlock *tb;
77
78 /* Should never happen.
79 We only end up here when an existing TB is too long. */
80 if (max_cycles > CF_COUNT_MASK)
81 max_cycles = CF_COUNT_MASK;
82
83 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
84 max_cycles);
Andreas Färberd77953b2013-01-16 19:29:31 +010085 cpu->current_tb = tb;
pbrook2e70f6e2008-06-29 01:03:05 +000086 /* execute the generated code */
Peter Maydell77211372013-02-22 18:10:02 +000087 cpu_tb_exec(cpu, tb->tc_ptr);
Andreas Färberd77953b2013-01-16 19:29:31 +010088 cpu->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +000089 tb_phys_invalidate(tb, -1);
90 tb_free(tb);
91}
92
Andreas Färber9349b4f2012-03-14 01:38:32 +010093static TranslationBlock *tb_find_slow(CPUArchState *env,
Blue Swirlcea5f9a2011-05-15 16:03:25 +000094 target_ulong pc,
bellard8a40a182005-11-20 10:35:40 +000095 target_ulong cs_base,
j_mayerc0686882007-09-20 22:47:42 +000096 uint64_t flags)
bellard8a40a182005-11-20 10:35:40 +000097{
98 TranslationBlock *tb, **ptb1;
bellard8a40a182005-11-20 10:35:40 +000099 unsigned int h;
Blue Swirl337fc752011-09-04 11:06:22 +0000100 tb_page_addr_t phys_pc, phys_page1;
Paul Brook41c1b1c2010-03-12 16:54:58 +0000101 target_ulong virt_page2;
ths3b46e622007-09-17 08:09:54 +0000102
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700103 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
ths3b46e622007-09-17 08:09:54 +0000104
bellard8a40a182005-11-20 10:35:40 +0000105 /* find translated block using physical mappings */
Paul Brook41c1b1c2010-03-12 16:54:58 +0000106 phys_pc = get_page_addr_code(env, pc);
bellard8a40a182005-11-20 10:35:40 +0000107 phys_page1 = phys_pc & TARGET_PAGE_MASK;
bellard8a40a182005-11-20 10:35:40 +0000108 h = tb_phys_hash_func(phys_pc);
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700109 ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[h];
bellard8a40a182005-11-20 10:35:40 +0000110 for(;;) {
111 tb = *ptb1;
112 if (!tb)
113 goto not_found;
ths5fafdf22007-09-16 21:08:06 +0000114 if (tb->pc == pc &&
bellard8a40a182005-11-20 10:35:40 +0000115 tb->page_addr[0] == phys_page1 &&
ths5fafdf22007-09-16 21:08:06 +0000116 tb->cs_base == cs_base &&
bellard8a40a182005-11-20 10:35:40 +0000117 tb->flags == flags) {
118 /* check next page if needed */
119 if (tb->page_addr[1] != -1) {
Blue Swirl337fc752011-09-04 11:06:22 +0000120 tb_page_addr_t phys_page2;
121
ths5fafdf22007-09-16 21:08:06 +0000122 virt_page2 = (pc & TARGET_PAGE_MASK) +
bellard8a40a182005-11-20 10:35:40 +0000123 TARGET_PAGE_SIZE;
Paul Brook41c1b1c2010-03-12 16:54:58 +0000124 phys_page2 = get_page_addr_code(env, virt_page2);
bellard8a40a182005-11-20 10:35:40 +0000125 if (tb->page_addr[1] == phys_page2)
126 goto found;
127 } else {
128 goto found;
129 }
130 }
131 ptb1 = &tb->phys_hash_next;
132 }
133 not_found:
pbrook2e70f6e2008-06-29 01:03:05 +0000134 /* if no translated code available, then translate it now */
135 tb = tb_gen_code(env, pc, cs_base, flags, 0);
ths3b46e622007-09-17 08:09:54 +0000136
bellard8a40a182005-11-20 10:35:40 +0000137 found:
Kirill Batuzov2c90fe22010-12-02 16:12:46 +0300138 /* Move the last found TB to the head of the list */
139 if (likely(*ptb1)) {
140 *ptb1 = tb->phys_hash_next;
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700141 tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
142 tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
Kirill Batuzov2c90fe22010-12-02 16:12:46 +0300143 }
bellard8a40a182005-11-20 10:35:40 +0000144 /* we add the TB in the virtual pc hash table */
145 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
bellard8a40a182005-11-20 10:35:40 +0000146 return tb;
147}
148
Andreas Färber9349b4f2012-03-14 01:38:32 +0100149static inline TranslationBlock *tb_find_fast(CPUArchState *env)
bellard8a40a182005-11-20 10:35:40 +0000150{
151 TranslationBlock *tb;
152 target_ulong cs_base, pc;
aliguori6b917542008-11-18 19:46:41 +0000153 int flags;
bellard8a40a182005-11-20 10:35:40 +0000154
155 /* we record a subset of the CPU state. It will
156 always be the same before a given translated block
157 is executed. */
aliguori6b917542008-11-18 19:46:41 +0000158 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
bellardbce61842008-02-01 22:18:51 +0000159 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
ths551bd272008-07-03 17:57:36 +0000160 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
161 tb->flags != flags)) {
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000162 tb = tb_find_slow(env, pc, cs_base, flags);
bellard8a40a182005-11-20 10:35:40 +0000163 }
164 return tb;
165}
166
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100167static CPUDebugExcpHandler *debug_excp_handler;
168
Igor Mammedov84e3b602012-06-21 18:29:38 +0200169void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100170{
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100171 debug_excp_handler = handler;
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100172}
173
Andreas Färber9349b4f2012-03-14 01:38:32 +0100174static void cpu_handle_debug_exception(CPUArchState *env)
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100175{
176 CPUWatchpoint *wp;
177
178 if (!env->watchpoint_hit) {
179 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
180 wp->flags &= ~BP_WATCHPOINT_HIT;
181 }
182 }
183 if (debug_excp_handler) {
184 debug_excp_handler(env);
185 }
186}
187
bellard7d132992003-03-06 23:23:54 +0000188/* main execution loop */
189
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300190volatile sig_atomic_t exit_request;
191
Andreas Färber9349b4f2012-03-14 01:38:32 +0100192int cpu_exec(CPUArchState *env)
bellard7d132992003-03-06 23:23:54 +0000193{
Andreas Färberc356a1b2012-05-04 19:39:23 +0200194 CPUState *cpu = ENV_GET_CPU(env);
bellard8a40a182005-11-20 10:35:40 +0000195 int ret, interrupt_request;
bellard8a40a182005-11-20 10:35:40 +0000196 TranslationBlock *tb;
bellardc27004e2005-01-03 23:35:10 +0000197 uint8_t *tc_ptr;
Stefan Weil69784ea2012-03-16 23:50:54 +0100198 tcg_target_ulong next_tb;
bellard8c6939c2003-06-09 15:28:00 +0000199
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000200 if (env->halted) {
Andreas Färber3993c6b2012-05-03 06:43:49 +0200201 if (!cpu_has_work(cpu)) {
Paolo Bonzinieda48c32011-03-12 17:43:56 +0100202 return EXCP_HALTED;
203 }
204
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000205 env->halted = 0;
Paolo Bonzinieda48c32011-03-12 17:43:56 +0100206 }
bellard5a1e3cf2005-11-23 21:02:53 +0000207
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000208 cpu_single_env = env;
bellarde4533c72003-06-15 19:51:39 +0000209
Jan Kiszkac629a4b2010-06-25 16:56:52 +0200210 if (unlikely(exit_request)) {
Andreas Färberfcd7d002012-12-17 08:02:44 +0100211 cpu->exit_request = 1;
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300212 }
213
thsecb644f2007-06-03 18:45:53 +0000214#if defined(TARGET_I386)
Jan Kiszka6792a572011-02-07 12:19:18 +0100215 /* put eflags in CPU temporary format */
216 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
217 DF = 1 - (2 * ((env->eflags >> 10) & 1));
218 CC_OP = CC_OP_EFLAGS;
219 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellard93ac68b2003-09-30 20:57:29 +0000220#elif defined(TARGET_SPARC)
pbrooke6e59062006-10-22 00:18:54 +0000221#elif defined(TARGET_M68K)
222 env->cc_op = CC_OP_FLAGS;
223 env->cc_dest = env->sr & 0xf;
224 env->cc_x = (env->sr >> 4) & 1;
thsecb644f2007-06-03 18:45:53 +0000225#elif defined(TARGET_ALPHA)
226#elif defined(TARGET_ARM)
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800227#elif defined(TARGET_UNICORE32)
thsecb644f2007-06-03 18:45:53 +0000228#elif defined(TARGET_PPC)
Elie Richa4e85f822011-07-22 05:58:39 +0000229 env->reserve_addr = -1;
Michael Walle81ea0e12011-02-17 23:45:02 +0100230#elif defined(TARGET_LM32)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200231#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000232#elif defined(TARGET_MIPS)
Jia Liue67db062012-07-20 15:50:39 +0800233#elif defined(TARGET_OPENRISC)
bellardfdf9b3e2006-04-27 21:07:38 +0000234#elif defined(TARGET_SH4)
thsf1ccf902007-10-08 13:16:14 +0000235#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100236#elif defined(TARGET_S390X)
Max Filippov23288262011-09-06 03:55:25 +0400237#elif defined(TARGET_XTENSA)
bellardfdf9b3e2006-04-27 21:07:38 +0000238 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000239#else
240#error unsupported target CPU
241#endif
bellard3fb2ded2003-06-24 13:22:59 +0000242 env->exception_index = -1;
bellard9d27abd2003-05-10 13:13:54 +0000243
bellard7d132992003-03-06 23:23:54 +0000244 /* prepare setjmp context for exception handling */
bellard3fb2ded2003-06-24 13:22:59 +0000245 for(;;) {
Peter Maydell6ab7e542013-02-20 15:21:09 +0000246 if (sigsetjmp(env->jmp_env, 0) == 0) {
bellard3fb2ded2003-06-24 13:22:59 +0000247 /* if an exception is pending, we execute it here */
248 if (env->exception_index >= 0) {
249 if (env->exception_index >= EXCP_INTERRUPT) {
250 /* exit request from the cpu execution loop */
251 ret = env->exception_index;
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100252 if (ret == EXCP_DEBUG) {
253 cpu_handle_debug_exception(env);
254 }
bellard3fb2ded2003-06-24 13:22:59 +0000255 break;
aurel3272d239e2009-01-14 19:40:27 +0000256 } else {
257#if defined(CONFIG_USER_ONLY)
bellard3fb2ded2003-06-24 13:22:59 +0000258 /* if user mode only, we simulate a fake exception
ths9f083492006-12-07 18:28:42 +0000259 which will be handled outside the cpu execution
bellard3fb2ded2003-06-24 13:22:59 +0000260 loop */
bellard83479e72003-06-25 16:12:37 +0000261#if defined(TARGET_I386)
Blue Swirle694d4e2011-05-16 19:38:48 +0000262 do_interrupt(env);
bellard83479e72003-06-25 16:12:37 +0000263#endif
bellard3fb2ded2003-06-24 13:22:59 +0000264 ret = env->exception_index;
265 break;
aurel3272d239e2009-01-14 19:40:27 +0000266#else
Blue Swirle694d4e2011-05-16 19:38:48 +0000267 do_interrupt(env);
Paolo Bonzini301d2902010-01-15 09:41:01 +0100268 env->exception_index = -1;
aurel3272d239e2009-01-14 19:40:27 +0000269#endif
bellard3fb2ded2003-06-24 13:22:59 +0000270 }
ths5fafdf22007-09-16 21:08:06 +0000271 }
bellard9df217a2005-02-10 22:05:51 +0000272
blueswir1b5fc09a2008-05-04 06:38:18 +0000273 next_tb = 0; /* force lookup of first TB */
bellard3fb2ded2003-06-24 13:22:59 +0000274 for(;;) {
bellard68a79312003-06-30 13:12:32 +0000275 interrupt_request = env->interrupt_request;
malce1638bd2008-11-06 18:54:46 +0000276 if (unlikely(interrupt_request)) {
277 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
278 /* Mask out external interrupts for this step. */
Richard Henderson3125f762011-05-04 13:34:25 -0700279 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
malce1638bd2008-11-06 18:54:46 +0000280 }
pbrook6658ffb2007-03-16 23:58:11 +0000281 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
282 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
283 env->exception_index = EXCP_DEBUG;
Blue Swirl1162c042011-05-14 12:52:35 +0000284 cpu_loop_exit(env);
pbrook6658ffb2007-03-16 23:58:11 +0000285 }
balroga90b7312007-05-01 01:28:01 +0000286#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200287 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800288 defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
balroga90b7312007-05-01 01:28:01 +0000289 if (interrupt_request & CPU_INTERRUPT_HALT) {
290 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
291 env->halted = 1;
292 env->exception_index = EXCP_HLT;
Blue Swirl1162c042011-05-14 12:52:35 +0000293 cpu_loop_exit(env);
balroga90b7312007-05-01 01:28:01 +0000294 }
295#endif
bellard68a79312003-06-30 13:12:32 +0000296#if defined(TARGET_I386)
Jan Kiszka5d62c432012-07-09 16:42:32 +0200297#if !defined(CONFIG_USER_ONLY)
298 if (interrupt_request & CPU_INTERRUPT_POLL) {
299 env->interrupt_request &= ~CPU_INTERRUPT_POLL;
300 apic_poll_irq(env->apic_state);
301 }
302#endif
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300303 if (interrupt_request & CPU_INTERRUPT_INIT) {
Blue Swirl77b2bc22012-04-28 19:35:10 +0000304 cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
305 0);
Andreas Färber232fc232012-05-05 01:14:41 +0200306 do_cpu_init(x86_env_get_cpu(env));
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300307 env->exception_index = EXCP_HALTED;
Blue Swirl1162c042011-05-14 12:52:35 +0000308 cpu_loop_exit(env);
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300309 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
Andreas Färber232fc232012-05-05 01:14:41 +0200310 do_cpu_sipi(x86_env_get_cpu(env));
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300311 } else if (env->hflags2 & HF2_GIF_MASK) {
bellarddb620f42008-06-04 17:02:19 +0000312 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
313 !(env->hflags & HF_SMM_MASK)) {
Blue Swirl77b2bc22012-04-28 19:35:10 +0000314 cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
315 0);
bellarddb620f42008-06-04 17:02:19 +0000316 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
Blue Swirle694d4e2011-05-16 19:38:48 +0000317 do_smm_enter(env);
bellarddb620f42008-06-04 17:02:19 +0000318 next_tb = 0;
319 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
320 !(env->hflags2 & HF2_NMI_MASK)) {
321 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
322 env->hflags2 |= HF2_NMI_MASK;
Blue Swirle694d4e2011-05-16 19:38:48 +0000323 do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
bellarddb620f42008-06-04 17:02:19 +0000324 next_tb = 0;
陳韋任e965fc32012-02-06 14:02:55 +0800325 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
Huang Ying79c4f6b2009-06-23 10:05:14 +0800326 env->interrupt_request &= ~CPU_INTERRUPT_MCE;
Blue Swirle694d4e2011-05-16 19:38:48 +0000327 do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
Huang Ying79c4f6b2009-06-23 10:05:14 +0800328 next_tb = 0;
bellarddb620f42008-06-04 17:02:19 +0000329 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
330 (((env->hflags2 & HF2_VINTR_MASK) &&
331 (env->hflags2 & HF2_HIF_MASK)) ||
332 (!(env->hflags2 & HF2_VINTR_MASK) &&
333 (env->eflags & IF_MASK &&
334 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
335 int intno;
Blue Swirl77b2bc22012-04-28 19:35:10 +0000336 cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,
337 0);
bellarddb620f42008-06-04 17:02:19 +0000338 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
339 intno = cpu_get_pic_interrupt(env);
malc4f213872012-08-27 18:33:12 +0400340 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
341 do_interrupt_x86_hardirq(env, intno, 1);
342 /* ensure that no TB jump will be modified as
343 the program flow was changed */
344 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000345#if !defined(CONFIG_USER_ONLY)
bellarddb620f42008-06-04 17:02:19 +0000346 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
347 (env->eflags & IF_MASK) &&
348 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
349 int intno;
350 /* FIXME: this should respect TPR */
Blue Swirl77b2bc22012-04-28 19:35:10 +0000351 cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR,
352 0);
bellarddb620f42008-06-04 17:02:19 +0000353 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
aliguori93fcfe32009-01-15 22:34:14 +0000354 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
Blue Swirle694d4e2011-05-16 19:38:48 +0000355 do_interrupt_x86_hardirq(env, intno, 1);
aurel32d40c54d2008-12-13 12:33:02 +0000356 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
bellarddb620f42008-06-04 17:02:19 +0000357 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000358#endif
bellarddb620f42008-06-04 17:02:19 +0000359 }
bellard68a79312003-06-30 13:12:32 +0000360 }
bellardce097762004-01-04 23:53:18 +0000361#elif defined(TARGET_PPC)
bellard9fddaa02004-05-21 12:59:32 +0000362 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
Andreas Färberc356a1b2012-05-04 19:39:23 +0200363 cpu_reset(cpu);
bellard9fddaa02004-05-21 12:59:32 +0000364 }
j_mayer47103572007-03-30 09:38:04 +0000365 if (interrupt_request & CPU_INTERRUPT_HARD) {
j_mayere9df0142007-04-09 22:45:36 +0000366 ppc_hw_interrupt(env);
367 if (env->pending_interrupts == 0)
368 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1b5fc09a2008-05-04 06:38:18 +0000369 next_tb = 0;
bellardce097762004-01-04 23:53:18 +0000370 }
Michael Walle81ea0e12011-02-17 23:45:02 +0100371#elif defined(TARGET_LM32)
372 if ((interrupt_request & CPU_INTERRUPT_HARD)
373 && (env->ie & IE_IE)) {
374 env->exception_index = EXCP_IRQ;
375 do_interrupt(env);
376 next_tb = 0;
377 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200378#elif defined(TARGET_MICROBLAZE)
379 if ((interrupt_request & CPU_INTERRUPT_HARD)
380 && (env->sregs[SR_MSR] & MSR_IE)
381 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
382 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
383 env->exception_index = EXCP_IRQ;
384 do_interrupt(env);
385 next_tb = 0;
386 }
bellard6af0bf92005-07-02 14:58:51 +0000387#elif defined(TARGET_MIPS)
388 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
Aurelien Jarno4cdc1cd2010-12-25 22:56:32 +0100389 cpu_mips_hw_interrupts_pending(env)) {
bellard6af0bf92005-07-02 14:58:51 +0000390 /* Raise it */
391 env->exception_index = EXCP_EXT_INTERRUPT;
392 env->error_code = 0;
393 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000394 next_tb = 0;
bellard6af0bf92005-07-02 14:58:51 +0000395 }
Jia Liub6a71ef2012-07-20 15:50:41 +0800396#elif defined(TARGET_OPENRISC)
397 {
398 int idx = -1;
399 if ((interrupt_request & CPU_INTERRUPT_HARD)
400 && (env->sr & SR_IEE)) {
401 idx = EXCP_INT;
402 }
403 if ((interrupt_request & CPU_INTERRUPT_TIMER)
404 && (env->sr & SR_TEE)) {
405 idx = EXCP_TICK;
406 }
407 if (idx >= 0) {
408 env->exception_index = idx;
409 do_interrupt(env);
410 next_tb = 0;
411 }
412 }
bellarde95c8d52004-09-30 22:22:08 +0000413#elif defined(TARGET_SPARC)
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300414 if (interrupt_request & CPU_INTERRUPT_HARD) {
415 if (cpu_interrupts_enabled(env) &&
416 env->interrupt_index > 0) {
417 int pil = env->interrupt_index & 0xf;
418 int type = env->interrupt_index & 0xf0;
bellard66321a12005-04-06 20:47:48 +0000419
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300420 if (((type == TT_EXTINT) &&
421 cpu_pil_allowed(env, pil)) ||
422 type != TT_EXTINT) {
423 env->exception_index = env->interrupt_index;
424 do_interrupt(env);
425 next_tb = 0;
426 }
427 }
陳韋任e965fc32012-02-06 14:02:55 +0800428 }
bellardb5ff1b32005-11-26 10:38:39 +0000429#elif defined(TARGET_ARM)
430 if (interrupt_request & CPU_INTERRUPT_FIQ
431 && !(env->uncached_cpsr & CPSR_F)) {
432 env->exception_index = EXCP_FIQ;
433 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000434 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000435 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000436 /* ARMv7-M interrupt return works by loading a magic value
437 into the PC. On real hardware the load causes the
438 return to occur. The qemu implementation performs the
439 jump normally, then does the exception return when the
440 CPU tries to execute code at the magic address.
441 This will cause the magic PC value to be pushed to
Stefan Weila1c72732011-04-28 17:20:38 +0200442 the stack if an interrupt occurred at the wrong time.
pbrook9ee6e8b2007-11-11 00:04:49 +0000443 We avoid this by disabling interrupts when
444 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000445 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000446 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
447 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000448 env->exception_index = EXCP_IRQ;
449 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000450 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000451 }
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800452#elif defined(TARGET_UNICORE32)
453 if (interrupt_request & CPU_INTERRUPT_HARD
454 && !(env->uncached_asr & ASR_I)) {
Guan Xuetaod48813d2012-08-10 14:42:23 +0800455 env->exception_index = UC32_EXCP_INTR;
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800456 do_interrupt(env);
457 next_tb = 0;
458 }
bellardfdf9b3e2006-04-27 21:07:38 +0000459#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000460 if (interrupt_request & CPU_INTERRUPT_HARD) {
461 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000462 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000463 }
j_mayereddf68a2007-04-05 07:22:49 +0000464#elif defined(TARGET_ALPHA)
Richard Henderson6a80e082011-04-18 15:09:09 -0700465 {
466 int idx = -1;
467 /* ??? This hard-codes the OSF/1 interrupt levels. */
陳韋任e965fc32012-02-06 14:02:55 +0800468 switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
Richard Henderson6a80e082011-04-18 15:09:09 -0700469 case 0 ... 3:
470 if (interrupt_request & CPU_INTERRUPT_HARD) {
471 idx = EXCP_DEV_INTERRUPT;
472 }
473 /* FALLTHRU */
474 case 4:
475 if (interrupt_request & CPU_INTERRUPT_TIMER) {
476 idx = EXCP_CLK_INTERRUPT;
477 }
478 /* FALLTHRU */
479 case 5:
480 if (interrupt_request & CPU_INTERRUPT_SMP) {
481 idx = EXCP_SMP_INTERRUPT;
482 }
483 /* FALLTHRU */
484 case 6:
485 if (interrupt_request & CPU_INTERRUPT_MCHK) {
486 idx = EXCP_MCHK;
487 }
488 }
489 if (idx >= 0) {
490 env->exception_index = idx;
491 env->error_code = 0;
492 do_interrupt(env);
493 next_tb = 0;
494 }
j_mayereddf68a2007-04-05 07:22:49 +0000495 }
thsf1ccf902007-10-08 13:16:14 +0000496#elif defined(TARGET_CRIS)
edgar_igl1b1a38b2008-06-09 23:18:06 +0000497 if (interrupt_request & CPU_INTERRUPT_HARD
Edgar E. Iglesiasfb9fb692010-02-15 11:17:33 +0100498 && (env->pregs[PR_CCS] & I_FLAG)
499 && !env->locked_irq) {
edgar_igl1b1a38b2008-06-09 23:18:06 +0000500 env->exception_index = EXCP_IRQ;
501 do_interrupt(env);
502 next_tb = 0;
503 }
Lars Persson82193142012-06-14 16:23:55 +0200504 if (interrupt_request & CPU_INTERRUPT_NMI) {
505 unsigned int m_flag_archval;
506 if (env->pregs[PR_VR] < 32) {
507 m_flag_archval = M_FLAG_V10;
508 } else {
509 m_flag_archval = M_FLAG_V32;
510 }
511 if ((env->pregs[PR_CCS] & m_flag_archval)) {
512 env->exception_index = EXCP_NMI;
513 do_interrupt(env);
514 next_tb = 0;
515 }
thsf1ccf902007-10-08 13:16:14 +0000516 }
pbrook06338792007-05-23 19:58:11 +0000517#elif defined(TARGET_M68K)
518 if (interrupt_request & CPU_INTERRUPT_HARD
519 && ((env->sr & SR_I) >> SR_I_SHIFT)
520 < env->pending_level) {
521 /* Real hardware gets the interrupt vector via an
522 IACK cycle at this point. Current emulated
523 hardware doesn't rely on this, so we
524 provide/save the vector when the interrupt is
525 first signalled. */
526 env->exception_index = env->pending_vector;
Blue Swirl3c688822011-05-21 07:55:24 +0000527 do_interrupt_m68k_hardirq(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000528 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000529 }
Alexander Graf3110e292011-04-15 17:32:48 +0200530#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
531 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
532 (env->psw.mask & PSW_MASK_EXT)) {
533 do_interrupt(env);
534 next_tb = 0;
535 }
Max Filippov40643d72011-09-06 03:55:41 +0400536#elif defined(TARGET_XTENSA)
537 if (interrupt_request & CPU_INTERRUPT_HARD) {
538 env->exception_index = EXC_IRQ;
539 do_interrupt(env);
540 next_tb = 0;
541 }
bellard68a79312003-06-30 13:12:32 +0000542#endif
Stefan Weilff2712b2011-04-28 17:20:35 +0200543 /* Don't use the cached interrupt_request value,
bellard9d050952006-05-22 22:03:52 +0000544 do_interrupt may have updated the EXITTB flag. */
bellardb5ff1b32005-11-26 10:38:39 +0000545 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bellardbf3e8bf2004-02-16 21:58:54 +0000546 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
547 /* ensure that no TB jump will be modified as
548 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000549 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000550 }
aurel32be214e62009-03-06 21:48:00 +0000551 }
Andreas Färberfcd7d002012-12-17 08:02:44 +0100552 if (unlikely(cpu->exit_request)) {
553 cpu->exit_request = 0;
aurel32be214e62009-03-06 21:48:00 +0000554 env->exception_index = EXCP_INTERRUPT;
Blue Swirl1162c042011-05-14 12:52:35 +0000555 cpu_loop_exit(env);
bellard3fb2ded2003-06-24 13:22:59 +0000556 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700557#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
aliguori8fec2b82009-01-15 22:36:53 +0000558 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000559 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000560#if defined(TARGET_I386)
Blue Swirle694d4e2011-05-16 19:38:48 +0000561 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
562 | (DF & DF_MASK);
Peter Maydell6fd2a022012-10-05 15:04:43 +0100563 log_cpu_state(env, CPU_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000564 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
pbrooke6e59062006-10-22 00:18:54 +0000565#elif defined(TARGET_M68K)
566 cpu_m68k_flush_flags(env, env->cc_op);
567 env->cc_op = CC_OP_FLAGS;
568 env->sr = (env->sr & 0xffe0)
569 | env->cc_dest | (env->cc_x << 4);
aliguori93fcfe32009-01-15 22:34:14 +0000570 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000571#else
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700572 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000573#endif
bellard3fb2ded2003-06-24 13:22:59 +0000574 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700575#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700576 spin_lock(&tcg_ctx.tb_ctx.tb_lock);
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000577 tb = tb_find_fast(env);
pbrookd5975362008-06-07 20:50:51 +0000578 /* Note: we do it here to avoid a gcc bug on Mac OS X when
579 doing it in tb_find_slow */
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700580 if (tcg_ctx.tb_ctx.tb_invalidated_flag) {
pbrookd5975362008-06-07 20:50:51 +0000581 /* as some TB could have been invalidated because
582 of memory exceptions while generating the code, we
583 must recompute the hash index here */
584 next_tb = 0;
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700585 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
pbrookd5975362008-06-07 20:50:51 +0000586 }
Juan Quintelaf0667e62009-07-27 16:13:05 +0200587#ifdef CONFIG_DEBUG_EXEC
Stefan Weil3ba19252012-04-12 15:44:24 +0200588 qemu_log_mask(CPU_LOG_EXEC, "Trace %p [" TARGET_FMT_lx "] %s\n",
589 tb->tc_ptr, tb->pc,
aliguori93fcfe32009-01-15 22:34:14 +0000590 lookup_symbol(tb->pc));
bellard9d27abd2003-05-10 13:13:54 +0000591#endif
bellard8a40a182005-11-20 10:35:40 +0000592 /* see if we can patch the calling TB. When the TB
593 spans two pages, we cannot safely do a direct
594 jump. */
Paolo Bonzini040f2fb2010-01-15 08:56:36 +0100595 if (next_tb != 0 && tb->page_addr[1] == -1) {
Peter Maydell09800112013-02-22 18:10:00 +0000596 tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
597 next_tb & TB_EXIT_MASK, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000598 }
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700599 spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
malc55e8b852008-11-04 14:18:13 +0000600
601 /* cpu_interrupt might be called while translating the
602 TB, but before it is linked into a potentially
603 infinite loop and becomes env->current_tb. Avoid
604 starting execution if there is a pending interrupt. */
Andreas Färberd77953b2013-01-16 19:29:31 +0100605 cpu->current_tb = tb;
Jan Kiszkab0052d12010-06-25 16:56:50 +0200606 barrier();
Andreas Färberfcd7d002012-12-17 08:02:44 +0100607 if (likely(!cpu->exit_request)) {
pbrook2e70f6e2008-06-29 01:03:05 +0000608 tc_ptr = tb->tc_ptr;
陳韋任e965fc32012-02-06 14:02:55 +0800609 /* execute the generated code */
Peter Maydell77211372013-02-22 18:10:02 +0000610 next_tb = cpu_tb_exec(cpu, tc_ptr);
Peter Maydell09800112013-02-22 18:10:00 +0000611 if ((next_tb & TB_EXIT_MASK) == TB_EXIT_ICOUNT_EXPIRED) {
thsbf20dc02008-06-30 17:22:19 +0000612 /* Instruction counter expired. */
pbrook2e70f6e2008-06-29 01:03:05 +0000613 int insns_left;
Peter Maydell09800112013-02-22 18:10:00 +0000614 tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);
pbrook2e70f6e2008-06-29 01:03:05 +0000615 insns_left = env->icount_decr.u32;
616 if (env->icount_extra && insns_left >= 0) {
617 /* Refill decrementer and continue execution. */
618 env->icount_extra += insns_left;
619 if (env->icount_extra > 0xffff) {
620 insns_left = 0xffff;
621 } else {
622 insns_left = env->icount_extra;
623 }
624 env->icount_extra -= insns_left;
625 env->icount_decr.u16.low = insns_left;
626 } else {
627 if (insns_left > 0) {
628 /* Execute remaining instructions. */
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000629 cpu_exec_nocache(env, insns_left, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000630 }
631 env->exception_index = EXCP_INTERRUPT;
632 next_tb = 0;
Blue Swirl1162c042011-05-14 12:52:35 +0000633 cpu_loop_exit(env);
pbrook2e70f6e2008-06-29 01:03:05 +0000634 }
635 }
636 }
Andreas Färberd77953b2013-01-16 19:29:31 +0100637 cpu->current_tb = NULL;
bellard4cbf74b2003-08-10 21:48:43 +0000638 /* reset soft MMU for next block (it can currently
639 only be set by a memory fault) */
ths50a518e2007-06-03 18:52:15 +0000640 } /* for(;;) */
Jan Kiszka0d101932011-07-02 09:50:51 +0200641 } else {
642 /* Reload env after longjmp - the compiler may have smashed all
643 * local variables as longjmp is marked 'noreturn'. */
644 env = cpu_single_env;
bellard7d132992003-03-06 23:23:54 +0000645 }
bellard3fb2ded2003-06-24 13:22:59 +0000646 } /* for(;;) */
647
bellard7d132992003-03-06 23:23:54 +0000648
bellarde4533c72003-06-15 19:51:39 +0000649#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000650 /* restore flags in standard format */
Blue Swirle694d4e2011-05-16 19:38:48 +0000651 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
652 | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000653#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000654 /* XXX: Save/restore host fpu exception state?. */
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800655#elif defined(TARGET_UNICORE32)
bellard93ac68b2003-09-30 20:57:29 +0000656#elif defined(TARGET_SPARC)
bellard67867302003-11-23 17:05:30 +0000657#elif defined(TARGET_PPC)
Michael Walle81ea0e12011-02-17 23:45:02 +0100658#elif defined(TARGET_LM32)
pbrooke6e59062006-10-22 00:18:54 +0000659#elif defined(TARGET_M68K)
660 cpu_m68k_flush_flags(env, env->cc_op);
661 env->cc_op = CC_OP_FLAGS;
662 env->sr = (env->sr & 0xffe0)
663 | env->cc_dest | (env->cc_x << 4);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200664#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000665#elif defined(TARGET_MIPS)
Jia Liue67db062012-07-20 15:50:39 +0800666#elif defined(TARGET_OPENRISC)
bellardfdf9b3e2006-04-27 21:07:38 +0000667#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000668#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000669#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100670#elif defined(TARGET_S390X)
Max Filippov23288262011-09-06 03:55:25 +0400671#elif defined(TARGET_XTENSA)
bellardfdf9b3e2006-04-27 21:07:38 +0000672 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000673#else
674#error unsupported target CPU
675#endif
pbrook1057eaa2007-02-04 13:37:44 +0000676
bellard6a00d602005-11-21 23:25:50 +0000677 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000678 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000679 return ret;
680}