Statistics
| Branch: | Revision:

root / exec-i386.c @ fc2b4c48

History | View | Annotate | Download (13 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 7d13299d bellard
22 dc99065b bellard
//#define DEBUG_EXEC
23 7d13299d bellard
#define DEBUG_FLUSH
24 9de5e440 bellard
//#define DEBUG_SIGNAL
25 7d13299d bellard
26 7d13299d bellard
/* main execution loop */
27 7d13299d bellard
28 7d13299d bellard
/* maximum total translate dcode allocated */
29 7d13299d bellard
#define CODE_GEN_BUFFER_SIZE     (2048 * 1024)
30 7d13299d bellard
//#define CODE_GEN_BUFFER_SIZE     (128 * 1024)
31 7d13299d bellard
#define CODE_GEN_MAX_SIZE        65536
32 7d13299d bellard
#define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */
33 7d13299d bellard
34 7d13299d bellard
/* threshold to flush the translated code buffer */
35 7d13299d bellard
#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
36 7d13299d bellard
37 7d13299d bellard
#define CODE_GEN_MAX_BLOCKS    (CODE_GEN_BUFFER_SIZE / 64)
38 7d13299d bellard
#define CODE_GEN_HASH_BITS     15
39 7d13299d bellard
#define CODE_GEN_HASH_SIZE     (1 << CODE_GEN_HASH_BITS)
40 6dbad63e bellard
41 7d13299d bellard
typedef struct TranslationBlock {
42 dab2ed99 bellard
    unsigned long pc;   /* simulated PC corresponding to this block (EIP + CS base) */
43 dab2ed99 bellard
    unsigned long cs_base; /* CS base for this block */
44 6dbad63e bellard
    unsigned int flags; /* flags defining in which context the code was generated */
45 7d13299d bellard
    uint8_t *tc_ptr;    /* pointer to the translated code */
46 7d13299d bellard
    struct TranslationBlock *hash_next; /* next matching block */
47 7d13299d bellard
} TranslationBlock;
48 7d13299d bellard
49 7d13299d bellard
TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
50 7d13299d bellard
TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
51 7d13299d bellard
int nb_tbs;
52 7d13299d bellard
53 7d13299d bellard
uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
54 7d13299d bellard
uint8_t *code_gen_ptr;
55 7d13299d bellard
56 1b6b029e bellard
/* thread support */
57 1b6b029e bellard
58 1b6b029e bellard
#ifdef __powerpc__
59 1b6b029e bellard
static inline int testandset (int *p)
60 1b6b029e bellard
{
61 1b6b029e bellard
    int ret;
62 1b6b029e bellard
    __asm__ __volatile__ (
63 1b6b029e bellard
                          "0:    lwarx %0,0,%1 ;"
64 1b6b029e bellard
                          "      xor. %0,%3,%0;"
65 1b6b029e bellard
                          "      bne 1f;"
66 1b6b029e bellard
                          "      stwcx. %2,0,%1;"
67 1b6b029e bellard
                          "      bne- 0b;"
68 1b6b029e bellard
                          "1:    "
69 1b6b029e bellard
                          : "=&r" (ret)
70 1b6b029e bellard
                          : "r" (p), "r" (1), "r" (0)
71 1b6b029e bellard
                          : "cr0", "memory");
72 1b6b029e bellard
    return ret;
73 1b6b029e bellard
}
74 1b6b029e bellard
#endif
75 1b6b029e bellard
76 1b6b029e bellard
#ifdef __i386__
77 1b6b029e bellard
static inline int testandset (int *p)
78 1b6b029e bellard
{
79 1b6b029e bellard
    char ret;
80 1b6b029e bellard
    long int readval;
81 1b6b029e bellard
    
82 1b6b029e bellard
    __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
83 1b6b029e bellard
                          : "=q" (ret), "=m" (*p), "=a" (readval)
84 1b6b029e bellard
                          : "r" (1), "m" (*p), "a" (0)
85 1b6b029e bellard
                          : "memory");
86 1b6b029e bellard
    return ret;
87 1b6b029e bellard
}
88 1b6b029e bellard
#endif
89 1b6b029e bellard
90 1b6b029e bellard
int global_cpu_lock = 0;
91 1b6b029e bellard
92 1b6b029e bellard
void cpu_lock(void)
93 1b6b029e bellard
{
94 1b6b029e bellard
    while (testandset(&global_cpu_lock));
95 1b6b029e bellard
}
96 1b6b029e bellard
97 1b6b029e bellard
void cpu_unlock(void)
98 1b6b029e bellard
{
99 1b6b029e bellard
    global_cpu_lock = 0;
100 1b6b029e bellard
}
101 1b6b029e bellard
102 9de5e440 bellard
/* exception support */
103 9de5e440 bellard
/* NOTE: not static to force relocation generation by GCC */
104 9de5e440 bellard
void raise_exception(int exception_index)
105 9de5e440 bellard
{
106 9de5e440 bellard
    /* NOTE: the register at this point must be saved by hand because
107 9de5e440 bellard
       longjmp restore them */
108 9de5e440 bellard
#ifdef reg_EAX
109 9de5e440 bellard
    env->regs[R_EAX] = EAX;
110 9de5e440 bellard
#endif
111 9de5e440 bellard
#ifdef reg_ECX
112 9de5e440 bellard
    env->regs[R_ECX] = ECX;
113 9de5e440 bellard
#endif
114 9de5e440 bellard
#ifdef reg_EDX
115 9de5e440 bellard
    env->regs[R_EDX] = EDX;
116 9de5e440 bellard
#endif
117 9de5e440 bellard
#ifdef reg_EBX
118 9de5e440 bellard
    env->regs[R_EBX] = EBX;
119 9de5e440 bellard
#endif
120 9de5e440 bellard
#ifdef reg_ESP
121 9de5e440 bellard
    env->regs[R_ESP] = ESP;
122 9de5e440 bellard
#endif
123 9de5e440 bellard
#ifdef reg_EBP
124 9de5e440 bellard
    env->regs[R_EBP] = EBP;
125 9de5e440 bellard
#endif
126 9de5e440 bellard
#ifdef reg_ESI
127 9de5e440 bellard
    env->regs[R_ESI] = ESI;
128 9de5e440 bellard
#endif
129 9de5e440 bellard
#ifdef reg_EDI
130 9de5e440 bellard
    env->regs[R_EDI] = EDI;
131 9de5e440 bellard
#endif
132 9de5e440 bellard
    env->exception_index = exception_index;
133 9de5e440 bellard
    longjmp(env->jmp_env, 1);
134 9de5e440 bellard
}
135 9de5e440 bellard
136 9de5e440 bellard
#if defined(DEBUG_EXEC)
137 7d13299d bellard
static const char *cc_op_str[] = {
138 7d13299d bellard
    "DYNAMIC",
139 7d13299d bellard
    "EFLAGS",
140 7d13299d bellard
    "MUL",
141 7d13299d bellard
    "ADDB",
142 7d13299d bellard
    "ADDW",
143 7d13299d bellard
    "ADDL",
144 7d13299d bellard
    "ADCB",
145 7d13299d bellard
    "ADCW",
146 7d13299d bellard
    "ADCL",
147 7d13299d bellard
    "SUBB",
148 7d13299d bellard
    "SUBW",
149 7d13299d bellard
    "SUBL",
150 7d13299d bellard
    "SBBB",
151 7d13299d bellard
    "SBBW",
152 7d13299d bellard
    "SBBL",
153 7d13299d bellard
    "LOGICB",
154 7d13299d bellard
    "LOGICW",
155 7d13299d bellard
    "LOGICL",
156 7d13299d bellard
    "INCB",
157 7d13299d bellard
    "INCW",
158 7d13299d bellard
    "INCL",
159 7d13299d bellard
    "DECB",
160 7d13299d bellard
    "DECW",
161 7d13299d bellard
    "DECL",
162 7d13299d bellard
    "SHLB",
163 7d13299d bellard
    "SHLW",
164 7d13299d bellard
    "SHLL",
165 7d13299d bellard
    "SARB",
166 7d13299d bellard
    "SARW",
167 7d13299d bellard
    "SARL",
168 7d13299d bellard
};
169 7d13299d bellard
170 9de5e440 bellard
static void cpu_x86_dump_state(FILE *f)
171 7d13299d bellard
{
172 7d13299d bellard
    int eflags;
173 7d13299d bellard
    eflags = cc_table[CC_OP].compute_all();
174 7d13299d bellard
    eflags |= (DF & DIRECTION_FLAG);
175 9de5e440 bellard
    fprintf(f, 
176 7d13299d bellard
            "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
177 7d13299d bellard
            "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
178 9de5e440 bellard
            "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n"
179 9de5e440 bellard
            "EIP=%08x\n",
180 7d13299d bellard
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
181 7d13299d bellard
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
182 7d13299d bellard
            env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
183 7d13299d bellard
            eflags & DIRECTION_FLAG ? 'D' : '-',
184 7d13299d bellard
            eflags & CC_O ? 'O' : '-',
185 7d13299d bellard
            eflags & CC_S ? 'S' : '-',
186 7d13299d bellard
            eflags & CC_Z ? 'Z' : '-',
187 7d13299d bellard
            eflags & CC_A ? 'A' : '-',
188 7d13299d bellard
            eflags & CC_P ? 'P' : '-',
189 9de5e440 bellard
            eflags & CC_C ? 'C' : '-',
190 9de5e440 bellard
            env->eip);
191 7d13299d bellard
#if 1
192 9de5e440 bellard
    fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
193 7d13299d bellard
            (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
194 7d13299d bellard
#endif
195 7d13299d bellard
}
196 7d13299d bellard
197 7d13299d bellard
#endif
198 7d13299d bellard
199 7d13299d bellard
void cpu_x86_tblocks_init(void)
200 7d13299d bellard
{
201 7d13299d bellard
    if (!code_gen_ptr) {
202 7d13299d bellard
        code_gen_ptr = code_gen_buffer;
203 7d13299d bellard
    }
204 7d13299d bellard
}
205 7d13299d bellard
206 7d13299d bellard
/* flush all the translation blocks */
207 7d13299d bellard
static void tb_flush(void)
208 7d13299d bellard
{
209 7d13299d bellard
    int i;
210 7d13299d bellard
#ifdef DEBUG_FLUSH
211 7d13299d bellard
    printf("gemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n", 
212 7d13299d bellard
           code_gen_ptr - code_gen_buffer, 
213 7d13299d bellard
           nb_tbs, 
214 7d13299d bellard
           (code_gen_ptr - code_gen_buffer) / nb_tbs);
215 7d13299d bellard
#endif
216 7d13299d bellard
    nb_tbs = 0;
217 7d13299d bellard
    for(i = 0;i < CODE_GEN_HASH_SIZE; i++)
218 7d13299d bellard
        tb_hash[i] = NULL;
219 7d13299d bellard
    code_gen_ptr = code_gen_buffer;
220 7d13299d bellard
    /* XXX: flush processor icache at this point */
221 7d13299d bellard
}
222 7d13299d bellard
223 7d13299d bellard
/* find a translation block in the translation cache. If not found,
224 9de5e440 bellard
   return NULL and the pointer to the last element of the list in pptb */
225 9de5e440 bellard
static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
226 9de5e440 bellard
                                        unsigned long pc, 
227 9de5e440 bellard
                                        unsigned long cs_base,
228 9de5e440 bellard
                                        unsigned int flags)
229 7d13299d bellard
{
230 7d13299d bellard
    TranslationBlock **ptb, *tb;
231 7d13299d bellard
    unsigned int h;
232 7d13299d bellard
 
233 7d13299d bellard
    h = pc & (CODE_GEN_HASH_SIZE - 1);
234 7d13299d bellard
    ptb = &tb_hash[h];
235 7d13299d bellard
    for(;;) {
236 7d13299d bellard
        tb = *ptb;
237 7d13299d bellard
        if (!tb)
238 7d13299d bellard
            break;
239 dab2ed99 bellard
        if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
240 7d13299d bellard
            return tb;
241 7d13299d bellard
        ptb = &tb->hash_next;
242 7d13299d bellard
    }
243 9de5e440 bellard
    *pptb = ptb;
244 9de5e440 bellard
    return NULL;
245 9de5e440 bellard
}
246 9de5e440 bellard
247 9de5e440 bellard
/* allocate a new translation block. flush the translation buffer if
248 9de5e440 bellard
   too many translation blocks or too much generated code */
249 9de5e440 bellard
static inline TranslationBlock *tb_alloc(void)
250 9de5e440 bellard
{
251 9de5e440 bellard
    TranslationBlock *tb;
252 7d13299d bellard
    if (nb_tbs >= CODE_GEN_MAX_BLOCKS || 
253 7d13299d bellard
        (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
254 7d13299d bellard
        tb_flush();
255 7d13299d bellard
    tb = &tbs[nb_tbs++];
256 7d13299d bellard
    return tb;
257 7d13299d bellard
}
258 7d13299d bellard
259 7d13299d bellard
int cpu_x86_exec(CPUX86State *env1)
260 7d13299d bellard
{
261 7d13299d bellard
    int saved_T0, saved_T1, saved_A0;
262 7d13299d bellard
    CPUX86State *saved_env;
263 04369ff2 bellard
#ifdef reg_EAX
264 04369ff2 bellard
    int saved_EAX;
265 04369ff2 bellard
#endif
266 04369ff2 bellard
#ifdef reg_ECX
267 04369ff2 bellard
    int saved_ECX;
268 04369ff2 bellard
#endif
269 04369ff2 bellard
#ifdef reg_EDX
270 04369ff2 bellard
    int saved_EDX;
271 04369ff2 bellard
#endif
272 04369ff2 bellard
#ifdef reg_EBX
273 04369ff2 bellard
    int saved_EBX;
274 04369ff2 bellard
#endif
275 04369ff2 bellard
#ifdef reg_ESP
276 04369ff2 bellard
    int saved_ESP;
277 04369ff2 bellard
#endif
278 04369ff2 bellard
#ifdef reg_EBP
279 04369ff2 bellard
    int saved_EBP;
280 04369ff2 bellard
#endif
281 04369ff2 bellard
#ifdef reg_ESI
282 04369ff2 bellard
    int saved_ESI;
283 04369ff2 bellard
#endif
284 04369ff2 bellard
#ifdef reg_EDI
285 04369ff2 bellard
    int saved_EDI;
286 04369ff2 bellard
#endif
287 7d13299d bellard
    int code_gen_size, ret;
288 7d13299d bellard
    void (*gen_func)(void);
289 9de5e440 bellard
    TranslationBlock *tb, **ptb;
290 dab2ed99 bellard
    uint8_t *tc_ptr, *cs_base, *pc;
291 6dbad63e bellard
    unsigned int flags;
292 6dbad63e bellard
293 7d13299d bellard
    /* first we save global registers */
294 7d13299d bellard
    saved_T0 = T0;
295 7d13299d bellard
    saved_T1 = T1;
296 7d13299d bellard
    saved_A0 = A0;
297 7d13299d bellard
    saved_env = env;
298 7d13299d bellard
    env = env1;
299 04369ff2 bellard
#ifdef reg_EAX
300 04369ff2 bellard
    saved_EAX = EAX;
301 04369ff2 bellard
    EAX = env->regs[R_EAX];
302 04369ff2 bellard
#endif
303 04369ff2 bellard
#ifdef reg_ECX
304 04369ff2 bellard
    saved_ECX = ECX;
305 04369ff2 bellard
    ECX = env->regs[R_ECX];
306 04369ff2 bellard
#endif
307 04369ff2 bellard
#ifdef reg_EDX
308 04369ff2 bellard
    saved_EDX = EDX;
309 04369ff2 bellard
    EDX = env->regs[R_EDX];
310 04369ff2 bellard
#endif
311 04369ff2 bellard
#ifdef reg_EBX
312 04369ff2 bellard
    saved_EBX = EBX;
313 04369ff2 bellard
    EBX = env->regs[R_EBX];
314 04369ff2 bellard
#endif
315 04369ff2 bellard
#ifdef reg_ESP
316 04369ff2 bellard
    saved_ESP = ESP;
317 04369ff2 bellard
    ESP = env->regs[R_ESP];
318 04369ff2 bellard
#endif
319 04369ff2 bellard
#ifdef reg_EBP
320 04369ff2 bellard
    saved_EBP = EBP;
321 04369ff2 bellard
    EBP = env->regs[R_EBP];
322 04369ff2 bellard
#endif
323 04369ff2 bellard
#ifdef reg_ESI
324 04369ff2 bellard
    saved_ESI = ESI;
325 04369ff2 bellard
    ESI = env->regs[R_ESI];
326 04369ff2 bellard
#endif
327 04369ff2 bellard
#ifdef reg_EDI
328 04369ff2 bellard
    saved_EDI = EDI;
329 04369ff2 bellard
    EDI = env->regs[R_EDI];
330 04369ff2 bellard
#endif
331 7d13299d bellard
    
332 9de5e440 bellard
    /* put eflags in CPU temporary format */
333 fc2b4c48 bellard
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
334 fc2b4c48 bellard
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
335 9de5e440 bellard
    CC_OP = CC_OP_EFLAGS;
336 fc2b4c48 bellard
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
337 9de5e440 bellard
    env->interrupt_request = 0;
338 9de5e440 bellard
    
339 7d13299d bellard
    /* prepare setjmp context for exception handling */
340 7d13299d bellard
    if (setjmp(env->jmp_env) == 0) {
341 7d13299d bellard
        for(;;) {
342 9de5e440 bellard
            if (env->interrupt_request) {
343 9de5e440 bellard
                raise_exception(EXCP_INTERRUPT);
344 9de5e440 bellard
            }
345 7d13299d bellard
#ifdef DEBUG_EXEC
346 7d13299d bellard
            if (loglevel) {
347 9de5e440 bellard
                cpu_x86_dump_state(logfile);
348 7d13299d bellard
            }
349 7d13299d bellard
#endif
350 6dbad63e bellard
            /* we compute the CPU state. We assume it will not
351 6dbad63e bellard
               change during the whole generated block. */
352 6dbad63e bellard
            flags = env->seg_cache[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT;
353 dab2ed99 bellard
            flags |= env->seg_cache[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT;
354 6dbad63e bellard
            flags |= (((unsigned long)env->seg_cache[R_DS].base | 
355 6dbad63e bellard
                       (unsigned long)env->seg_cache[R_ES].base |
356 6dbad63e bellard
                       (unsigned long)env->seg_cache[R_SS].base) != 0) << 
357 6dbad63e bellard
                GEN_FLAG_ADDSEG_SHIFT;
358 fc2b4c48 bellard
            flags |= (env->eflags & VM_MASK) >> (17 - GEN_FLAG_VM_SHIFT);
359 dab2ed99 bellard
            cs_base = env->seg_cache[R_CS].base;
360 dab2ed99 bellard
            pc = cs_base + env->eip;
361 9de5e440 bellard
            tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base, 
362 9de5e440 bellard
                         flags);
363 9de5e440 bellard
            if (!tb) {
364 7d13299d bellard
                /* if no translated code available, then translate it now */
365 1b6b029e bellard
                /* XXX: very inefficient: we lock all the cpus when
366 1b6b029e bellard
                   generating code */
367 1b6b029e bellard
                cpu_lock();
368 7d13299d bellard
                tc_ptr = code_gen_ptr;
369 9de5e440 bellard
                ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE, 
370 9de5e440 bellard
                                       &code_gen_size, pc, cs_base, flags);
371 9de5e440 bellard
                /* if invalid instruction, signal it */
372 9de5e440 bellard
                if (ret != 0) {
373 9de5e440 bellard
                    cpu_unlock();
374 9de5e440 bellard
                    raise_exception(EXCP06_ILLOP);
375 9de5e440 bellard
                }
376 9de5e440 bellard
                tb = tb_alloc();
377 9de5e440 bellard
                *ptb = tb;
378 9de5e440 bellard
                tb->pc = (unsigned long)pc;
379 9de5e440 bellard
                tb->cs_base = (unsigned long)cs_base;
380 9de5e440 bellard
                tb->flags = flags;
381 7d13299d bellard
                tb->tc_ptr = tc_ptr;
382 9de5e440 bellard
                tb->hash_next = NULL;
383 7d13299d bellard
                code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
384 1b6b029e bellard
                cpu_unlock();
385 7d13299d bellard
            }
386 7d13299d bellard
            /* execute the generated code */
387 9de5e440 bellard
            tc_ptr = tb->tc_ptr;
388 7d13299d bellard
            gen_func = (void *)tc_ptr;
389 7d13299d bellard
            gen_func();
390 7d13299d bellard
        }
391 7d13299d bellard
    }
392 7d13299d bellard
    ret = env->exception_index;
393 7d13299d bellard
394 9de5e440 bellard
    /* restore flags in standard format */
395 fc2b4c48 bellard
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
396 9de5e440 bellard
397 7d13299d bellard
    /* restore global registers */
398 04369ff2 bellard
#ifdef reg_EAX
399 04369ff2 bellard
    EAX = saved_EAX;
400 04369ff2 bellard
#endif
401 04369ff2 bellard
#ifdef reg_ECX
402 04369ff2 bellard
    ECX = saved_ECX;
403 04369ff2 bellard
#endif
404 04369ff2 bellard
#ifdef reg_EDX
405 04369ff2 bellard
    EDX = saved_EDX;
406 04369ff2 bellard
#endif
407 04369ff2 bellard
#ifdef reg_EBX
408 04369ff2 bellard
    EBX = saved_EBX;
409 04369ff2 bellard
#endif
410 04369ff2 bellard
#ifdef reg_ESP
411 04369ff2 bellard
    ESP = saved_ESP;
412 04369ff2 bellard
#endif
413 04369ff2 bellard
#ifdef reg_EBP
414 04369ff2 bellard
    EBP = saved_EBP;
415 04369ff2 bellard
#endif
416 04369ff2 bellard
#ifdef reg_ESI
417 04369ff2 bellard
    ESI = saved_ESI;
418 04369ff2 bellard
#endif
419 04369ff2 bellard
#ifdef reg_EDI
420 04369ff2 bellard
    EDI = saved_EDI;
421 04369ff2 bellard
#endif
422 7d13299d bellard
    T0 = saved_T0;
423 7d13299d bellard
    T1 = saved_T1;
424 7d13299d bellard
    A0 = saved_A0;
425 7d13299d bellard
    env = saved_env;
426 7d13299d bellard
    return ret;
427 7d13299d bellard
}
428 6dbad63e bellard
429 9de5e440 bellard
void cpu_x86_interrupt(CPUX86State *s)
430 9de5e440 bellard
{
431 9de5e440 bellard
    s->interrupt_request = 1;
432 9de5e440 bellard
}
433 9de5e440 bellard
434 9de5e440 bellard
435 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
436 6dbad63e bellard
{
437 6dbad63e bellard
    CPUX86State *saved_env;
438 6dbad63e bellard
439 6dbad63e bellard
    saved_env = env;
440 6dbad63e bellard
    env = s;
441 6dbad63e bellard
    load_seg(seg_reg, selector);
442 6dbad63e bellard
    env = saved_env;
443 6dbad63e bellard
}
444 9de5e440 bellard
445 9de5e440 bellard
#undef EAX
446 9de5e440 bellard
#undef ECX
447 9de5e440 bellard
#undef EDX
448 9de5e440 bellard
#undef EBX
449 9de5e440 bellard
#undef ESP
450 9de5e440 bellard
#undef EBP
451 9de5e440 bellard
#undef ESI
452 9de5e440 bellard
#undef EDI
453 9de5e440 bellard
#undef EIP
454 9de5e440 bellard
#include <signal.h>
455 9de5e440 bellard
#include <sys/ucontext.h>
456 9de5e440 bellard
457 9de5e440 bellard
static inline int handle_cpu_signal(unsigned long pc,
458 9de5e440 bellard
                                    sigset_t *old_set)
459 9de5e440 bellard
{
460 9de5e440 bellard
#ifdef DEBUG_SIGNAL
461 9de5e440 bellard
    printf("gemu: SIGSEGV pc=0x%08lx oldset=0x%08lx\n", 
462 9de5e440 bellard
           pc, *(unsigned long *)old_set);
463 9de5e440 bellard
#endif
464 9de5e440 bellard
    if (pc >= (unsigned long)code_gen_buffer &&
465 9de5e440 bellard
        pc < (unsigned long)code_gen_buffer + CODE_GEN_BUFFER_SIZE) {
466 9de5e440 bellard
        /* the PC is inside the translated code. It means that we have
467 9de5e440 bellard
           a virtual CPU fault */
468 9de5e440 bellard
        /* we restore the process signal mask as the sigreturn should
469 9de5e440 bellard
           do it */
470 9de5e440 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
471 9de5e440 bellard
        /* XXX: need to compute virtual pc position by retranslating
472 9de5e440 bellard
           code. The rest of the CPU state should be correct. */
473 9de5e440 bellard
        raise_exception(EXCP0D_GPF);
474 9de5e440 bellard
        /* never comes here */
475 9de5e440 bellard
        return 1;
476 9de5e440 bellard
    } else {
477 9de5e440 bellard
        return 0;
478 9de5e440 bellard
    }
479 9de5e440 bellard
}
480 9de5e440 bellard
481 9de5e440 bellard
int cpu_x86_signal_handler(int host_signum, struct siginfo *info, 
482 9de5e440 bellard
                           void *puc)
483 9de5e440 bellard
{
484 9de5e440 bellard
#if defined(__i386__)
485 9de5e440 bellard
    struct ucontext *uc = puc;
486 9de5e440 bellard
    unsigned long pc;
487 9de5e440 bellard
    sigset_t *pold_set;
488 9de5e440 bellard
    
489 d691f669 bellard
#ifndef REG_EIP
490 d691f669 bellard
/* for glibc 2.1 */
491 d691f669 bellard
#define REG_EIP EIP
492 d691f669 bellard
#endif
493 fc2b4c48 bellard
    pc = uc->uc_mcontext.gregs[REG_EIP];
494 9de5e440 bellard
    pold_set = &uc->uc_sigmask;
495 9de5e440 bellard
    return handle_cpu_signal(pc, pold_set);
496 9de5e440 bellard
#else
497 9de5e440 bellard
#warning No CPU specific signal handler: cannot handle target SIGSEGV events
498 9de5e440 bellard
    return 0;
499 9de5e440 bellard
#endif
500 9de5e440 bellard
}