Statistics
| Branch: | Revision:

root / cpu-exec.c @ e7c5e893

History | View | Annotate | Download (25.2 kB)

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