Revision 9de5e440 exec-i386.c

b/exec-i386.c
21 21

  
22 22
//#define DEBUG_EXEC
23 23
#define DEBUG_FLUSH
24
//#define DEBUG_SIGNAL
24 25

  
25 26
/* main execution loop */
26 27

  
......
98 99
    global_cpu_lock = 0;
99 100
}
100 101

  
101
#ifdef DEBUG_EXEC
102
/* exception support */
103
/* NOTE: not static to force relocation generation by GCC */
104
void raise_exception(int exception_index)
105
{
106
    /* NOTE: the register at this point must be saved by hand because
107
       longjmp restore them */
108
#ifdef reg_EAX
109
    env->regs[R_EAX] = EAX;
110
#endif
111
#ifdef reg_ECX
112
    env->regs[R_ECX] = ECX;
113
#endif
114
#ifdef reg_EDX
115
    env->regs[R_EDX] = EDX;
116
#endif
117
#ifdef reg_EBX
118
    env->regs[R_EBX] = EBX;
119
#endif
120
#ifdef reg_ESP
121
    env->regs[R_ESP] = ESP;
122
#endif
123
#ifdef reg_EBP
124
    env->regs[R_EBP] = EBP;
125
#endif
126
#ifdef reg_ESI
127
    env->regs[R_ESI] = ESI;
128
#endif
129
#ifdef reg_EDI
130
    env->regs[R_EDI] = EDI;
131
#endif
132
    env->exception_index = exception_index;
133
    longjmp(env->jmp_env, 1);
134
}
135

  
136
#if defined(DEBUG_EXEC)
102 137
static const char *cc_op_str[] = {
103 138
    "DYNAMIC",
104 139
    "EFLAGS",
......
132 167
    "SARL",
133 168
};
134 169

  
135
static void cpu_x86_dump_state(void)
170
static void cpu_x86_dump_state(FILE *f)
136 171
{
137 172
    int eflags;
138 173
    eflags = cc_table[CC_OP].compute_all();
139 174
    eflags |= (DF & DIRECTION_FLAG);
140
    fprintf(logfile, 
175
    fprintf(f, 
141 176
            "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
142 177
            "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
143
            "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",
178
            "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n"
179
            "EIP=%08x\n",
144 180
            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
145 181
            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
146 182
            env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
......
150 186
            eflags & CC_Z ? 'Z' : '-',
151 187
            eflags & CC_A ? 'A' : '-',
152 188
            eflags & CC_P ? 'P' : '-',
153
            eflags & CC_C ? 'C' : '-'
154
            );
189
            eflags & CC_C ? 'C' : '-',
190
            env->eip);
155 191
#if 1
156
    fprintf(logfile, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
192
    fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
157 193
            (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
158 194
#endif
159 195
}
......
185 221
}
186 222

  
187 223
/* find a translation block in the translation cache. If not found,
188
   allocate a new one */
189
static inline TranslationBlock *tb_find_and_alloc(unsigned long pc, 
190
                                                  unsigned long cs_base,
191
                                                  unsigned int flags)
224
   return NULL and the pointer to the last element of the list in pptb */
225
static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
226
                                        unsigned long pc, 
227
                                        unsigned long cs_base,
228
                                        unsigned int flags)
192 229
{
193 230
    TranslationBlock **ptb, *tb;
194 231
    unsigned int h;
......
203 240
            return tb;
204 241
        ptb = &tb->hash_next;
205 242
    }
243
    *pptb = ptb;
244
    return NULL;
245
}
246

  
247
/* allocate a new translation block. flush the translation buffer if
248
   too many translation blocks or too much generated code */
249
static inline TranslationBlock *tb_alloc(void)
250
{
251
    TranslationBlock *tb;
206 252
    if (nb_tbs >= CODE_GEN_MAX_BLOCKS || 
207 253
        (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
208 254
        tb_flush();
209 255
    tb = &tbs[nb_tbs++];
210
    *ptb = tb;
211
    tb->pc = pc;
212
    tb->cs_base = cs_base;
213
    tb->flags = flags;
214
    tb->tc_ptr = NULL;
215
    tb->hash_next = NULL;
216 256
    return tb;
217 257
}
218 258

  
......
246 286
#endif
247 287
    int code_gen_size, ret;
248 288
    void (*gen_func)(void);
249
    TranslationBlock *tb;
289
    TranslationBlock *tb, **ptb;
250 290
    uint8_t *tc_ptr, *cs_base, *pc;
251 291
    unsigned int flags;
252 292

  
......
289 329
    EDI = env->regs[R_EDI];
290 330
#endif
291 331
    
332
    /* put eflags in CPU temporary format */
333
    T0 = env->eflags;
334
    op_movl_eflags_T0();
335
    CC_OP = CC_OP_EFLAGS;
336
    env->interrupt_request = 0;
337
    
292 338
    /* prepare setjmp context for exception handling */
293 339
    if (setjmp(env->jmp_env) == 0) {
294 340
        for(;;) {
341
            if (env->interrupt_request) {
342
                raise_exception(EXCP_INTERRUPT);
343
            }
295 344
#ifdef DEBUG_EXEC
296 345
            if (loglevel) {
297
                cpu_x86_dump_state();
346
                cpu_x86_dump_state(logfile);
298 347
            }
299 348
#endif
300 349
            /* we compute the CPU state. We assume it will not
......
307 356
                GEN_FLAG_ADDSEG_SHIFT;
308 357
            cs_base = env->seg_cache[R_CS].base;
309 358
            pc = cs_base + env->eip;
310
            tb = tb_find_and_alloc((unsigned long)pc, (unsigned long)cs_base, 
311
                                   flags);
312
            tc_ptr = tb->tc_ptr;
313
            if (!tb->tc_ptr) {
359
            tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base, 
360
                         flags);
361
            if (!tb) {
314 362
                /* if no translated code available, then translate it now */
315 363
                /* XXX: very inefficient: we lock all the cpus when
316 364
                   generating code */
317 365
                cpu_lock();
318 366
                tc_ptr = code_gen_ptr;
319
                cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE, 
320
                                 &code_gen_size, pc, cs_base, flags);
367
                ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE, 
368
                                       &code_gen_size, pc, cs_base, flags);
369
                /* if invalid instruction, signal it */
370
                if (ret != 0) {
371
                    cpu_unlock();
372
                    raise_exception(EXCP06_ILLOP);
373
                }
374
                tb = tb_alloc();
375
                *ptb = tb;
376
                tb->pc = (unsigned long)pc;
377
                tb->cs_base = (unsigned long)cs_base;
378
                tb->flags = flags;
321 379
                tb->tc_ptr = tc_ptr;
380
                tb->hash_next = NULL;
322 381
                code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
323 382
                cpu_unlock();
324 383
            }
325 384
            /* execute the generated code */
385
            tc_ptr = tb->tc_ptr;
326 386
            gen_func = (void *)tc_ptr;
327 387
            gen_func();
328 388
        }
329 389
    }
330 390
    ret = env->exception_index;
331 391

  
392
    /* restore flags in standard format */
393
    op_movl_T0_eflags();
394
    env->eflags = T0;
395

  
332 396
    /* restore global registers */
333 397
#ifdef reg_EAX
334 398
    EAX = saved_EAX;
......
361 425
    return ret;
362 426
}
363 427

  
428
void cpu_x86_interrupt(CPUX86State *s)
429
{
430
    s->interrupt_request = 1;
431
}
432

  
433

  
364 434
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
365 435
{
366 436
    CPUX86State *saved_env;
......
370 440
    load_seg(seg_reg, selector);
371 441
    env = saved_env;
372 442
}
443

  
444
#undef EAX
445
#undef ECX
446
#undef EDX
447
#undef EBX
448
#undef ESP
449
#undef EBP
450
#undef ESI
451
#undef EDI
452
#undef EIP
453
#include <signal.h>
454
#include <sys/ucontext.h>
455

  
456
static inline int handle_cpu_signal(unsigned long pc,
457
                                    sigset_t *old_set)
458
{
459
#ifdef DEBUG_SIGNAL
460
    printf("gemu: SIGSEGV pc=0x%08lx oldset=0x%08lx\n", 
461
           pc, *(unsigned long *)old_set);
462
#endif
463
    if (pc >= (unsigned long)code_gen_buffer &&
464
        pc < (unsigned long)code_gen_buffer + CODE_GEN_BUFFER_SIZE) {
465
        /* the PC is inside the translated code. It means that we have
466
           a virtual CPU fault */
467
        /* we restore the process signal mask as the sigreturn should
468
           do it */
469
        sigprocmask(SIG_SETMASK, old_set, NULL);
470
        /* XXX: need to compute virtual pc position by retranslating
471
           code. The rest of the CPU state should be correct. */
472
        raise_exception(EXCP0D_GPF);
473
        /* never comes here */
474
        return 1;
475
    } else {
476
        return 0;
477
    }
478
}
479

  
480
int cpu_x86_signal_handler(int host_signum, struct siginfo *info, 
481
                           void *puc)
482
{
483
#if defined(__i386__)
484
    struct ucontext *uc = puc;
485
    unsigned long pc;
486
    sigset_t *pold_set;
487
    
488
    pc = uc->uc_mcontext.gregs[EIP];
489
    pold_set = &uc->uc_sigmask;
490
    return handle_cpu_signal(pc, pold_set);
491
#else
492
#warning No CPU specific signal handler: cannot handle target SIGSEGV events
493
    return 0;
494
#endif
495
}

Also available in: Unified diff