Statistics
| Branch: | Revision:

root / cpu-exec.c @ 5f8ae8e2

History | View | Annotate | Download (26.9 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 3993c6bd Andreas Färber
bool qemu_cpu_has_work(CPUState *cpu)
31 6a4955a8 aliguori
{
32 3993c6bd Andreas Färber
    return cpu_has_work(cpu);
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 84e3b602 Igor Mammedov
void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
160 1009d2ed Jan Kiszka
{
161 1009d2ed Jan Kiszka
    debug_excp_handler = handler;
162 1009d2ed Jan Kiszka
}
163 1009d2ed Jan Kiszka
164 9349b4f9 Andreas Färber
static void cpu_handle_debug_exception(CPUArchState *env)
165 1009d2ed Jan Kiszka
{
166 1009d2ed Jan Kiszka
    CPUWatchpoint *wp;
167 1009d2ed Jan Kiszka
168 1009d2ed Jan Kiszka
    if (!env->watchpoint_hit) {
169 1009d2ed Jan Kiszka
        QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
170 1009d2ed Jan Kiszka
            wp->flags &= ~BP_WATCHPOINT_HIT;
171 1009d2ed Jan Kiszka
        }
172 1009d2ed Jan Kiszka
    }
173 1009d2ed Jan Kiszka
    if (debug_excp_handler) {
174 1009d2ed Jan Kiszka
        debug_excp_handler(env);
175 1009d2ed Jan Kiszka
    }
176 1009d2ed Jan Kiszka
}
177 1009d2ed Jan Kiszka
178 7d13299d bellard
/* main execution loop */
179 7d13299d bellard
180 1a28cac3 Marcelo Tosatti
volatile sig_atomic_t exit_request;
181 1a28cac3 Marcelo Tosatti
182 9349b4f9 Andreas Färber
int cpu_exec(CPUArchState *env)
183 7d13299d bellard
{
184 c356a1bc Andreas Färber
    CPUState *cpu = ENV_GET_CPU(env);
185 8a40a180 bellard
    int ret, interrupt_request;
186 8a40a180 bellard
    TranslationBlock *tb;
187 c27004ec bellard
    uint8_t *tc_ptr;
188 69784eae Stefan Weil
    tcg_target_ulong next_tb;
189 8c6939c0 bellard
190 cea5f9a2 Blue Swirl
    if (env->halted) {
191 3993c6bd Andreas Färber
        if (!cpu_has_work(cpu)) {
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 4e85f82c Elie Richa
    env->reserve_addr = -1;
220 81ea0e13 Michael Walle
#elif defined(TARGET_LM32)
221 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
222 6af0bf9c bellard
#elif defined(TARGET_MIPS)
223 e67db06e Jia Liu
#elif defined(TARGET_OPENRISC)
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 5d62c43a Jan Kiszka
#if !defined(CONFIG_USER_ONLY)
288 5d62c43a Jan Kiszka
                    if (interrupt_request & CPU_INTERRUPT_POLL) {
289 5d62c43a Jan Kiszka
                        env->interrupt_request &= ~CPU_INTERRUPT_POLL;
290 5d62c43a Jan Kiszka
                        apic_poll_irq(env->apic_state);
291 5d62c43a Jan Kiszka
                    }
292 5d62c43a Jan Kiszka
#endif
293 b09ea7d5 Gleb Natapov
                    if (interrupt_request & CPU_INTERRUPT_INIT) {
294 77b2bc2c Blue Swirl
                            cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,
295 77b2bc2c Blue Swirl
                                                          0);
296 232fc23b Andreas Färber
                            do_cpu_init(x86_env_get_cpu(env));
297 b09ea7d5 Gleb Natapov
                            env->exception_index = EXCP_HALTED;
298 1162c041 Blue Swirl
                            cpu_loop_exit(env);
299 b09ea7d5 Gleb Natapov
                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
300 232fc23b Andreas Färber
                            do_cpu_sipi(x86_env_get_cpu(env));
301 b09ea7d5 Gleb Natapov
                    } else if (env->hflags2 & HF2_GIF_MASK) {
302 db620f46 bellard
                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
303 db620f46 bellard
                            !(env->hflags & HF_SMM_MASK)) {
304 77b2bc2c Blue Swirl
                            cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,
305 77b2bc2c Blue Swirl
                                                          0);
306 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
307 e694d4e2 Blue Swirl
                            do_smm_enter(env);
308 db620f46 bellard
                            next_tb = 0;
309 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
310 db620f46 bellard
                                   !(env->hflags2 & HF2_NMI_MASK)) {
311 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
312 db620f46 bellard
                            env->hflags2 |= HF2_NMI_MASK;
313 e694d4e2 Blue Swirl
                            do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);
314 db620f46 bellard
                            next_tb = 0;
315 e965fc38 陳韋任
                        } else if (interrupt_request & CPU_INTERRUPT_MCE) {
316 79c4f6b0 Huang Ying
                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
317 e694d4e2 Blue Swirl
                            do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);
318 79c4f6b0 Huang Ying
                            next_tb = 0;
319 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
320 db620f46 bellard
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
321 db620f46 bellard
                                     (env->hflags2 & HF2_HIF_MASK)) ||
322 db620f46 bellard
                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
323 db620f46 bellard
                                     (env->eflags & IF_MASK && 
324 db620f46 bellard
                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
325 db620f46 bellard
                            int intno;
326 77b2bc2c Blue Swirl
                            cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,
327 77b2bc2c Blue Swirl
                                                          0);
328 db620f46 bellard
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
329 db620f46 bellard
                            intno = cpu_get_pic_interrupt(env);
330 4f213879 malc
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
331 4f213879 malc
                            do_interrupt_x86_hardirq(env, intno, 1);
332 4f213879 malc
                            /* ensure that no TB jump will be modified as
333 4f213879 malc
                               the program flow was changed */
334 4f213879 malc
                            next_tb = 0;
335 0573fbfc ths
#if !defined(CONFIG_USER_ONLY)
336 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
337 db620f46 bellard
                                   (env->eflags & IF_MASK) && 
338 db620f46 bellard
                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
339 db620f46 bellard
                            int intno;
340 db620f46 bellard
                            /* FIXME: this should respect TPR */
341 77b2bc2c Blue Swirl
                            cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR,
342 77b2bc2c Blue Swirl
                                                          0);
343 db620f46 bellard
                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
344 93fcfe39 aliguori
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
345 e694d4e2 Blue Swirl
                            do_interrupt_x86_hardirq(env, intno, 1);
346 d40c54d6 aurel32
                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
347 db620f46 bellard
                            next_tb = 0;
348 0573fbfc ths
#endif
349 db620f46 bellard
                        }
350 68a79315 bellard
                    }
351 ce09776b bellard
#elif defined(TARGET_PPC)
352 9fddaa0c bellard
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
353 c356a1bc Andreas Färber
                        cpu_reset(cpu);
354 9fddaa0c bellard
                    }
355 47103572 j_mayer
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
356 e9df014c j_mayer
                        ppc_hw_interrupt(env);
357 e9df014c j_mayer
                        if (env->pending_interrupts == 0)
358 e9df014c j_mayer
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
359 b5fc09ae blueswir1
                        next_tb = 0;
360 ce09776b bellard
                    }
361 81ea0e13 Michael Walle
#elif defined(TARGET_LM32)
362 81ea0e13 Michael Walle
                    if ((interrupt_request & CPU_INTERRUPT_HARD)
363 81ea0e13 Michael Walle
                        && (env->ie & IE_IE)) {
364 81ea0e13 Michael Walle
                        env->exception_index = EXCP_IRQ;
365 81ea0e13 Michael Walle
                        do_interrupt(env);
366 81ea0e13 Michael Walle
                        next_tb = 0;
367 81ea0e13 Michael Walle
                    }
368 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
369 b779e29e Edgar E. Iglesias
                    if ((interrupt_request & CPU_INTERRUPT_HARD)
370 b779e29e Edgar E. Iglesias
                        && (env->sregs[SR_MSR] & MSR_IE)
371 b779e29e Edgar E. Iglesias
                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
372 b779e29e Edgar E. Iglesias
                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
373 b779e29e Edgar E. Iglesias
                        env->exception_index = EXCP_IRQ;
374 b779e29e Edgar E. Iglesias
                        do_interrupt(env);
375 b779e29e Edgar E. Iglesias
                        next_tb = 0;
376 b779e29e Edgar E. Iglesias
                    }
377 6af0bf9c bellard
#elif defined(TARGET_MIPS)
378 6af0bf9c bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
379 4cdc1cd1 Aurelien Jarno
                        cpu_mips_hw_interrupts_pending(env)) {
380 6af0bf9c bellard
                        /* Raise it */
381 6af0bf9c bellard
                        env->exception_index = EXCP_EXT_INTERRUPT;
382 6af0bf9c bellard
                        env->error_code = 0;
383 6af0bf9c bellard
                        do_interrupt(env);
384 b5fc09ae blueswir1
                        next_tb = 0;
385 6af0bf9c bellard
                    }
386 b6a71ef7 Jia Liu
#elif defined(TARGET_OPENRISC)
387 b6a71ef7 Jia Liu
                    {
388 b6a71ef7 Jia Liu
                        int idx = -1;
389 b6a71ef7 Jia Liu
                        if ((interrupt_request & CPU_INTERRUPT_HARD)
390 b6a71ef7 Jia Liu
                            && (env->sr & SR_IEE)) {
391 b6a71ef7 Jia Liu
                            idx = EXCP_INT;
392 b6a71ef7 Jia Liu
                        }
393 b6a71ef7 Jia Liu
                        if ((interrupt_request & CPU_INTERRUPT_TIMER)
394 b6a71ef7 Jia Liu
                            && (env->sr & SR_TEE)) {
395 b6a71ef7 Jia Liu
                            idx = EXCP_TICK;
396 b6a71ef7 Jia Liu
                        }
397 b6a71ef7 Jia Liu
                        if (idx >= 0) {
398 b6a71ef7 Jia Liu
                            env->exception_index = idx;
399 b6a71ef7 Jia Liu
                            do_interrupt(env);
400 b6a71ef7 Jia Liu
                            next_tb = 0;
401 b6a71ef7 Jia Liu
                        }
402 b6a71ef7 Jia Liu
                    }
403 e95c8d51 bellard
#elif defined(TARGET_SPARC)
404 d532b26c Igor V. Kovalenko
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
405 d532b26c Igor V. Kovalenko
                        if (cpu_interrupts_enabled(env) &&
406 d532b26c Igor V. Kovalenko
                            env->interrupt_index > 0) {
407 d532b26c Igor V. Kovalenko
                            int pil = env->interrupt_index & 0xf;
408 d532b26c Igor V. Kovalenko
                            int type = env->interrupt_index & 0xf0;
409 d532b26c Igor V. Kovalenko
410 d532b26c Igor V. Kovalenko
                            if (((type == TT_EXTINT) &&
411 d532b26c Igor V. Kovalenko
                                  cpu_pil_allowed(env, pil)) ||
412 d532b26c Igor V. Kovalenko
                                  type != TT_EXTINT) {
413 d532b26c Igor V. Kovalenko
                                env->exception_index = env->interrupt_index;
414 d532b26c Igor V. Kovalenko
                                do_interrupt(env);
415 d532b26c Igor V. Kovalenko
                                next_tb = 0;
416 d532b26c Igor V. Kovalenko
                            }
417 d532b26c Igor V. Kovalenko
                        }
418 e965fc38 陳韋任
                    }
419 b5ff1b31 bellard
#elif defined(TARGET_ARM)
420 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_FIQ
421 b5ff1b31 bellard
                        && !(env->uncached_cpsr & CPSR_F)) {
422 b5ff1b31 bellard
                        env->exception_index = EXCP_FIQ;
423 b5ff1b31 bellard
                        do_interrupt(env);
424 b5fc09ae blueswir1
                        next_tb = 0;
425 b5ff1b31 bellard
                    }
426 9ee6e8bb pbrook
                    /* ARMv7-M interrupt return works by loading a magic value
427 9ee6e8bb pbrook
                       into the PC.  On real hardware the load causes the
428 9ee6e8bb pbrook
                       return to occur.  The qemu implementation performs the
429 9ee6e8bb pbrook
                       jump normally, then does the exception return when the
430 9ee6e8bb pbrook
                       CPU tries to execute code at the magic address.
431 9ee6e8bb pbrook
                       This will cause the magic PC value to be pushed to
432 a1c7273b Stefan Weil
                       the stack if an interrupt occurred at the wrong time.
433 9ee6e8bb pbrook
                       We avoid this by disabling interrupts when
434 9ee6e8bb pbrook
                       pc contains a magic address.  */
435 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_HARD
436 9ee6e8bb pbrook
                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
437 9ee6e8bb pbrook
                            || !(env->uncached_cpsr & CPSR_I))) {
438 b5ff1b31 bellard
                        env->exception_index = EXCP_IRQ;
439 b5ff1b31 bellard
                        do_interrupt(env);
440 b5fc09ae blueswir1
                        next_tb = 0;
441 b5ff1b31 bellard
                    }
442 d2fbca94 Guan Xuetao
#elif defined(TARGET_UNICORE32)
443 d2fbca94 Guan Xuetao
                    if (interrupt_request & CPU_INTERRUPT_HARD
444 d2fbca94 Guan Xuetao
                        && !(env->uncached_asr & ASR_I)) {
445 d48813dd Guan Xuetao
                        env->exception_index = UC32_EXCP_INTR;
446 d2fbca94 Guan Xuetao
                        do_interrupt(env);
447 d2fbca94 Guan Xuetao
                        next_tb = 0;
448 d2fbca94 Guan Xuetao
                    }
449 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
450 e96e2044 ths
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
451 e96e2044 ths
                        do_interrupt(env);
452 b5fc09ae blueswir1
                        next_tb = 0;
453 e96e2044 ths
                    }
454 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
455 6a80e088 Richard Henderson
                    {
456 6a80e088 Richard Henderson
                        int idx = -1;
457 6a80e088 Richard Henderson
                        /* ??? This hard-codes the OSF/1 interrupt levels.  */
458 e965fc38 陳韋任
                        switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
459 6a80e088 Richard Henderson
                        case 0 ... 3:
460 6a80e088 Richard Henderson
                            if (interrupt_request & CPU_INTERRUPT_HARD) {
461 6a80e088 Richard Henderson
                                idx = EXCP_DEV_INTERRUPT;
462 6a80e088 Richard Henderson
                            }
463 6a80e088 Richard Henderson
                            /* FALLTHRU */
464 6a80e088 Richard Henderson
                        case 4:
465 6a80e088 Richard Henderson
                            if (interrupt_request & CPU_INTERRUPT_TIMER) {
466 6a80e088 Richard Henderson
                                idx = EXCP_CLK_INTERRUPT;
467 6a80e088 Richard Henderson
                            }
468 6a80e088 Richard Henderson
                            /* FALLTHRU */
469 6a80e088 Richard Henderson
                        case 5:
470 6a80e088 Richard Henderson
                            if (interrupt_request & CPU_INTERRUPT_SMP) {
471 6a80e088 Richard Henderson
                                idx = EXCP_SMP_INTERRUPT;
472 6a80e088 Richard Henderson
                            }
473 6a80e088 Richard Henderson
                            /* FALLTHRU */
474 6a80e088 Richard Henderson
                        case 6:
475 6a80e088 Richard Henderson
                            if (interrupt_request & CPU_INTERRUPT_MCHK) {
476 6a80e088 Richard Henderson
                                idx = EXCP_MCHK;
477 6a80e088 Richard Henderson
                            }
478 6a80e088 Richard Henderson
                        }
479 6a80e088 Richard Henderson
                        if (idx >= 0) {
480 6a80e088 Richard Henderson
                            env->exception_index = idx;
481 6a80e088 Richard Henderson
                            env->error_code = 0;
482 6a80e088 Richard Henderson
                            do_interrupt(env);
483 6a80e088 Richard Henderson
                            next_tb = 0;
484 6a80e088 Richard Henderson
                        }
485 eddf68a6 j_mayer
                    }
486 f1ccf904 ths
#elif defined(TARGET_CRIS)
487 1b1a38b0 edgar_igl
                    if (interrupt_request & CPU_INTERRUPT_HARD
488 fb9fb692 Edgar E. Iglesias
                        && (env->pregs[PR_CCS] & I_FLAG)
489 fb9fb692 Edgar E. Iglesias
                        && !env->locked_irq) {
490 1b1a38b0 edgar_igl
                        env->exception_index = EXCP_IRQ;
491 1b1a38b0 edgar_igl
                        do_interrupt(env);
492 1b1a38b0 edgar_igl
                        next_tb = 0;
493 1b1a38b0 edgar_igl
                    }
494 8219314b Lars Persson
                    if (interrupt_request & CPU_INTERRUPT_NMI) {
495 8219314b Lars Persson
                        unsigned int m_flag_archval;
496 8219314b Lars Persson
                        if (env->pregs[PR_VR] < 32) {
497 8219314b Lars Persson
                            m_flag_archval = M_FLAG_V10;
498 8219314b Lars Persson
                        } else {
499 8219314b Lars Persson
                            m_flag_archval = M_FLAG_V32;
500 8219314b Lars Persson
                        }
501 8219314b Lars Persson
                        if ((env->pregs[PR_CCS] & m_flag_archval)) {
502 8219314b Lars Persson
                            env->exception_index = EXCP_NMI;
503 8219314b Lars Persson
                            do_interrupt(env);
504 8219314b Lars Persson
                            next_tb = 0;
505 8219314b Lars Persson
                        }
506 f1ccf904 ths
                    }
507 0633879f pbrook
#elif defined(TARGET_M68K)
508 0633879f pbrook
                    if (interrupt_request & CPU_INTERRUPT_HARD
509 0633879f pbrook
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
510 0633879f pbrook
                            < env->pending_level) {
511 0633879f pbrook
                        /* Real hardware gets the interrupt vector via an
512 0633879f pbrook
                           IACK cycle at this point.  Current emulated
513 0633879f pbrook
                           hardware doesn't rely on this, so we
514 0633879f pbrook
                           provide/save the vector when the interrupt is
515 0633879f pbrook
                           first signalled.  */
516 0633879f pbrook
                        env->exception_index = env->pending_vector;
517 3c688828 Blue Swirl
                        do_interrupt_m68k_hardirq(env);
518 b5fc09ae blueswir1
                        next_tb = 0;
519 0633879f pbrook
                    }
520 3110e292 Alexander Graf
#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)
521 3110e292 Alexander Graf
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
522 3110e292 Alexander Graf
                        (env->psw.mask & PSW_MASK_EXT)) {
523 3110e292 Alexander Graf
                        do_interrupt(env);
524 3110e292 Alexander Graf
                        next_tb = 0;
525 3110e292 Alexander Graf
                    }
526 40643d7c Max Filippov
#elif defined(TARGET_XTENSA)
527 40643d7c Max Filippov
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
528 40643d7c Max Filippov
                        env->exception_index = EXC_IRQ;
529 40643d7c Max Filippov
                        do_interrupt(env);
530 40643d7c Max Filippov
                        next_tb = 0;
531 40643d7c Max Filippov
                    }
532 68a79315 bellard
#endif
533 ff2712ba Stefan Weil
                   /* Don't use the cached interrupt_request value,
534 9d05095e bellard
                      do_interrupt may have updated the EXITTB flag. */
535 b5ff1b31 bellard
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
536 bf3e8bf1 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
537 bf3e8bf1 bellard
                        /* ensure that no TB jump will be modified as
538 bf3e8bf1 bellard
                           the program flow was changed */
539 b5fc09ae blueswir1
                        next_tb = 0;
540 bf3e8bf1 bellard
                    }
541 be214e6c aurel32
                }
542 be214e6c aurel32
                if (unlikely(env->exit_request)) {
543 be214e6c aurel32
                    env->exit_request = 0;
544 be214e6c aurel32
                    env->exception_index = EXCP_INTERRUPT;
545 1162c041 Blue Swirl
                    cpu_loop_exit(env);
546 3fb2ded1 bellard
                }
547 a73b1fd9 Richard Henderson
#if defined(DEBUG_DISAS) || defined(CONFIG_DEBUG_EXEC)
548 8fec2b8c aliguori
                if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
549 3fb2ded1 bellard
                    /* restore flags in standard format */
550 ecb644f4 ths
#if defined(TARGET_I386)
551 e694d4e2 Blue Swirl
                    env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
552 e694d4e2 Blue Swirl
                        | (DF & DF_MASK);
553 6fd2a026 Peter Maydell
                    log_cpu_state(env, CPU_DUMP_CCOP);
554 3fb2ded1 bellard
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
555 e6e5906b pbrook
#elif defined(TARGET_M68K)
556 e6e5906b pbrook
                    cpu_m68k_flush_flags(env, env->cc_op);
557 e6e5906b pbrook
                    env->cc_op = CC_OP_FLAGS;
558 e6e5906b pbrook
                    env->sr = (env->sr & 0xffe0)
559 e6e5906b pbrook
                              | env->cc_dest | (env->cc_x << 4);
560 93fcfe39 aliguori
                    log_cpu_state(env, 0);
561 e4533c7a bellard
#else
562 a73b1fd9 Richard Henderson
                    log_cpu_state(env, 0);
563 e4533c7a bellard
#endif
564 3fb2ded1 bellard
                }
565 a73b1fd9 Richard Henderson
#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
566 d5975363 pbrook
                spin_lock(&tb_lock);
567 cea5f9a2 Blue Swirl
                tb = tb_find_fast(env);
568 d5975363 pbrook
                /* Note: we do it here to avoid a gcc bug on Mac OS X when
569 d5975363 pbrook
                   doing it in tb_find_slow */
570 d5975363 pbrook
                if (tb_invalidated_flag) {
571 d5975363 pbrook
                    /* as some TB could have been invalidated because
572 d5975363 pbrook
                       of memory exceptions while generating the code, we
573 d5975363 pbrook
                       must recompute the hash index here */
574 d5975363 pbrook
                    next_tb = 0;
575 2e70f6ef pbrook
                    tb_invalidated_flag = 0;
576 d5975363 pbrook
                }
577 f0667e66 Juan Quintela
#ifdef CONFIG_DEBUG_EXEC
578 3ba19255 Stefan Weil
                qemu_log_mask(CPU_LOG_EXEC, "Trace %p [" TARGET_FMT_lx "] %s\n",
579 3ba19255 Stefan Weil
                             tb->tc_ptr, tb->pc,
580 93fcfe39 aliguori
                             lookup_symbol(tb->pc));
581 9d27abd9 bellard
#endif
582 8a40a180 bellard
                /* see if we can patch the calling TB. When the TB
583 8a40a180 bellard
                   spans two pages, we cannot safely do a direct
584 8a40a180 bellard
                   jump. */
585 040f2fb2 Paolo Bonzini
                if (next_tb != 0 && tb->page_addr[1] == -1) {
586 b5fc09ae blueswir1
                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
587 3fb2ded1 bellard
                }
588 d5975363 pbrook
                spin_unlock(&tb_lock);
589 55e8b85e malc
590 55e8b85e malc
                /* cpu_interrupt might be called while translating the
591 55e8b85e malc
                   TB, but before it is linked into a potentially
592 55e8b85e malc
                   infinite loop and becomes env->current_tb. Avoid
593 55e8b85e malc
                   starting execution if there is a pending interrupt. */
594 b0052d15 Jan Kiszka
                env->current_tb = tb;
595 b0052d15 Jan Kiszka
                barrier();
596 b0052d15 Jan Kiszka
                if (likely(!env->exit_request)) {
597 2e70f6ef pbrook
                    tc_ptr = tb->tc_ptr;
598 e965fc38 陳韋任
                    /* execute the generated code */
599 cea5f9a2 Blue Swirl
                    next_tb = tcg_qemu_tb_exec(env, tc_ptr);
600 2e70f6ef pbrook
                    if ((next_tb & 3) == 2) {
601 bf20dc07 ths
                        /* Instruction counter expired.  */
602 2e70f6ef pbrook
                        int insns_left;
603 69784eae Stefan Weil
                        tb = (TranslationBlock *)(next_tb & ~3);
604 2e70f6ef pbrook
                        /* Restore PC.  */
605 622ed360 aliguori
                        cpu_pc_from_tb(env, tb);
606 2e70f6ef pbrook
                        insns_left = env->icount_decr.u32;
607 2e70f6ef pbrook
                        if (env->icount_extra && insns_left >= 0) {
608 2e70f6ef pbrook
                            /* Refill decrementer and continue execution.  */
609 2e70f6ef pbrook
                            env->icount_extra += insns_left;
610 2e70f6ef pbrook
                            if (env->icount_extra > 0xffff) {
611 2e70f6ef pbrook
                                insns_left = 0xffff;
612 2e70f6ef pbrook
                            } else {
613 2e70f6ef pbrook
                                insns_left = env->icount_extra;
614 2e70f6ef pbrook
                            }
615 2e70f6ef pbrook
                            env->icount_extra -= insns_left;
616 2e70f6ef pbrook
                            env->icount_decr.u16.low = insns_left;
617 2e70f6ef pbrook
                        } else {
618 2e70f6ef pbrook
                            if (insns_left > 0) {
619 2e70f6ef pbrook
                                /* Execute remaining instructions.  */
620 cea5f9a2 Blue Swirl
                                cpu_exec_nocache(env, insns_left, tb);
621 2e70f6ef pbrook
                            }
622 2e70f6ef pbrook
                            env->exception_index = EXCP_INTERRUPT;
623 2e70f6ef pbrook
                            next_tb = 0;
624 1162c041 Blue Swirl
                            cpu_loop_exit(env);
625 2e70f6ef pbrook
                        }
626 2e70f6ef pbrook
                    }
627 2e70f6ef pbrook
                }
628 b0052d15 Jan Kiszka
                env->current_tb = NULL;
629 4cbf74b6 bellard
                /* reset soft MMU for next block (it can currently
630 4cbf74b6 bellard
                   only be set by a memory fault) */
631 50a518e3 ths
            } /* for(;;) */
632 0d101938 Jan Kiszka
        } else {
633 0d101938 Jan Kiszka
            /* Reload env after longjmp - the compiler may have smashed all
634 0d101938 Jan Kiszka
             * local variables as longjmp is marked 'noreturn'. */
635 0d101938 Jan Kiszka
            env = cpu_single_env;
636 7d13299d bellard
        }
637 3fb2ded1 bellard
    } /* for(;;) */
638 3fb2ded1 bellard
639 7d13299d bellard
640 e4533c7a bellard
#if defined(TARGET_I386)
641 9de5e440 bellard
    /* restore flags in standard format */
642 e694d4e2 Blue Swirl
    env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)
643 e694d4e2 Blue Swirl
        | (DF & DF_MASK);
644 e4533c7a bellard
#elif defined(TARGET_ARM)
645 b7bcbe95 bellard
    /* XXX: Save/restore host fpu exception state?.  */
646 d2fbca94 Guan Xuetao
#elif defined(TARGET_UNICORE32)
647 93ac68bc bellard
#elif defined(TARGET_SPARC)
648 67867308 bellard
#elif defined(TARGET_PPC)
649 81ea0e13 Michael Walle
#elif defined(TARGET_LM32)
650 e6e5906b pbrook
#elif defined(TARGET_M68K)
651 e6e5906b pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
652 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
653 e6e5906b pbrook
    env->sr = (env->sr & 0xffe0)
654 e6e5906b pbrook
              | env->cc_dest | (env->cc_x << 4);
655 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
656 6af0bf9c bellard
#elif defined(TARGET_MIPS)
657 e67db06e Jia Liu
#elif defined(TARGET_OPENRISC)
658 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
659 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
660 f1ccf904 ths
#elif defined(TARGET_CRIS)
661 10ec5117 Alexander Graf
#elif defined(TARGET_S390X)
662 2328826b Max Filippov
#elif defined(TARGET_XTENSA)
663 fdf9b3e8 bellard
    /* XXXXX */
664 e4533c7a bellard
#else
665 e4533c7a bellard
#error unsupported target CPU
666 e4533c7a bellard
#endif
667 1057eaa7 pbrook
668 6a00d601 bellard
    /* fail safe : never use cpu_single_env outside cpu_exec() */
669 5fafdf24 ths
    cpu_single_env = NULL;
670 7d13299d bellard
    return ret;
671 7d13299d bellard
}