Statistics
| Branch: | Revision:

root / exec-i386.c @ e026db58

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