Statistics
| Branch: | Revision:

root / cpu-exec.c @ 0d101938

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