Revision 891b38e4

b/target-i386/helper.c
531 531
    check_io(EDX & 0xffff, 4);
532 532
}
533 533

  
534
static inline unsigned int get_sp_mask(unsigned int e2)
535
{
536
    if (e2 & DESC_B_MASK)
537
        return 0xffffffff;
538
    else
539
        return 0xffff;
540
}
541

  
542
/* XXX: add a is_user flag to have proper security support */
543
#define PUSHW(ssp, sp, sp_mask, val)\
544
{\
545
    sp -= 2;\
546
    stw_kernel((ssp) + (sp & (sp_mask)), (val));\
547
}
548

  
549
#define PUSHL(ssp, sp, sp_mask, val)\
550
{\
551
    sp -= 4;\
552
    stl_kernel((ssp) + (sp & (sp_mask)), (val));\
553
}
554

  
555
#define POPW(ssp, sp, sp_mask, val)\
556
{\
557
    val = lduw_kernel((ssp) + (sp & (sp_mask)));\
558
    sp += 2;\
559
}
560

  
561
#define POPL(ssp, sp, sp_mask, val)\
562
{\
563
    val = ldl_kernel((ssp) + (sp & (sp_mask)));\
564
    sp += 4;\
565
}
566

  
534 567
/* protected mode interrupt */
535 568
static void do_interrupt_protected(int intno, int is_int, int error_code,
536 569
                                   unsigned int next_eip, int is_hw)
537 570
{
538 571
    SegmentCache *dt;
539 572
    uint8_t *ptr, *ssp;
540
    int type, dpl, selector, ss_dpl, cpl;
573
    int type, dpl, selector, ss_dpl, cpl, sp_mask;
541 574
    int has_error_code, new_stack, shift;
542
    uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size;
543
    uint32_t old_cs, old_ss, old_esp, old_eip;
575
    uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
576
    uint32_t old_eip;
544 577

  
545 578
#ifdef DEBUG_PCALL
546 579
    if (loglevel) {
......
659 692
        if (!(ss_e2 & DESC_P_MASK))
660 693
            raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
661 694
        new_stack = 1;
695
        sp_mask = get_sp_mask(ss_e2);
696
        ssp = get_seg_base(ss_e1, ss_e2);
662 697
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
663 698
        /* to same priviledge */
664 699
        new_stack = 0;
700
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
701
        ssp = env->segs[R_SS].base;
702
        esp = ESP;
665 703
    } else {
666 704
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
667 705
        new_stack = 0; /* avoid warning */
706
        sp_mask = 0; /* avoid warning */
707
        ssp = NULL; /* avoid warning */
708
        esp = 0; /* avoid warning */
668 709
    }
669 710

  
670 711
    shift = type >> 3;
712

  
713
#if 0
714
    /* XXX: check that enough room is available */
671 715
    push_size = 6 + (new_stack << 2) + (has_error_code << 1);
672 716
    if (env->eflags & VM_MASK)
673 717
        push_size += 8;
674 718
    push_size <<= shift;
675

  
676
    /* XXX: check that enough room is available */
677
    if (new_stack) {
678
        old_esp = ESP;
679
        old_ss = env->segs[R_SS].selector;
680
        ss = (ss & ~3) | dpl;
681
        cpu_x86_load_seg_cache(env, R_SS, ss, 
682
                       get_seg_base(ss_e1, ss_e2),
683
                       get_seg_limit(ss_e1, ss_e2),
684
                       ss_e2);
685
    } else {
686
        old_esp = 0;
687
        old_ss = 0;
688
        esp = ESP;
689
    }
719
#endif
690 720
    if (is_int)
691 721
        old_eip = next_eip;
692 722
    else
693 723
        old_eip = env->eip;
694
    old_cs = env->segs[R_CS].selector;
695
    selector = (selector & ~3) | dpl;
696
    cpu_x86_load_seg_cache(env, R_CS, selector, 
697
                   get_seg_base(e1, e2),
698
                   get_seg_limit(e1, e2),
699
                   e2);
700
    cpu_x86_set_cpl(env, dpl);
701
    env->eip = offset;
702
    ESP = esp - push_size;
703
    ssp = env->segs[R_SS].base + esp;
704 724
    if (shift == 1) {
705
        int old_eflags;
706 725
        if (env->eflags & VM_MASK) {
707
            ssp -= 4;
708
            stl_kernel(ssp, env->segs[R_GS].selector);
709
            ssp -= 4;
710
            stl_kernel(ssp, env->segs[R_FS].selector);
711
            ssp -= 4;
712
            stl_kernel(ssp, env->segs[R_DS].selector);
713
            ssp -= 4;
714
            stl_kernel(ssp, env->segs[R_ES].selector);
726
            PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
727
            PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
728
            PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
729
            PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
715 730
        }
716 731
        if (new_stack) {
717
            ssp -= 4;
718
            stl_kernel(ssp, old_ss);
719
            ssp -= 4;
720
            stl_kernel(ssp, old_esp);
732
            PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
733
            PUSHL(ssp, esp, sp_mask, ESP);
721 734
        }
722
        ssp -= 4;
723
        old_eflags = compute_eflags();
724
        stl_kernel(ssp, old_eflags);
725
        ssp -= 4;
726
        stl_kernel(ssp, old_cs);
727
        ssp -= 4;
728
        stl_kernel(ssp, old_eip);
735
        PUSHL(ssp, esp, sp_mask, compute_eflags());
736
        PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
737
        PUSHL(ssp, esp, sp_mask, old_eip);
729 738
        if (has_error_code) {
730
            ssp -= 4;
731
            stl_kernel(ssp, error_code);
739
            PUSHL(ssp, esp, sp_mask, error_code);
732 740
        }
733 741
    } else {
734 742
        if (new_stack) {
735
            ssp -= 2;
736
            stw_kernel(ssp, old_ss);
737
            ssp -= 2;
738
            stw_kernel(ssp, old_esp);
743
            PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
744
            PUSHW(ssp, esp, sp_mask, ESP);
739 745
        }
740
        ssp -= 2;
741
        stw_kernel(ssp, compute_eflags());
742
        ssp -= 2;
743
        stw_kernel(ssp, old_cs);
744
        ssp -= 2;
745
        stw_kernel(ssp, old_eip);
746
        PUSHW(ssp, esp, sp_mask, compute_eflags());
747
        PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
748
        PUSHW(ssp, esp, sp_mask, old_eip);
746 749
        if (has_error_code) {
747
            ssp -= 2;
748
            stw_kernel(ssp, error_code);
750
            PUSHW(ssp, esp, sp_mask, error_code);
749 751
        }
750 752
    }
751 753
    
754
    if (new_stack) {
755
        ss = (ss & ~3) | dpl;
756
        cpu_x86_load_seg_cache(env, R_SS, ss, 
757
                               ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
758
    }
759
    ESP = (ESP & ~sp_mask) | (esp & sp_mask);
760

  
761
    selector = (selector & ~3) | dpl;
762
    cpu_x86_load_seg_cache(env, R_CS, selector, 
763
                   get_seg_base(e1, e2),
764
                   get_seg_limit(e1, e2),
765
                   e2);
766
    cpu_x86_set_cpl(env, dpl);
767
    env->eip = offset;
768

  
752 769
    /* interrupt gate clear IF mask */
753 770
    if ((type & 1) == 0) {
754 771
        env->eflags &= ~IF_MASK;
......
780 797
    else
781 798
        old_eip = env->eip;
782 799
    old_cs = env->segs[R_CS].selector;
783
    esp -= 2;
784
    stw_kernel(ssp + (esp & 0xffff), compute_eflags());
785
    esp -= 2;
786
    stw_kernel(ssp + (esp & 0xffff), old_cs);
787
    esp -= 2;
788
    stw_kernel(ssp + (esp & 0xffff), old_eip);
800
    /* XXX: use SS segment size ? */
801
    PUSHW(ssp, esp, 0xffff, compute_eflags());
802
    PUSHW(ssp, esp, 0xffff, old_cs);
803
    PUSHW(ssp, esp, 0xffff, old_eip);
789 804
    
790 805
    /* update processor state */
791 806
    ESP = (ESP & ~0xffff) | (esp & 0xffff);
......
1247 1262
    new_cs = T0;
1248 1263
    new_eip = T1;
1249 1264
    esp = ESP;
1250
    esp_mask = 0xffffffff;
1251
    if (!(env->segs[R_SS].flags & DESC_B_MASK))
1252
        esp_mask = 0xffff;
1265
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
1253 1266
    ssp = env->segs[R_SS].base;
1254 1267
    if (shift) {
1255
        esp -= 4;
1256
        stl_kernel(ssp + (esp & esp_mask), env->segs[R_CS].selector);
1257
        esp -= 4;
1258
        stl_kernel(ssp + (esp & esp_mask), next_eip);
1268
        PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
1269
        PUSHL(ssp, esp, esp_mask, next_eip);
1259 1270
    } else {
1260
        esp -= 2;
1261
        stw_kernel(ssp + (esp & esp_mask), env->segs[R_CS].selector);
1262
        esp -= 2;
1263
        stw_kernel(ssp + (esp & esp_mask), next_eip);
1271
        PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
1272
        PUSHW(ssp, esp, esp_mask, next_eip);
1264 1273
    }
1265 1274

  
1266
    if (!(env->segs[R_SS].flags & DESC_B_MASK))
1267
        ESP = (ESP & ~0xffff) | (esp & 0xffff);
1268
    else
1269
        ESP = esp;
1275
    ESP = (ESP & ~esp_mask) | (esp & esp_mask);
1270 1276
    env->eip = new_eip;
1271 1277
    env->segs[R_CS].selector = new_cs;
1272 1278
    env->segs[R_CS].base = (uint8_t *)(new_cs << 4);
......
1275 1281
/* protected mode call */
1276 1282
void helper_lcall_protected_T0_T1(int shift, int next_eip)
1277 1283
{
1278
    int new_cs, new_eip;
1284
    int new_cs, new_eip, new_stack, i;
1279 1285
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
1280
    uint32_t ss, ss_e1, ss_e2, push_size, sp, type, ss_dpl;
1281
    uint32_t old_ss, old_esp, val, i, limit;
1286
    uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
1287
    uint32_t val, limit, old_sp_mask;
1282 1288
    uint8_t *ssp, *old_ssp;
1283 1289
    
1284 1290
    new_cs = T0;
......
1319 1325
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1320 1326

  
1321 1327
        sp = ESP;
1322
        if (!(env->segs[R_SS].flags & DESC_B_MASK))
1323
            sp &= 0xffff;
1324
        ssp = env->segs[R_SS].base + sp;
1328
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
1329
        ssp = env->segs[R_SS].base;
1325 1330
        if (shift) {
1326
            ssp -= 4;
1327
            stl_kernel(ssp, env->segs[R_CS].selector);
1328
            ssp -= 4;
1329
            stl_kernel(ssp, next_eip);
1331
            PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
1332
            PUSHL(ssp, sp, sp_mask, next_eip);
1330 1333
        } else {
1331
            ssp -= 2;
1332
            stw_kernel(ssp, env->segs[R_CS].selector);
1333
            ssp -= 2;
1334
            stw_kernel(ssp, next_eip);
1334
            PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
1335
            PUSHW(ssp, sp, sp_mask, next_eip);
1335 1336
        }
1336
        sp -= (4 << shift);
1337 1337
        
1338 1338
        limit = get_seg_limit(e1, e2);
1339 1339
        if (new_eip > limit)
1340 1340
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1341 1341
        /* from this point, not restartable */
1342
        if (!(env->segs[R_SS].flags & DESC_B_MASK))
1343
            ESP = (ESP & 0xffff0000) | (sp & 0xffff);
1344
        else
1345
            ESP = sp;
1342
        ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1346 1343
        cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
1347 1344
                       get_seg_base(e1, e2), limit, e2);
1348 1345
        EIP = new_eip;
......
1413 1410
            if (!(ss_e2 & DESC_P_MASK))
1414 1411
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
1415 1412
            
1416
            push_size = ((param_count * 2) + 8) << shift;
1413
            //            push_size = ((param_count * 2) + 8) << shift;
1417 1414

  
1418
            old_esp = ESP;
1419
            old_ss = env->segs[R_SS].selector;
1420
            if (!(env->segs[R_SS].flags & DESC_B_MASK))
1421
                old_esp &= 0xffff;
1422
            old_ssp = env->segs[R_SS].base + old_esp;
1415
            old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
1416
            old_ssp = env->segs[R_SS].base;
1423 1417
            
1424
            /* XXX: from this point not restartable */
1425
            ss = (ss & ~3) | dpl;
1426
            cpu_x86_load_seg_cache(env, R_SS, ss, 
1427
                           get_seg_base(ss_e1, ss_e2),
1428
                           get_seg_limit(ss_e1, ss_e2),
1429
                           ss_e2);
1430

  
1431
            if (!(ss_e2 & DESC_B_MASK))
1432
                sp &= 0xffff;
1433
            ssp = env->segs[R_SS].base + sp;
1418
            sp_mask = get_sp_mask(ss_e2);
1419
            ssp = get_seg_base(ss_e1, ss_e2);
1434 1420
            if (shift) {
1435
                ssp -= 4;
1436
                stl_kernel(ssp, old_ss);
1437
                ssp -= 4;
1438
                stl_kernel(ssp, old_esp);
1439
                ssp -= 4 * param_count;
1440
                for(i = 0; i < param_count; i++) {
1441
                    val = ldl_kernel(old_ssp + i * 4);
1442
                    stl_kernel(ssp + i * 4, val);
1421
                PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
1422
                PUSHL(ssp, sp, sp_mask, ESP);
1423
                for(i = param_count - 1; i >= 0; i--) {
1424
                    val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
1425
                    PUSHL(ssp, sp, sp_mask, val);
1443 1426
                }
1444 1427
            } else {
1445
                ssp -= 2;
1446
                stw_kernel(ssp, old_ss);
1447
                ssp -= 2;
1448
                stw_kernel(ssp, old_esp);
1449
                ssp -= 2 * param_count;
1450
                for(i = 0; i < param_count; i++) {
1451
                    val = lduw_kernel(old_ssp + i * 2);
1452
                    stw_kernel(ssp + i * 2, val);
1428
                PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
1429
                PUSHW(ssp, sp, sp_mask, ESP);
1430
                for(i = param_count - 1; i >= 0; i--) {
1431
                    val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
1432
                    PUSHW(ssp, sp, sp_mask, val);
1453 1433
                }
1454 1434
            }
1435
            new_stack = 1;
1455 1436
        } else {
1456 1437
            /* to same priviledge */
1457
            if (!(env->segs[R_SS].flags & DESC_B_MASK))
1458
                sp &= 0xffff;
1459
            ssp = env->segs[R_SS].base + sp;
1460
            push_size = (4 << shift);
1438
            sp = ESP;
1439
            sp_mask = get_sp_mask(env->segs[R_SS].flags);
1440
            ssp = env->segs[R_SS].base;
1441
            //            push_size = (4 << shift);
1442
            new_stack = 0;
1461 1443
        }
1462 1444

  
1463 1445
        if (shift) {
1464
            ssp -= 4;
1465
            stl_kernel(ssp, env->segs[R_CS].selector);
1466
            ssp -= 4;
1467
            stl_kernel(ssp, next_eip);
1446
            PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
1447
            PUSHL(ssp, sp, sp_mask, next_eip);
1468 1448
        } else {
1469
            ssp -= 2;
1470
            stw_kernel(ssp, env->segs[R_CS].selector);
1471
            ssp -= 2;
1472
            stw_kernel(ssp, next_eip);
1449
            PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
1450
            PUSHW(ssp, sp, sp_mask, next_eip);
1451
        }
1452

  
1453
        /* from this point, not restartable */
1454

  
1455
        if (new_stack) {
1456
            ss = (ss & ~3) | dpl;
1457
            cpu_x86_load_seg_cache(env, R_SS, ss, 
1458
                                   ssp,
1459
                                   get_seg_limit(ss_e1, ss_e2),
1460
                                   ss_e2);
1473 1461
        }
1474 1462

  
1475
        sp -= push_size;
1476 1463
        selector = (selector & ~3) | dpl;
1477 1464
        cpu_x86_load_seg_cache(env, R_CS, selector, 
1478 1465
                       get_seg_base(e1, e2),
1479 1466
                       get_seg_limit(e1, e2),
1480 1467
                       e2);
1481 1468
        cpu_x86_set_cpl(env, dpl);
1482
        
1483
        if (!(env->segs[R_SS].flags & DESC_B_MASK))
1484
            ESP = (ESP & 0xffff0000) | (sp & 0xffff);
1485
        else
1486
            ESP = sp;
1469
        ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1487 1470
        EIP = offset;
1488 1471
    }
1489 1472
}
......
1491 1474
/* real and vm86 mode iret */
1492 1475
void helper_iret_real(int shift)
1493 1476
{
1494
    uint32_t sp, new_cs, new_eip, new_eflags, new_esp;
1477
    uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
1495 1478
    uint8_t *ssp;
1496 1479
    int eflags_mask;
1497 1480

  
1498
    sp = ESP & 0xffff;
1499
    ssp = env->segs[R_SS].base + sp;
1481
    sp_mask = 0xffff; /* XXXX: use SS segment size ? */
1482
    sp = ESP;
1483
    ssp = env->segs[R_SS].base;
1500 1484
    if (shift == 1) {
1501 1485
        /* 32 bits */
1502
        new_eflags = ldl_kernel(ssp + 8);
1503
        new_cs = ldl_kernel(ssp + 4) & 0xffff;
1504
        new_eip = ldl_kernel(ssp) & 0xffff;
1486
        POPL(ssp, sp, sp_mask, new_eip);
1487
        POPL(ssp, sp, sp_mask, new_cs);
1488
        new_cs &= 0xffff;
1489
        POPL(ssp, sp, sp_mask, new_eflags);
1505 1490
    } else {
1506 1491
        /* 16 bits */
1507
        new_eflags = lduw_kernel(ssp + 4);
1508
        new_cs = lduw_kernel(ssp + 2);
1509
        new_eip = lduw_kernel(ssp);
1492
        POPW(ssp, sp, sp_mask, new_eip);
1493
        POPW(ssp, sp, sp_mask, new_cs);
1494
        POPW(ssp, sp, sp_mask, new_eflags);
1510 1495
    }
1511
    new_esp = sp + (6 << shift);
1512
    ESP = (ESP & 0xffff0000) | 
1513
        (new_esp & 0xffff);
1496
    ESP = (ESP & ~sp_mask) | (sp & 0xffff);
1514 1497
    load_seg_vm(R_CS, new_cs);
1515 1498
    env->eip = new_eip;
1516 1499
    if (env->eflags & VM_MASK)
......
1525 1508
/* protected mode iret */
1526 1509
static inline void helper_ret_protected(int shift, int is_iret, int addend)
1527 1510
{
1528
    uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss;
1511
    uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask;
1529 1512
    uint32_t new_es, new_ds, new_fs, new_gs;
1530 1513
    uint32_t e1, e2, ss_e1, ss_e2;
1531 1514
    int cpl, dpl, rpl, eflags_mask;
1532 1515
    uint8_t *ssp;
1533 1516
    
1517
    sp_mask = get_sp_mask(env->segs[R_SS].flags);
1534 1518
    sp = ESP;
1535
    if (!(env->segs[R_SS].flags & DESC_B_MASK))
1536
        sp &= 0xffff;
1537
    ssp = env->segs[R_SS].base + sp;
1519
    ssp = env->segs[R_SS].base;
1538 1520
    if (shift == 1) {
1539 1521
        /* 32 bits */
1540
        if (is_iret)
1541
            new_eflags = ldl_kernel(ssp + 8);
1542
        new_cs = ldl_kernel(ssp + 4) & 0xffff;
1543
        new_eip = ldl_kernel(ssp);
1544
        if (is_iret && (new_eflags & VM_MASK))
1545
            goto return_to_vm86;
1522
        POPL(ssp, sp, sp_mask, new_eip);
1523
        POPL(ssp, sp, sp_mask, new_cs);
1524
        new_cs &= 0xffff;
1525
        if (is_iret) {
1526
            POPL(ssp, sp, sp_mask, new_eflags);
1527
            if (new_eflags & VM_MASK)
1528
                goto return_to_vm86;
1529
        }
1546 1530
    } else {
1547 1531
        /* 16 bits */
1532
        POPW(ssp, sp, sp_mask, new_eip);
1533
        POPW(ssp, sp, sp_mask, new_cs);
1548 1534
        if (is_iret)
1549
            new_eflags = lduw_kernel(ssp + 4);
1550
        new_cs = lduw_kernel(ssp + 2);
1551
        new_eip = lduw_kernel(ssp);
1535
            POPW(ssp, sp, sp_mask, new_eflags);
1552 1536
    }
1537
#ifdef DEBUG_PCALL
1538
    if (loglevel) {
1539
        fprintf(logfile, "lret new %04x:%08x\n",
1540
                new_cs, new_eip);
1541
    }
1542
#endif
1553 1543
    if ((new_cs & 0xfffc) == 0)
1554 1544
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
1555 1545
    if (load_segment(&e1, &e2, new_cs) != 0)
......
1572 1562
    if (!(e2 & DESC_P_MASK))
1573 1563
        raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1574 1564
    
1565
    sp += addend;
1575 1566
    if (rpl == cpl) {
1576 1567
        /* return to same priledge level */
1577 1568
        cpu_x86_load_seg_cache(env, R_CS, new_cs, 
1578 1569
                       get_seg_base(e1, e2),
1579 1570
                       get_seg_limit(e1, e2),
1580 1571
                       e2);
1581
        new_esp = sp + (4 << shift) + ((2 * is_iret) << shift) + addend;
1582 1572
    } else {
1583 1573
        /* return to different priviledge level */
1584
        ssp += (4 << shift) + ((2 * is_iret) << shift) + addend;
1585 1574
        if (shift == 1) {
1586 1575
            /* 32 bits */
1587
            new_esp = ldl_kernel(ssp);
1588
            new_ss = ldl_kernel(ssp + 4) & 0xffff;
1576
            POPL(ssp, sp, sp_mask, new_esp);
1577
            POPL(ssp, sp, sp_mask, new_ss);
1578
            new_ss &= 0xffff;
1589 1579
        } else {
1590 1580
            /* 16 bits */
1591
            new_esp = lduw_kernel(ssp);
1592
            new_ss = lduw_kernel(ssp + 2);
1581
            POPW(ssp, sp, sp_mask, new_esp);
1582
            POPW(ssp, sp, sp_mask, new_ss);
1593 1583
        }
1594 1584
        
1595 1585
        if ((new_ss & 3) != rpl)
......
1615 1605
                       get_seg_limit(ss_e1, ss_e2),
1616 1606
                       ss_e2);
1617 1607
        cpu_x86_set_cpl(env, rpl);
1608
        sp = new_esp;
1609
        /* XXX: change sp_mask according to old segment ? */
1618 1610
    }
1619
    if (env->segs[R_SS].flags & DESC_B_MASK)
1620
        ESP = new_esp;
1621
    else
1622
        ESP = (ESP & 0xffff0000) | 
1623
            (new_esp & 0xffff);
1611
    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
1624 1612
    env->eip = new_eip;
1625 1613
    if (is_iret) {
1626 1614
        /* NOTE: 'cpl' can be different from the current CPL */
......
1635 1623
    return;
1636 1624

  
1637 1625
 return_to_vm86:
1638
    new_esp = ldl_kernel(ssp + 12);
1639
    new_ss = ldl_kernel(ssp + 16);
1640
    new_es = ldl_kernel(ssp + 20);
1641
    new_ds = ldl_kernel(ssp + 24);
1642
    new_fs = ldl_kernel(ssp + 28);
1643
    new_gs = ldl_kernel(ssp + 32);
1626
    POPL(ssp, sp, sp_mask, new_esp);
1627
    POPL(ssp, sp, sp_mask, new_ss);
1628
    POPL(ssp, sp, sp_mask, new_es);
1629
    POPL(ssp, sp, sp_mask, new_ds);
1630
    POPL(ssp, sp, sp_mask, new_fs);
1631
    POPL(ssp, sp, sp_mask, new_gs);
1644 1632
    
1645 1633
    /* modify processor state */
1646 1634
    load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK);
1647
    load_seg_vm(R_CS, new_cs);
1635
    load_seg_vm(R_CS, new_cs & 0xffff);
1648 1636
    cpu_x86_set_cpl(env, 3);
1649
    load_seg_vm(R_SS, new_ss);
1650
    load_seg_vm(R_ES, new_es);
1651
    load_seg_vm(R_DS, new_ds);
1652
    load_seg_vm(R_FS, new_fs);
1653
    load_seg_vm(R_GS, new_gs);
1637
    load_seg_vm(R_SS, new_ss & 0xffff);
1638
    load_seg_vm(R_ES, new_es & 0xffff);
1639
    load_seg_vm(R_DS, new_ds & 0xffff);
1640
    load_seg_vm(R_FS, new_fs & 0xffff);
1641
    load_seg_vm(R_GS, new_gs & 0xffff);
1654 1642

  
1655 1643
    env->eip = new_eip;
1656 1644
    ESP = new_esp;

Also available in: Unified diff