Statistics
| Branch: | Revision:

root / cpu-exec.c @ e120d449

History | View | Annotate | Download (25.2 kB)

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