Statistics
| Branch: | Revision:

root / cpu-exec.c @ a7ec4229

History | View | Annotate | Download (51 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 3ef693a0 bellard
 * License along with this library; if not, write to the Free Software
18 3ef693a0 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 7d13299d bellard
 */
20 e4533c7a bellard
#include "config.h"
21 7cb69cae bellard
#define CPU_NO_GLOBAL_REGS
22 93ac68bc bellard
#include "exec.h"
23 956034d7 bellard
#include "disas.h"
24 7cb69cae bellard
#include "tcg.h"
25 7d13299d bellard
26 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
27 fbf9eeb3 bellard
#undef EAX
28 fbf9eeb3 bellard
#undef ECX
29 fbf9eeb3 bellard
#undef EDX
30 fbf9eeb3 bellard
#undef EBX
31 fbf9eeb3 bellard
#undef ESP
32 fbf9eeb3 bellard
#undef EBP
33 fbf9eeb3 bellard
#undef ESI
34 fbf9eeb3 bellard
#undef EDI
35 fbf9eeb3 bellard
#undef EIP
36 fbf9eeb3 bellard
#include <signal.h>
37 fbf9eeb3 bellard
#include <sys/ucontext.h>
38 fbf9eeb3 bellard
#endif
39 fbf9eeb3 bellard
40 572a9d4a blueswir1
#if defined(__sparc__) && !defined(HOST_SOLARIS)
41 572a9d4a blueswir1
// Work around ugly bugs in glibc that mangle global register contents
42 572a9d4a blueswir1
#undef env
43 572a9d4a blueswir1
#define env cpu_single_env
44 572a9d4a blueswir1
#endif
45 572a9d4a blueswir1
46 36bdbe54 bellard
int tb_invalidated_flag;
47 36bdbe54 bellard
48 dc99065b bellard
//#define DEBUG_EXEC
49 9de5e440 bellard
//#define DEBUG_SIGNAL
50 7d13299d bellard
51 e4533c7a bellard
void cpu_loop_exit(void)
52 e4533c7a bellard
{
53 bfed01fc ths
    /* NOTE: the register at this point must be saved by hand because
54 bfed01fc ths
       longjmp restore them */
55 bfed01fc ths
    regs_to_env();
56 e4533c7a bellard
    longjmp(env->jmp_env, 1);
57 e4533c7a bellard
}
58 bfed01fc ths
59 e6e5906b pbrook
#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
60 3475187d bellard
#define reg_T2
61 3475187d bellard
#endif
62 e4533c7a bellard
63 fbf9eeb3 bellard
/* exit the current TB from a signal handler. The host registers are
64 fbf9eeb3 bellard
   restored in a state compatible with the CPU emulator
65 fbf9eeb3 bellard
 */
66 5fafdf24 ths
void cpu_resume_from_signal(CPUState *env1, void *puc)
67 fbf9eeb3 bellard
{
68 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
69 fbf9eeb3 bellard
    struct ucontext *uc = puc;
70 fbf9eeb3 bellard
#endif
71 fbf9eeb3 bellard
72 fbf9eeb3 bellard
    env = env1;
73 fbf9eeb3 bellard
74 fbf9eeb3 bellard
    /* XXX: restore cpu registers saved in host registers */
75 fbf9eeb3 bellard
76 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
77 fbf9eeb3 bellard
    if (puc) {
78 fbf9eeb3 bellard
        /* XXX: use siglongjmp ? */
79 fbf9eeb3 bellard
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
80 fbf9eeb3 bellard
    }
81 fbf9eeb3 bellard
#endif
82 fbf9eeb3 bellard
    longjmp(env->jmp_env, 1);
83 fbf9eeb3 bellard
}
84 fbf9eeb3 bellard
85 2e70f6ef pbrook
/* Execute the code without caching the generated code. An interpreter
86 2e70f6ef pbrook
   could be used if available. */
87 2e70f6ef pbrook
static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
88 2e70f6ef pbrook
{
89 2e70f6ef pbrook
    unsigned long next_tb;
90 2e70f6ef pbrook
    TranslationBlock *tb;
91 2e70f6ef pbrook
92 2e70f6ef pbrook
    /* Should never happen.
93 2e70f6ef pbrook
       We only end up here when an existing TB is too long.  */
94 2e70f6ef pbrook
    if (max_cycles > CF_COUNT_MASK)
95 2e70f6ef pbrook
        max_cycles = CF_COUNT_MASK;
96 2e70f6ef pbrook
97 2e70f6ef pbrook
    tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
98 2e70f6ef pbrook
                     max_cycles);
99 2e70f6ef pbrook
    env->current_tb = tb;
100 2e70f6ef pbrook
    /* execute the generated code */
101 2e70f6ef pbrook
    next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
102 2e70f6ef pbrook
103 2e70f6ef pbrook
    if ((next_tb & 3) == 2) {
104 2e70f6ef pbrook
        /* Restore PC.  This may happen if async event occurs before
105 2e70f6ef pbrook
           the TB starts executing.  */
106 2e70f6ef pbrook
        CPU_PC_FROM_TB(env, tb);
107 2e70f6ef pbrook
    }
108 2e70f6ef pbrook
    tb_phys_invalidate(tb, -1);
109 2e70f6ef pbrook
    tb_free(tb);
110 2e70f6ef pbrook
}
111 2e70f6ef pbrook
112 8a40a180 bellard
static TranslationBlock *tb_find_slow(target_ulong pc,
113 8a40a180 bellard
                                      target_ulong cs_base,
114 c068688b j_mayer
                                      uint64_t flags)
115 8a40a180 bellard
{
116 8a40a180 bellard
    TranslationBlock *tb, **ptb1;
117 8a40a180 bellard
    unsigned int h;
118 8a40a180 bellard
    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
119 3b46e624 ths
120 8a40a180 bellard
    tb_invalidated_flag = 0;
121 3b46e624 ths
122 8a40a180 bellard
    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
123 3b46e624 ths
124 8a40a180 bellard
    /* find translated block using physical mappings */
125 8a40a180 bellard
    phys_pc = get_phys_addr_code(env, pc);
126 8a40a180 bellard
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
127 8a40a180 bellard
    phys_page2 = -1;
128 8a40a180 bellard
    h = tb_phys_hash_func(phys_pc);
129 8a40a180 bellard
    ptb1 = &tb_phys_hash[h];
130 8a40a180 bellard
    for(;;) {
131 8a40a180 bellard
        tb = *ptb1;
132 8a40a180 bellard
        if (!tb)
133 8a40a180 bellard
            goto not_found;
134 5fafdf24 ths
        if (tb->pc == pc &&
135 8a40a180 bellard
            tb->page_addr[0] == phys_page1 &&
136 5fafdf24 ths
            tb->cs_base == cs_base &&
137 8a40a180 bellard
            tb->flags == flags) {
138 8a40a180 bellard
            /* check next page if needed */
139 8a40a180 bellard
            if (tb->page_addr[1] != -1) {
140 5fafdf24 ths
                virt_page2 = (pc & TARGET_PAGE_MASK) +
141 8a40a180 bellard
                    TARGET_PAGE_SIZE;
142 8a40a180 bellard
                phys_page2 = get_phys_addr_code(env, virt_page2);
143 8a40a180 bellard
                if (tb->page_addr[1] == phys_page2)
144 8a40a180 bellard
                    goto found;
145 8a40a180 bellard
            } else {
146 8a40a180 bellard
                goto found;
147 8a40a180 bellard
            }
148 8a40a180 bellard
        }
149 8a40a180 bellard
        ptb1 = &tb->phys_hash_next;
150 8a40a180 bellard
    }
151 8a40a180 bellard
 not_found:
152 2e70f6ef pbrook
   /* if no translated code available, then translate it now */
153 2e70f6ef pbrook
    tb = tb_gen_code(env, pc, cs_base, flags, 0);
154 3b46e624 ths
155 8a40a180 bellard
 found:
156 8a40a180 bellard
    /* we add the TB in the virtual pc hash table */
157 8a40a180 bellard
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
158 8a40a180 bellard
    return tb;
159 8a40a180 bellard
}
160 8a40a180 bellard
161 8a40a180 bellard
static inline TranslationBlock *tb_find_fast(void)
162 8a40a180 bellard
{
163 8a40a180 bellard
    TranslationBlock *tb;
164 8a40a180 bellard
    target_ulong cs_base, pc;
165 c068688b j_mayer
    uint64_t flags;
166 8a40a180 bellard
167 8a40a180 bellard
    /* we record a subset of the CPU state. It will
168 8a40a180 bellard
       always be the same before a given translated block
169 8a40a180 bellard
       is executed. */
170 8a40a180 bellard
#if defined(TARGET_I386)
171 8a40a180 bellard
    flags = env->hflags;
172 8a40a180 bellard
    flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
173 8a40a180 bellard
    cs_base = env->segs[R_CS].base;
174 8a40a180 bellard
    pc = cs_base + env->eip;
175 8a40a180 bellard
#elif defined(TARGET_ARM)
176 8a40a180 bellard
    flags = env->thumb | (env->vfp.vec_len << 1)
177 b5ff1b31 bellard
            | (env->vfp.vec_stride << 4);
178 b5ff1b31 bellard
    if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
179 b5ff1b31 bellard
        flags |= (1 << 6);
180 40f137e1 pbrook
    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
181 40f137e1 pbrook
        flags |= (1 << 7);
182 9ee6e8bb pbrook
    flags |= (env->condexec_bits << 8);
183 8a40a180 bellard
    cs_base = 0;
184 8a40a180 bellard
    pc = env->regs[15];
185 8a40a180 bellard
#elif defined(TARGET_SPARC)
186 8a40a180 bellard
#ifdef TARGET_SPARC64
187 2cade6a3 blueswir1
    // AM . Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
188 2cade6a3 blueswir1
    flags = ((env->pstate & PS_AM) << 2)
189 2cade6a3 blueswir1
        | (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
190 a80dde08 bellard
        | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
191 8a40a180 bellard
#else
192 6d5f237a blueswir1
    // FPU enable . Supervisor
193 6d5f237a blueswir1
    flags = (env->psref << 4) | env->psrs;
194 8a40a180 bellard
#endif
195 8a40a180 bellard
    cs_base = env->npc;
196 8a40a180 bellard
    pc = env->pc;
197 8a40a180 bellard
#elif defined(TARGET_PPC)
198 1527c87e j_mayer
    flags = env->hflags;
199 8a40a180 bellard
    cs_base = 0;
200 8a40a180 bellard
    pc = env->nip;
201 8a40a180 bellard
#elif defined(TARGET_MIPS)
202 56b19403 pbrook
    flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
203 cc9442b9 bellard
    cs_base = 0;
204 b5dc7732 ths
    pc = env->active_tc.PC;
205 e6e5906b pbrook
#elif defined(TARGET_M68K)
206 acf930aa pbrook
    flags = (env->fpcr & M68K_FPCR_PREC)  /* Bit  6 */
207 acf930aa pbrook
            | (env->sr & SR_S)            /* Bit  13 */
208 acf930aa pbrook
            | ((env->macsr >> 4) & 0xf);  /* Bits 0-3 */
209 e6e5906b pbrook
    cs_base = 0;
210 e6e5906b pbrook
    pc = env->pc;
211 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
212 fe25591e aurel32
    flags = (env->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL
213 fe25591e aurel32
                    | DELAY_SLOT_TRUE | DELAY_SLOT_CLEARME))   /* Bits  0- 3 */
214 fe25591e aurel32
            | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR))  /* Bits 19-21 */
215 fe25591e aurel32
            | (env->sr & (SR_MD | SR_RB));                     /* Bits 29-30 */
216 823029f9 ths
    cs_base = 0;
217 fdf9b3e8 bellard
    pc = env->pc;
218 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
219 eddf68a6 j_mayer
    flags = env->ps;
220 eddf68a6 j_mayer
    cs_base = 0;
221 eddf68a6 j_mayer
    pc = env->pc;
222 f1ccf904 ths
#elif defined(TARGET_CRIS)
223 7e15e603 edgar_igl
    flags = env->pregs[PR_CCS] & (P_FLAG | U_FLAG | X_FLAG);
224 cf1d97f0 edgar_igl
    flags |= env->dslot;
225 f1ccf904 ths
    cs_base = 0;
226 f1ccf904 ths
    pc = env->pc;
227 8a40a180 bellard
#else
228 8a40a180 bellard
#error unsupported CPU
229 8a40a180 bellard
#endif
230 bce61846 bellard
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
231 551bd27f ths
    if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
232 551bd27f ths
                 tb->flags != flags)) {
233 8a40a180 bellard
        tb = tb_find_slow(pc, cs_base, flags);
234 8a40a180 bellard
    }
235 8a40a180 bellard
    return tb;
236 8a40a180 bellard
}
237 8a40a180 bellard
238 7d13299d bellard
/* main execution loop */
239 7d13299d bellard
240 e4533c7a bellard
int cpu_exec(CPUState *env1)
241 7d13299d bellard
{
242 1057eaa7 pbrook
#define DECLARE_HOST_REGS 1
243 1057eaa7 pbrook
#include "hostregs_helper.h"
244 8a40a180 bellard
    int ret, interrupt_request;
245 8a40a180 bellard
    TranslationBlock *tb;
246 c27004ec bellard
    uint8_t *tc_ptr;
247 d5975363 pbrook
    unsigned long next_tb;
248 8c6939c0 bellard
249 bfed01fc ths
    if (cpu_halted(env1) == EXCP_HALTED)
250 bfed01fc ths
        return EXCP_HALTED;
251 5a1e3cfc bellard
252 5fafdf24 ths
    cpu_single_env = env1;
253 6a00d601 bellard
254 7d13299d bellard
    /* first we save global registers */
255 1057eaa7 pbrook
#define SAVE_HOST_REGS 1
256 1057eaa7 pbrook
#include "hostregs_helper.h"
257 c27004ec bellard
    env = env1;
258 e4533c7a bellard
259 0d1a29f9 bellard
    env_to_regs();
260 ecb644f4 ths
#if defined(TARGET_I386)
261 9de5e440 bellard
    /* put eflags in CPU temporary format */
262 fc2b4c48 bellard
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
263 fc2b4c48 bellard
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
264 9de5e440 bellard
    CC_OP = CC_OP_EFLAGS;
265 fc2b4c48 bellard
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
266 93ac68bc bellard
#elif defined(TARGET_SPARC)
267 e6e5906b pbrook
#elif defined(TARGET_M68K)
268 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
269 e6e5906b pbrook
    env->cc_dest = env->sr & 0xf;
270 e6e5906b pbrook
    env->cc_x = (env->sr >> 4) & 1;
271 ecb644f4 ths
#elif defined(TARGET_ALPHA)
272 ecb644f4 ths
#elif defined(TARGET_ARM)
273 ecb644f4 ths
#elif defined(TARGET_PPC)
274 6af0bf9c bellard
#elif defined(TARGET_MIPS)
275 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
276 f1ccf904 ths
#elif defined(TARGET_CRIS)
277 fdf9b3e8 bellard
    /* XXXXX */
278 e4533c7a bellard
#else
279 e4533c7a bellard
#error unsupported target CPU
280 e4533c7a bellard
#endif
281 3fb2ded1 bellard
    env->exception_index = -1;
282 9d27abd9 bellard
283 7d13299d bellard
    /* prepare setjmp context for exception handling */
284 3fb2ded1 bellard
    for(;;) {
285 3fb2ded1 bellard
        if (setjmp(env->jmp_env) == 0) {
286 ee8b7021 bellard
            env->current_tb = NULL;
287 3fb2ded1 bellard
            /* if an exception is pending, we execute it here */
288 3fb2ded1 bellard
            if (env->exception_index >= 0) {
289 3fb2ded1 bellard
                if (env->exception_index >= EXCP_INTERRUPT) {
290 3fb2ded1 bellard
                    /* exit request from the cpu execution loop */
291 3fb2ded1 bellard
                    ret = env->exception_index;
292 3fb2ded1 bellard
                    break;
293 3fb2ded1 bellard
                } else if (env->user_mode_only) {
294 3fb2ded1 bellard
                    /* if user mode only, we simulate a fake exception
295 9f083493 ths
                       which will be handled outside the cpu execution
296 3fb2ded1 bellard
                       loop */
297 83479e77 bellard
#if defined(TARGET_I386)
298 5fafdf24 ths
                    do_interrupt_user(env->exception_index,
299 5fafdf24 ths
                                      env->exception_is_int,
300 5fafdf24 ths
                                      env->error_code,
301 3fb2ded1 bellard
                                      env->exception_next_eip);
302 eba01623 bellard
                    /* successfully delivered */
303 eba01623 bellard
                    env->old_exception = -1;
304 83479e77 bellard
#endif
305 3fb2ded1 bellard
                    ret = env->exception_index;
306 3fb2ded1 bellard
                    break;
307 3fb2ded1 bellard
                } else {
308 83479e77 bellard
#if defined(TARGET_I386)
309 3fb2ded1 bellard
                    /* simulate a real cpu exception. On i386, it can
310 3fb2ded1 bellard
                       trigger new exceptions, but we do not handle
311 3fb2ded1 bellard
                       double or triple faults yet. */
312 5fafdf24 ths
                    do_interrupt(env->exception_index,
313 5fafdf24 ths
                                 env->exception_is_int,
314 5fafdf24 ths
                                 env->error_code,
315 d05e66d2 bellard
                                 env->exception_next_eip, 0);
316 678dde13 ths
                    /* successfully delivered */
317 678dde13 ths
                    env->old_exception = -1;
318 ce09776b bellard
#elif defined(TARGET_PPC)
319 ce09776b bellard
                    do_interrupt(env);
320 6af0bf9c bellard
#elif defined(TARGET_MIPS)
321 6af0bf9c bellard
                    do_interrupt(env);
322 e95c8d51 bellard
#elif defined(TARGET_SPARC)
323 f2bc7e7f blueswir1
                    do_interrupt(env);
324 b5ff1b31 bellard
#elif defined(TARGET_ARM)
325 b5ff1b31 bellard
                    do_interrupt(env);
326 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
327 fdf9b3e8 bellard
                    do_interrupt(env);
328 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
329 eddf68a6 j_mayer
                    do_interrupt(env);
330 f1ccf904 ths
#elif defined(TARGET_CRIS)
331 f1ccf904 ths
                    do_interrupt(env);
332 0633879f pbrook
#elif defined(TARGET_M68K)
333 0633879f pbrook
                    do_interrupt(0);
334 83479e77 bellard
#endif
335 3fb2ded1 bellard
                }
336 3fb2ded1 bellard
                env->exception_index = -1;
337 5fafdf24 ths
            }
338 9df217a3 bellard
#ifdef USE_KQEMU
339 9df217a3 bellard
            if (kqemu_is_ok(env) && env->interrupt_request == 0) {
340 9df217a3 bellard
                int ret;
341 9df217a3 bellard
                env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
342 9df217a3 bellard
                ret = kqemu_cpu_exec(env);
343 9df217a3 bellard
                /* put eflags in CPU temporary format */
344 9df217a3 bellard
                CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
345 9df217a3 bellard
                DF = 1 - (2 * ((env->eflags >> 10) & 1));
346 9df217a3 bellard
                CC_OP = CC_OP_EFLAGS;
347 9df217a3 bellard
                env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
348 9df217a3 bellard
                if (ret == 1) {
349 9df217a3 bellard
                    /* exception */
350 9df217a3 bellard
                    longjmp(env->jmp_env, 1);
351 9df217a3 bellard
                } else if (ret == 2) {
352 9df217a3 bellard
                    /* softmmu execution needed */
353 9df217a3 bellard
                } else {
354 9df217a3 bellard
                    if (env->interrupt_request != 0) {
355 9df217a3 bellard
                        /* hardware interrupt will be executed just after */
356 9df217a3 bellard
                    } else {
357 9df217a3 bellard
                        /* otherwise, we restart */
358 9df217a3 bellard
                        longjmp(env->jmp_env, 1);
359 9df217a3 bellard
                    }
360 9df217a3 bellard
                }
361 3fb2ded1 bellard
            }
362 9df217a3 bellard
#endif
363 9df217a3 bellard
364 b5fc09ae blueswir1
            next_tb = 0; /* force lookup of first TB */
365 3fb2ded1 bellard
            for(;;) {
366 68a79315 bellard
                interrupt_request = env->interrupt_request;
367 551bd27f ths
                if (unlikely(interrupt_request) &&
368 db620f46 bellard
                    likely(!(env->singlestep_enabled & SSTEP_NOIRQ))) {
369 6658ffb8 pbrook
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
370 6658ffb8 pbrook
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
371 6658ffb8 pbrook
                        env->exception_index = EXCP_DEBUG;
372 6658ffb8 pbrook
                        cpu_loop_exit();
373 6658ffb8 pbrook
                    }
374 a90b7318 balrog
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
375 f1ccf904 ths
    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS)
376 a90b7318 balrog
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
377 a90b7318 balrog
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
378 a90b7318 balrog
                        env->halted = 1;
379 a90b7318 balrog
                        env->exception_index = EXCP_HLT;
380 a90b7318 balrog
                        cpu_loop_exit();
381 a90b7318 balrog
                    }
382 a90b7318 balrog
#endif
383 68a79315 bellard
#if defined(TARGET_I386)
384 db620f46 bellard
                    if (env->hflags2 & HF2_GIF_MASK) {
385 db620f46 bellard
                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
386 db620f46 bellard
                            !(env->hflags & HF_SMM_MASK)) {
387 db620f46 bellard
                            svm_check_intercept(SVM_EXIT_SMI);
388 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
389 db620f46 bellard
                            do_smm_enter();
390 db620f46 bellard
                            next_tb = 0;
391 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
392 db620f46 bellard
                                   !(env->hflags2 & HF2_NMI_MASK)) {
393 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
394 db620f46 bellard
                            env->hflags2 |= HF2_NMI_MASK;
395 db620f46 bellard
                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
396 db620f46 bellard
                            next_tb = 0;
397 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
398 db620f46 bellard
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
399 db620f46 bellard
                                     (env->hflags2 & HF2_HIF_MASK)) ||
400 db620f46 bellard
                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
401 db620f46 bellard
                                     (env->eflags & IF_MASK && 
402 db620f46 bellard
                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
403 db620f46 bellard
                            int intno;
404 db620f46 bellard
                            svm_check_intercept(SVM_EXIT_INTR);
405 db620f46 bellard
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
406 db620f46 bellard
                            intno = cpu_get_pic_interrupt(env);
407 db620f46 bellard
                            if (loglevel & CPU_LOG_TB_IN_ASM) {
408 db620f46 bellard
                                fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
409 db620f46 bellard
                            }
410 db620f46 bellard
                            do_interrupt(intno, 0, 0, 0, 1);
411 db620f46 bellard
                            /* ensure that no TB jump will be modified as
412 db620f46 bellard
                               the program flow was changed */
413 db620f46 bellard
                            next_tb = 0;
414 0573fbfc ths
#if !defined(CONFIG_USER_ONLY)
415 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
416 db620f46 bellard
                                   (env->eflags & IF_MASK) && 
417 db620f46 bellard
                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
418 db620f46 bellard
                            int intno;
419 db620f46 bellard
                            /* FIXME: this should respect TPR */
420 db620f46 bellard
                            svm_check_intercept(SVM_EXIT_VINTR);
421 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
422 db620f46 bellard
                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
423 db620f46 bellard
                            if (loglevel & CPU_LOG_TB_IN_ASM)
424 db620f46 bellard
                                fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
425 db620f46 bellard
                            do_interrupt(intno, 0, 0, 0, 1);
426 db620f46 bellard
                            next_tb = 0;
427 0573fbfc ths
#endif
428 db620f46 bellard
                        }
429 68a79315 bellard
                    }
430 ce09776b bellard
#elif defined(TARGET_PPC)
431 9fddaa0c bellard
#if 0
432 9fddaa0c bellard
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
433 9fddaa0c bellard
                        cpu_ppc_reset(env);
434 9fddaa0c bellard
                    }
435 9fddaa0c bellard
#endif
436 47103572 j_mayer
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
437 e9df014c j_mayer
                        ppc_hw_interrupt(env);
438 e9df014c j_mayer
                        if (env->pending_interrupts == 0)
439 e9df014c j_mayer
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
440 b5fc09ae blueswir1
                        next_tb = 0;
441 ce09776b bellard
                    }
442 6af0bf9c bellard
#elif defined(TARGET_MIPS)
443 6af0bf9c bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
444 24c7b0e3 ths
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
445 6af0bf9c bellard
                        (env->CP0_Status & (1 << CP0St_IE)) &&
446 24c7b0e3 ths
                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
447 24c7b0e3 ths
                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
448 6af0bf9c bellard
                        !(env->hflags & MIPS_HFLAG_DM)) {
449 6af0bf9c bellard
                        /* Raise it */
450 6af0bf9c bellard
                        env->exception_index = EXCP_EXT_INTERRUPT;
451 6af0bf9c bellard
                        env->error_code = 0;
452 6af0bf9c bellard
                        do_interrupt(env);
453 b5fc09ae blueswir1
                        next_tb = 0;
454 6af0bf9c bellard
                    }
455 e95c8d51 bellard
#elif defined(TARGET_SPARC)
456 66321a11 bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
457 66321a11 bellard
                        (env->psret != 0)) {
458 66321a11 bellard
                        int pil = env->interrupt_index & 15;
459 66321a11 bellard
                        int type = env->interrupt_index & 0xf0;
460 66321a11 bellard
461 66321a11 bellard
                        if (((type == TT_EXTINT) &&
462 66321a11 bellard
                             (pil == 15 || pil > env->psrpil)) ||
463 66321a11 bellard
                            type != TT_EXTINT) {
464 66321a11 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
465 f2bc7e7f blueswir1
                            env->exception_index = env->interrupt_index;
466 f2bc7e7f blueswir1
                            do_interrupt(env);
467 66321a11 bellard
                            env->interrupt_index = 0;
468 327ac2e7 blueswir1
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
469 327ac2e7 blueswir1
                            cpu_check_irqs(env);
470 327ac2e7 blueswir1
#endif
471 b5fc09ae blueswir1
                        next_tb = 0;
472 66321a11 bellard
                        }
473 e95c8d51 bellard
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
474 e95c8d51 bellard
                        //do_interrupt(0, 0, 0, 0, 0);
475 e95c8d51 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
476 a90b7318 balrog
                    }
477 b5ff1b31 bellard
#elif defined(TARGET_ARM)
478 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_FIQ
479 b5ff1b31 bellard
                        && !(env->uncached_cpsr & CPSR_F)) {
480 b5ff1b31 bellard
                        env->exception_index = EXCP_FIQ;
481 b5ff1b31 bellard
                        do_interrupt(env);
482 b5fc09ae blueswir1
                        next_tb = 0;
483 b5ff1b31 bellard
                    }
484 9ee6e8bb pbrook
                    /* ARMv7-M interrupt return works by loading a magic value
485 9ee6e8bb pbrook
                       into the PC.  On real hardware the load causes the
486 9ee6e8bb pbrook
                       return to occur.  The qemu implementation performs the
487 9ee6e8bb pbrook
                       jump normally, then does the exception return when the
488 9ee6e8bb pbrook
                       CPU tries to execute code at the magic address.
489 9ee6e8bb pbrook
                       This will cause the magic PC value to be pushed to
490 9ee6e8bb pbrook
                       the stack if an interrupt occured at the wrong time.
491 9ee6e8bb pbrook
                       We avoid this by disabling interrupts when
492 9ee6e8bb pbrook
                       pc contains a magic address.  */
493 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_HARD
494 9ee6e8bb pbrook
                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
495 9ee6e8bb pbrook
                            || !(env->uncached_cpsr & CPSR_I))) {
496 b5ff1b31 bellard
                        env->exception_index = EXCP_IRQ;
497 b5ff1b31 bellard
                        do_interrupt(env);
498 b5fc09ae blueswir1
                        next_tb = 0;
499 b5ff1b31 bellard
                    }
500 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
501 e96e2044 ths
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
502 e96e2044 ths
                        do_interrupt(env);
503 b5fc09ae blueswir1
                        next_tb = 0;
504 e96e2044 ths
                    }
505 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
506 eddf68a6 j_mayer
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
507 eddf68a6 j_mayer
                        do_interrupt(env);
508 b5fc09ae blueswir1
                        next_tb = 0;
509 eddf68a6 j_mayer
                    }
510 f1ccf904 ths
#elif defined(TARGET_CRIS)
511 1b1a38b0 edgar_igl
                    if (interrupt_request & CPU_INTERRUPT_HARD
512 1b1a38b0 edgar_igl
                        && (env->pregs[PR_CCS] & I_FLAG)) {
513 1b1a38b0 edgar_igl
                        env->exception_index = EXCP_IRQ;
514 1b1a38b0 edgar_igl
                        do_interrupt(env);
515 1b1a38b0 edgar_igl
                        next_tb = 0;
516 1b1a38b0 edgar_igl
                    }
517 1b1a38b0 edgar_igl
                    if (interrupt_request & CPU_INTERRUPT_NMI
518 1b1a38b0 edgar_igl
                        && (env->pregs[PR_CCS] & M_FLAG)) {
519 1b1a38b0 edgar_igl
                        env->exception_index = EXCP_NMI;
520 f1ccf904 ths
                        do_interrupt(env);
521 b5fc09ae blueswir1
                        next_tb = 0;
522 f1ccf904 ths
                    }
523 0633879f pbrook
#elif defined(TARGET_M68K)
524 0633879f pbrook
                    if (interrupt_request & CPU_INTERRUPT_HARD
525 0633879f pbrook
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
526 0633879f pbrook
                            < env->pending_level) {
527 0633879f pbrook
                        /* Real hardware gets the interrupt vector via an
528 0633879f pbrook
                           IACK cycle at this point.  Current emulated
529 0633879f pbrook
                           hardware doesn't rely on this, so we
530 0633879f pbrook
                           provide/save the vector when the interrupt is
531 0633879f pbrook
                           first signalled.  */
532 0633879f pbrook
                        env->exception_index = env->pending_vector;
533 0633879f pbrook
                        do_interrupt(1);
534 b5fc09ae blueswir1
                        next_tb = 0;
535 0633879f pbrook
                    }
536 68a79315 bellard
#endif
537 9d05095e bellard
                   /* Don't use the cached interupt_request value,
538 9d05095e bellard
                      do_interrupt may have updated the EXITTB flag. */
539 b5ff1b31 bellard
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
540 bf3e8bf1 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
541 bf3e8bf1 bellard
                        /* ensure that no TB jump will be modified as
542 bf3e8bf1 bellard
                           the program flow was changed */
543 b5fc09ae blueswir1
                        next_tb = 0;
544 bf3e8bf1 bellard
                    }
545 68a79315 bellard
                    if (interrupt_request & CPU_INTERRUPT_EXIT) {
546 68a79315 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
547 68a79315 bellard
                        env->exception_index = EXCP_INTERRUPT;
548 68a79315 bellard
                        cpu_loop_exit();
549 68a79315 bellard
                    }
550 3fb2ded1 bellard
                }
551 7d13299d bellard
#ifdef DEBUG_EXEC
552 b5ff1b31 bellard
                if ((loglevel & CPU_LOG_TB_CPU)) {
553 3fb2ded1 bellard
                    /* restore flags in standard format */
554 ecb644f4 ths
                    regs_to_env();
555 ecb644f4 ths
#if defined(TARGET_I386)
556 3fb2ded1 bellard
                    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
557 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
558 3fb2ded1 bellard
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
559 e4533c7a bellard
#elif defined(TARGET_ARM)
560 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
561 93ac68bc bellard
#elif defined(TARGET_SPARC)
562 3475187d bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
563 67867308 bellard
#elif defined(TARGET_PPC)
564 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
565 e6e5906b pbrook
#elif defined(TARGET_M68K)
566 e6e5906b pbrook
                    cpu_m68k_flush_flags(env, env->cc_op);
567 e6e5906b pbrook
                    env->cc_op = CC_OP_FLAGS;
568 e6e5906b pbrook
                    env->sr = (env->sr & 0xffe0)
569 e6e5906b pbrook
                              | env->cc_dest | (env->cc_x << 4);
570 e6e5906b pbrook
                    cpu_dump_state(env, logfile, fprintf, 0);
571 6af0bf9c bellard
#elif defined(TARGET_MIPS)
572 6af0bf9c bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
573 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
574 fdf9b3e8 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
575 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
576 eddf68a6 j_mayer
                    cpu_dump_state(env, logfile, fprintf, 0);
577 f1ccf904 ths
#elif defined(TARGET_CRIS)
578 f1ccf904 ths
                    cpu_dump_state(env, logfile, fprintf, 0);
579 e4533c7a bellard
#else
580 5fafdf24 ths
#error unsupported target CPU
581 e4533c7a bellard
#endif
582 3fb2ded1 bellard
                }
583 7d13299d bellard
#endif
584 d5975363 pbrook
                spin_lock(&tb_lock);
585 8a40a180 bellard
                tb = tb_find_fast();
586 d5975363 pbrook
                /* Note: we do it here to avoid a gcc bug on Mac OS X when
587 d5975363 pbrook
                   doing it in tb_find_slow */
588 d5975363 pbrook
                if (tb_invalidated_flag) {
589 d5975363 pbrook
                    /* as some TB could have been invalidated because
590 d5975363 pbrook
                       of memory exceptions while generating the code, we
591 d5975363 pbrook
                       must recompute the hash index here */
592 d5975363 pbrook
                    next_tb = 0;
593 2e70f6ef pbrook
                    tb_invalidated_flag = 0;
594 d5975363 pbrook
                }
595 9d27abd9 bellard
#ifdef DEBUG_EXEC
596 c1135f61 bellard
                if ((loglevel & CPU_LOG_EXEC)) {
597 c27004ec bellard
                    fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
598 c27004ec bellard
                            (long)tb->tc_ptr, tb->pc,
599 c27004ec bellard
                            lookup_symbol(tb->pc));
600 3fb2ded1 bellard
                }
601 9d27abd9 bellard
#endif
602 8a40a180 bellard
                /* see if we can patch the calling TB. When the TB
603 8a40a180 bellard
                   spans two pages, we cannot safely do a direct
604 8a40a180 bellard
                   jump. */
605 c27004ec bellard
                {
606 b5fc09ae blueswir1
                    if (next_tb != 0 &&
607 4d7a0880 blueswir1
#ifdef USE_KQEMU
608 f32fc648 bellard
                        (env->kqemu_enabled != 2) &&
609 f32fc648 bellard
#endif
610 ec6338ba bellard
                        tb->page_addr[1] == -1) {
611 b5fc09ae blueswir1
                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
612 3fb2ded1 bellard
                }
613 c27004ec bellard
                }
614 d5975363 pbrook
                spin_unlock(&tb_lock);
615 83479e77 bellard
                env->current_tb = tb;
616 2e70f6ef pbrook
                while (env->current_tb) {
617 2e70f6ef pbrook
                    tc_ptr = tb->tc_ptr;
618 3fb2ded1 bellard
                /* execute the generated code */
619 572a9d4a blueswir1
#if defined(__sparc__) && !defined(HOST_SOLARIS)
620 572a9d4a blueswir1
#undef env
621 2e70f6ef pbrook
                    env = cpu_single_env;
622 572a9d4a blueswir1
#define env cpu_single_env
623 572a9d4a blueswir1
#endif
624 2e70f6ef pbrook
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
625 2e70f6ef pbrook
                    env->current_tb = NULL;
626 2e70f6ef pbrook
                    if ((next_tb & 3) == 2) {
627 bf20dc07 ths
                        /* Instruction counter expired.  */
628 2e70f6ef pbrook
                        int insns_left;
629 2e70f6ef pbrook
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
630 2e70f6ef pbrook
                        /* Restore PC.  */
631 2e70f6ef pbrook
                        CPU_PC_FROM_TB(env, tb);
632 2e70f6ef pbrook
                        insns_left = env->icount_decr.u32;
633 2e70f6ef pbrook
                        if (env->icount_extra && insns_left >= 0) {
634 2e70f6ef pbrook
                            /* Refill decrementer and continue execution.  */
635 2e70f6ef pbrook
                            env->icount_extra += insns_left;
636 2e70f6ef pbrook
                            if (env->icount_extra > 0xffff) {
637 2e70f6ef pbrook
                                insns_left = 0xffff;
638 2e70f6ef pbrook
                            } else {
639 2e70f6ef pbrook
                                insns_left = env->icount_extra;
640 2e70f6ef pbrook
                            }
641 2e70f6ef pbrook
                            env->icount_extra -= insns_left;
642 2e70f6ef pbrook
                            env->icount_decr.u16.low = insns_left;
643 2e70f6ef pbrook
                        } else {
644 2e70f6ef pbrook
                            if (insns_left > 0) {
645 2e70f6ef pbrook
                                /* Execute remaining instructions.  */
646 2e70f6ef pbrook
                                cpu_exec_nocache(insns_left, tb);
647 2e70f6ef pbrook
                            }
648 2e70f6ef pbrook
                            env->exception_index = EXCP_INTERRUPT;
649 2e70f6ef pbrook
                            next_tb = 0;
650 2e70f6ef pbrook
                            cpu_loop_exit();
651 2e70f6ef pbrook
                        }
652 2e70f6ef pbrook
                    }
653 2e70f6ef pbrook
                }
654 4cbf74b6 bellard
                /* reset soft MMU for next block (it can currently
655 4cbf74b6 bellard
                   only be set by a memory fault) */
656 f32fc648 bellard
#if defined(USE_KQEMU)
657 f32fc648 bellard
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
658 f32fc648 bellard
                if (kqemu_is_ok(env) &&
659 f32fc648 bellard
                    (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
660 f32fc648 bellard
                    cpu_loop_exit();
661 f32fc648 bellard
                }
662 f32fc648 bellard
#endif
663 50a518e3 ths
            } /* for(;;) */
664 3fb2ded1 bellard
        } else {
665 0d1a29f9 bellard
            env_to_regs();
666 7d13299d bellard
        }
667 3fb2ded1 bellard
    } /* for(;;) */
668 3fb2ded1 bellard
669 7d13299d bellard
670 e4533c7a bellard
#if defined(TARGET_I386)
671 9de5e440 bellard
    /* restore flags in standard format */
672 fc2b4c48 bellard
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
673 e4533c7a bellard
#elif defined(TARGET_ARM)
674 b7bcbe95 bellard
    /* XXX: Save/restore host fpu exception state?.  */
675 93ac68bc bellard
#elif defined(TARGET_SPARC)
676 67867308 bellard
#elif defined(TARGET_PPC)
677 e6e5906b pbrook
#elif defined(TARGET_M68K)
678 e6e5906b pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
679 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
680 e6e5906b pbrook
    env->sr = (env->sr & 0xffe0)
681 e6e5906b pbrook
              | env->cc_dest | (env->cc_x << 4);
682 6af0bf9c bellard
#elif defined(TARGET_MIPS)
683 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
684 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
685 f1ccf904 ths
#elif defined(TARGET_CRIS)
686 fdf9b3e8 bellard
    /* XXXXX */
687 e4533c7a bellard
#else
688 e4533c7a bellard
#error unsupported target CPU
689 e4533c7a bellard
#endif
690 1057eaa7 pbrook
691 1057eaa7 pbrook
    /* restore global registers */
692 1057eaa7 pbrook
#include "hostregs_helper.h"
693 1057eaa7 pbrook
694 6a00d601 bellard
    /* fail safe : never use cpu_single_env outside cpu_exec() */
695 5fafdf24 ths
    cpu_single_env = NULL;
696 7d13299d bellard
    return ret;
697 7d13299d bellard
}
698 6dbad63e bellard
699 fbf9eeb3 bellard
/* must only be called from the generated code as an exception can be
700 fbf9eeb3 bellard
   generated */
701 fbf9eeb3 bellard
void tb_invalidate_page_range(target_ulong start, target_ulong end)
702 fbf9eeb3 bellard
{
703 dc5d0b3d bellard
    /* XXX: cannot enable it yet because it yields to MMU exception
704 dc5d0b3d bellard
       where NIP != read address on PowerPC */
705 dc5d0b3d bellard
#if 0
706 fbf9eeb3 bellard
    target_ulong phys_addr;
707 fbf9eeb3 bellard
    phys_addr = get_phys_addr_code(env, start);
708 fbf9eeb3 bellard
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
709 dc5d0b3d bellard
#endif
710 fbf9eeb3 bellard
}
711 fbf9eeb3 bellard
712 1a18c71b bellard
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
713 e4533c7a bellard
714 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
715 6dbad63e bellard
{
716 6dbad63e bellard
    CPUX86State *saved_env;
717 6dbad63e bellard
718 6dbad63e bellard
    saved_env = env;
719 6dbad63e bellard
    env = s;
720 a412ac57 bellard
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
721 a513fe19 bellard
        selector &= 0xffff;
722 5fafdf24 ths
        cpu_x86_load_seg_cache(env, seg_reg, selector,
723 c27004ec bellard
                               (selector << 4), 0xffff, 0);
724 a513fe19 bellard
    } else {
725 5d97559d bellard
        helper_load_seg(seg_reg, selector);
726 a513fe19 bellard
    }
727 6dbad63e bellard
    env = saved_env;
728 6dbad63e bellard
}
729 9de5e440 bellard
730 6f12a2a6 bellard
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
731 d0a1ffc9 bellard
{
732 d0a1ffc9 bellard
    CPUX86State *saved_env;
733 d0a1ffc9 bellard
734 d0a1ffc9 bellard
    saved_env = env;
735 d0a1ffc9 bellard
    env = s;
736 3b46e624 ths
737 6f12a2a6 bellard
    helper_fsave(ptr, data32);
738 d0a1ffc9 bellard
739 d0a1ffc9 bellard
    env = saved_env;
740 d0a1ffc9 bellard
}
741 d0a1ffc9 bellard
742 6f12a2a6 bellard
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
743 d0a1ffc9 bellard
{
744 d0a1ffc9 bellard
    CPUX86State *saved_env;
745 d0a1ffc9 bellard
746 d0a1ffc9 bellard
    saved_env = env;
747 d0a1ffc9 bellard
    env = s;
748 3b46e624 ths
749 6f12a2a6 bellard
    helper_frstor(ptr, data32);
750 d0a1ffc9 bellard
751 d0a1ffc9 bellard
    env = saved_env;
752 d0a1ffc9 bellard
}
753 d0a1ffc9 bellard
754 e4533c7a bellard
#endif /* TARGET_I386 */
755 e4533c7a bellard
756 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
757 67b915a5 bellard
758 3fb2ded1 bellard
#if defined(TARGET_I386)
759 3fb2ded1 bellard
760 b56dad1c bellard
/* 'pc' is the host PC at which the exception was raised. 'address' is
761 fd6ce8f6 bellard
   the effective address of the memory exception. 'is_write' is 1 if a
762 fd6ce8f6 bellard
   write caused the exception and otherwise 0'. 'old_set' is the
763 fd6ce8f6 bellard
   signal set which should be restored */
764 2b413144 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
765 5fafdf24 ths
                                    int is_write, sigset_t *old_set,
766 bf3e8bf1 bellard
                                    void *puc)
767 9de5e440 bellard
{
768 a513fe19 bellard
    TranslationBlock *tb;
769 a513fe19 bellard
    int ret;
770 68a79315 bellard
771 83479e77 bellard
    if (cpu_single_env)
772 83479e77 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
773 fd6ce8f6 bellard
#if defined(DEBUG_SIGNAL)
774 5fafdf24 ths
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
775 bf3e8bf1 bellard
                pc, address, is_write, *(unsigned long *)old_set);
776 9de5e440 bellard
#endif
777 25eb4484 bellard
    /* XXX: locking issue */
778 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
779 fd6ce8f6 bellard
        return 1;
780 fd6ce8f6 bellard
    }
781 fbf9eeb3 bellard
782 3fb2ded1 bellard
    /* see if it is an MMU fault */
783 6ebbf390 j_mayer
    ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
784 3fb2ded1 bellard
    if (ret < 0)
785 3fb2ded1 bellard
        return 0; /* not an MMU fault */
786 3fb2ded1 bellard
    if (ret == 0)
787 3fb2ded1 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
788 3fb2ded1 bellard
    /* now we have a real cpu fault */
789 a513fe19 bellard
    tb = tb_find_pc(pc);
790 a513fe19 bellard
    if (tb) {
791 9de5e440 bellard
        /* the PC is inside the translated code. It means that we have
792 9de5e440 bellard
           a virtual CPU fault */
793 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, puc);
794 3fb2ded1 bellard
    }
795 4cbf74b6 bellard
    if (ret == 1) {
796 3fb2ded1 bellard
#if 0
797 5fafdf24 ths
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
798 4cbf74b6 bellard
               env->eip, env->cr[2], env->error_code);
799 3fb2ded1 bellard
#endif
800 4cbf74b6 bellard
        /* we restore the process signal mask as the sigreturn should
801 4cbf74b6 bellard
           do it (XXX: use sigsetjmp) */
802 4cbf74b6 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
803 54ca9095 bellard
        raise_exception_err(env->exception_index, env->error_code);
804 4cbf74b6 bellard
    } else {
805 4cbf74b6 bellard
        /* activate soft MMU for this block */
806 3f337316 bellard
        env->hflags |= HF_SOFTMMU_MASK;
807 fbf9eeb3 bellard
        cpu_resume_from_signal(env, puc);
808 4cbf74b6 bellard
    }
809 3fb2ded1 bellard
    /* never comes here */
810 3fb2ded1 bellard
    return 1;
811 3fb2ded1 bellard
}
812 3fb2ded1 bellard
813 e4533c7a bellard
#elif defined(TARGET_ARM)
814 3fb2ded1 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
815 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
816 bf3e8bf1 bellard
                                    void *puc)
817 3fb2ded1 bellard
{
818 68016c62 bellard
    TranslationBlock *tb;
819 68016c62 bellard
    int ret;
820 68016c62 bellard
821 68016c62 bellard
    if (cpu_single_env)
822 68016c62 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
823 68016c62 bellard
#if defined(DEBUG_SIGNAL)
824 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
825 68016c62 bellard
           pc, address, is_write, *(unsigned long *)old_set);
826 68016c62 bellard
#endif
827 9f0777ed bellard
    /* XXX: locking issue */
828 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
829 9f0777ed bellard
        return 1;
830 9f0777ed bellard
    }
831 68016c62 bellard
    /* see if it is an MMU fault */
832 6ebbf390 j_mayer
    ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
833 68016c62 bellard
    if (ret < 0)
834 68016c62 bellard
        return 0; /* not an MMU fault */
835 68016c62 bellard
    if (ret == 0)
836 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
837 68016c62 bellard
    /* now we have a real cpu fault */
838 68016c62 bellard
    tb = tb_find_pc(pc);
839 68016c62 bellard
    if (tb) {
840 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
841 68016c62 bellard
           a virtual CPU fault */
842 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
843 68016c62 bellard
    }
844 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
845 68016c62 bellard
       do it (XXX: use sigsetjmp) */
846 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
847 68016c62 bellard
    cpu_loop_exit();
848 968c74da aurel32
    /* never comes here */
849 968c74da aurel32
    return 1;
850 3fb2ded1 bellard
}
851 93ac68bc bellard
#elif defined(TARGET_SPARC)
852 93ac68bc bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
853 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
854 bf3e8bf1 bellard
                                    void *puc)
855 93ac68bc bellard
{
856 68016c62 bellard
    TranslationBlock *tb;
857 68016c62 bellard
    int ret;
858 68016c62 bellard
859 68016c62 bellard
    if (cpu_single_env)
860 68016c62 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
861 68016c62 bellard
#if defined(DEBUG_SIGNAL)
862 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
863 68016c62 bellard
           pc, address, is_write, *(unsigned long *)old_set);
864 68016c62 bellard
#endif
865 b453b70b bellard
    /* XXX: locking issue */
866 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
867 b453b70b bellard
        return 1;
868 b453b70b bellard
    }
869 68016c62 bellard
    /* see if it is an MMU fault */
870 6ebbf390 j_mayer
    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
871 68016c62 bellard
    if (ret < 0)
872 68016c62 bellard
        return 0; /* not an MMU fault */
873 68016c62 bellard
    if (ret == 0)
874 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
875 68016c62 bellard
    /* now we have a real cpu fault */
876 68016c62 bellard
    tb = tb_find_pc(pc);
877 68016c62 bellard
    if (tb) {
878 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
879 68016c62 bellard
           a virtual CPU fault */
880 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
881 68016c62 bellard
    }
882 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
883 68016c62 bellard
       do it (XXX: use sigsetjmp) */
884 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
885 68016c62 bellard
    cpu_loop_exit();
886 968c74da aurel32
    /* never comes here */
887 968c74da aurel32
    return 1;
888 93ac68bc bellard
}
889 67867308 bellard
#elif defined (TARGET_PPC)
890 67867308 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
891 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
892 bf3e8bf1 bellard
                                    void *puc)
893 67867308 bellard
{
894 67867308 bellard
    TranslationBlock *tb;
895 ce09776b bellard
    int ret;
896 3b46e624 ths
897 67867308 bellard
    if (cpu_single_env)
898 67867308 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
899 67867308 bellard
#if defined(DEBUG_SIGNAL)
900 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
901 67867308 bellard
           pc, address, is_write, *(unsigned long *)old_set);
902 67867308 bellard
#endif
903 67867308 bellard
    /* XXX: locking issue */
904 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
905 67867308 bellard
        return 1;
906 67867308 bellard
    }
907 67867308 bellard
908 ce09776b bellard
    /* see if it is an MMU fault */
909 6ebbf390 j_mayer
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
910 ce09776b bellard
    if (ret < 0)
911 ce09776b bellard
        return 0; /* not an MMU fault */
912 ce09776b bellard
    if (ret == 0)
913 ce09776b bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
914 ce09776b bellard
915 67867308 bellard
    /* now we have a real cpu fault */
916 67867308 bellard
    tb = tb_find_pc(pc);
917 67867308 bellard
    if (tb) {
918 67867308 bellard
        /* the PC is inside the translated code. It means that we have
919 67867308 bellard
           a virtual CPU fault */
920 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, puc);
921 67867308 bellard
    }
922 ce09776b bellard
    if (ret == 1) {
923 67867308 bellard
#if 0
924 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
925 ce09776b bellard
               env->nip, env->error_code, tb);
926 67867308 bellard
#endif
927 67867308 bellard
    /* we restore the process signal mask as the sigreturn should
928 67867308 bellard
       do it (XXX: use sigsetjmp) */
929 bf3e8bf1 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
930 9fddaa0c bellard
        do_raise_exception_err(env->exception_index, env->error_code);
931 ce09776b bellard
    } else {
932 ce09776b bellard
        /* activate soft MMU for this block */
933 fbf9eeb3 bellard
        cpu_resume_from_signal(env, puc);
934 ce09776b bellard
    }
935 67867308 bellard
    /* never comes here */
936 e6e5906b pbrook
    return 1;
937 e6e5906b pbrook
}
938 e6e5906b pbrook
939 e6e5906b pbrook
#elif defined(TARGET_M68K)
940 e6e5906b pbrook
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
941 e6e5906b pbrook
                                    int is_write, sigset_t *old_set,
942 e6e5906b pbrook
                                    void *puc)
943 e6e5906b pbrook
{
944 e6e5906b pbrook
    TranslationBlock *tb;
945 e6e5906b pbrook
    int ret;
946 e6e5906b pbrook
947 e6e5906b pbrook
    if (cpu_single_env)
948 e6e5906b pbrook
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
949 e6e5906b pbrook
#if defined(DEBUG_SIGNAL)
950 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
951 e6e5906b pbrook
           pc, address, is_write, *(unsigned long *)old_set);
952 e6e5906b pbrook
#endif
953 e6e5906b pbrook
    /* XXX: locking issue */
954 e6e5906b pbrook
    if (is_write && page_unprotect(address, pc, puc)) {
955 e6e5906b pbrook
        return 1;
956 e6e5906b pbrook
    }
957 e6e5906b pbrook
    /* see if it is an MMU fault */
958 6ebbf390 j_mayer
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
959 e6e5906b pbrook
    if (ret < 0)
960 e6e5906b pbrook
        return 0; /* not an MMU fault */
961 e6e5906b pbrook
    if (ret == 0)
962 e6e5906b pbrook
        return 1; /* the MMU fault was handled without causing real CPU fault */
963 e6e5906b pbrook
    /* now we have a real cpu fault */
964 e6e5906b pbrook
    tb = tb_find_pc(pc);
965 e6e5906b pbrook
    if (tb) {
966 e6e5906b pbrook
        /* the PC is inside the translated code. It means that we have
967 e6e5906b pbrook
           a virtual CPU fault */
968 e6e5906b pbrook
        cpu_restore_state(tb, env, pc, puc);
969 e6e5906b pbrook
    }
970 e6e5906b pbrook
    /* we restore the process signal mask as the sigreturn should
971 e6e5906b pbrook
       do it (XXX: use sigsetjmp) */
972 e6e5906b pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
973 e6e5906b pbrook
    cpu_loop_exit();
974 e6e5906b pbrook
    /* never comes here */
975 67867308 bellard
    return 1;
976 67867308 bellard
}
977 6af0bf9c bellard
978 6af0bf9c bellard
#elif defined (TARGET_MIPS)
979 6af0bf9c bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
980 6af0bf9c bellard
                                    int is_write, sigset_t *old_set,
981 6af0bf9c bellard
                                    void *puc)
982 6af0bf9c bellard
{
983 6af0bf9c bellard
    TranslationBlock *tb;
984 6af0bf9c bellard
    int ret;
985 3b46e624 ths
986 6af0bf9c bellard
    if (cpu_single_env)
987 6af0bf9c bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
988 6af0bf9c bellard
#if defined(DEBUG_SIGNAL)
989 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
990 6af0bf9c bellard
           pc, address, is_write, *(unsigned long *)old_set);
991 6af0bf9c bellard
#endif
992 6af0bf9c bellard
    /* XXX: locking issue */
993 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
994 6af0bf9c bellard
        return 1;
995 6af0bf9c bellard
    }
996 6af0bf9c bellard
997 6af0bf9c bellard
    /* see if it is an MMU fault */
998 6ebbf390 j_mayer
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
999 6af0bf9c bellard
    if (ret < 0)
1000 6af0bf9c bellard
        return 0; /* not an MMU fault */
1001 6af0bf9c bellard
    if (ret == 0)
1002 6af0bf9c bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1003 6af0bf9c bellard
1004 6af0bf9c bellard
    /* now we have a real cpu fault */
1005 6af0bf9c bellard
    tb = tb_find_pc(pc);
1006 6af0bf9c bellard
    if (tb) {
1007 6af0bf9c bellard
        /* the PC is inside the translated code. It means that we have
1008 6af0bf9c bellard
           a virtual CPU fault */
1009 6af0bf9c bellard
        cpu_restore_state(tb, env, pc, puc);
1010 6af0bf9c bellard
    }
1011 6af0bf9c bellard
    if (ret == 1) {
1012 6af0bf9c bellard
#if 0
1013 5fafdf24 ths
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1014 1eb5207b ths
               env->PC, env->error_code, tb);
1015 6af0bf9c bellard
#endif
1016 6af0bf9c bellard
    /* we restore the process signal mask as the sigreturn should
1017 6af0bf9c bellard
       do it (XXX: use sigsetjmp) */
1018 6af0bf9c bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
1019 6af0bf9c bellard
        do_raise_exception_err(env->exception_index, env->error_code);
1020 6af0bf9c bellard
    } else {
1021 6af0bf9c bellard
        /* activate soft MMU for this block */
1022 6af0bf9c bellard
        cpu_resume_from_signal(env, puc);
1023 6af0bf9c bellard
    }
1024 6af0bf9c bellard
    /* never comes here */
1025 6af0bf9c bellard
    return 1;
1026 6af0bf9c bellard
}
1027 6af0bf9c bellard
1028 fdf9b3e8 bellard
#elif defined (TARGET_SH4)
1029 fdf9b3e8 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1030 fdf9b3e8 bellard
                                    int is_write, sigset_t *old_set,
1031 fdf9b3e8 bellard
                                    void *puc)
1032 fdf9b3e8 bellard
{
1033 fdf9b3e8 bellard
    TranslationBlock *tb;
1034 fdf9b3e8 bellard
    int ret;
1035 3b46e624 ths
1036 fdf9b3e8 bellard
    if (cpu_single_env)
1037 fdf9b3e8 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1038 fdf9b3e8 bellard
#if defined(DEBUG_SIGNAL)
1039 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1040 fdf9b3e8 bellard
           pc, address, is_write, *(unsigned long *)old_set);
1041 fdf9b3e8 bellard
#endif
1042 fdf9b3e8 bellard
    /* XXX: locking issue */
1043 fdf9b3e8 bellard
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1044 fdf9b3e8 bellard
        return 1;
1045 fdf9b3e8 bellard
    }
1046 fdf9b3e8 bellard
1047 fdf9b3e8 bellard
    /* see if it is an MMU fault */
1048 6ebbf390 j_mayer
    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1049 fdf9b3e8 bellard
    if (ret < 0)
1050 fdf9b3e8 bellard
        return 0; /* not an MMU fault */
1051 fdf9b3e8 bellard
    if (ret == 0)
1052 fdf9b3e8 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1053 fdf9b3e8 bellard
1054 fdf9b3e8 bellard
    /* now we have a real cpu fault */
1055 eddf68a6 j_mayer
    tb = tb_find_pc(pc);
1056 eddf68a6 j_mayer
    if (tb) {
1057 eddf68a6 j_mayer
        /* the PC is inside the translated code. It means that we have
1058 eddf68a6 j_mayer
           a virtual CPU fault */
1059 eddf68a6 j_mayer
        cpu_restore_state(tb, env, pc, puc);
1060 eddf68a6 j_mayer
    }
1061 eddf68a6 j_mayer
#if 0
1062 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1063 eddf68a6 j_mayer
               env->nip, env->error_code, tb);
1064 eddf68a6 j_mayer
#endif
1065 eddf68a6 j_mayer
    /* we restore the process signal mask as the sigreturn should
1066 eddf68a6 j_mayer
       do it (XXX: use sigsetjmp) */
1067 eddf68a6 j_mayer
    sigprocmask(SIG_SETMASK, old_set, NULL);
1068 eddf68a6 j_mayer
    cpu_loop_exit();
1069 eddf68a6 j_mayer
    /* never comes here */
1070 eddf68a6 j_mayer
    return 1;
1071 eddf68a6 j_mayer
}
1072 eddf68a6 j_mayer
1073 eddf68a6 j_mayer
#elif defined (TARGET_ALPHA)
1074 eddf68a6 j_mayer
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1075 eddf68a6 j_mayer
                                    int is_write, sigset_t *old_set,
1076 eddf68a6 j_mayer
                                    void *puc)
1077 eddf68a6 j_mayer
{
1078 eddf68a6 j_mayer
    TranslationBlock *tb;
1079 eddf68a6 j_mayer
    int ret;
1080 3b46e624 ths
1081 eddf68a6 j_mayer
    if (cpu_single_env)
1082 eddf68a6 j_mayer
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1083 eddf68a6 j_mayer
#if defined(DEBUG_SIGNAL)
1084 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1085 eddf68a6 j_mayer
           pc, address, is_write, *(unsigned long *)old_set);
1086 eddf68a6 j_mayer
#endif
1087 eddf68a6 j_mayer
    /* XXX: locking issue */
1088 eddf68a6 j_mayer
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1089 eddf68a6 j_mayer
        return 1;
1090 eddf68a6 j_mayer
    }
1091 eddf68a6 j_mayer
1092 eddf68a6 j_mayer
    /* see if it is an MMU fault */
1093 6ebbf390 j_mayer
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1094 eddf68a6 j_mayer
    if (ret < 0)
1095 eddf68a6 j_mayer
        return 0; /* not an MMU fault */
1096 eddf68a6 j_mayer
    if (ret == 0)
1097 eddf68a6 j_mayer
        return 1; /* the MMU fault was handled without causing real CPU fault */
1098 eddf68a6 j_mayer
1099 eddf68a6 j_mayer
    /* now we have a real cpu fault */
1100 fdf9b3e8 bellard
    tb = tb_find_pc(pc);
1101 fdf9b3e8 bellard
    if (tb) {
1102 fdf9b3e8 bellard
        /* the PC is inside the translated code. It means that we have
1103 fdf9b3e8 bellard
           a virtual CPU fault */
1104 fdf9b3e8 bellard
        cpu_restore_state(tb, env, pc, puc);
1105 fdf9b3e8 bellard
    }
1106 fdf9b3e8 bellard
#if 0
1107 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1108 fdf9b3e8 bellard
               env->nip, env->error_code, tb);
1109 fdf9b3e8 bellard
#endif
1110 fdf9b3e8 bellard
    /* we restore the process signal mask as the sigreturn should
1111 fdf9b3e8 bellard
       do it (XXX: use sigsetjmp) */
1112 355fb23d pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
1113 355fb23d pbrook
    cpu_loop_exit();
1114 fdf9b3e8 bellard
    /* never comes here */
1115 fdf9b3e8 bellard
    return 1;
1116 fdf9b3e8 bellard
}
1117 f1ccf904 ths
#elif defined (TARGET_CRIS)
1118 f1ccf904 ths
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1119 f1ccf904 ths
                                    int is_write, sigset_t *old_set,
1120 f1ccf904 ths
                                    void *puc)
1121 f1ccf904 ths
{
1122 f1ccf904 ths
    TranslationBlock *tb;
1123 f1ccf904 ths
    int ret;
1124 f1ccf904 ths
1125 f1ccf904 ths
    if (cpu_single_env)
1126 f1ccf904 ths
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1127 f1ccf904 ths
#if defined(DEBUG_SIGNAL)
1128 f1ccf904 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1129 f1ccf904 ths
           pc, address, is_write, *(unsigned long *)old_set);
1130 f1ccf904 ths
#endif
1131 f1ccf904 ths
    /* XXX: locking issue */
1132 f1ccf904 ths
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1133 f1ccf904 ths
        return 1;
1134 f1ccf904 ths
    }
1135 f1ccf904 ths
1136 f1ccf904 ths
    /* see if it is an MMU fault */
1137 6ebbf390 j_mayer
    ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1138 f1ccf904 ths
    if (ret < 0)
1139 f1ccf904 ths
        return 0; /* not an MMU fault */
1140 f1ccf904 ths
    if (ret == 0)
1141 f1ccf904 ths
        return 1; /* the MMU fault was handled without causing real CPU fault */
1142 f1ccf904 ths
1143 f1ccf904 ths
    /* now we have a real cpu fault */
1144 f1ccf904 ths
    tb = tb_find_pc(pc);
1145 f1ccf904 ths
    if (tb) {
1146 f1ccf904 ths
        /* the PC is inside the translated code. It means that we have
1147 f1ccf904 ths
           a virtual CPU fault */
1148 f1ccf904 ths
        cpu_restore_state(tb, env, pc, puc);
1149 f1ccf904 ths
    }
1150 f1ccf904 ths
    /* we restore the process signal mask as the sigreturn should
1151 f1ccf904 ths
       do it (XXX: use sigsetjmp) */
1152 f1ccf904 ths
    sigprocmask(SIG_SETMASK, old_set, NULL);
1153 f1ccf904 ths
    cpu_loop_exit();
1154 f1ccf904 ths
    /* never comes here */
1155 f1ccf904 ths
    return 1;
1156 f1ccf904 ths
}
1157 f1ccf904 ths
1158 e4533c7a bellard
#else
1159 e4533c7a bellard
#error unsupported target CPU
1160 e4533c7a bellard
#endif
1161 9de5e440 bellard
1162 2b413144 bellard
#if defined(__i386__)
1163 2b413144 bellard
1164 d8ecc0b9 bellard
#if defined(__APPLE__)
1165 d8ecc0b9 bellard
# include <sys/ucontext.h>
1166 d8ecc0b9 bellard
1167 d8ecc0b9 bellard
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1168 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1169 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1170 d8ecc0b9 bellard
#else
1171 d8ecc0b9 bellard
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1172 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1173 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1174 d8ecc0b9 bellard
#endif
1175 d8ecc0b9 bellard
1176 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1177 e4533c7a bellard
                       void *puc)
1178 9de5e440 bellard
{
1179 5a7b542b ths
    siginfo_t *info = pinfo;
1180 9de5e440 bellard
    struct ucontext *uc = puc;
1181 9de5e440 bellard
    unsigned long pc;
1182 bf3e8bf1 bellard
    int trapno;
1183 97eb5b14 bellard
1184 d691f669 bellard
#ifndef REG_EIP
1185 d691f669 bellard
/* for glibc 2.1 */
1186 fd6ce8f6 bellard
#define REG_EIP    EIP
1187 fd6ce8f6 bellard
#define REG_ERR    ERR
1188 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
1189 d691f669 bellard
#endif
1190 d8ecc0b9 bellard
    pc = EIP_sig(uc);
1191 d8ecc0b9 bellard
    trapno = TRAP_sig(uc);
1192 ec6338ba bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1193 ec6338ba bellard
                             trapno == 0xe ?
1194 ec6338ba bellard
                             (ERROR_sig(uc) >> 1) & 1 : 0,
1195 ec6338ba bellard
                             &uc->uc_sigmask, puc);
1196 2b413144 bellard
}
1197 2b413144 bellard
1198 bc51c5c9 bellard
#elif defined(__x86_64__)
1199 bc51c5c9 bellard
1200 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo,
1201 bc51c5c9 bellard
                       void *puc)
1202 bc51c5c9 bellard
{
1203 5a7b542b ths
    siginfo_t *info = pinfo;
1204 bc51c5c9 bellard
    struct ucontext *uc = puc;
1205 bc51c5c9 bellard
    unsigned long pc;
1206 bc51c5c9 bellard
1207 bc51c5c9 bellard
    pc = uc->uc_mcontext.gregs[REG_RIP];
1208 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1209 5fafdf24 ths
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1210 bc51c5c9 bellard
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1211 bc51c5c9 bellard
                             &uc->uc_sigmask, puc);
1212 bc51c5c9 bellard
}
1213 bc51c5c9 bellard
1214 83fb7adf bellard
#elif defined(__powerpc__)
1215 2b413144 bellard
1216 83fb7adf bellard
/***********************************************************************
1217 83fb7adf bellard
 * signal context platform-specific definitions
1218 83fb7adf bellard
 * From Wine
1219 83fb7adf bellard
 */
1220 83fb7adf bellard
#ifdef linux
1221 83fb7adf bellard
/* All Registers access - only for local access */
1222 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1223 83fb7adf bellard
/* Gpr Registers access  */
1224 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1225 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1226 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1227 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1228 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1229 83fb7adf bellard
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1230 83fb7adf bellard
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1231 83fb7adf bellard
/* Float Registers access  */
1232 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1233 83fb7adf bellard
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1234 83fb7adf bellard
/* Exception Registers access */
1235 83fb7adf bellard
# define DAR_sig(context)                        REG_sig(dar, context)
1236 83fb7adf bellard
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1237 83fb7adf bellard
# define TRAP_sig(context)                        REG_sig(trap, context)
1238 83fb7adf bellard
#endif /* linux */
1239 83fb7adf bellard
1240 83fb7adf bellard
#ifdef __APPLE__
1241 83fb7adf bellard
# include <sys/ucontext.h>
1242 83fb7adf bellard
typedef struct ucontext SIGCONTEXT;
1243 83fb7adf bellard
/* All Registers access - only for local access */
1244 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1245 83fb7adf bellard
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1246 83fb7adf bellard
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1247 83fb7adf bellard
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1248 83fb7adf bellard
/* Gpr Registers access */
1249 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1250 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1251 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1252 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)
1253 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1254 83fb7adf bellard
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1255 83fb7adf bellard
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1256 83fb7adf bellard
/* Float Registers access */
1257 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1258 83fb7adf bellard
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1259 83fb7adf bellard
/* Exception Registers access */
1260 83fb7adf bellard
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1261 83fb7adf bellard
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1262 83fb7adf bellard
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1263 83fb7adf bellard
#endif /* __APPLE__ */
1264 83fb7adf bellard
1265 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1266 e4533c7a bellard
                       void *puc)
1267 2b413144 bellard
{
1268 5a7b542b ths
    siginfo_t *info = pinfo;
1269 25eb4484 bellard
    struct ucontext *uc = puc;
1270 25eb4484 bellard
    unsigned long pc;
1271 25eb4484 bellard
    int is_write;
1272 25eb4484 bellard
1273 83fb7adf bellard
    pc = IAR_sig(uc);
1274 25eb4484 bellard
    is_write = 0;
1275 25eb4484 bellard
#if 0
1276 25eb4484 bellard
    /* ppc 4xx case */
1277 83fb7adf bellard
    if (DSISR_sig(uc) & 0x00800000)
1278 25eb4484 bellard
        is_write = 1;
1279 25eb4484 bellard
#else
1280 83fb7adf bellard
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1281 25eb4484 bellard
        is_write = 1;
1282 25eb4484 bellard
#endif
1283 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1284 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1285 2b413144 bellard
}
1286 2b413144 bellard
1287 2f87c607 bellard
#elif defined(__alpha__)
1288 2f87c607 bellard
1289 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1290 2f87c607 bellard
                           void *puc)
1291 2f87c607 bellard
{
1292 5a7b542b ths
    siginfo_t *info = pinfo;
1293 2f87c607 bellard
    struct ucontext *uc = puc;
1294 2f87c607 bellard
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1295 2f87c607 bellard
    uint32_t insn = *pc;
1296 2f87c607 bellard
    int is_write = 0;
1297 2f87c607 bellard
1298 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1299 2f87c607 bellard
    switch (insn >> 26) {
1300 2f87c607 bellard
    case 0x0d: // stw
1301 2f87c607 bellard
    case 0x0e: // stb
1302 2f87c607 bellard
    case 0x0f: // stq_u
1303 2f87c607 bellard
    case 0x24: // stf
1304 2f87c607 bellard
    case 0x25: // stg
1305 2f87c607 bellard
    case 0x26: // sts
1306 2f87c607 bellard
    case 0x27: // stt
1307 2f87c607 bellard
    case 0x2c: // stl
1308 2f87c607 bellard
    case 0x2d: // stq
1309 2f87c607 bellard
    case 0x2e: // stl_c
1310 2f87c607 bellard
    case 0x2f: // stq_c
1311 2f87c607 bellard
        is_write = 1;
1312 2f87c607 bellard
    }
1313 2f87c607 bellard
1314 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1315 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1316 2f87c607 bellard
}
1317 8c6939c0 bellard
#elif defined(__sparc__)
1318 8c6939c0 bellard
1319 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1320 e4533c7a bellard
                       void *puc)
1321 8c6939c0 bellard
{
1322 5a7b542b ths
    siginfo_t *info = pinfo;
1323 8c6939c0 bellard
    int is_write;
1324 8c6939c0 bellard
    uint32_t insn;
1325 6b4c11cd blueswir1
#if !defined(__arch64__) || defined(HOST_SOLARIS)
1326 c9e1e2b0 blueswir1
    uint32_t *regs = (uint32_t *)(info + 1);
1327 c9e1e2b0 blueswir1
    void *sigmask = (regs + 20);
1328 8c6939c0 bellard
    /* XXX: is there a standard glibc define ? */
1329 c9e1e2b0 blueswir1
    unsigned long pc = regs[1];
1330 c9e1e2b0 blueswir1
#else
1331 c9e1e2b0 blueswir1
    struct sigcontext *sc = puc;
1332 c9e1e2b0 blueswir1
    unsigned long pc = sc->sigc_regs.tpc;
1333 c9e1e2b0 blueswir1
    void *sigmask = (void *)sc->sigc_mask;
1334 c9e1e2b0 blueswir1
#endif
1335 c9e1e2b0 blueswir1
1336 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1337 8c6939c0 bellard
    is_write = 0;
1338 8c6939c0 bellard
    insn = *(uint32_t *)pc;
1339 8c6939c0 bellard
    if ((insn >> 30) == 3) {
1340 8c6939c0 bellard
      switch((insn >> 19) & 0x3f) {
1341 8c6939c0 bellard
      case 0x05: // stb
1342 8c6939c0 bellard
      case 0x06: // sth
1343 8c6939c0 bellard
      case 0x04: // st
1344 8c6939c0 bellard
      case 0x07: // std
1345 8c6939c0 bellard
      case 0x24: // stf
1346 8c6939c0 bellard
      case 0x27: // stdf
1347 8c6939c0 bellard
      case 0x25: // stfsr
1348 8c6939c0 bellard
        is_write = 1;
1349 8c6939c0 bellard
        break;
1350 8c6939c0 bellard
      }
1351 8c6939c0 bellard
    }
1352 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1353 bf3e8bf1 bellard
                             is_write, sigmask, NULL);
1354 8c6939c0 bellard
}
1355 8c6939c0 bellard
1356 8c6939c0 bellard
#elif defined(__arm__)
1357 8c6939c0 bellard
1358 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1359 e4533c7a bellard
                       void *puc)
1360 8c6939c0 bellard
{
1361 5a7b542b ths
    siginfo_t *info = pinfo;
1362 8c6939c0 bellard
    struct ucontext *uc = puc;
1363 8c6939c0 bellard
    unsigned long pc;
1364 8c6939c0 bellard
    int is_write;
1365 3b46e624 ths
1366 48bbf11b blueswir1
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1367 5c49b363 balrog
    pc = uc->uc_mcontext.gregs[R15];
1368 5c49b363 balrog
#else
1369 4eee57f5 balrog
    pc = uc->uc_mcontext.arm_pc;
1370 5c49b363 balrog
#endif
1371 8c6939c0 bellard
    /* XXX: compute is_write */
1372 8c6939c0 bellard
    is_write = 0;
1373 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1374 8c6939c0 bellard
                             is_write,
1375 f3a9676a pbrook
                             &uc->uc_sigmask, puc);
1376 8c6939c0 bellard
}
1377 8c6939c0 bellard
1378 38e584a0 bellard
#elif defined(__mc68000)
1379 38e584a0 bellard
1380 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1381 38e584a0 bellard
                       void *puc)
1382 38e584a0 bellard
{
1383 5a7b542b ths
    siginfo_t *info = pinfo;
1384 38e584a0 bellard
    struct ucontext *uc = puc;
1385 38e584a0 bellard
    unsigned long pc;
1386 38e584a0 bellard
    int is_write;
1387 3b46e624 ths
1388 38e584a0 bellard
    pc = uc->uc_mcontext.gregs[16];
1389 38e584a0 bellard
    /* XXX: compute is_write */
1390 38e584a0 bellard
    is_write = 0;
1391 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1392 38e584a0 bellard
                             is_write,
1393 bf3e8bf1 bellard
                             &uc->uc_sigmask, puc);
1394 38e584a0 bellard
}
1395 38e584a0 bellard
1396 b8076a74 bellard
#elif defined(__ia64)
1397 b8076a74 bellard
1398 b8076a74 bellard
#ifndef __ISR_VALID
1399 b8076a74 bellard
  /* This ought to be in <bits/siginfo.h>... */
1400 b8076a74 bellard
# define __ISR_VALID        1
1401 b8076a74 bellard
#endif
1402 b8076a74 bellard
1403 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1404 b8076a74 bellard
{
1405 5a7b542b ths
    siginfo_t *info = pinfo;
1406 b8076a74 bellard
    struct ucontext *uc = puc;
1407 b8076a74 bellard
    unsigned long ip;
1408 b8076a74 bellard
    int is_write = 0;
1409 b8076a74 bellard
1410 b8076a74 bellard
    ip = uc->uc_mcontext.sc_ip;
1411 b8076a74 bellard
    switch (host_signum) {
1412 b8076a74 bellard
      case SIGILL:
1413 b8076a74 bellard
      case SIGFPE:
1414 b8076a74 bellard
      case SIGSEGV:
1415 b8076a74 bellard
      case SIGBUS:
1416 b8076a74 bellard
      case SIGTRAP:
1417 fd4a43e4 bellard
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1418 b8076a74 bellard
              /* ISR.W (write-access) is bit 33:  */
1419 b8076a74 bellard
              is_write = (info->si_isr >> 33) & 1;
1420 b8076a74 bellard
          break;
1421 b8076a74 bellard
1422 b8076a74 bellard
      default:
1423 b8076a74 bellard
          break;
1424 b8076a74 bellard
    }
1425 b8076a74 bellard
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1426 b8076a74 bellard
                             is_write,
1427 b8076a74 bellard
                             &uc->uc_sigmask, puc);
1428 b8076a74 bellard
}
1429 b8076a74 bellard
1430 90cb9493 bellard
#elif defined(__s390__)
1431 90cb9493 bellard
1432 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1433 90cb9493 bellard
                       void *puc)
1434 90cb9493 bellard
{
1435 5a7b542b ths
    siginfo_t *info = pinfo;
1436 90cb9493 bellard
    struct ucontext *uc = puc;
1437 90cb9493 bellard
    unsigned long pc;
1438 90cb9493 bellard
    int is_write;
1439 3b46e624 ths
1440 90cb9493 bellard
    pc = uc->uc_mcontext.psw.addr;
1441 90cb9493 bellard
    /* XXX: compute is_write */
1442 90cb9493 bellard
    is_write = 0;
1443 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1444 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1445 c4b89d18 ths
}
1446 c4b89d18 ths
1447 c4b89d18 ths
#elif defined(__mips__)
1448 c4b89d18 ths
1449 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1450 c4b89d18 ths
                       void *puc)
1451 c4b89d18 ths
{
1452 9617efe8 ths
    siginfo_t *info = pinfo;
1453 c4b89d18 ths
    struct ucontext *uc = puc;
1454 c4b89d18 ths
    greg_t pc = uc->uc_mcontext.pc;
1455 c4b89d18 ths
    int is_write;
1456 3b46e624 ths
1457 c4b89d18 ths
    /* XXX: compute is_write */
1458 c4b89d18 ths
    is_write = 0;
1459 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1460 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1461 90cb9493 bellard
}
1462 90cb9493 bellard
1463 f54b3f92 aurel32
#elif defined(__hppa__)
1464 f54b3f92 aurel32
1465 f54b3f92 aurel32
int cpu_signal_handler(int host_signum, void *pinfo,
1466 f54b3f92 aurel32
                       void *puc)
1467 f54b3f92 aurel32
{
1468 f54b3f92 aurel32
    struct siginfo *info = pinfo;
1469 f54b3f92 aurel32
    struct ucontext *uc = puc;
1470 f54b3f92 aurel32
    unsigned long pc;
1471 f54b3f92 aurel32
    int is_write;
1472 f54b3f92 aurel32
1473 f54b3f92 aurel32
    pc = uc->uc_mcontext.sc_iaoq[0];
1474 f54b3f92 aurel32
    /* FIXME: compute is_write */
1475 f54b3f92 aurel32
    is_write = 0;
1476 f54b3f92 aurel32
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1477 f54b3f92 aurel32
                             is_write,
1478 f54b3f92 aurel32
                             &uc->uc_sigmask, puc);
1479 f54b3f92 aurel32
}
1480 f54b3f92 aurel32
1481 9de5e440 bellard
#else
1482 2b413144 bellard
1483 3fb2ded1 bellard
#error host CPU specific signal handler needed
1484 2b413144 bellard
1485 9de5e440 bellard
#endif
1486 67b915a5 bellard
1487 67b915a5 bellard
#endif /* !defined(CONFIG_SOFTMMU) */