blob: 904ee73c7b55d748f5752d9ccd453f6c73b78929 [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"
bellard956034d2003-04-29 20:40:53 +000021#include "disas.h"
bellard7cb69ca2008-05-10 10:55:51 +000022#include "tcg.h"
Jan Kiszka1d93f0f2010-06-25 16:56:49 +020023#include "qemu-barrier.h"
Anthony Liguoric7f0f3b2012-03-28 15:42:02 +020024#include "qtest.h"
bellard7d132992003-03-06 23:23:54 +000025
bellard36bdbe52003-11-19 22:12:02 +000026int tb_invalidated_flag;
27
Juan Quintelaf0667e62009-07-27 16:13:05 +020028//#define CONFIG_DEBUG_EXEC
bellard7d132992003-03-06 23:23:54 +000029
Andreas Färber3993c6b2012-05-03 06:43:49 +020030bool qemu_cpu_has_work(CPUState *cpu)
aliguori6a4955a2009-04-24 18:03:20 +000031{
Andreas Färber3993c6b2012-05-03 06:43:49 +020032 return cpu_has_work(cpu);
aliguori6a4955a2009-04-24 18:03:20 +000033}
34
Andreas Färber9349b4f2012-03-14 01:38:32 +010035void cpu_loop_exit(CPUArchState *env)
bellarde4533c72003-06-15 19:51:39 +000036{
Blue Swirlcea5f9a2011-05-15 16:03:25 +000037 env->current_tb = NULL;
38 longjmp(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;
50 longjmp(env->jmp_env, 1);
51}
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{
Stefan Weil69784ea2012-03-16 23:50:54 +010059 tcg_target_ulong next_tb;
pbrook2e70f6e2008-06-29 01:03:05 +000060 TranslationBlock *tb;
61
62 /* Should never happen.
63 We only end up here when an existing TB is too long. */
64 if (max_cycles > CF_COUNT_MASK)
65 max_cycles = CF_COUNT_MASK;
66
67 tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
68 max_cycles);
69 env->current_tb = tb;
70 /* execute the generated code */
Blue Swirlcea5f9a2011-05-15 16:03:25 +000071 next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
Paolo Bonzini1c3569f2010-01-15 09:42:07 +010072 env->current_tb = NULL;
pbrook2e70f6e2008-06-29 01:03:05 +000073
74 if ((next_tb & 3) == 2) {
75 /* Restore PC. This may happen if async event occurs before
76 the TB starts executing. */
aliguori622ed362008-11-18 19:36:03 +000077 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +000078 }
79 tb_phys_invalidate(tb, -1);
80 tb_free(tb);
81}
82
Andreas Färber9349b4f2012-03-14 01:38:32 +010083static TranslationBlock *tb_find_slow(CPUArchState *env,
Blue Swirlcea5f9a2011-05-15 16:03:25 +000084 target_ulong pc,
bellard8a40a182005-11-20 10:35:40 +000085 target_ulong cs_base,
j_mayerc0686882007-09-20 22:47:42 +000086 uint64_t flags)
bellard8a40a182005-11-20 10:35:40 +000087{
88 TranslationBlock *tb, **ptb1;
bellard8a40a182005-11-20 10:35:40 +000089 unsigned int h;
Blue Swirl337fc752011-09-04 11:06:22 +000090 tb_page_addr_t phys_pc, phys_page1;
Paul Brook41c1b1c2010-03-12 16:54:58 +000091 target_ulong virt_page2;
ths3b46e622007-09-17 08:09:54 +000092
bellard8a40a182005-11-20 10:35:40 +000093 tb_invalidated_flag = 0;
ths3b46e622007-09-17 08:09:54 +000094
bellard8a40a182005-11-20 10:35:40 +000095 /* find translated block using physical mappings */
Paul Brook41c1b1c2010-03-12 16:54:58 +000096 phys_pc = get_page_addr_code(env, pc);
bellard8a40a182005-11-20 10:35:40 +000097 phys_page1 = phys_pc & TARGET_PAGE_MASK;
bellard8a40a182005-11-20 10:35:40 +000098 h = tb_phys_hash_func(phys_pc);
99 ptb1 = &tb_phys_hash[h];
100 for(;;) {
101 tb = *ptb1;
102 if (!tb)
103 goto not_found;
ths5fafdf22007-09-16 21:08:06 +0000104 if (tb->pc == pc &&
bellard8a40a182005-11-20 10:35:40 +0000105 tb->page_addr[0] == phys_page1 &&
ths5fafdf22007-09-16 21:08:06 +0000106 tb->cs_base == cs_base &&
bellard8a40a182005-11-20 10:35:40 +0000107 tb->flags == flags) {
108 /* check next page if needed */
109 if (tb->page_addr[1] != -1) {
Blue Swirl337fc752011-09-04 11:06:22 +0000110 tb_page_addr_t phys_page2;
111
ths5fafdf22007-09-16 21:08:06 +0000112 virt_page2 = (pc & TARGET_PAGE_MASK) +
bellard8a40a182005-11-20 10:35:40 +0000113 TARGET_PAGE_SIZE;
Paul Brook41c1b1c2010-03-12 16:54:58 +0000114 phys_page2 = get_page_addr_code(env, virt_page2);
bellard8a40a182005-11-20 10:35:40 +0000115 if (tb->page_addr[1] == phys_page2)
116 goto found;
117 } else {
118 goto found;
119 }
120 }
121 ptb1 = &tb->phys_hash_next;
122 }
123 not_found:
pbrook2e70f6e2008-06-29 01:03:05 +0000124 /* if no translated code available, then translate it now */
125 tb = tb_gen_code(env, pc, cs_base, flags, 0);
ths3b46e622007-09-17 08:09:54 +0000126
bellard8a40a182005-11-20 10:35:40 +0000127 found:
Kirill Batuzov2c90fe22010-12-02 16:12:46 +0300128 /* Move the last found TB to the head of the list */
129 if (likely(*ptb1)) {
130 *ptb1 = tb->phys_hash_next;
131 tb->phys_hash_next = tb_phys_hash[h];
132 tb_phys_hash[h] = tb;
133 }
bellard8a40a182005-11-20 10:35:40 +0000134 /* we add the TB in the virtual pc hash table */
135 env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
bellard8a40a182005-11-20 10:35:40 +0000136 return tb;
137}
138
Andreas Färber9349b4f2012-03-14 01:38:32 +0100139static inline TranslationBlock *tb_find_fast(CPUArchState *env)
bellard8a40a182005-11-20 10:35:40 +0000140{
141 TranslationBlock *tb;
142 target_ulong cs_base, pc;
aliguori6b917542008-11-18 19:46:41 +0000143 int flags;
bellard8a40a182005-11-20 10:35:40 +0000144
145 /* we record a subset of the CPU state. It will
146 always be the same before a given translated block
147 is executed. */
aliguori6b917542008-11-18 19:46:41 +0000148 cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
bellardbce61842008-02-01 22:18:51 +0000149 tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
ths551bd272008-07-03 17:57:36 +0000150 if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
151 tb->flags != flags)) {
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000152 tb = tb_find_slow(env, pc, cs_base, flags);
bellard8a40a182005-11-20 10:35:40 +0000153 }
154 return tb;
155}
156
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100157static CPUDebugExcpHandler *debug_excp_handler;
158
Igor Mammedov84e3b602012-06-21 18:29:38 +0200159void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100160{
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100161 debug_excp_handler = handler;
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100162}
163
Andreas Färber9349b4f2012-03-14 01:38:32 +0100164static void cpu_handle_debug_exception(CPUArchState *env)
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100165{
166 CPUWatchpoint *wp;
167
168 if (!env->watchpoint_hit) {
169 QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
170 wp->flags &= ~BP_WATCHPOINT_HIT;
171 }
172 }
173 if (debug_excp_handler) {
174 debug_excp_handler(env);
175 }
176}
177
bellard7d132992003-03-06 23:23:54 +0000178/* main execution loop */
179
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300180volatile sig_atomic_t exit_request;
181
Andreas Färber9349b4f2012-03-14 01:38:32 +0100182int cpu_exec(CPUArchState *env)
bellard7d132992003-03-06 23:23:54 +0000183{
Andreas Färberc356a1b2012-05-04 19:39:23 +0200184 CPUState *cpu = ENV_GET_CPU(env);
bellard8a40a182005-11-20 10:35:40 +0000185 int ret, interrupt_request;
bellard8a40a182005-11-20 10:35:40 +0000186 TranslationBlock *tb;
bellardc27004e2005-01-03 23:35:10 +0000187 uint8_t *tc_ptr;
Stefan Weil69784ea2012-03-16 23:50:54 +0100188 tcg_target_ulong next_tb;
bellard8c6939c2003-06-09 15:28:00 +0000189
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000190 if (env->halted) {
Andreas Färber3993c6b2012-05-03 06:43:49 +0200191 if (!cpu_has_work(cpu)) {
Paolo Bonzinieda48c32011-03-12 17:43:56 +0100192 return EXCP_HALTED;
193 }
194
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000195 env->halted = 0;
Paolo Bonzinieda48c32011-03-12 17:43:56 +0100196 }
bellard5a1e3cf2005-11-23 21:02:53 +0000197
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000198 cpu_single_env = env;
bellarde4533c72003-06-15 19:51:39 +0000199
Jan Kiszkac629a4b2010-06-25 16:56:52 +0200200 if (unlikely(exit_request)) {
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300201 env->exit_request = 1;
Marcelo Tosatti1a28cac2010-05-04 09:45:20 -0300202 }
203
thsecb644f2007-06-03 18:45:53 +0000204#if defined(TARGET_I386)
Jan Kiszka6792a572011-02-07 12:19:18 +0100205 /* put eflags in CPU temporary format */
206 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
207 DF = 1 - (2 * ((env->eflags >> 10) & 1));
208 CC_OP = CC_OP_EFLAGS;
209 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellard93ac68b2003-09-30 20:57:29 +0000210#elif defined(TARGET_SPARC)
pbrooke6e59062006-10-22 00:18:54 +0000211#elif defined(TARGET_M68K)
212 env->cc_op = CC_OP_FLAGS;
213 env->cc_dest = env->sr & 0xf;
214 env->cc_x = (env->sr >> 4) & 1;
thsecb644f2007-06-03 18:45:53 +0000215#elif defined(TARGET_ALPHA)
216#elif defined(TARGET_ARM)
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800217#elif defined(TARGET_UNICORE32)
thsecb644f2007-06-03 18:45:53 +0000218#elif defined(TARGET_PPC)
Elie Richa4e85f822011-07-22 05:58:39 +0000219 env->reserve_addr = -1;
Michael Walle81ea0e12011-02-17 23:45:02 +0100220#elif defined(TARGET_LM32)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200221#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000222#elif defined(TARGET_MIPS)
Jia Liue67db062012-07-20 15:50:39 +0800223#elif defined(TARGET_OPENRISC)
bellardfdf9b3e2006-04-27 21:07:38 +0000224#elif defined(TARGET_SH4)
thsf1ccf902007-10-08 13:16:14 +0000225#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100226#elif defined(TARGET_S390X)
Max Filippov23288262011-09-06 03:55:25 +0400227#elif defined(TARGET_XTENSA)
bellardfdf9b3e2006-04-27 21:07:38 +0000228 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000229#else
230#error unsupported target CPU
231#endif
bellard3fb2ded2003-06-24 13:22:59 +0000232 env->exception_index = -1;
bellard9d27abd2003-05-10 13:13:54 +0000233
bellard7d132992003-03-06 23:23:54 +0000234 /* prepare setjmp context for exception handling */
bellard3fb2ded2003-06-24 13:22:59 +0000235 for(;;) {
236 if (setjmp(env->jmp_env) == 0) {
237 /* if an exception is pending, we execute it here */
238 if (env->exception_index >= 0) {
239 if (env->exception_index >= EXCP_INTERRUPT) {
240 /* exit request from the cpu execution loop */
241 ret = env->exception_index;
Jan Kiszka1009d2e2011-03-15 12:26:13 +0100242 if (ret == EXCP_DEBUG) {
243 cpu_handle_debug_exception(env);
244 }
bellard3fb2ded2003-06-24 13:22:59 +0000245 break;
aurel3272d239e2009-01-14 19:40:27 +0000246 } else {
247#if defined(CONFIG_USER_ONLY)
bellard3fb2ded2003-06-24 13:22:59 +0000248 /* if user mode only, we simulate a fake exception
ths9f083492006-12-07 18:28:42 +0000249 which will be handled outside the cpu execution
bellard3fb2ded2003-06-24 13:22:59 +0000250 loop */
bellard83479e72003-06-25 16:12:37 +0000251#if defined(TARGET_I386)
Blue Swirle694d4e2011-05-16 19:38:48 +0000252 do_interrupt(env);
bellard83479e72003-06-25 16:12:37 +0000253#endif
bellard3fb2ded2003-06-24 13:22:59 +0000254 ret = env->exception_index;
255 break;
aurel3272d239e2009-01-14 19:40:27 +0000256#else
Blue Swirle694d4e2011-05-16 19:38:48 +0000257 do_interrupt(env);
Paolo Bonzini301d2902010-01-15 09:41:01 +0100258 env->exception_index = -1;
aurel3272d239e2009-01-14 19:40:27 +0000259#endif
bellard3fb2ded2003-06-24 13:22:59 +0000260 }
ths5fafdf22007-09-16 21:08:06 +0000261 }
bellard9df217a2005-02-10 22:05:51 +0000262
blueswir1b5fc09a2008-05-04 06:38:18 +0000263 next_tb = 0; /* force lookup of first TB */
bellard3fb2ded2003-06-24 13:22:59 +0000264 for(;;) {
bellard68a79312003-06-30 13:12:32 +0000265 interrupt_request = env->interrupt_request;
malce1638bd2008-11-06 18:54:46 +0000266 if (unlikely(interrupt_request)) {
267 if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
268 /* Mask out external interrupts for this step. */
Richard Henderson3125f762011-05-04 13:34:25 -0700269 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
malce1638bd2008-11-06 18:54:46 +0000270 }
pbrook6658ffb2007-03-16 23:58:11 +0000271 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
272 env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
273 env->exception_index = EXCP_DEBUG;
Blue Swirl1162c042011-05-14 12:52:35 +0000274 cpu_loop_exit(env);
pbrook6658ffb2007-03-16 23:58:11 +0000275 }
balroga90b7312007-05-01 01:28:01 +0000276#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200277 defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800278 defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)
balroga90b7312007-05-01 01:28:01 +0000279 if (interrupt_request & CPU_INTERRUPT_HALT) {
280 env->interrupt_request &= ~CPU_INTERRUPT_HALT;
281 env->halted = 1;
282 env->exception_index = EXCP_HLT;
Blue Swirl1162c042011-05-14 12:52:35 +0000283 cpu_loop_exit(env);
balroga90b7312007-05-01 01:28:01 +0000284 }
285#endif
bellard68a79312003-06-30 13:12:32 +0000286#if defined(TARGET_I386)
Jan Kiszka5d62c432012-07-09 16:42:32 +0200287#if !defined(CONFIG_USER_ONLY)
288 if (interrupt_request & CPU_INTERRUPT_POLL) {
289 env->interrupt_request &= ~CPU_INTERRUPT_POLL;
290 apic_poll_irq(env->apic_state);
291 }
292#endif
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300293 if (interrupt_request & CPU_INTERRUPT_INIT) {
Blue Swirl77b2bc22012-04-28 19:35:10 +0000294 cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
295 0);
Andreas Färber232fc232012-05-05 01:14:41 +0200296 do_cpu_init(x86_env_get_cpu(env));
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300297 env->exception_index = EXCP_HALTED;
Blue Swirl1162c042011-05-14 12:52:35 +0000298 cpu_loop_exit(env);
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300299 } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
Andreas Färber232fc232012-05-05 01:14:41 +0200300 do_cpu_sipi(x86_env_get_cpu(env));
Gleb Natapovb09ea7d2009-06-17 23:26:59 +0300301 } else if (env->hflags2 & HF2_GIF_MASK) {
bellarddb620f42008-06-04 17:02:19 +0000302 if ((interrupt_request & CPU_INTERRUPT_SMI) &&
303 !(env->hflags & HF_SMM_MASK)) {
Blue Swirl77b2bc22012-04-28 19:35:10 +0000304 cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
305 0);
bellarddb620f42008-06-04 17:02:19 +0000306 env->interrupt_request &= ~CPU_INTERRUPT_SMI;
Blue Swirle694d4e2011-05-16 19:38:48 +0000307 do_smm_enter(env);
bellarddb620f42008-06-04 17:02:19 +0000308 next_tb = 0;
309 } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
310 !(env->hflags2 & HF2_NMI_MASK)) {
311 env->interrupt_request &= ~CPU_INTERRUPT_NMI;
312 env->hflags2 |= HF2_NMI_MASK;
Blue Swirle694d4e2011-05-16 19:38:48 +0000313 do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
bellarddb620f42008-06-04 17:02:19 +0000314 next_tb = 0;
陳韋任e965fc32012-02-06 14:02:55 +0800315 } else if (interrupt_request & CPU_INTERRUPT_MCE) {
Huang Ying79c4f6b2009-06-23 10:05:14 +0800316 env->interrupt_request &= ~CPU_INTERRUPT_MCE;
Blue Swirle694d4e2011-05-16 19:38:48 +0000317 do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
Huang Ying79c4f6b2009-06-23 10:05:14 +0800318 next_tb = 0;
bellarddb620f42008-06-04 17:02:19 +0000319 } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
320 (((env->hflags2 & HF2_VINTR_MASK) &&
321 (env->hflags2 & HF2_HIF_MASK)) ||
322 (!(env->hflags2 & HF2_VINTR_MASK) &&
323 (env->eflags & IF_MASK &&
324 !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
325 int intno;
Blue Swirl77b2bc22012-04-28 19:35:10 +0000326 cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,
327 0);
bellarddb620f42008-06-04 17:02:19 +0000328 env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
329 intno = cpu_get_pic_interrupt(env);
malc4f213872012-08-27 18:33:12 +0400330 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
331 do_interrupt_x86_hardirq(env, intno, 1);
332 /* ensure that no TB jump will be modified as
333 the program flow was changed */
334 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000335#if !defined(CONFIG_USER_ONLY)
bellarddb620f42008-06-04 17:02:19 +0000336 } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
337 (env->eflags & IF_MASK) &&
338 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
339 int intno;
340 /* FIXME: this should respect TPR */
Blue Swirl77b2bc22012-04-28 19:35:10 +0000341 cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR,
342 0);
bellarddb620f42008-06-04 17:02:19 +0000343 intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
aliguori93fcfe32009-01-15 22:34:14 +0000344 qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
Blue Swirle694d4e2011-05-16 19:38:48 +0000345 do_interrupt_x86_hardirq(env, intno, 1);
aurel32d40c54d2008-12-13 12:33:02 +0000346 env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
bellarddb620f42008-06-04 17:02:19 +0000347 next_tb = 0;
ths0573fbf2007-09-23 15:28:04 +0000348#endif
bellarddb620f42008-06-04 17:02:19 +0000349 }
bellard68a79312003-06-30 13:12:32 +0000350 }
bellardce097762004-01-04 23:53:18 +0000351#elif defined(TARGET_PPC)
bellard9fddaa02004-05-21 12:59:32 +0000352 if ((interrupt_request & CPU_INTERRUPT_RESET)) {
Andreas Färberc356a1b2012-05-04 19:39:23 +0200353 cpu_reset(cpu);
bellard9fddaa02004-05-21 12:59:32 +0000354 }
j_mayer47103572007-03-30 09:38:04 +0000355 if (interrupt_request & CPU_INTERRUPT_HARD) {
j_mayere9df0142007-04-09 22:45:36 +0000356 ppc_hw_interrupt(env);
357 if (env->pending_interrupts == 0)
358 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
blueswir1b5fc09a2008-05-04 06:38:18 +0000359 next_tb = 0;
bellardce097762004-01-04 23:53:18 +0000360 }
Michael Walle81ea0e12011-02-17 23:45:02 +0100361#elif defined(TARGET_LM32)
362 if ((interrupt_request & CPU_INTERRUPT_HARD)
363 && (env->ie & IE_IE)) {
364 env->exception_index = EXCP_IRQ;
365 do_interrupt(env);
366 next_tb = 0;
367 }
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200368#elif defined(TARGET_MICROBLAZE)
369 if ((interrupt_request & CPU_INTERRUPT_HARD)
370 && (env->sregs[SR_MSR] & MSR_IE)
371 && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
372 && !(env->iflags & (D_FLAG | IMM_FLAG))) {
373 env->exception_index = EXCP_IRQ;
374 do_interrupt(env);
375 next_tb = 0;
376 }
bellard6af0bf92005-07-02 14:58:51 +0000377#elif defined(TARGET_MIPS)
378 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
Aurelien Jarno4cdc1cd2010-12-25 22:56:32 +0100379 cpu_mips_hw_interrupts_pending(env)) {
bellard6af0bf92005-07-02 14:58:51 +0000380 /* Raise it */
381 env->exception_index = EXCP_EXT_INTERRUPT;
382 env->error_code = 0;
383 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000384 next_tb = 0;
bellard6af0bf92005-07-02 14:58:51 +0000385 }
Jia Liub6a71ef2012-07-20 15:50:41 +0800386#elif defined(TARGET_OPENRISC)
387 {
388 int idx = -1;
389 if ((interrupt_request & CPU_INTERRUPT_HARD)
390 && (env->sr & SR_IEE)) {
391 idx = EXCP_INT;
392 }
393 if ((interrupt_request & CPU_INTERRUPT_TIMER)
394 && (env->sr & SR_TEE)) {
395 idx = EXCP_TICK;
396 }
397 if (idx >= 0) {
398 env->exception_index = idx;
399 do_interrupt(env);
400 next_tb = 0;
401 }
402 }
bellarde95c8d52004-09-30 22:22:08 +0000403#elif defined(TARGET_SPARC)
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300404 if (interrupt_request & CPU_INTERRUPT_HARD) {
405 if (cpu_interrupts_enabled(env) &&
406 env->interrupt_index > 0) {
407 int pil = env->interrupt_index & 0xf;
408 int type = env->interrupt_index & 0xf0;
bellard66321a12005-04-06 20:47:48 +0000409
Igor V. Kovalenkod532b262010-01-07 23:28:31 +0300410 if (((type == TT_EXTINT) &&
411 cpu_pil_allowed(env, pil)) ||
412 type != TT_EXTINT) {
413 env->exception_index = env->interrupt_index;
414 do_interrupt(env);
415 next_tb = 0;
416 }
417 }
陳韋任e965fc32012-02-06 14:02:55 +0800418 }
bellardb5ff1b32005-11-26 10:38:39 +0000419#elif defined(TARGET_ARM)
420 if (interrupt_request & CPU_INTERRUPT_FIQ
421 && !(env->uncached_cpsr & CPSR_F)) {
422 env->exception_index = EXCP_FIQ;
423 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000424 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000425 }
pbrook9ee6e8b2007-11-11 00:04:49 +0000426 /* ARMv7-M interrupt return works by loading a magic value
427 into the PC. On real hardware the load causes the
428 return to occur. The qemu implementation performs the
429 jump normally, then does the exception return when the
430 CPU tries to execute code at the magic address.
431 This will cause the magic PC value to be pushed to
Stefan Weila1c72732011-04-28 17:20:38 +0200432 the stack if an interrupt occurred at the wrong time.
pbrook9ee6e8b2007-11-11 00:04:49 +0000433 We avoid this by disabling interrupts when
434 pc contains a magic address. */
bellardb5ff1b32005-11-26 10:38:39 +0000435 if (interrupt_request & CPU_INTERRUPT_HARD
pbrook9ee6e8b2007-11-11 00:04:49 +0000436 && ((IS_M(env) && env->regs[15] < 0xfffffff0)
437 || !(env->uncached_cpsr & CPSR_I))) {
bellardb5ff1b32005-11-26 10:38:39 +0000438 env->exception_index = EXCP_IRQ;
439 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000440 next_tb = 0;
bellardb5ff1b32005-11-26 10:38:39 +0000441 }
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800442#elif defined(TARGET_UNICORE32)
443 if (interrupt_request & CPU_INTERRUPT_HARD
444 && !(env->uncached_asr & ASR_I)) {
Guan Xuetaod48813d2012-08-10 14:42:23 +0800445 env->exception_index = UC32_EXCP_INTR;
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800446 do_interrupt(env);
447 next_tb = 0;
448 }
bellardfdf9b3e2006-04-27 21:07:38 +0000449#elif defined(TARGET_SH4)
thse96e2042007-12-02 06:18:24 +0000450 if (interrupt_request & CPU_INTERRUPT_HARD) {
451 do_interrupt(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000452 next_tb = 0;
thse96e2042007-12-02 06:18:24 +0000453 }
j_mayereddf68a2007-04-05 07:22:49 +0000454#elif defined(TARGET_ALPHA)
Richard Henderson6a80e082011-04-18 15:09:09 -0700455 {
456 int idx = -1;
457 /* ??? This hard-codes the OSF/1 interrupt levels. */
陳韋任e965fc32012-02-06 14:02:55 +0800458 switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
Richard Henderson6a80e082011-04-18 15:09:09 -0700459 case 0 ... 3:
460 if (interrupt_request & CPU_INTERRUPT_HARD) {
461 idx = EXCP_DEV_INTERRUPT;
462 }
463 /* FALLTHRU */
464 case 4:
465 if (interrupt_request & CPU_INTERRUPT_TIMER) {
466 idx = EXCP_CLK_INTERRUPT;
467 }
468 /* FALLTHRU */
469 case 5:
470 if (interrupt_request & CPU_INTERRUPT_SMP) {
471 idx = EXCP_SMP_INTERRUPT;
472 }
473 /* FALLTHRU */
474 case 6:
475 if (interrupt_request & CPU_INTERRUPT_MCHK) {
476 idx = EXCP_MCHK;
477 }
478 }
479 if (idx >= 0) {
480 env->exception_index = idx;
481 env->error_code = 0;
482 do_interrupt(env);
483 next_tb = 0;
484 }
j_mayereddf68a2007-04-05 07:22:49 +0000485 }
thsf1ccf902007-10-08 13:16:14 +0000486#elif defined(TARGET_CRIS)
edgar_igl1b1a38b2008-06-09 23:18:06 +0000487 if (interrupt_request & CPU_INTERRUPT_HARD
Edgar E. Iglesiasfb9fb692010-02-15 11:17:33 +0100488 && (env->pregs[PR_CCS] & I_FLAG)
489 && !env->locked_irq) {
edgar_igl1b1a38b2008-06-09 23:18:06 +0000490 env->exception_index = EXCP_IRQ;
491 do_interrupt(env);
492 next_tb = 0;
493 }
Lars Persson82193142012-06-14 16:23:55 +0200494 if (interrupt_request & CPU_INTERRUPT_NMI) {
495 unsigned int m_flag_archval;
496 if (env->pregs[PR_VR] < 32) {
497 m_flag_archval = M_FLAG_V10;
498 } else {
499 m_flag_archval = M_FLAG_V32;
500 }
501 if ((env->pregs[PR_CCS] & m_flag_archval)) {
502 env->exception_index = EXCP_NMI;
503 do_interrupt(env);
504 next_tb = 0;
505 }
thsf1ccf902007-10-08 13:16:14 +0000506 }
pbrook06338792007-05-23 19:58:11 +0000507#elif defined(TARGET_M68K)
508 if (interrupt_request & CPU_INTERRUPT_HARD
509 && ((env->sr & SR_I) >> SR_I_SHIFT)
510 < env->pending_level) {
511 /* Real hardware gets the interrupt vector via an
512 IACK cycle at this point. Current emulated
513 hardware doesn't rely on this, so we
514 provide/save the vector when the interrupt is
515 first signalled. */
516 env->exception_index = env->pending_vector;
Blue Swirl3c688822011-05-21 07:55:24 +0000517 do_interrupt_m68k_hardirq(env);
blueswir1b5fc09a2008-05-04 06:38:18 +0000518 next_tb = 0;
pbrook06338792007-05-23 19:58:11 +0000519 }
Alexander Graf3110e292011-04-15 17:32:48 +0200520#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
521 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
522 (env->psw.mask & PSW_MASK_EXT)) {
523 do_interrupt(env);
524 next_tb = 0;
525 }
Max Filippov40643d72011-09-06 03:55:41 +0400526#elif defined(TARGET_XTENSA)
527 if (interrupt_request & CPU_INTERRUPT_HARD) {
528 env->exception_index = EXC_IRQ;
529 do_interrupt(env);
530 next_tb = 0;
531 }
bellard68a79312003-06-30 13:12:32 +0000532#endif
Stefan Weilff2712b2011-04-28 17:20:35 +0200533 /* Don't use the cached interrupt_request value,
bellard9d050952006-05-22 22:03:52 +0000534 do_interrupt may have updated the EXITTB flag. */
bellardb5ff1b32005-11-26 10:38:39 +0000535 if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
bellardbf3e8bf2004-02-16 21:58:54 +0000536 env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
537 /* ensure that no TB jump will be modified as
538 the program flow was changed */
blueswir1b5fc09a2008-05-04 06:38:18 +0000539 next_tb = 0;
bellardbf3e8bf2004-02-16 21:58:54 +0000540 }
aurel32be214e62009-03-06 21:48:00 +0000541 }
542 if (unlikely(env->exit_request)) {
543 env->exit_request = 0;
544 env->exception_index = EXCP_INTERRUPT;
Blue Swirl1162c042011-05-14 12:52:35 +0000545 cpu_loop_exit(env);
bellard3fb2ded2003-06-24 13:22:59 +0000546 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700547#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
aliguori8fec2b82009-01-15 22:36:53 +0000548 if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
bellard3fb2ded2003-06-24 13:22:59 +0000549 /* restore flags in standard format */
thsecb644f2007-06-03 18:45:53 +0000550#if defined(TARGET_I386)
Blue Swirle694d4e2011-05-16 19:38:48 +0000551 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
552 | (DF & DF_MASK);
Peter Maydell6fd2a022012-10-05 15:04:43 +0100553 log_cpu_state(env, CPU_DUMP_CCOP);
bellard3fb2ded2003-06-24 13:22:59 +0000554 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
pbrooke6e59062006-10-22 00:18:54 +0000555#elif defined(TARGET_M68K)
556 cpu_m68k_flush_flags(env, env->cc_op);
557 env->cc_op = CC_OP_FLAGS;
558 env->sr = (env->sr & 0xffe0)
559 | env->cc_dest | (env->cc_x << 4);
aliguori93fcfe32009-01-15 22:34:14 +0000560 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000561#else
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700562 log_cpu_state(env, 0);
bellarde4533c72003-06-15 19:51:39 +0000563#endif
bellard3fb2ded2003-06-24 13:22:59 +0000564 }
Richard Hendersona73b1fd2010-04-28 16:07:57 -0700565#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
pbrookd5975362008-06-07 20:50:51 +0000566 spin_lock(&tb_lock);
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000567 tb = tb_find_fast(env);
pbrookd5975362008-06-07 20:50:51 +0000568 /* Note: we do it here to avoid a gcc bug on Mac OS X when
569 doing it in tb_find_slow */
570 if (tb_invalidated_flag) {
571 /* as some TB could have been invalidated because
572 of memory exceptions while generating the code, we
573 must recompute the hash index here */
574 next_tb = 0;
pbrook2e70f6e2008-06-29 01:03:05 +0000575 tb_invalidated_flag = 0;
pbrookd5975362008-06-07 20:50:51 +0000576 }
Juan Quintelaf0667e62009-07-27 16:13:05 +0200577#ifdef CONFIG_DEBUG_EXEC
Stefan Weil3ba19252012-04-12 15:44:24 +0200578 qemu_log_mask(CPU_LOG_EXEC, "Trace %p [" TARGET_FMT_lx "] %s\n",
579 tb->tc_ptr, tb->pc,
aliguori93fcfe32009-01-15 22:34:14 +0000580 lookup_symbol(tb->pc));
bellard9d27abd2003-05-10 13:13:54 +0000581#endif
bellard8a40a182005-11-20 10:35:40 +0000582 /* see if we can patch the calling TB. When the TB
583 spans two pages, we cannot safely do a direct
584 jump. */
Paolo Bonzini040f2fb2010-01-15 08:56:36 +0100585 if (next_tb != 0 && tb->page_addr[1] == -1) {
blueswir1b5fc09a2008-05-04 06:38:18 +0000586 tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
bellard3fb2ded2003-06-24 13:22:59 +0000587 }
pbrookd5975362008-06-07 20:50:51 +0000588 spin_unlock(&tb_lock);
malc55e8b852008-11-04 14:18:13 +0000589
590 /* cpu_interrupt might be called while translating the
591 TB, but before it is linked into a potentially
592 infinite loop and becomes env->current_tb. Avoid
593 starting execution if there is a pending interrupt. */
Jan Kiszkab0052d12010-06-25 16:56:50 +0200594 env->current_tb = tb;
595 barrier();
596 if (likely(!env->exit_request)) {
pbrook2e70f6e2008-06-29 01:03:05 +0000597 tc_ptr = tb->tc_ptr;
陳韋任e965fc32012-02-06 14:02:55 +0800598 /* execute the generated code */
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000599 next_tb = tcg_qemu_tb_exec(env, tc_ptr);
pbrook2e70f6e2008-06-29 01:03:05 +0000600 if ((next_tb & 3) == 2) {
thsbf20dc02008-06-30 17:22:19 +0000601 /* Instruction counter expired. */
pbrook2e70f6e2008-06-29 01:03:05 +0000602 int insns_left;
Stefan Weil69784ea2012-03-16 23:50:54 +0100603 tb = (TranslationBlock *)(next_tb & ~3);
pbrook2e70f6e2008-06-29 01:03:05 +0000604 /* Restore PC. */
aliguori622ed362008-11-18 19:36:03 +0000605 cpu_pc_from_tb(env, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000606 insns_left = env->icount_decr.u32;
607 if (env->icount_extra && insns_left >= 0) {
608 /* Refill decrementer and continue execution. */
609 env->icount_extra += insns_left;
610 if (env->icount_extra > 0xffff) {
611 insns_left = 0xffff;
612 } else {
613 insns_left = env->icount_extra;
614 }
615 env->icount_extra -= insns_left;
616 env->icount_decr.u16.low = insns_left;
617 } else {
618 if (insns_left > 0) {
619 /* Execute remaining instructions. */
Blue Swirlcea5f9a2011-05-15 16:03:25 +0000620 cpu_exec_nocache(env, insns_left, tb);
pbrook2e70f6e2008-06-29 01:03:05 +0000621 }
622 env->exception_index = EXCP_INTERRUPT;
623 next_tb = 0;
Blue Swirl1162c042011-05-14 12:52:35 +0000624 cpu_loop_exit(env);
pbrook2e70f6e2008-06-29 01:03:05 +0000625 }
626 }
627 }
Jan Kiszkab0052d12010-06-25 16:56:50 +0200628 env->current_tb = NULL;
bellard4cbf74b2003-08-10 21:48:43 +0000629 /* reset soft MMU for next block (it can currently
630 only be set by a memory fault) */
ths50a518e2007-06-03 18:52:15 +0000631 } /* for(;;) */
Jan Kiszka0d101932011-07-02 09:50:51 +0200632 } else {
633 /* Reload env after longjmp - the compiler may have smashed all
634 * local variables as longjmp is marked 'noreturn'. */
635 env = cpu_single_env;
bellard7d132992003-03-06 23:23:54 +0000636 }
bellard3fb2ded2003-06-24 13:22:59 +0000637 } /* for(;;) */
638
bellard7d132992003-03-06 23:23:54 +0000639
bellarde4533c72003-06-15 19:51:39 +0000640#if defined(TARGET_I386)
bellard9de5e442003-03-23 16:49:39 +0000641 /* restore flags in standard format */
Blue Swirle694d4e2011-05-16 19:38:48 +0000642 env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
643 | (DF & DF_MASK);
bellarde4533c72003-06-15 19:51:39 +0000644#elif defined(TARGET_ARM)
bellardb7bcbe92005-02-22 19:27:29 +0000645 /* XXX: Save/restore host fpu exception state?. */
Guan Xuetaod2fbca92011-04-12 16:27:03 +0800646#elif defined(TARGET_UNICORE32)
bellard93ac68b2003-09-30 20:57:29 +0000647#elif defined(TARGET_SPARC)
bellard67867302003-11-23 17:05:30 +0000648#elif defined(TARGET_PPC)
Michael Walle81ea0e12011-02-17 23:45:02 +0100649#elif defined(TARGET_LM32)
pbrooke6e59062006-10-22 00:18:54 +0000650#elif defined(TARGET_M68K)
651 cpu_m68k_flush_flags(env, env->cc_op);
652 env->cc_op = CC_OP_FLAGS;
653 env->sr = (env->sr & 0xffe0)
654 | env->cc_dest | (env->cc_x << 4);
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200655#elif defined(TARGET_MICROBLAZE)
bellard6af0bf92005-07-02 14:58:51 +0000656#elif defined(TARGET_MIPS)
Jia Liue67db062012-07-20 15:50:39 +0800657#elif defined(TARGET_OPENRISC)
bellardfdf9b3e2006-04-27 21:07:38 +0000658#elif defined(TARGET_SH4)
j_mayereddf68a2007-04-05 07:22:49 +0000659#elif defined(TARGET_ALPHA)
thsf1ccf902007-10-08 13:16:14 +0000660#elif defined(TARGET_CRIS)
Alexander Graf10ec5112009-12-05 12:44:21 +0100661#elif defined(TARGET_S390X)
Max Filippov23288262011-09-06 03:55:25 +0400662#elif defined(TARGET_XTENSA)
bellardfdf9b3e2006-04-27 21:07:38 +0000663 /* XXXXX */
bellarde4533c72003-06-15 19:51:39 +0000664#else
665#error unsupported target CPU
666#endif
pbrook1057eaa2007-02-04 13:37:44 +0000667
bellard6a00d602005-11-21 23:25:50 +0000668 /* fail safe : never use cpu_single_env outside cpu_exec() */
ths5fafdf22007-09-16 21:08:06 +0000669 cpu_single_env = NULL;
bellard7d132992003-03-06 23:23:54 +0000670 return ret;
671}