Statistics
| Branch: | Revision:

root / exec-i386.c @ 25eb4484

History | View | Annotate | Download (11.1 kB)

1 7d13299d bellard
/*
2 7d13299d bellard
 *  i386 emulator main execution loop
3 7d13299d bellard
 * 
4 7d13299d bellard
 *  Copyright (c) 2003 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 7d13299d bellard
#include "exec-i386.h"
21 956034d7 bellard
#include "disas.h"
22 7d13299d bellard
23 dc99065b bellard
//#define DEBUG_EXEC
24 9de5e440 bellard
//#define DEBUG_SIGNAL
25 7d13299d bellard
26 7d13299d bellard
/* main execution loop */
27 7d13299d bellard
28 1b6b029e bellard
/* thread support */
29 1b6b029e bellard
30 25eb4484 bellard
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
31 1b6b029e bellard
32 1b6b029e bellard
void cpu_lock(void)
33 1b6b029e bellard
{
34 25eb4484 bellard
    spin_lock(&global_cpu_lock);
35 1b6b029e bellard
}
36 1b6b029e bellard
37 1b6b029e bellard
void cpu_unlock(void)
38 1b6b029e bellard
{
39 25eb4484 bellard
    spin_unlock(&global_cpu_lock);
40 1b6b029e bellard
}
41 1b6b029e bellard
42 9de5e440 bellard
/* exception support */
43 9de5e440 bellard
/* NOTE: not static to force relocation generation by GCC */
44 b56dad1c bellard
void raise_exception_err(int exception_index, int error_code)
45 9de5e440 bellard
{
46 9de5e440 bellard
    /* NOTE: the register at this point must be saved by hand because
47 9de5e440 bellard
       longjmp restore them */
48 ae228531 bellard
#ifdef __sparc__
49 ae228531 bellard
        /* We have to stay in the same register window as our caller,
50 ae228531 bellard
         * thus this trick.
51 ae228531 bellard
         */
52 ae228531 bellard
        __asm__ __volatile__("restore\n\t"
53 ae228531 bellard
                             "mov\t%o0, %i0");
54 ae228531 bellard
#endif
55 9de5e440 bellard
#ifdef reg_EAX
56 9de5e440 bellard
    env->regs[R_EAX] = EAX;
57 9de5e440 bellard
#endif
58 9de5e440 bellard
#ifdef reg_ECX
59 9de5e440 bellard
    env->regs[R_ECX] = ECX;
60 9de5e440 bellard
#endif
61 9de5e440 bellard
#ifdef reg_EDX
62 9de5e440 bellard
    env->regs[R_EDX] = EDX;
63 9de5e440 bellard
#endif
64 9de5e440 bellard
#ifdef reg_EBX
65 9de5e440 bellard
    env->regs[R_EBX] = EBX;
66 9de5e440 bellard
#endif
67 9de5e440 bellard
#ifdef reg_ESP
68 9de5e440 bellard
    env->regs[R_ESP] = ESP;
69 9de5e440 bellard
#endif
70 9de5e440 bellard
#ifdef reg_EBP
71 9de5e440 bellard
    env->regs[R_EBP] = EBP;
72 9de5e440 bellard
#endif
73 9de5e440 bellard
#ifdef reg_ESI
74 9de5e440 bellard
    env->regs[R_ESI] = ESI;
75 9de5e440 bellard
#endif
76 9de5e440 bellard
#ifdef reg_EDI
77 9de5e440 bellard
    env->regs[R_EDI] = EDI;
78 9de5e440 bellard
#endif
79 9de5e440 bellard
    env->exception_index = exception_index;
80 b56dad1c bellard
    env->error_code = error_code;
81 9de5e440 bellard
    longjmp(env->jmp_env, 1);
82 9de5e440 bellard
}
83 9de5e440 bellard
84 b56dad1c bellard
/* short cut if error_code is 0 or not present */
85 b56dad1c bellard
void raise_exception(int exception_index)
86 b56dad1c bellard
{
87 b56dad1c bellard
    raise_exception_err(exception_index, 0);
88 b56dad1c bellard
}
89 b56dad1c bellard
90 7d13299d bellard
int cpu_x86_exec(CPUX86State *env1)
91 7d13299d bellard
{
92 7d13299d bellard
    int saved_T0, saved_T1, saved_A0;
93 7d13299d bellard
    CPUX86State *saved_env;
94 04369ff2 bellard
#ifdef reg_EAX
95 04369ff2 bellard
    int saved_EAX;
96 04369ff2 bellard
#endif
97 04369ff2 bellard
#ifdef reg_ECX
98 04369ff2 bellard
    int saved_ECX;
99 04369ff2 bellard
#endif
100 04369ff2 bellard
#ifdef reg_EDX
101 04369ff2 bellard
    int saved_EDX;
102 04369ff2 bellard
#endif
103 04369ff2 bellard
#ifdef reg_EBX
104 04369ff2 bellard
    int saved_EBX;
105 04369ff2 bellard
#endif
106 04369ff2 bellard
#ifdef reg_ESP
107 04369ff2 bellard
    int saved_ESP;
108 04369ff2 bellard
#endif
109 04369ff2 bellard
#ifdef reg_EBP
110 04369ff2 bellard
    int saved_EBP;
111 04369ff2 bellard
#endif
112 04369ff2 bellard
#ifdef reg_ESI
113 04369ff2 bellard
    int saved_ESI;
114 04369ff2 bellard
#endif
115 04369ff2 bellard
#ifdef reg_EDI
116 04369ff2 bellard
    int saved_EDI;
117 04369ff2 bellard
#endif
118 fd6ce8f6 bellard
    int code_gen_size, ret, code_size;
119 7d13299d bellard
    void (*gen_func)(void);
120 9de5e440 bellard
    TranslationBlock *tb, **ptb;
121 dab2ed99 bellard
    uint8_t *tc_ptr, *cs_base, *pc;
122 6dbad63e bellard
    unsigned int flags;
123 6dbad63e bellard
124 7d13299d bellard
    /* first we save global registers */
125 7d13299d bellard
    saved_T0 = T0;
126 7d13299d bellard
    saved_T1 = T1;
127 7d13299d bellard
    saved_A0 = A0;
128 7d13299d bellard
    saved_env = env;
129 7d13299d bellard
    env = env1;
130 04369ff2 bellard
#ifdef reg_EAX
131 04369ff2 bellard
    saved_EAX = EAX;
132 04369ff2 bellard
    EAX = env->regs[R_EAX];
133 04369ff2 bellard
#endif
134 04369ff2 bellard
#ifdef reg_ECX
135 04369ff2 bellard
    saved_ECX = ECX;
136 04369ff2 bellard
    ECX = env->regs[R_ECX];
137 04369ff2 bellard
#endif
138 04369ff2 bellard
#ifdef reg_EDX
139 04369ff2 bellard
    saved_EDX = EDX;
140 04369ff2 bellard
    EDX = env->regs[R_EDX];
141 04369ff2 bellard
#endif
142 04369ff2 bellard
#ifdef reg_EBX
143 04369ff2 bellard
    saved_EBX = EBX;
144 04369ff2 bellard
    EBX = env->regs[R_EBX];
145 04369ff2 bellard
#endif
146 04369ff2 bellard
#ifdef reg_ESP
147 04369ff2 bellard
    saved_ESP = ESP;
148 04369ff2 bellard
    ESP = env->regs[R_ESP];
149 04369ff2 bellard
#endif
150 04369ff2 bellard
#ifdef reg_EBP
151 04369ff2 bellard
    saved_EBP = EBP;
152 04369ff2 bellard
    EBP = env->regs[R_EBP];
153 04369ff2 bellard
#endif
154 04369ff2 bellard
#ifdef reg_ESI
155 04369ff2 bellard
    saved_ESI = ESI;
156 04369ff2 bellard
    ESI = env->regs[R_ESI];
157 04369ff2 bellard
#endif
158 04369ff2 bellard
#ifdef reg_EDI
159 04369ff2 bellard
    saved_EDI = EDI;
160 04369ff2 bellard
    EDI = env->regs[R_EDI];
161 04369ff2 bellard
#endif
162 7d13299d bellard
    
163 9de5e440 bellard
    /* put eflags in CPU temporary format */
164 fc2b4c48 bellard
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
165 fc2b4c48 bellard
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
166 9de5e440 bellard
    CC_OP = CC_OP_EFLAGS;
167 fc2b4c48 bellard
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
168 9de5e440 bellard
    env->interrupt_request = 0;
169 9d27abd9 bellard
170 7d13299d bellard
    /* prepare setjmp context for exception handling */
171 7d13299d bellard
    if (setjmp(env->jmp_env) == 0) {
172 7d13299d bellard
        for(;;) {
173 9de5e440 bellard
            if (env->interrupt_request) {
174 9de5e440 bellard
                raise_exception(EXCP_INTERRUPT);
175 9de5e440 bellard
            }
176 7d13299d bellard
#ifdef DEBUG_EXEC
177 7d13299d bellard
            if (loglevel) {
178 9d27abd9 bellard
                /* XXX: save all volatile state in cpu state */
179 9d27abd9 bellard
                /* restore flags in standard format */
180 9d27abd9 bellard
                env->regs[R_EAX] = EAX;
181 9d27abd9 bellard
                env->regs[R_EBX] = EBX;
182 9d27abd9 bellard
                env->regs[R_ECX] = ECX;
183 9d27abd9 bellard
                env->regs[R_EDX] = EDX;
184 9d27abd9 bellard
                env->regs[R_ESI] = ESI;
185 9d27abd9 bellard
                env->regs[R_EDI] = EDI;
186 9d27abd9 bellard
                env->regs[R_EBP] = EBP;
187 9d27abd9 bellard
                env->regs[R_ESP] = ESP;
188 9d27abd9 bellard
                env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
189 9d27abd9 bellard
                cpu_x86_dump_state(env, logfile, 0);
190 9d27abd9 bellard
                env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
191 7d13299d bellard
            }
192 7d13299d bellard
#endif
193 6dbad63e bellard
            /* we compute the CPU state. We assume it will not
194 6dbad63e bellard
               change during the whole generated block. */
195 6dbad63e bellard
            flags = env->seg_cache[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT;
196 dab2ed99 bellard
            flags |= env->seg_cache[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT;
197 6dbad63e bellard
            flags |= (((unsigned long)env->seg_cache[R_DS].base | 
198 6dbad63e bellard
                       (unsigned long)env->seg_cache[R_ES].base |
199 6dbad63e bellard
                       (unsigned long)env->seg_cache[R_SS].base) != 0) << 
200 6dbad63e bellard
                GEN_FLAG_ADDSEG_SHIFT;
201 9d27abd9 bellard
            if (!(env->eflags & VM_MASK)) {
202 9d27abd9 bellard
                flags |= (env->segs[R_CS] & 3) << GEN_FLAG_CPL_SHIFT;
203 9d27abd9 bellard
            } else {
204 9d27abd9 bellard
                /* NOTE: a dummy CPL is kept */
205 9d27abd9 bellard
                flags |= (1 << GEN_FLAG_VM_SHIFT);
206 9d27abd9 bellard
                flags |= (3 << GEN_FLAG_CPL_SHIFT);
207 9d27abd9 bellard
            }
208 b56dad1c bellard
            flags |= (env->eflags & IOPL_MASK) >> (12 - GEN_FLAG_IOPL_SHIFT);
209 cabb4d61 bellard
            flags |= (env->eflags & TF_MASK) << (GEN_FLAG_TF_SHIFT - 8);
210 dab2ed99 bellard
            cs_base = env->seg_cache[R_CS].base;
211 dab2ed99 bellard
            pc = cs_base + env->eip;
212 9de5e440 bellard
            tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base, 
213 9de5e440 bellard
                         flags);
214 9de5e440 bellard
            if (!tb) {
215 7d13299d bellard
                /* if no translated code available, then translate it now */
216 25eb4484 bellard
                /* very inefficient but safe: we lock all the cpus
217 25eb4484 bellard
                   when generating code */
218 25eb4484 bellard
                spin_lock(&tb_lock);
219 7d13299d bellard
                tc_ptr = code_gen_ptr;
220 9de5e440 bellard
                ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE, 
221 fd6ce8f6 bellard
                                       &code_gen_size, pc, cs_base, flags,
222 fd6ce8f6 bellard
                                       &code_size);
223 9de5e440 bellard
                /* if invalid instruction, signal it */
224 9de5e440 bellard
                if (ret != 0) {
225 25eb4484 bellard
                    spin_unlock(&tb_lock);
226 9de5e440 bellard
                    raise_exception(EXCP06_ILLOP);
227 9de5e440 bellard
                }
228 fd6ce8f6 bellard
                tb = tb_alloc((unsigned long)pc, code_size);
229 9de5e440 bellard
                *ptb = tb;
230 9de5e440 bellard
                tb->cs_base = (unsigned long)cs_base;
231 9de5e440 bellard
                tb->flags = flags;
232 7d13299d bellard
                tb->tc_ptr = tc_ptr;
233 9de5e440 bellard
                tb->hash_next = NULL;
234 7d13299d bellard
                code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
235 25eb4484 bellard
                spin_unlock(&tb_lock);
236 7d13299d bellard
            }
237 9d27abd9 bellard
#ifdef DEBUG_EXEC
238 956034d7 bellard
            if (loglevel) {
239 956034d7 bellard
                fprintf(logfile, "Trace 0x%08lx [0x%08lx] %s\n",
240 956034d7 bellard
                        (long)tb->tc_ptr, (long)tb->pc,
241 956034d7 bellard
                        lookup_symbol((void *)tb->pc));
242 956034d7 bellard
            }
243 9d27abd9 bellard
#endif
244 7d13299d bellard
            /* execute the generated code */
245 9de5e440 bellard
            tc_ptr = tb->tc_ptr;
246 7d13299d bellard
            gen_func = (void *)tc_ptr;
247 ae228531 bellard
#ifdef __sparc__
248 ae228531 bellard
            __asm__ __volatile__("call        %0\n\t"
249 ae228531 bellard
                                 " mov        %%o7,%%i0"
250 ae228531 bellard
                                 : /* no outputs */
251 ae228531 bellard
                                 : "r" (gen_func)
252 ae228531 bellard
                                 : "i0", "i1", "i2", "i3", "i4", "i5");
253 ae228531 bellard
#else
254 7d13299d bellard
            gen_func();
255 ae228531 bellard
#endif
256 7d13299d bellard
        }
257 7d13299d bellard
    }
258 7d13299d bellard
    ret = env->exception_index;
259 7d13299d bellard
260 9de5e440 bellard
    /* restore flags in standard format */
261 fc2b4c48 bellard
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
262 9de5e440 bellard
263 7d13299d bellard
    /* restore global registers */
264 04369ff2 bellard
#ifdef reg_EAX
265 04369ff2 bellard
    EAX = saved_EAX;
266 04369ff2 bellard
#endif
267 04369ff2 bellard
#ifdef reg_ECX
268 04369ff2 bellard
    ECX = saved_ECX;
269 04369ff2 bellard
#endif
270 04369ff2 bellard
#ifdef reg_EDX
271 04369ff2 bellard
    EDX = saved_EDX;
272 04369ff2 bellard
#endif
273 04369ff2 bellard
#ifdef reg_EBX
274 04369ff2 bellard
    EBX = saved_EBX;
275 04369ff2 bellard
#endif
276 04369ff2 bellard
#ifdef reg_ESP
277 04369ff2 bellard
    ESP = saved_ESP;
278 04369ff2 bellard
#endif
279 04369ff2 bellard
#ifdef reg_EBP
280 04369ff2 bellard
    EBP = saved_EBP;
281 04369ff2 bellard
#endif
282 04369ff2 bellard
#ifdef reg_ESI
283 04369ff2 bellard
    ESI = saved_ESI;
284 04369ff2 bellard
#endif
285 04369ff2 bellard
#ifdef reg_EDI
286 04369ff2 bellard
    EDI = saved_EDI;
287 04369ff2 bellard
#endif
288 7d13299d bellard
    T0 = saved_T0;
289 7d13299d bellard
    T1 = saved_T1;
290 7d13299d bellard
    A0 = saved_A0;
291 7d13299d bellard
    env = saved_env;
292 7d13299d bellard
    return ret;
293 7d13299d bellard
}
294 6dbad63e bellard
295 9de5e440 bellard
void cpu_x86_interrupt(CPUX86State *s)
296 9de5e440 bellard
{
297 9de5e440 bellard
    s->interrupt_request = 1;
298 9de5e440 bellard
}
299 9de5e440 bellard
300 9de5e440 bellard
301 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
302 6dbad63e bellard
{
303 6dbad63e bellard
    CPUX86State *saved_env;
304 6dbad63e bellard
305 6dbad63e bellard
    saved_env = env;
306 6dbad63e bellard
    env = s;
307 6dbad63e bellard
    load_seg(seg_reg, selector);
308 6dbad63e bellard
    env = saved_env;
309 6dbad63e bellard
}
310 9de5e440 bellard
311 9de5e440 bellard
#undef EAX
312 9de5e440 bellard
#undef ECX
313 9de5e440 bellard
#undef EDX
314 9de5e440 bellard
#undef EBX
315 9de5e440 bellard
#undef ESP
316 9de5e440 bellard
#undef EBP
317 9de5e440 bellard
#undef ESI
318 9de5e440 bellard
#undef EDI
319 9de5e440 bellard
#undef EIP
320 9de5e440 bellard
#include <signal.h>
321 9de5e440 bellard
#include <sys/ucontext.h>
322 9de5e440 bellard
323 b56dad1c bellard
/* 'pc' is the host PC at which the exception was raised. 'address' is
324 fd6ce8f6 bellard
   the effective address of the memory exception. 'is_write' is 1 if a
325 fd6ce8f6 bellard
   write caused the exception and otherwise 0'. 'old_set' is the
326 fd6ce8f6 bellard
   signal set which should be restored */
327 9de5e440 bellard
static inline int handle_cpu_signal(unsigned long pc,
328 b56dad1c bellard
                                    unsigned long address,
329 fd6ce8f6 bellard
                                    int is_write,
330 9de5e440 bellard
                                    sigset_t *old_set)
331 9de5e440 bellard
{
332 fd6ce8f6 bellard
#if defined(DEBUG_SIGNAL)
333 fd6ce8f6 bellard
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx wr=%d oldset=0x%08lx\n", 
334 fd6ce8f6 bellard
           pc, address, is_write, *(unsigned long *)old_set);
335 9de5e440 bellard
#endif
336 25eb4484 bellard
    /* XXX: locking issue */
337 fd6ce8f6 bellard
    if (is_write && page_unprotect(address)) {
338 fd6ce8f6 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
339 fd6ce8f6 bellard
        return 1;
340 fd6ce8f6 bellard
    }
341 9de5e440 bellard
    if (pc >= (unsigned long)code_gen_buffer &&
342 9de5e440 bellard
        pc < (unsigned long)code_gen_buffer + CODE_GEN_BUFFER_SIZE) {
343 9de5e440 bellard
        /* the PC is inside the translated code. It means that we have
344 9de5e440 bellard
           a virtual CPU fault */
345 9de5e440 bellard
        /* we restore the process signal mask as the sigreturn should
346 9de5e440 bellard
           do it */
347 9de5e440 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
348 9de5e440 bellard
        /* XXX: need to compute virtual pc position by retranslating
349 9de5e440 bellard
           code. The rest of the CPU state should be correct. */
350 b56dad1c bellard
        env->cr2 = address;
351 fd6ce8f6 bellard
        raise_exception_err(EXCP0E_PAGE, 4 | (is_write << 1));
352 9de5e440 bellard
        /* never comes here */
353 9de5e440 bellard
        return 1;
354 9de5e440 bellard
    } else {
355 9de5e440 bellard
        return 0;
356 9de5e440 bellard
    }
357 9de5e440 bellard
}
358 9de5e440 bellard
359 9de5e440 bellard
int cpu_x86_signal_handler(int host_signum, struct siginfo *info, 
360 9de5e440 bellard
                           void *puc)
361 9de5e440 bellard
{
362 9de5e440 bellard
#if defined(__i386__)
363 9de5e440 bellard
    struct ucontext *uc = puc;
364 9de5e440 bellard
    unsigned long pc;
365 9de5e440 bellard
    sigset_t *pold_set;
366 9de5e440 bellard
    
367 d691f669 bellard
#ifndef REG_EIP
368 d691f669 bellard
/* for glibc 2.1 */
369 fd6ce8f6 bellard
#define REG_EIP    EIP
370 fd6ce8f6 bellard
#define REG_ERR    ERR
371 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
372 d691f669 bellard
#endif
373 fc2b4c48 bellard
    pc = uc->uc_mcontext.gregs[REG_EIP];
374 9de5e440 bellard
    pold_set = &uc->uc_sigmask;
375 fd6ce8f6 bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
376 fd6ce8f6 bellard
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? 
377 fd6ce8f6 bellard
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
378 fd6ce8f6 bellard
                             pold_set);
379 25eb4484 bellard
#elif defined(__powerpc)
380 25eb4484 bellard
    struct ucontext *uc = puc;
381 25eb4484 bellard
    struct pt_regs *regs = uc->uc_mcontext.regs;
382 25eb4484 bellard
    unsigned long pc;
383 25eb4484 bellard
    sigset_t *pold_set;
384 25eb4484 bellard
    int is_write;
385 25eb4484 bellard
386 25eb4484 bellard
    pc = regs->nip;
387 25eb4484 bellard
    pold_set = &uc->uc_sigmask;
388 25eb4484 bellard
    is_write = 0;
389 25eb4484 bellard
#if 0
390 25eb4484 bellard
    /* ppc 4xx case */
391 25eb4484 bellard
    if (regs->dsisr & 0x00800000)
392 25eb4484 bellard
        is_write = 1;
393 25eb4484 bellard
#else
394 25eb4484 bellard
    if (regs->trap != 0x400 && (regs->dsisr & 0x02000000))
395 25eb4484 bellard
        is_write = 1;
396 25eb4484 bellard
#endif
397 25eb4484 bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
398 25eb4484 bellard
                             is_write, pold_set);
399 9de5e440 bellard
#else
400 25eb4484 bellard
#error CPU specific signal handler needed
401 9de5e440 bellard
    return 0;
402 9de5e440 bellard
#endif
403 9de5e440 bellard
}