Statistics
| Branch: | Revision:

root / exec-i386.c @ ae48a073

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