Revision b333af06 linux-user/vm86.c

b/linux-user/vm86.c
36 36

  
37 37
static inline int is_revectored(int nr, struct target_revectored_struct *bitmap)
38 38
{
39
    return (tswap32(bitmap->__map[nr >> 5]) >> (nr & 0x1f)) & 1;
39
    return (((uint8_t *)bitmap)[nr >> 3] >> (nr & 7)) & 1;
40 40
}
41 41

  
42 42
static inline void vm_putw(uint8_t *segptr, unsigned int reg16, unsigned int val)
......
194 194
    uint8_t *ssp;
195 195
    unsigned int sp;
196 196

  
197
#if 1
198
    if (intno == 0xe6 && (env->regs[R_EAX] & 0xffff) == 0x00c0)
199
        loglevel = 1;
200
#endif
201

  
202 197
    if (env->segs[R_CS] == TARGET_BIOSSEG)
203 198
        goto cannot_handle;
204
    if (is_revectored(intno, &ts->target_v86->int_revectored))
199
    if (is_revectored(intno, &ts->vm86plus.int_revectored))
205 200
        goto cannot_handle;
206 201
    if (intno == 0x21 && is_revectored((env->regs[R_EAX] >> 8) & 0xff, 
207
                                       &ts->target_v86->int21_revectored))
202
                                       &ts->vm86plus.int21_revectored))
208 203
        goto cannot_handle;
209 204
    int_ptr = (uint32_t *)(intno << 2);
210 205
    segoffs = tswap32(*int_ptr);
......
244 239
    }
245 240
}
246 241

  
247
#define CHECK_IF_IN_TRAP(disp) \
248
      if ((tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_active) && \
249
          (tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_TFpendig)) \
250
		vm_putw(ssp,sp + disp,vm_getw(ssp,sp + disp) | TF_MASK)
242
#define CHECK_IF_IN_TRAP() \
243
      if ((ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_active) && \
244
          (ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_TFpendig)) \
245
		newflags |= TF_MASK
251 246

  
252 247
#define VM86_FAULT_RETURN \
253
        if ((tswap32(ts->target_v86->vm86plus.flags) & TARGET_force_return_for_pic) && \
248
        if ((ts->vm86plus.vm86plus.flags & TARGET_force_return_for_pic) && \
254 249
            (ts->v86flags & (IF_MASK | VIF_MASK))) \
255 250
            return_to_32bit(env, TARGET_VM86_PICRETURN); \
256 251
        return
......
259 254
{
260 255
    TaskState *ts = env->opaque;
261 256
    uint8_t *csp, *pc, *ssp;
262
    unsigned int ip, sp;
257
    unsigned int ip, sp, newflags, newip, newcs, opcode, intno;
258
    int data32, pref_done;
263 259

  
264 260
    csp = (uint8_t *)(env->segs[R_CS] << 4);
265 261
    ip = env->eip & 0xffff;
......
273 269
            env->segs[R_CS], env->eip, pc[0], pc[1]);
274 270
#endif
275 271

  
272
    data32 = 0;
273
    pref_done = 0;
274
    do {
275
        opcode = csp[ip];
276
        ADD16(ip, 1);
277
        switch (opcode) {
278
        case 0x66:      /* 32-bit data */     data32=1; break;
279
        case 0x67:      /* 32-bit address */  break;
280
        case 0x2e:      /* CS */              break;
281
        case 0x3e:      /* DS */              break;
282
        case 0x26:      /* ES */              break;
283
        case 0x36:      /* SS */              break;
284
        case 0x65:      /* GS */              break;
285
        case 0x64:      /* FS */              break;
286
        case 0xf2:      /* repnz */	      break;
287
        case 0xf3:      /* rep */             break;
288
        default: pref_done = 1;
289
        }
290
    } while (!pref_done);
291

  
276 292
    /* VM86 mode */
277
    switch(pc[0]) {
278
    case 0x66:
279
        switch(pc[1]) {
280
        case 0x9c: /* pushfd */
281
            ADD16(env->eip, 2);
282
            ADD16(env->regs[R_ESP], -4);
293
    switch(opcode) {
294
    case 0x9c: /* pushf */
295
        ADD16(env->eip, 2);
296
        if (data32) {
283 297
            vm_putl(ssp, sp - 4, get_vflags(env));
284
            VM86_FAULT_RETURN;
298
            ADD16(env->regs[R_ESP], -4);
299
        } else {
300
            vm_putw(ssp, sp - 2, get_vflags(env));
301
            ADD16(env->regs[R_ESP], -2);
302
        }
303
        env->eip = ip;
304
        VM86_FAULT_RETURN;
285 305

  
286
        case 0x9d: /* popfd */
287
            ADD16(env->eip, 2);
306
    case 0x9d: /* popf */
307
        if (data32) {
308
            newflags = vm_getl(ssp, sp);
288 309
            ADD16(env->regs[R_ESP], 4);
289
            CHECK_IF_IN_TRAP(0);
290
            if (set_vflags_long(vm_getl(ssp, sp), env))
310
        } else {
311
            newflags = vm_getw(ssp, sp);
312
            ADD16(env->regs[R_ESP], 2);
313
        }
314
        env->eip = ip;
315
        CHECK_IF_IN_TRAP();
316
        if (data32) {
317
            if (set_vflags_long(newflags, env))
291 318
                return;
292
            VM86_FAULT_RETURN;
293

  
294
        case 0xcf: /* iretd */
295
            ADD16(env->regs[R_ESP], 12);
296
            env->eip = vm_getl(ssp, sp) & 0xffff;
297
            cpu_x86_load_seg(env, R_CS, vm_getl(ssp, sp + 4) & 0xffff);
298
            CHECK_IF_IN_TRAP(8);
299
            if (set_vflags_long(vm_getl(ssp, sp + 8), env))
319
        } else {
320
            if (set_vflags_short(newflags, env))
300 321
                return;
301
            VM86_FAULT_RETURN;
302

  
303
        default:
304
            goto vm86_gpf;
305 322
        }
306
        break;
307
    case 0x9c: /* pushf */
308
        ADD16(env->eip, 1);
309
        ADD16(env->regs[R_ESP], -2);
310
        vm_putw(ssp, sp - 2, get_vflags(env));
311
        VM86_FAULT_RETURN;
312

  
313
    case 0x9d: /* popf */
314
        ADD16(env->eip, 1);
315
        ADD16(env->regs[R_ESP], 2);
316
        CHECK_IF_IN_TRAP(0);
317
        if (set_vflags_short(vm_getw(ssp, sp), env))
318
            return;
319 323
        VM86_FAULT_RETURN;
320 324

  
321 325
    case 0xcd: /* int */
322
        ADD16(env->eip, 2);
323
        do_int(env, pc[1]);
326
        intno = csp[ip];
327
        ADD16(ip, 1);
328
        env->eip = ip;
329
        if (ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_active) {
330
            if ( (ts->vm86plus.vm86plus.vm86dbg_intxxtab[intno >> 3] >> 
331
                  (intno &7)) & 1) {
332
                return_to_32bit(env, TARGET_VM86_INTx + (intno << 8));
333
                return;
334
            }
335
        }
336
        do_int(env, intno);
324 337
        break;
325 338

  
326 339
    case 0xcf: /* iret */
327
        ADD16(env->regs[R_ESP], 6);
328
        env->eip = vm_getw(ssp, sp);
329
        cpu_x86_load_seg(env, R_CS, vm_getw(ssp, sp + 2));
330
        CHECK_IF_IN_TRAP(4);
331
        if (set_vflags_short(vm_getw(ssp, sp + 4), env))
332
            return;
340
        if (data32) {
341
            newip = vm_getl(ssp, sp) & 0xffff;
342
            newcs = vm_getl(ssp, sp + 4) & 0xffff;
343
            newflags = vm_getl(ssp, sp + 8);
344
            ADD16(env->regs[R_ESP], 12);
345
        } else {
346
            newip = vm_getw(ssp, sp);
347
            newcs = vm_getw(ssp, sp + 2);
348
            newflags = vm_getw(ssp, sp + 4);
349
            ADD16(env->regs[R_ESP], 6);
350
        }
351
        env->eip = newip;
352
        cpu_x86_load_seg(env, R_CS, newcs);
353
        CHECK_IF_IN_TRAP();
354
        if (data32) {
355
            if (set_vflags_long(newflags, env))
356
                return;
357
        } else {
358
            if (set_vflags_short(newflags, env))
359
                return;
360
        }
333 361
        VM86_FAULT_RETURN;
334

  
362
        
335 363
    case 0xfa: /* cli */
336
        ADD16(env->eip, 1);
364
        env->eip = ip;
337 365
        clear_IF(env);
338 366
        VM86_FAULT_RETURN;
339 367
        
340 368
    case 0xfb: /* sti */
341
        ADD16(env->eip, 1);
369
        env->eip = ip;
342 370
        if (set_IF(env))
343 371
            return;
344 372
        VM86_FAULT_RETURN;
345 373

  
346 374
    default:
347
    vm86_gpf:
348 375
        /* real VM86 GPF exception */
349 376
        return_to_32bit(env, TARGET_VM86_UNKNOWN);
350 377
        break;
......
398 425
    ts->v86flags = tswap32(target_v86->regs.eflags);
399 426
    env->eflags = (env->eflags & ~SAFE_MASK) | 
400 427
        (tswap32(target_v86->regs.eflags) & SAFE_MASK) | VM_MASK;
401
    ts->v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK;
428

  
429
    ts->vm86plus.cpu_type = tswapl(target_v86->cpu_type);
430
    switch (ts->vm86plus.cpu_type) {
431
    case TARGET_CPU_286:
432
        ts->v86mask = 0;
433
        break;
434
    case TARGET_CPU_386:
435
        ts->v86mask = NT_MASK | IOPL_MASK;
436
        break;
437
    case TARGET_CPU_486:
438
        ts->v86mask = AC_MASK | NT_MASK | IOPL_MASK;
439
        break;
440
    default:
441
        ts->v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK;
442
        break;
443
    }
402 444

  
403 445
    env->regs[R_EBX] = tswap32(target_v86->regs.ebx);
404 446
    env->regs[R_ECX] = tswap32(target_v86->regs.ecx);
......
416 458
    cpu_x86_load_seg(env, R_GS, tswap16(target_v86->regs.gs));
417 459
    ret = tswap32(target_v86->regs.eax); /* eax will be restored at
418 460
                                            the end of the syscall */
461
    memcpy(&ts->vm86plus.int_revectored, 
462
           &target_v86->int_revectored, 32);
463
    memcpy(&ts->vm86plus.int21_revectored, 
464
           &target_v86->int21_revectored, 32);
465
    ts->vm86plus.vm86plus.flags = tswapl(target_v86->vm86plus.flags);
466
    memcpy(&ts->vm86plus.vm86plus.vm86dbg_intxxtab, 
467
           target_v86->vm86plus.vm86dbg_intxxtab, 32);
468
    
419 469
#ifdef DEBUG_VM86
420 470
    fprintf(logfile, "do_vm86: cs:ip=%04x:%04x\n", env->segs[R_CS], env->eip);
421 471
#endif

Also available in: Unified diff