Statistics
| Branch: | Revision:

root / exec-i386.c @ 504e56eb

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