Statistics
| Branch: | Revision:

root / exec-i386.c @ a69d83b6

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