blob: 376b1bbeb11045731f12496a50a6450934b684ee [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
pbrook2e70f6e2008-06-29 01:03:05 +000054/* Execute the code without caching the generated code. An interpreter
55 could be used if available. */
Andreas Färber9349b4f2012-03-14 01:38:32 +010056static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
Blue Swirlcea5f9a2011-05-15 16:03:25 +000057 TranslationBlock *orig_tb)
pbrook2e70f6e2008-06-29 01:03:05 +000058{
Andreas Färberd77953b2013-01-16 19:29:31 +010059 CPUState *cpu = ENV_GET_CPU(env);
Stefan Weil69784ea2012-03-16 23:50:54 +010060 tcg_target_ulong next_tb;
pbrook2e70f6e2008-06-29 01:03:05 +000061 TranslationBlock *tb;
62
63 /* Should never happen.
64 We only end up here when an existing TB is too long. */
65 if (max_cycles > CF_COUNT_MASK)
66 max_cycles = CF_COUNT_MASK;
67
68 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
69 max_cycles);
Andreas Färberd77953b2013-01-16 19:29:31 +010070 cpu->current_tb = tb;
pbrook2e70f6e2008-06-29 01:03:05 +000071 /* execute the generated code */
Blue Swirlcea5f9a2011-05-15 16:03:25 +000072 next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
Andreas Färberd77953b2013-01-16 19:29:31 +010073 cpu->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +000074
75 if ((next_tb & 3) == 2) {
76 /* Restore PC. This may happen if async event occurs before
77 the TB starts executing. */
aliguori622ed362008-11-18 19:36:03 +000078 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +000079 }
80 tb_phys_invalidate(tb, -1);
81 tb_free(tb);
82}
83
Andreas Färber9349b4f2012-03-14 01:38:32 +010084static TranslationBlock *tb_find_slow(CPUArchState *env,
Blue Swirlcea5f9a2011-05-15 16:03:25 +000085 target_ulong pc,
bellard8a40a182005-11-20 10:35:40 +000086 target_ulong cs_base,
j_mayerc0686882007-09-20 22:47:42 +000087 uint64_t flags)
bellard8a40a182005-11-20 10:35:40 +000088{
89 TranslationBlock *tb, **ptb1;
bellard8a40a182005-11-20 10:35:40 +000090 unsigned int h;
Blue Swirl337fc752011-09-04 11:06:22 +000091 tb_page_addr_t phys_pc, phys_page1;
Paul Brook41c1b1c2010-03-12 16:54:58 +000092 target_ulong virt_page2;
ths3b46e622007-09-17 08:09:54 +000093
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +070094 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
ths3b46e622007-09-17 08:09:54 +000095
bellard8a40a182005-11-20 10:35:40 +000096 /* find translated block using physical mappings */
Paul Brook41c1b1c2010-03-12 16:54:58 +000097 phys_pc = get_page_addr_code(env, pc);
bellard8a40a182005-11-20 10:35:40 +000098 phys_page1 = phys_pc & TARGET_PAGE_MASK;
bellard8a40a182005-11-20 10:35:40 +000099 h = tb_phys_hash_func(phys_pc);
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700100 ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[h];
bellard8a40a182005-11-20 10:35:40 +0000101 for(;;) {
102 tb = *ptb1;
103 if (!tb)
104 goto not_found;
ths5fafdf22007-09-16 21:08:06 +0000105 if (tb->pc == pc &&
bellard8a40a182005-11-20 10:35:40 +0000106 tb->page_addr[0] == phys_page1 &&
ths5fafdf22007-09-16 21:08:06 +0000107 tb->cs_base == cs_base &&
bellard8a40a182005-11-20 10:35:40 +0000108 tb->flags == flags) {
109 /* check next page if needed */
110 if (tb->page_addr[1] != -1) {
Blue Swirl337fc752011-09-04 11:06:22 +0000111 tb_page_addr_t phys_page2;
112
ths5fafdf22007-09-16 21:08:06 +0000113 virt_page2 = (pc & TARGET_PAGE_MASK) +
bellard8a40a182005-11-20 10:35:40 +0000114 TARGET_PAGE_SIZE;
Paul Brook41c1b1c2010-03-12 16:54:58 +0000115 phys_page2 = get_page_addr_code(env, virt_page2);
bellard8a40a182005-11-20 10:35:40 +0000116 if (tb->page_addr[1] == phys_page2)
117 goto found;
118 } else {
119 goto found;
120 }
121 }
122 ptb1 = &tb->phys_hash_next;
123 }
124 not_found:
pbrook2e70f6e2008-06-29 01:03:05 +0000125 /* if no translated code available, then translate it now */
126 tb = tb_gen_code(env, pc, cs_base, flags, 0);
ths3b46e622007-09-17 08:09:54 +0000127
bellard8a40a182005-11-20 10:35:40 +0000128 found:
Kirill Batuzov2c90fe22010-12-02 16:12:46 +0300129 /* Move the last found TB to the head of the list */
130 if (likely(*ptb1)) {
131 *ptb1 = tb->phys_hash_next;
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700132 tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
133 tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
Kirill Batuzov2c90fe22010-12-02 16:12:46 +0300134 }
bellard8a40a182005-11-20 10:35:40 +0000135 /* we add the TB in the virtual pc hash table */
136 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
bellard8a40a182005-11-20 10:35:40 +0000137 return tb;
138}
139
Andreas Färber9349b4f2012-03-14 01:38:32 +0100140static inline TranslationBlock *tb_find_fast(CPUArchState *env)
bellard8a40a182005-11-20 10:35:40 +0000141{
142 TranslationBlock *tb;
143 target_ulong cs_base, pc;
aliguori6b917542008-11-18 19:46:41 +0000144 int flags;
bellard8a40a182005-11-20 10:35:40 +0000145
146 /* we record a subset of the CPU state. It will
147 always be the same before a given translated block
148 is executed. */
aliguori6b917542008-11-18 19:46:41 +0000149 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
bellardbce61842008-02-01 22:18:51 +0000150 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
ths551bd272008-07-03 17:57:36 +0000151 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
152 tb->flags != flags)) {
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000153 tb = tb_find_slow(env, pc, cs_base, flags);
bellard8a40a182005-11-20 10:35:40 +0000154 }
155 return tb;
156}
157
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100158static CPUDebugExcpHandler *debug_excp_handler;
159
Igor Mammedov84e3b602012-06-21 18:29:38 +0200160void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100161{
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100162 debug_excp_handler = handler;
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100163}
164
Andreas Färber9349b4f2012-03-14 01:38:32 +0100165static void cpu_handle_debug_exception(CPUArchState *env)
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100166{
167 CPUWatchpoint *wp;
168
169 if (!env->watchpoint_hit) {
170 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
171 wp->flags &= ~BP_WATCHPOINT_HIT;
172 }
173 }
174 if (debug_excp_handler) {
175 debug_excp_handler(env);
176 }
177}
178
bellard7d132992003-03-06 23:23:54 +0000179/* main execution loop */
180
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300181volatile sig_atomic_t exit_request;
182
Andreas Färber9349b4f2012-03-14 01:38:32 +0100183int cpu_exec(CPUArchState *env)
bellard7d132992003-03-06 23:23:54 +0000184{
Andreas Färberc356a1b2012-05-04 19:39:23 +0200185 CPUState *cpu = ENV_GET_CPU(env);
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100186#if !(defined(CONFIG_USER_ONLY) && \
187 (defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))
188 CPUClass *cc = CPU_GET_CLASS(cpu);
189#endif
bellard8a40a182005-11-20 10:35:40 +0000190 int ret, interrupt_request;
bellard8a40a182005-11-20 10:35:40 +0000191 TranslationBlock *tb;
bellardc27004e2005-01-03 23:35:10 +0000192 uint8_t *tc_ptr;
Stefan Weil69784ea2012-03-16 23:50:54 +0100193 tcg_target_ulong next_tb;
bellard8c6939c2003-06-09 15:28:00 +0000194
Andreas Färber84501402013-01-17 18:51:17 +0100195 if (cpu->halted) {
Andreas Färber3993c6b2012-05-03 06:43:49 +0200196 if (!cpu_has_work(cpu)) {
Paolo Bonzinieda48c32011-03-12 17:43:56 +0100197 return EXCP_HALTED;
198 }
199
Andreas Färber84501402013-01-17 18:51:17 +0100200 cpu->halted = 0;
Paolo Bonzinieda48c32011-03-12 17:43:56 +0100201 }
bellard5a1e3cf2005-11-23 21:02:53 +0000202
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000203 cpu_single_env = env;
bellarde4533c72003-06-15 19:51:39 +0000204
Jan Kiszkac629a4b2010-06-25 16:56:52 +0200205 if (unlikely(exit_request)) {
Andreas Färberfcd7d002012-12-17 08:02:44 +0100206 cpu->exit_request = 1;
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300207 }
208
thsecb644f2007-06-03 18:45:53 +0000209#if defined(TARGET_I386)
Jan Kiszka6792a572011-02-07 12:19:18 +0100210 /* put eflags in CPU temporary format */
211 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
212 DF = 1 - (2 * ((env->eflags >> 10) & 1));
213 CC_OP = CC_OP_EFLAGS;
214 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellard93ac68b2003-09-30 20:57:29 +0000215#elif defined(TARGET_SPARC)
pbrooke6e59062006-10-22 00:18:54 +0000216#elif defined(TARGET_M68K)
217 env->cc_op = CC_OP_FLAGS;
218 env->cc_dest = env->sr & 0xf;
219 env->cc_x = (env->sr >> 4) & 1;
thsecb644f2007-06-03 18:45:53 +0000220#elif defined(TARGET_ALPHA)
221#elif defined(TARGET_ARM)
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800222#elif defined(TARGET_UNICORE32)
thsecb644f2007-06-03 18:45:53 +0000223#elif defined(TARGET_PPC)
Elie Richa4e85f822011-07-22 05:58:39 +0000224 env->reserve_addr = -1;
Michael Walle81ea0e12011-02-17 23:45:02 +0100225#elif defined(TARGET_LM32)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200226#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000227#elif defined(TARGET_MIPS)
Jia Liue67db062012-07-20 15:50:39 +0800228#elif defined(TARGET_OPENRISC)
bellardfdf9b3e2006-04-27 21:07:38 +0000229#elif defined(TARGET_SH4)
thsf1ccf902007-10-08 13:16:14 +0000230#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100231#elif defined(TARGET_S390X)
Max Filippov23288262011-09-06 03:55:25 +0400232#elif defined(TARGET_XTENSA)
bellardfdf9b3e2006-04-27 21:07:38 +0000233 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000234#else
235#error unsupported target CPU
236#endif
bellard3fb2ded2003-06-24 13:22:59 +0000237 env->exception_index = -1;
bellard9d27abd2003-05-10 13:13:54 +0000238
bellard7d132992003-03-06 23:23:54 +0000239 /* prepare setjmp context for exception handling */
bellard3fb2ded2003-06-24 13:22:59 +0000240 for(;;) {
Peter Maydell6ab7e542013-02-20 15:21:09 +0000241 if (sigsetjmp(env->jmp_env, 0) == 0) {
bellard3fb2ded2003-06-24 13:22:59 +0000242 /* if an exception is pending, we execute it here */
243 if (env->exception_index >= 0) {
244 if (env->exception_index >= EXCP_INTERRUPT) {
245 /* exit request from the cpu execution loop */
246 ret = env->exception_index;
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100247 if (ret == EXCP_DEBUG) {
248 cpu_handle_debug_exception(env);
249 }
bellard3fb2ded2003-06-24 13:22:59 +0000250 break;
aurel3272d239e2009-01-14 19:40:27 +0000251 } else {
252#if defined(CONFIG_USER_ONLY)
bellard3fb2ded2003-06-24 13:22:59 +0000253 /* if user mode only, we simulate a fake exception
ths9f083492006-12-07 18:28:42 +0000254 which will be handled outside the cpu execution
bellard3fb2ded2003-06-24 13:22:59 +0000255 loop */
bellard83479e72003-06-25 16:12:37 +0000256#if defined(TARGET_I386)
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100257 cc->do_interrupt(cpu);
bellard83479e72003-06-25 16:12:37 +0000258#endif
bellard3fb2ded2003-06-24 13:22:59 +0000259 ret = env->exception_index;
260 break;
aurel3272d239e2009-01-14 19:40:27 +0000261#else
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100262 cc->do_interrupt(cpu);
Paolo Bonzini301d2902010-01-15 09:41:01 +0100263 env->exception_index = -1;
aurel3272d239e2009-01-14 19:40:27 +0000264#endif
bellard3fb2ded2003-06-24 13:22:59 +0000265 }
ths5fafdf22007-09-16 21:08:06 +0000266 }
bellard9df217a2005-02-10 22:05:51 +0000267
blueswir1b5fc09a2008-05-04 06:38:18 +0000268 next_tb = 0; /* force lookup of first TB */
bellard3fb2ded2003-06-24 13:22:59 +0000269 for(;;) {
Andreas Färber84501402013-01-17 18:51:17 +0100270 interrupt_request = cpu->interrupt_request;
malce1638bd2008-11-06 18:54:46 +0000271 if (unlikely(interrupt_request)) {
272 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
273 /* Mask out external interrupts for this step. */
Richard Henderson3125f762011-05-04 13:34:25 -0700274 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
malce1638bd2008-11-06 18:54:46 +0000275 }
pbrook6658ffb2007-03-16 23:58:11 +0000276 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
Andreas Färber84501402013-01-17 18:51:17 +0100277 cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
pbrook6658ffb2007-03-16 23:58:11 +0000278 env->exception_index = EXCP_DEBUG;
Blue Swirl1162c042011-05-14 12:52:35 +0000279 cpu_loop_exit(env);
pbrook6658ffb2007-03-16 23:58:11 +0000280 }
balroga90b7312007-05-01 01:28:01 +0000281#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200282 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800283 defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
balroga90b7312007-05-01 01:28:01 +0000284 if (interrupt_request & CPU_INTERRUPT_HALT) {
Andreas Färber84501402013-01-17 18:51:17 +0100285 cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
286 cpu->halted = 1;
balroga90b7312007-05-01 01:28:01 +0000287 env->exception_index = EXCP_HLT;
Blue Swirl1162c042011-05-14 12:52:35 +0000288 cpu_loop_exit(env);
balroga90b7312007-05-01 01:28:01 +0000289 }
290#endif
bellard68a79312003-06-30 13:12:32 +0000291#if defined(TARGET_I386)
Jan Kiszka5d62c432012-07-09 16:42:32 +0200292#if !defined(CONFIG_USER_ONLY)
293 if (interrupt_request & CPU_INTERRUPT_POLL) {
Andreas Färber84501402013-01-17 18:51:17 +0100294 cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
Jan Kiszka5d62c432012-07-09 16:42:32 +0200295 apic_poll_irq(env->apic_state);
296 }
297#endif
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300298 if (interrupt_request & CPU_INTERRUPT_INIT) {
Blue Swirl77b2bc22012-04-28 19:35:10 +0000299 cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
300 0);
Andreas Färber232fc232012-05-05 01:14:41 +0200301 do_cpu_init(x86_env_get_cpu(env));
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300302 env->exception_index = EXCP_HALTED;
Blue Swirl1162c042011-05-14 12:52:35 +0000303 cpu_loop_exit(env);
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300304 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
Andreas Färber232fc232012-05-05 01:14:41 +0200305 do_cpu_sipi(x86_env_get_cpu(env));
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300306 } else if (env->hflags2 & HF2_GIF_MASK) {
bellarddb620f42008-06-04 17:02:19 +0000307 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
308 !(env->hflags & HF_SMM_MASK)) {
Blue Swirl77b2bc22012-04-28 19:35:10 +0000309 cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
310 0);
Andreas Färber84501402013-01-17 18:51:17 +0100311 cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
Blue Swirle694d4e2011-05-16 19:38:48 +0000312 do_smm_enter(env);
bellarddb620f42008-06-04 17:02:19 +0000313 next_tb = 0;
314 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
315 !(env->hflags2 & HF2_NMI_MASK)) {
Andreas Färber84501402013-01-17 18:51:17 +0100316 cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
bellarddb620f42008-06-04 17:02:19 +0000317 env->hflags2 |= HF2_NMI_MASK;
Blue Swirle694d4e2011-05-16 19:38:48 +0000318 do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
bellarddb620f42008-06-04 17:02:19 +0000319 next_tb = 0;
陳韋任e965fc32012-02-06 14:02:55 +0800320 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
Andreas Färber84501402013-01-17 18:51:17 +0100321 cpu->interrupt_request &= ~CPU_INTERRUPT_MCE;
Blue Swirle694d4e2011-05-16 19:38:48 +0000322 do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
Huang Ying79c4f6b2009-06-23 10:05:14 +0800323 next_tb = 0;
bellarddb620f42008-06-04 17:02:19 +0000324 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
325 (((env->hflags2 & HF2_VINTR_MASK) &&
326 (env->hflags2 & HF2_HIF_MASK)) ||
327 (!(env->hflags2 & HF2_VINTR_MASK) &&
328 (env->eflags & IF_MASK &&
329 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
330 int intno;
Blue Swirl77b2bc22012-04-28 19:35:10 +0000331 cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,
332 0);
Andreas Färber84501402013-01-17 18:51:17 +0100333 cpu->interrupt_request &= ~(CPU_INTERRUPT_HARD |
334 CPU_INTERRUPT_VIRQ);
bellarddb620f42008-06-04 17:02:19 +0000335 intno = cpu_get_pic_interrupt(env);
malc4f213872012-08-27 18:33:12 +0400336 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
337 do_interrupt_x86_hardirq(env, intno, 1);
338 /* ensure that no TB jump will be modified as
339 the program flow was changed */
340 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000341#if !defined(CONFIG_USER_ONLY)
bellarddb620f42008-06-04 17:02:19 +0000342 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
343 (env->eflags & IF_MASK) &&
344 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
345 int intno;
346 /* FIXME: this should respect TPR */
Blue Swirl77b2bc22012-04-28 19:35:10 +0000347 cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR,
348 0);
bellarddb620f42008-06-04 17:02:19 +0000349 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
aliguori93fcfe32009-01-15 22:34:14 +0000350 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
Blue Swirle694d4e2011-05-16 19:38:48 +0000351 do_interrupt_x86_hardirq(env, intno, 1);
Andreas Färber84501402013-01-17 18:51:17 +0100352 cpu->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
bellarddb620f42008-06-04 17:02:19 +0000353 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000354#endif
bellarddb620f42008-06-04 17:02:19 +0000355 }
bellard68a79312003-06-30 13:12:32 +0000356 }
bellardce097762004-01-04 23:53:18 +0000357#elif defined(TARGET_PPC)
bellard9fddaa02004-05-21 12:59:32 +0000358 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
Andreas Färberc356a1b2012-05-04 19:39:23 +0200359 cpu_reset(cpu);
bellard9fddaa02004-05-21 12:59:32 +0000360 }
j_mayer47103572007-03-30 09:38:04 +0000361 if (interrupt_request & CPU_INTERRUPT_HARD) {
j_mayere9df0142007-04-09 22:45:36 +0000362 ppc_hw_interrupt(env);
Andreas Färber84501402013-01-17 18:51:17 +0100363 if (env->pending_interrupts == 0) {
364 cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;
365 }
blueswir1b5fc09a2008-05-04 06:38:18 +0000366 next_tb = 0;
bellardce097762004-01-04 23:53:18 +0000367 }
Michael Walle81ea0e12011-02-17 23:45:02 +0100368#elif defined(TARGET_LM32)
369 if ((interrupt_request & CPU_INTERRUPT_HARD)
370 && (env->ie & IE_IE)) {
371 env->exception_index = EXCP_IRQ;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100372 cc->do_interrupt(cpu);
Michael Walle81ea0e12011-02-17 23:45:02 +0100373 next_tb = 0;
374 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200375#elif defined(TARGET_MICROBLAZE)
376 if ((interrupt_request & CPU_INTERRUPT_HARD)
377 && (env->sregs[SR_MSR] & MSR_IE)
378 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
379 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
380 env->exception_index = EXCP_IRQ;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100381 cc->do_interrupt(cpu);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200382 next_tb = 0;
383 }
bellard6af0bf92005-07-02 14:58:51 +0000384#elif defined(TARGET_MIPS)
385 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
Aurelien Jarno4cdc1cd2010-12-25 22:56:32 +0100386 cpu_mips_hw_interrupts_pending(env)) {
bellard6af0bf92005-07-02 14:58:51 +0000387 /* Raise it */
388 env->exception_index = EXCP_EXT_INTERRUPT;
389 env->error_code = 0;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100390 cc->do_interrupt(cpu);
blueswir1b5fc09a2008-05-04 06:38:18 +0000391 next_tb = 0;
bellard6af0bf92005-07-02 14:58:51 +0000392 }
Jia Liub6a71ef2012-07-20 15:50:41 +0800393#elif defined(TARGET_OPENRISC)
394 {
395 int idx = -1;
396 if ((interrupt_request & CPU_INTERRUPT_HARD)
397 && (env->sr & SR_IEE)) {
398 idx = EXCP_INT;
399 }
400 if ((interrupt_request & CPU_INTERRUPT_TIMER)
401 && (env->sr & SR_TEE)) {
402 idx = EXCP_TICK;
403 }
404 if (idx >= 0) {
405 env->exception_index = idx;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100406 cc->do_interrupt(cpu);
Jia Liub6a71ef2012-07-20 15:50:41 +0800407 next_tb = 0;
408 }
409 }
bellarde95c8d52004-09-30 22:22:08 +0000410#elif defined(TARGET_SPARC)
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300411 if (interrupt_request & CPU_INTERRUPT_HARD) {
412 if (cpu_interrupts_enabled(env) &&
413 env->interrupt_index > 0) {
414 int pil = env->interrupt_index & 0xf;
415 int type = env->interrupt_index & 0xf0;
bellard66321a12005-04-06 20:47:48 +0000416
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300417 if (((type == TT_EXTINT) &&
418 cpu_pil_allowed(env, pil)) ||
419 type != TT_EXTINT) {
420 env->exception_index = env->interrupt_index;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100421 cc->do_interrupt(cpu);
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300422 next_tb = 0;
423 }
424 }
陳韋任e965fc32012-02-06 14:02:55 +0800425 }
bellardb5ff1b32005-11-26 10:38:39 +0000426#elif defined(TARGET_ARM)
427 if (interrupt_request & CPU_INTERRUPT_FIQ
428 && !(env->uncached_cpsr & CPSR_F)) {
429 env->exception_index = EXCP_FIQ;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100430 cc->do_interrupt(cpu);
blueswir1b5fc09a2008-05-04 06:38:18 +0000431 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000432 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000433 /* ARMv7-M interrupt return works by loading a magic value
434 into the PC. On real hardware the load causes the
435 return to occur. The qemu implementation performs the
436 jump normally, then does the exception return when the
437 CPU tries to execute code at the magic address.
438 This will cause the magic PC value to be pushed to
Stefan Weila1c72732011-04-28 17:20:38 +0200439 the stack if an interrupt occurred at the wrong time.
pbrook9ee6e8b2007-11-11 00:04:49 +0000440 We avoid this by disabling interrupts when
441 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000442 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000443 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
444 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000445 env->exception_index = EXCP_IRQ;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100446 cc->do_interrupt(cpu);
blueswir1b5fc09a2008-05-04 06:38:18 +0000447 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000448 }
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800449#elif defined(TARGET_UNICORE32)
450 if (interrupt_request & CPU_INTERRUPT_HARD
451 && !(env->uncached_asr & ASR_I)) {
Guan Xuetaod48813d2012-08-10 14:42:23 +0800452 env->exception_index = UC32_EXCP_INTR;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100453 cc->do_interrupt(cpu);
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800454 next_tb = 0;
455 }
bellardfdf9b3e2006-04-27 21:07:38 +0000456#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000457 if (interrupt_request & CPU_INTERRUPT_HARD) {
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100458 cc->do_interrupt(cpu);
blueswir1b5fc09a2008-05-04 06:38:18 +0000459 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000460 }
j_mayereddf68a2007-04-05 07:22:49 +0000461#elif defined(TARGET_ALPHA)
Richard Henderson6a80e082011-04-18 15:09:09 -0700462 {
463 int idx = -1;
464 /* ??? This hard-codes the OSF/1 interrupt levels. */
陳韋任e965fc32012-02-06 14:02:55 +0800465 switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
Richard Henderson6a80e082011-04-18 15:09:09 -0700466 case 0 ... 3:
467 if (interrupt_request & CPU_INTERRUPT_HARD) {
468 idx = EXCP_DEV_INTERRUPT;
469 }
470 /* FALLTHRU */
471 case 4:
472 if (interrupt_request & CPU_INTERRUPT_TIMER) {
473 idx = EXCP_CLK_INTERRUPT;
474 }
475 /* FALLTHRU */
476 case 5:
477 if (interrupt_request & CPU_INTERRUPT_SMP) {
478 idx = EXCP_SMP_INTERRUPT;
479 }
480 /* FALLTHRU */
481 case 6:
482 if (interrupt_request & CPU_INTERRUPT_MCHK) {
483 idx = EXCP_MCHK;
484 }
485 }
486 if (idx >= 0) {
487 env->exception_index = idx;
488 env->error_code = 0;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100489 cc->do_interrupt(cpu);
Richard Henderson6a80e082011-04-18 15:09:09 -0700490 next_tb = 0;
491 }
j_mayereddf68a2007-04-05 07:22:49 +0000492 }
thsf1ccf902007-10-08 13:16:14 +0000493#elif defined(TARGET_CRIS)
edgar_igl1b1a38b2008-06-09 23:18:06 +0000494 if (interrupt_request & CPU_INTERRUPT_HARD
Edgar E. Iglesiasfb9fb692010-02-15 11:17:33 +0100495 && (env->pregs[PR_CCS] & I_FLAG)
496 && !env->locked_irq) {
edgar_igl1b1a38b2008-06-09 23:18:06 +0000497 env->exception_index = EXCP_IRQ;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100498 cc->do_interrupt(cpu);
edgar_igl1b1a38b2008-06-09 23:18:06 +0000499 next_tb = 0;
500 }
Lars Persson82193142012-06-14 16:23:55 +0200501 if (interrupt_request & CPU_INTERRUPT_NMI) {
502 unsigned int m_flag_archval;
503 if (env->pregs[PR_VR] < 32) {
504 m_flag_archval = M_FLAG_V10;
505 } else {
506 m_flag_archval = M_FLAG_V32;
507 }
508 if ((env->pregs[PR_CCS] & m_flag_archval)) {
509 env->exception_index = EXCP_NMI;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100510 cc->do_interrupt(cpu);
Lars Persson82193142012-06-14 16:23:55 +0200511 next_tb = 0;
512 }
thsf1ccf902007-10-08 13:16:14 +0000513 }
pbrook06338792007-05-23 19:58:11 +0000514#elif defined(TARGET_M68K)
515 if (interrupt_request & CPU_INTERRUPT_HARD
516 && ((env->sr & SR_I) >> SR_I_SHIFT)
517 < env->pending_level) {
518 /* Real hardware gets the interrupt vector via an
519 IACK cycle at this point. Current emulated
520 hardware doesn't rely on this, so we
521 provide/save the vector when the interrupt is
522 first signalled. */
523 env->exception_index = env->pending_vector;
Blue Swirl3c688822011-05-21 07:55:24 +0000524 do_interrupt_m68k_hardirq(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000525 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000526 }
Alexander Graf3110e292011-04-15 17:32:48 +0200527#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
528 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
529 (env->psw.mask & PSW_MASK_EXT)) {
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100530 cc->do_interrupt(cpu);
Alexander Graf3110e292011-04-15 17:32:48 +0200531 next_tb = 0;
532 }
Max Filippov40643d72011-09-06 03:55:41 +0400533#elif defined(TARGET_XTENSA)
534 if (interrupt_request & CPU_INTERRUPT_HARD) {
535 env->exception_index = EXC_IRQ;
Andreas Färbere3d5f2c2013-02-02 10:57:51 +0100536 cc->do_interrupt(cpu);
Max Filippov40643d72011-09-06 03:55:41 +0400537 next_tb = 0;
538 }
bellard68a79312003-06-30 13:12:32 +0000539#endif
Stefan Weilff2712b2011-04-28 17:20:35 +0200540 /* Don't use the cached interrupt_request value,
bellard9d050952006-05-22 22:03:52 +0000541 do_interrupt may have updated the EXITTB flag. */
Andreas Färber84501402013-01-17 18:51:17 +0100542 if (cpu->interrupt_request & CPU_INTERRUPT_EXITTB) {
543 cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
bellardbf3e8bf2004-02-16 21:58:54 +0000544 /* ensure that no TB jump will be modified as
545 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000546 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000547 }
aurel32be214e62009-03-06 21:48:00 +0000548 }
Andreas Färberfcd7d002012-12-17 08:02:44 +0100549 if (unlikely(cpu->exit_request)) {
550 cpu->exit_request = 0;
aurel32be214e62009-03-06 21:48:00 +0000551 env->exception_index = EXCP_INTERRUPT;
Blue Swirl1162c042011-05-14 12:52:35 +0000552 cpu_loop_exit(env);
bellard3fb2ded2003-06-24 13:22:59 +0000553 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700554#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
aliguori8fec2b82009-01-15 22:36:53 +0000555 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000556 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000557#if defined(TARGET_I386)
Blue Swirle694d4e2011-05-16 19:38:48 +0000558 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
559 | (DF & DF_MASK);
Peter Maydell6fd2a022012-10-05 15:04:43 +0100560 log_cpu_state(env, CPU_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000561 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
pbrooke6e59062006-10-22 00:18:54 +0000562#elif defined(TARGET_M68K)
563 cpu_m68k_flush_flags(env, env->cc_op);
564 env->cc_op = CC_OP_FLAGS;
565 env->sr = (env->sr & 0xffe0)
566 | env->cc_dest | (env->cc_x << 4);
aliguori93fcfe32009-01-15 22:34:14 +0000567 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000568#else
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700569 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000570#endif
bellard3fb2ded2003-06-24 13:22:59 +0000571 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700572#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700573 spin_lock(&tcg_ctx.tb_ctx.tb_lock);
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000574 tb = tb_find_fast(env);
pbrookd5975362008-06-07 20:50:51 +0000575 /* Note: we do it here to avoid a gcc bug on Mac OS X when
576 doing it in tb_find_slow */
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700577 if (tcg_ctx.tb_ctx.tb_invalidated_flag) {
pbrookd5975362008-06-07 20:50:51 +0000578 /* as some TB could have been invalidated because
579 of memory exceptions while generating the code, we
580 must recompute the hash index here */
581 next_tb = 0;
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700582 tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
pbrookd5975362008-06-07 20:50:51 +0000583 }
Juan Quintelaf0667e62009-07-27 16:13:05 +0200584#ifdef CONFIG_DEBUG_EXEC
Stefan Weil3ba19252012-04-12 15:44:24 +0200585 qemu_log_mask(CPU_LOG_EXEC, "Trace %p [" TARGET_FMT_lx "] %s\n",
586 tb->tc_ptr, tb->pc,
aliguori93fcfe32009-01-15 22:34:14 +0000587 lookup_symbol(tb->pc));
bellard9d27abd2003-05-10 13:13:54 +0000588#endif
bellard8a40a182005-11-20 10:35:40 +0000589 /* see if we can patch the calling TB. When the TB
590 spans two pages, we cannot safely do a direct
591 jump. */
Paolo Bonzini040f2fb2010-01-15 08:56:36 +0100592 if (next_tb != 0 && tb->page_addr[1] == -1) {
blueswir1b5fc09a2008-05-04 06:38:18 +0000593 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000594 }
Evgeny Voevodin5e5f07e2013-02-01 01:47:23 +0700595 spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
malc55e8b852008-11-04 14:18:13 +0000596
597 /* cpu_interrupt might be called while translating the
598 TB, but before it is linked into a potentially
599 infinite loop and becomes env->current_tb. Avoid
600 starting execution if there is a pending interrupt. */
Andreas Färberd77953b2013-01-16 19:29:31 +0100601 cpu->current_tb = tb;
Jan Kiszkab0052d12010-06-25 16:56:50 +0200602 barrier();
Andreas Färberfcd7d002012-12-17 08:02:44 +0100603 if (likely(!cpu->exit_request)) {
pbrook2e70f6e2008-06-29 01:03:05 +0000604 tc_ptr = tb->tc_ptr;
陳韋任e965fc32012-02-06 14:02:55 +0800605 /* execute the generated code */
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000606 next_tb = tcg_qemu_tb_exec(env, tc_ptr);
pbrook2e70f6e2008-06-29 01:03:05 +0000607 if ((next_tb & 3) == 2) {
thsbf20dc02008-06-30 17:22:19 +0000608 /* Instruction counter expired. */
pbrook2e70f6e2008-06-29 01:03:05 +0000609 int insns_left;
Stefan Weil69784ea2012-03-16 23:50:54 +0100610 tb = (TranslationBlock *)(next_tb & ~3);
pbrook2e70f6e2008-06-29 01:03:05 +0000611 /* Restore PC. */
aliguori622ed362008-11-18 19:36:03 +0000612 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000613 insns_left = env->icount_decr.u32;
614 if (env->icount_extra && insns_left >= 0) {
615 /* Refill decrementer and continue execution. */
616 env->icount_extra += insns_left;
617 if (env->icount_extra > 0xffff) {
618 insns_left = 0xffff;
619 } else {
620 insns_left = env->icount_extra;
621 }
622 env->icount_extra -= insns_left;
623 env->icount_decr.u16.low = insns_left;
624 } else {
625 if (insns_left > 0) {
626 /* Execute remaining instructions. */
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000627 cpu_exec_nocache(env, insns_left, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000628 }
629 env->exception_index = EXCP_INTERRUPT;
630 next_tb = 0;
Blue Swirl1162c042011-05-14 12:52:35 +0000631 cpu_loop_exit(env);
pbrook2e70f6e2008-06-29 01:03:05 +0000632 }
633 }
634 }
Andreas Färberd77953b2013-01-16 19:29:31 +0100635 cpu->current_tb = NULL;
bellard4cbf74b2003-08-10 21:48:43 +0000636 /* reset soft MMU for next block (it can currently
637 only be set by a memory fault) */
ths50a518e2007-06-03 18:52:15 +0000638 } /* for(;;) */
Jan Kiszka0d101932011-07-02 09:50:51 +0200639 } else {
640 /* Reload env after longjmp - the compiler may have smashed all
641 * local variables as longjmp is marked 'noreturn'. */
642 env = cpu_single_env;
bellard7d132992003-03-06 23:23:54 +0000643 }
bellard3fb2ded2003-06-24 13:22:59 +0000644 } /* for(;;) */
645
bellard7d132992003-03-06 23:23:54 +0000646
bellarde4533c72003-06-15 19:51:39 +0000647#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000648 /* restore flags in standard format */
Blue Swirle694d4e2011-05-16 19:38:48 +0000649 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
650 | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000651#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000652 /* XXX: Save/restore host fpu exception state?. */
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800653#elif defined(TARGET_UNICORE32)
bellard93ac68b2003-09-30 20:57:29 +0000654#elif defined(TARGET_SPARC)
bellard67867302003-11-23 17:05:30 +0000655#elif defined(TARGET_PPC)
Michael Walle81ea0e12011-02-17 23:45:02 +0100656#elif defined(TARGET_LM32)
pbrooke6e59062006-10-22 00:18:54 +0000657#elif defined(TARGET_M68K)
658 cpu_m68k_flush_flags(env, env->cc_op);
659 env->cc_op = CC_OP_FLAGS;
660 env->sr = (env->sr & 0xffe0)
661 | env->cc_dest | (env->cc_x << 4);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200662#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000663#elif defined(TARGET_MIPS)
Jia Liue67db062012-07-20 15:50:39 +0800664#elif defined(TARGET_OPENRISC)
bellardfdf9b3e2006-04-27 21:07:38 +0000665#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000666#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000667#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100668#elif defined(TARGET_S390X)
Max Filippov23288262011-09-06 03:55:25 +0400669#elif defined(TARGET_XTENSA)
bellardfdf9b3e2006-04-27 21:07:38 +0000670 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000671#else
672#error unsupported target CPU
673#endif
pbrook1057eaa2007-02-04 13:37:44 +0000674
bellard6a00d602005-11-21 23:25:50 +0000675 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000676 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000677 return ret;
678}