blob: ec738faad0c263e42869097c11858f9cb43e8819 [file] [log] [blame]
bellard7d132992003-03-06 23:23:54 +00001/*
2 * i386 emulator main execution loop
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
bellard3ef693a2003-03-23 20:17:16 +00006 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
bellard7d132992003-03-06 23:23:54 +000010 *
bellard3ef693a2003-03-23 20:17:16 +000011 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
bellard7d132992003-03-06 23:23:54 +000015 *
bellard3ef693a2003-03-23 20:17:16 +000016 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
bellard7d132992003-03-06 23:23:54 +000019 */
20#include "exec-i386.h"
bellard956034d2003-04-29 20:40:53 +000021#include "disas.h"
bellard7d132992003-03-06 23:23:54 +000022
bellarddc990652003-03-19 00:00:28 +000023//#define DEBUG_EXEC
bellard7d132992003-03-06 23:23:54 +000024#define DEBUG_FLUSH
bellard9de5e442003-03-23 16:49:39 +000025//#define DEBUG_SIGNAL
bellard7d132992003-03-06 23:23:54 +000026
27/* main execution loop */
28
29/* maximum total translate dcode allocated */
30#define CODE_GEN_BUFFER_SIZE (2048 * 1024)
31//#define CODE_GEN_BUFFER_SIZE (128 * 1024)
32#define CODE_GEN_MAX_SIZE 65536
33#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
34
35/* threshold to flush the translated code buffer */
36#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
37
38#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / 64)
39#define CODE_GEN_HASH_BITS 15
40#define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS)
bellard6dbad632003-03-16 18:05:05 +000041
bellard7d132992003-03-06 23:23:54 +000042typedef struct TranslationBlock {
bellarddab2ed92003-03-22 15:23:14 +000043 unsigned long pc; /* simulated PC corresponding to this block (EIP + CS base) */
44 unsigned long cs_base; /* CS base for this block */
bellard6dbad632003-03-16 18:05:05 +000045 unsigned int flags; /* flags defining in which context the code was generated */
bellard7d132992003-03-06 23:23:54 +000046 uint8_t *tc_ptr; /* pointer to the translated code */
47 struct TranslationBlock *hash_next; /* next matching block */
48} TranslationBlock;
49
50TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
51TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
52int nb_tbs;
53
54uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
55uint8_t *code_gen_ptr;
56
bellard1b6b0292003-03-22 17:31:38 +000057/* thread support */
58
59#ifdef __powerpc__
60static inline int testandset (int *p)
61{
62 int ret;
63 __asm__ __volatile__ (
64 "0: lwarx %0,0,%1 ;"
65 " xor. %0,%3,%0;"
66 " bne 1f;"
67 " stwcx. %2,0,%1;"
68 " bne- 0b;"
69 "1: "
70 : "=&r" (ret)
71 : "r" (p), "r" (1), "r" (0)
72 : "cr0", "memory");
73 return ret;
74}
75#endif
76
77#ifdef __i386__
78static inline int testandset (int *p)
79{
80 char ret;
81 long int readval;
82
83 __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
84 : "=q" (ret), "=m" (*p), "=a" (readval)
85 : "r" (1), "m" (*p), "a" (0)
86 : "memory");
87 return ret;
88}
89#endif
90
bellardfb3e5842003-03-29 17:32:36 +000091#ifdef __s390__
92static inline int testandset (int *p)
93{
94 int ret;
95
96 __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
97 " jl 0b"
98 : "=&d" (ret)
99 : "r" (1), "a" (p), "0" (*p)
100 : "cc", "memory" );
101 return ret;
102}
103#endif
104
bellarde026db52003-04-29 21:07:28 +0000105#ifdef __alpha__
106int testandset (int *p)
107{
108 int ret;
109 unsigned long one;
110
111 __asm__ __volatile__ ("0: mov 1,%2\n"
112 " ldl_l %0,%1\n"
113 " stl_c %2,%1\n"
114 " beq %2,1f\n"
115 ".subsection 2\n"
116 "1: br 0b\n"
117 ".previous"
118 : "=r" (ret), "=m" (*p), "=r" (one)
119 : "m" (*p));
120 return ret;
121}
122#endif
123
bellardd014c982003-04-29 21:26:53 +0000124#ifdef __sparc__
125static inline int testandset (int *p)
126{
127 int ret;
128
129 __asm__ __volatile__("ldstub [%1], %0"
130 : "=r" (ret)
131 : "r" (p)
132 : "memory");
133
134 return (ret ? 1 : 0);
135}
136#endif
137
bellard1b6b0292003-03-22 17:31:38 +0000138int global_cpu_lock = 0;
139
140void cpu_lock(void)
141{
142 while (testandset(&global_cpu_lock));
143}
144
145void cpu_unlock(void)
146{
147 global_cpu_lock = 0;
148}
149
bellard9de5e442003-03-23 16:49:39 +0000150/* exception support */
151/* NOTE: not static to force relocation generation by GCC */
bellardb56dad12003-05-08 15:38:04 +0000152void raise_exception_err(int exception_index, int error_code)
bellard9de5e442003-03-23 16:49:39 +0000153{
154 /* NOTE: the register at this point must be saved by hand because
155 longjmp restore them */
156#ifdef reg_EAX
157 env->regs[R_EAX] = EAX;
158#endif
159#ifdef reg_ECX
160 env->regs[R_ECX] = ECX;
161#endif
162#ifdef reg_EDX
163 env->regs[R_EDX] = EDX;
164#endif
165#ifdef reg_EBX
166 env->regs[R_EBX] = EBX;
167#endif
168#ifdef reg_ESP
169 env->regs[R_ESP] = ESP;
170#endif
171#ifdef reg_EBP
172 env->regs[R_EBP] = EBP;
173#endif
174#ifdef reg_ESI
175 env->regs[R_ESI] = ESI;
176#endif
177#ifdef reg_EDI
178 env->regs[R_EDI] = EDI;
179#endif
180 env->exception_index = exception_index;
bellardb56dad12003-05-08 15:38:04 +0000181 env->error_code = error_code;
bellard9de5e442003-03-23 16:49:39 +0000182 longjmp(env->jmp_env, 1);
183}
184
bellardb56dad12003-05-08 15:38:04 +0000185/* short cut if error_code is 0 or not present */
186void raise_exception(int exception_index)
187{
188 raise_exception_err(exception_index, 0);
189}
190
bellard9de5e442003-03-23 16:49:39 +0000191#if defined(DEBUG_EXEC)
bellard7d132992003-03-06 23:23:54 +0000192static const char *cc_op_str[] = {
193 "DYNAMIC",
194 "EFLAGS",
195 "MUL",
196 "ADDB",
197 "ADDW",
198 "ADDL",
199 "ADCB",
200 "ADCW",
201 "ADCL",
202 "SUBB",
203 "SUBW",
204 "SUBL",
205 "SBBB",
206 "SBBW",
207 "SBBL",
208 "LOGICB",
209 "LOGICW",
210 "LOGICL",
211 "INCB",
212 "INCW",
213 "INCL",
214 "DECB",
215 "DECW",
216 "DECL",
217 "SHLB",
218 "SHLW",
219 "SHLL",
220 "SARB",
221 "SARW",
222 "SARL",
223};
224
bellard9de5e442003-03-23 16:49:39 +0000225static void cpu_x86_dump_state(FILE *f)
bellard7d132992003-03-06 23:23:54 +0000226{
227 int eflags;
bellardb56dad12003-05-08 15:38:04 +0000228 char cc_op_name[32];
bellard7d132992003-03-06 23:23:54 +0000229 eflags = cc_table[CC_OP].compute_all();
bellard956034d2003-04-29 20:40:53 +0000230 eflags |= (DF & DF_MASK);
bellardb56dad12003-05-08 15:38:04 +0000231 if ((unsigned)env->cc_op < CC_OP_NB)
232 strcpy(cc_op_name, cc_op_str[env->cc_op]);
233 else
234 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
bellard9de5e442003-03-23 16:49:39 +0000235 fprintf(f,
bellard7d132992003-03-06 23:23:54 +0000236 "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
237 "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
bellard9de5e442003-03-23 16:49:39 +0000238 "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n"
239 "EIP=%08x\n",
bellard7d132992003-03-06 23:23:54 +0000240 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
241 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
bellardb56dad12003-05-08 15:38:04 +0000242 env->cc_src, env->cc_dst, cc_op_name,
bellard956034d2003-04-29 20:40:53 +0000243 eflags & DF_MASK ? 'D' : '-',
bellard7d132992003-03-06 23:23:54 +0000244 eflags & CC_O ? 'O' : '-',
245 eflags & CC_S ? 'S' : '-',
246 eflags & CC_Z ? 'Z' : '-',
247 eflags & CC_A ? 'A' : '-',
248 eflags & CC_P ? 'P' : '-',
bellard9de5e442003-03-23 16:49:39 +0000249 eflags & CC_C ? 'C' : '-',
250 env->eip);
bellard7d132992003-03-06 23:23:54 +0000251#if 1
bellard9de5e442003-03-23 16:49:39 +0000252 fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
bellard7d132992003-03-06 23:23:54 +0000253 (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
254#endif
255}
256
257#endif
258
259void cpu_x86_tblocks_init(void)
260{
261 if (!code_gen_ptr) {
262 code_gen_ptr = code_gen_buffer;
263 }
264}
265
266/* flush all the translation blocks */
267static void tb_flush(void)
268{
269 int i;
270#ifdef DEBUG_FLUSH
271 printf("gemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n",
272 code_gen_ptr - code_gen_buffer,
273 nb_tbs,
274 (code_gen_ptr - code_gen_buffer) / nb_tbs);
275#endif
276 nb_tbs = 0;
277 for(i = 0;i < CODE_GEN_HASH_SIZE; i++)
278 tb_hash[i] = NULL;
279 code_gen_ptr = code_gen_buffer;
280 /* XXX: flush processor icache at this point */
281}
282
283/* find a translation block in the translation cache. If not found,
bellard9de5e442003-03-23 16:49:39 +0000284 return NULL and the pointer to the last element of the list in pptb */
285static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
286 unsigned long pc,
287 unsigned long cs_base,
288 unsigned int flags)
bellard7d132992003-03-06 23:23:54 +0000289{
290 TranslationBlock **ptb, *tb;
291 unsigned int h;
292
293 h = pc & (CODE_GEN_HASH_SIZE - 1);
294 ptb = &tb_hash[h];
bellardb56dad12003-05-08 15:38:04 +0000295#if 0
296 /* XXX: hack to handle 16 bit modyfing code */
297 if (flags & (1 << GEN_FLAG_CODE32_SHIFT))
298#endif
299 for(;;) {
300 tb = *ptb;
301 if (!tb)
302 break;
303 if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
bellard7d132992003-03-06 23:23:54 +0000304 return tb;
bellardb56dad12003-05-08 15:38:04 +0000305 ptb = &tb->hash_next;
306 }
bellard9de5e442003-03-23 16:49:39 +0000307 *pptb = ptb;
308 return NULL;
309}
310
311/* allocate a new translation block. flush the translation buffer if
312 too many translation blocks or too much generated code */
313static inline TranslationBlock *tb_alloc(void)
314{
315 TranslationBlock *tb;
bellard7d132992003-03-06 23:23:54 +0000316 if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||
317 (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
318 tb_flush();
319 tb = &tbs[nb_tbs++];
bellard7d132992003-03-06 23:23:54 +0000320 return tb;
321}
322
323int cpu_x86_exec(CPUX86State *env1)
324{
325 int saved_T0, saved_T1, saved_A0;
326 CPUX86State *saved_env;
bellard04369ff2003-03-20 22:33:23 +0000327#ifdef reg_EAX
328 int saved_EAX;
329#endif
330#ifdef reg_ECX
331 int saved_ECX;
332#endif
333#ifdef reg_EDX
334 int saved_EDX;
335#endif
336#ifdef reg_EBX
337 int saved_EBX;
338#endif
339#ifdef reg_ESP
340 int saved_ESP;
341#endif
342#ifdef reg_EBP
343 int saved_EBP;
344#endif
345#ifdef reg_ESI
346 int saved_ESI;
347#endif
348#ifdef reg_EDI
349 int saved_EDI;
350#endif
bellard7d132992003-03-06 23:23:54 +0000351 int code_gen_size, ret;
352 void (*gen_func)(void);
bellard9de5e442003-03-23 16:49:39 +0000353 TranslationBlock *tb, **ptb;
bellarddab2ed92003-03-22 15:23:14 +0000354 uint8_t *tc_ptr, *cs_base, *pc;
bellard6dbad632003-03-16 18:05:05 +0000355 unsigned int flags;
356
bellard7d132992003-03-06 23:23:54 +0000357 /* first we save global registers */
358 saved_T0 = T0;
359 saved_T1 = T1;
360 saved_A0 = A0;
361 saved_env = env;
362 env = env1;
bellard04369ff2003-03-20 22:33:23 +0000363#ifdef reg_EAX
364 saved_EAX = EAX;
365 EAX = env->regs[R_EAX];
366#endif
367#ifdef reg_ECX
368 saved_ECX = ECX;
369 ECX = env->regs[R_ECX];
370#endif
371#ifdef reg_EDX
372 saved_EDX = EDX;
373 EDX = env->regs[R_EDX];
374#endif
375#ifdef reg_EBX
376 saved_EBX = EBX;
377 EBX = env->regs[R_EBX];
378#endif
379#ifdef reg_ESP
380 saved_ESP = ESP;
381 ESP = env->regs[R_ESP];
382#endif
383#ifdef reg_EBP
384 saved_EBP = EBP;
385 EBP = env->regs[R_EBP];
386#endif
387#ifdef reg_ESI
388 saved_ESI = ESI;
389 ESI = env->regs[R_ESI];
390#endif
391#ifdef reg_EDI
392 saved_EDI = EDI;
393 EDI = env->regs[R_EDI];
394#endif
bellard7d132992003-03-06 23:23:54 +0000395
bellard9de5e442003-03-23 16:49:39 +0000396 /* put eflags in CPU temporary format */
bellardfc2b4c42003-03-29 16:52:44 +0000397 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
398 DF = 1 - (2 * ((env->eflags >> 10) & 1));
bellard9de5e442003-03-23 16:49:39 +0000399 CC_OP = CC_OP_EFLAGS;
bellardfc2b4c42003-03-29 16:52:44 +0000400 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
bellard9de5e442003-03-23 16:49:39 +0000401 env->interrupt_request = 0;
402
bellard7d132992003-03-06 23:23:54 +0000403 /* prepare setjmp context for exception handling */
404 if (setjmp(env->jmp_env) == 0) {
405 for(;;) {
bellard9de5e442003-03-23 16:49:39 +0000406 if (env->interrupt_request) {
407 raise_exception(EXCP_INTERRUPT);
408 }
bellard7d132992003-03-06 23:23:54 +0000409#ifdef DEBUG_EXEC
410 if (loglevel) {
bellard9de5e442003-03-23 16:49:39 +0000411 cpu_x86_dump_state(logfile);
bellard7d132992003-03-06 23:23:54 +0000412 }
413#endif
bellard6dbad632003-03-16 18:05:05 +0000414 /* we compute the CPU state. We assume it will not
415 change during the whole generated block. */
416 flags = env->seg_cache[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT;
bellarddab2ed92003-03-22 15:23:14 +0000417 flags |= env->seg_cache[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT;
bellard6dbad632003-03-16 18:05:05 +0000418 flags |= (((unsigned long)env->seg_cache[R_DS].base |
419 (unsigned long)env->seg_cache[R_ES].base |
420 (unsigned long)env->seg_cache[R_SS].base) != 0) <<
421 GEN_FLAG_ADDSEG_SHIFT;
bellardfc2b4c42003-03-29 16:52:44 +0000422 flags |= (env->eflags & VM_MASK) >> (17 - GEN_FLAG_VM_SHIFT);
bellardb56dad12003-05-08 15:38:04 +0000423 flags |= (env->eflags & IOPL_MASK) >> (12 - GEN_FLAG_IOPL_SHIFT);
424 flags |= (env->segs[R_CS] & 3) << GEN_FLAG_CPL_SHIFT;
bellarddab2ed92003-03-22 15:23:14 +0000425 cs_base = env->seg_cache[R_CS].base;
426 pc = cs_base + env->eip;
bellard9de5e442003-03-23 16:49:39 +0000427 tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base,
428 flags);
429 if (!tb) {
bellard7d132992003-03-06 23:23:54 +0000430 /* if no translated code available, then translate it now */
bellard1b6b0292003-03-22 17:31:38 +0000431 /* XXX: very inefficient: we lock all the cpus when
432 generating code */
433 cpu_lock();
bellard7d132992003-03-06 23:23:54 +0000434 tc_ptr = code_gen_ptr;
bellard9de5e442003-03-23 16:49:39 +0000435 ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,
436 &code_gen_size, pc, cs_base, flags);
437 /* if invalid instruction, signal it */
438 if (ret != 0) {
439 cpu_unlock();
440 raise_exception(EXCP06_ILLOP);
441 }
442 tb = tb_alloc();
443 *ptb = tb;
444 tb->pc = (unsigned long)pc;
445 tb->cs_base = (unsigned long)cs_base;
446 tb->flags = flags;
bellard7d132992003-03-06 23:23:54 +0000447 tb->tc_ptr = tc_ptr;
bellard9de5e442003-03-23 16:49:39 +0000448 tb->hash_next = NULL;
bellard7d132992003-03-06 23:23:54 +0000449 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
bellard1b6b0292003-03-22 17:31:38 +0000450 cpu_unlock();
bellard7d132992003-03-06 23:23:54 +0000451 }
bellard956034d2003-04-29 20:40:53 +0000452 if (loglevel) {
453 fprintf(logfile, "Trace 0x%08lx [0x%08lx] %s\n",
454 (long)tb->tc_ptr, (long)tb->pc,
455 lookup_symbol((void *)tb->pc));
456 fflush(logfile);
457 }
bellard7d132992003-03-06 23:23:54 +0000458 /* execute the generated code */
bellard9de5e442003-03-23 16:49:39 +0000459 tc_ptr = tb->tc_ptr;
bellard7d132992003-03-06 23:23:54 +0000460 gen_func = (void *)tc_ptr;
461 gen_func();
462 }
463 }
464 ret = env->exception_index;
465
bellard9de5e442003-03-23 16:49:39 +0000466 /* restore flags in standard format */
bellardfc2b4c42003-03-29 16:52:44 +0000467 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
bellard9de5e442003-03-23 16:49:39 +0000468
bellard7d132992003-03-06 23:23:54 +0000469 /* restore global registers */
bellard04369ff2003-03-20 22:33:23 +0000470#ifdef reg_EAX
471 EAX = saved_EAX;
472#endif
473#ifdef reg_ECX
474 ECX = saved_ECX;
475#endif
476#ifdef reg_EDX
477 EDX = saved_EDX;
478#endif
479#ifdef reg_EBX
480 EBX = saved_EBX;
481#endif
482#ifdef reg_ESP
483 ESP = saved_ESP;
484#endif
485#ifdef reg_EBP
486 EBP = saved_EBP;
487#endif
488#ifdef reg_ESI
489 ESI = saved_ESI;
490#endif
491#ifdef reg_EDI
492 EDI = saved_EDI;
493#endif
bellard7d132992003-03-06 23:23:54 +0000494 T0 = saved_T0;
495 T1 = saved_T1;
496 A0 = saved_A0;
497 env = saved_env;
498 return ret;
499}
bellard6dbad632003-03-16 18:05:05 +0000500
bellard9de5e442003-03-23 16:49:39 +0000501void cpu_x86_interrupt(CPUX86State *s)
502{
503 s->interrupt_request = 1;
504}
505
506
bellard6dbad632003-03-16 18:05:05 +0000507void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
508{
509 CPUX86State *saved_env;
510
511 saved_env = env;
512 env = s;
513 load_seg(seg_reg, selector);
514 env = saved_env;
515}
bellard9de5e442003-03-23 16:49:39 +0000516
517#undef EAX
518#undef ECX
519#undef EDX
520#undef EBX
521#undef ESP
522#undef EBP
523#undef ESI
524#undef EDI
525#undef EIP
526#include <signal.h>
527#include <sys/ucontext.h>
528
bellardb56dad12003-05-08 15:38:04 +0000529/* 'pc' is the host PC at which the exception was raised. 'address' is
530 the effective address of the memory exception */
bellard9de5e442003-03-23 16:49:39 +0000531static inline int handle_cpu_signal(unsigned long pc,
bellardb56dad12003-05-08 15:38:04 +0000532 unsigned long address,
bellard9de5e442003-03-23 16:49:39 +0000533 sigset_t *old_set)
534{
535#ifdef DEBUG_SIGNAL
536 printf("gemu: SIGSEGV pc=0x%08lx oldset=0x%08lx\n",
537 pc, *(unsigned long *)old_set);
538#endif
539 if (pc >= (unsigned long)code_gen_buffer &&
540 pc < (unsigned long)code_gen_buffer + CODE_GEN_BUFFER_SIZE) {
541 /* the PC is inside the translated code. It means that we have
542 a virtual CPU fault */
543 /* we restore the process signal mask as the sigreturn should
544 do it */
545 sigprocmask(SIG_SETMASK, old_set, NULL);
546 /* XXX: need to compute virtual pc position by retranslating
547 code. The rest of the CPU state should be correct. */
bellardb56dad12003-05-08 15:38:04 +0000548 env->cr2 = address;
549 /* XXX: more precise exception code */
550 raise_exception_err(EXCP0E_PAGE, 4);
bellard9de5e442003-03-23 16:49:39 +0000551 /* never comes here */
552 return 1;
553 } else {
554 return 0;
555 }
556}
557
558int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
559 void *puc)
560{
561#if defined(__i386__)
562 struct ucontext *uc = puc;
563 unsigned long pc;
564 sigset_t *pold_set;
565
bellardd691f662003-03-24 21:58:34 +0000566#ifndef REG_EIP
567/* for glibc 2.1 */
568#define REG_EIP EIP
569#endif
bellardfc2b4c42003-03-29 16:52:44 +0000570 pc = uc->uc_mcontext.gregs[REG_EIP];
bellard9de5e442003-03-23 16:49:39 +0000571 pold_set = &uc->uc_sigmask;
bellardb56dad12003-05-08 15:38:04 +0000572 return handle_cpu_signal(pc, (unsigned long)info->si_addr, pold_set);
bellard9de5e442003-03-23 16:49:39 +0000573#else
574#warning No CPU specific signal handler: cannot handle target SIGSEGV events
575 return 0;
576#endif
577}