Revision 3b46e624 target-i386/helper.c

b/target-i386/helper.c
91 91
    1.44269504088896340739L,  /*l2e*/
92 92
    3.32192809488736234781L,  /*l2t*/
93 93
};
94
   
94

  
95 95
/* thread support */
96 96

  
97 97
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
......
126 126
    *e2_ptr = ldl_kernel(ptr + 4);
127 127
    return 0;
128 128
}
129
                                    
129

  
130 130
static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
131 131
{
132 132
    unsigned int limit;
......
160 160
                                       uint32_t *esp_ptr, int dpl)
161 161
{
162 162
    int type, index, shift;
163
   
163

  
164 164
#if 0
165 165
    {
166 166
        int i;
......
325 325
        new_segs[R_GS] = 0;
326 326
        new_trap = 0;
327 327
    }
328
   
328

  
329 329
    /* NOTE: we must avoid memory exceptions during the task switch,
330 330
       so we make dummy accesses before */
331 331
    /* XXX: it can still fail in some cases, so a bigger hack is
......
335 335
    v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
336 336
    stb_kernel(env->tr.base, v1);
337 337
    stb_kernel(env->tr.base + old_tss_limit_max, v2);
338
   
338

  
339 339
    /* clear busy bit (it is restartable) */
340 340
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
341 341
        target_ulong ptr;
......
348 348
    old_eflags = compute_eflags();
349 349
    if (source == SWITCH_TSS_IRET)
350 350
        old_eflags &= ~NT_MASK;
351
   
351

  
352 352
    /* save the current state in the old TSS */
353 353
    if (type & 8) {
354 354
        /* 32 bit */
......
379 379
        for(i = 0; i < 4; i++)
380 380
            stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
381 381
    }
382
   
382

  
383 383
    /* now if an exception occurs, it will occurs in the next task
384 384
       context */
385 385

  
......
406 406
    env->tr.base = tss_base;
407 407
    env->tr.limit = tss_limit;
408 408
    env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
409
   
409

  
410 410
    if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
411 411
        cpu_x86_update_cr3(env, new_cr3);
412 412
    }
413
   
413

  
414 414
    /* load all registers without an exception, then reload them with
415 415
       possible exception */
416 416
    env->eip = new_eip;
......
440 440
        for(i = 0; i < 6; i++)
441 441
            cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
442 442
    }
443
   
443

  
444 444
    env->ldt.selector = new_ldt & ~4;
445 445
    env->ldt.base = 0;
446 446
    env->ldt.limit = 0;
......
464 464
            raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
465 465
        load_seg_cache_raw_dt(&env->ldt, e1, e2);
466 466
    }
467
   
467

  
468 468
    /* load the segments */
469 469
    if (!(new_eflags & VM_MASK)) {
470 470
        tss_load_seg(R_CS, new_segs[R_CS]);
......
474 474
        tss_load_seg(R_FS, new_segs[R_FS]);
475 475
        tss_load_seg(R_GS, new_segs[R_GS]);
476 476
    }
477
   
477

  
478 478
    /* check that EIP is in the CS segment limits */
479 479
    if (new_eip > env->segs[R_CS].limit) {
480 480
        /* XXX: different exception if CALL ? */
......
486 486
static inline void check_io(int addr, int size)
487 487
{
488 488
    int io_offset, val, mask;
489
   
489

  
490 490
    /* TSS must be a valid 32 bit one */
491 491
    if (!(env->tr.flags & DESC_P_MASK) ||
492 492
        ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
......
760 760
            PUSHW(ssp, esp, sp_mask, error_code);
761 761
        }
762 762
    }
763
   
763

  
764 764
    if (new_stack) {
765 765
        if (env->eflags & VM_MASK) {
766 766
            cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
......
806 806
static inline target_ulong get_rsp_from_tss(int level)
807 807
{
808 808
    int index;
809
   
809

  
810 810
#if 0
811 811
    printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
812 812
           env->tr.base, env->tr.limit);
......
926 926
    if (has_error_code) {
927 927
        PUSHQ(esp, error_code);
928 928
    }
929
   
929

  
930 930
    if (new_stack) {
931 931
        ss = 0 | dpl;
932 932
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
......
963 963

  
964 964
        ECX = env->eip + next_eip_addend;
965 965
        env->regs[11] = compute_eflags();
966
       
966

  
967 967
        code64 = env->hflags & HF_CS64_MASK;
968 968

  
969 969
        cpu_x86_set_cpl(env, 0);
......
986 986
#endif
987 987
    {
988 988
        ECX = (uint32_t)(env->eip + next_eip_addend);
989
       
989

  
990 990
        cpu_x86_set_cpl(env, 0);
991 991
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
992 992
                           0, 0xffffffff,
......
1096 1096
    PUSHW(ssp, esp, 0xffff, compute_eflags());
1097 1097
    PUSHW(ssp, esp, 0xffff, old_cs);
1098 1098
    PUSHW(ssp, esp, 0xffff, old_eip);
1099
   
1099

  
1100 1100
    /* update processor state */
1101 1101
    ESP = (ESP & ~0xffff) | (esp & 0xffff);
1102 1102
    env->eip = offset;
......
1117 1117
    dt = &env->idt;
1118 1118
    ptr = dt->base + (intno * 8);
1119 1119
    e2 = ldl_kernel(ptr + 4);
1120
   
1120

  
1121 1121
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
1122 1122
    cpl = env->hflags & HF_CPL_MASK;
1123 1123
    /* check privledge if software int */
......
1134 1134
/*
1135 1135
 * Begin execution of an interruption. is_int is TRUE if coming from
1136 1136
 * the int instruction. next_eip is the EIP value AFTER the interrupt
1137
 * instruction. It is only relevant if is_int is TRUE. 
1137
 * instruction. It is only relevant if is_int is TRUE.
1138 1138
 */
1139 1139
void do_interrupt(int intno, int is_int, int error_code,
1140 1140
                  target_ulong next_eip, int is_hw)
......
1222 1222
 * Signal an interruption. It is executed in the main CPU loop.
1223 1223
 * is_int is TRUE if coming from the int instruction. next_eip is the
1224 1224
 * EIP value AFTER the interrupt instruction. It is only relevant if
1225
 * is_int is TRUE. 
1225
 * is_int is TRUE.
1226 1226
 */
1227 1227
void raise_interrupt(int intno, int is_int, int error_code,
1228 1228
                     int next_eip_addend)
......
1296 1296
    cpu_smm_update(env);
1297 1297

  
1298 1298
    sm_state = env->smbase + 0x8000;
1299
   
1299

  
1300 1300
#ifdef TARGET_X86_64
1301 1301
    for(i = 0; i < 6; i++) {
1302 1302
        dt = &env->segs[i];
......
1314 1314
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1315 1315
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1316 1316
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1317
   
1317

  
1318 1318
    stq_phys(sm_state + 0x7e88, env->idt.base);
1319 1319
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1320 1320

  
......
1322 1322
    stq_phys(sm_state + 0x7e98, env->tr.base);
1323 1323
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1324 1324
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1325
   
1325

  
1326 1326
    stq_phys(sm_state + 0x7ed0, env->efer);
1327 1327

  
1328 1328
    stq_phys(sm_state + 0x7ff8, EAX);
......
1361 1361
    stl_phys(sm_state + 0x7fd0, EAX);
1362 1362
    stl_phys(sm_state + 0x7fcc, env->dr[6]);
1363 1363
    stl_phys(sm_state + 0x7fc8, env->dr[7]);
1364
   
1364

  
1365 1365
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1366 1366
    stl_phys(sm_state + 0x7f64, env->tr.base);
1367 1367
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1368 1368
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1369
   
1369

  
1370 1370
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1371 1371
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1372 1372
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1373 1373
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1374
   
1374

  
1375 1375
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1376 1376
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1377 1377

  
......
1409 1409
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1410 1410
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1411 1411
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1412
   
1412

  
1413 1413
    cpu_x86_update_cr0(env,
1414 1414
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1415 1415
    cpu_x86_update_cr4(env, 0);
......
1447 1447
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1448 1448
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1449 1449
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1450
   
1450

  
1451 1451
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1452 1452
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1453 1453

  
......
1455 1455
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1456 1456
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1457 1457
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1458
   
1458

  
1459 1459
    EAX = ldq_phys(sm_state + 0x7ff8);
1460 1460
    ECX = ldq_phys(sm_state + 0x7ff0);
1461 1461
    EDX = ldq_phys(sm_state + 0x7fe8);
......
1496 1496
    EAX = ldl_phys(sm_state + 0x7fd0);
1497 1497
    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1498 1498
    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1499
   
1499

  
1500 1500
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1501 1501
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1502 1502
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1503 1503
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1504
   
1504

  
1505 1505
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1506 1506
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1507 1507
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1508 1508
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1509
   
1509

  
1510 1510
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1511 1511
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1512 1512

  
......
1564 1564
{
1565 1565
    unsigned int den, r;
1566 1566
    uint64_t num, q;
1567
   
1567

  
1568 1568
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1569 1569
    den = T0;
1570 1570
    if (den == 0) {
......
1586 1586
{
1587 1587
    int den, r;
1588 1588
    int64_t num, q;
1589
   
1589

  
1590 1590
    num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
1591 1591
    den = T0;
1592 1592
    if (den == 0) {
......
1632 1632
{
1633 1633
    uint32_t index;
1634 1634
    index = (uint32_t)EAX;
1635
   
1635

  
1636 1636
    /* test if maximum index reached */
1637 1637
    if (index & 0x80000000) {
1638 1638
        if (index > env->cpuid_xlevel)
......
1641 1641
        if (index > env->cpuid_level)
1642 1642
            index = env->cpuid_level;
1643 1643
    }
1644
       
1644

  
1645 1645
    switch(index) {
1646 1646
    case 0:
1647 1647
        EAX = env->cpuid_level;
......
1783 1783
    uint32_t e1, e2;
1784 1784
    int index, entry_limit;
1785 1785
    target_ulong ptr;
1786
   
1786

  
1787 1787
    selector = T0 & 0xffff;
1788 1788
    if ((selector & 0xfffc) == 0) {
1789 1789
        /* XXX: NULL selector case: invalid LDT */
......
1798 1798
        if (env->hflags & HF_LMA_MASK)
1799 1799
            entry_limit = 15;
1800 1800
        else
1801
#endif           
1801
#endif
1802 1802
            entry_limit = 7;
1803 1803
        if ((index + entry_limit) > dt->limit)
1804 1804
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
......
1831 1831
    uint32_t e1, e2;
1832 1832
    int index, type, entry_limit;
1833 1833
    target_ulong ptr;
1834
   
1834

  
1835 1835
    selector = T0 & 0xffff;
1836 1836
    if ((selector & 0xfffc) == 0) {
1837 1837
        /* NULL selector case: invalid TR */
......
1847 1847
        if (env->hflags & HF_LMA_MASK)
1848 1848
            entry_limit = 15;
1849 1849
        else
1850
#endif           
1850
#endif
1851 1851
            entry_limit = 7;
1852 1852
        if ((index + entry_limit) > dt->limit)
1853 1853
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
......
1901 1901
            raise_exception_err(EXCP0D_GPF, 0);
1902 1902
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
1903 1903
    } else {
1904
       
1904

  
1905 1905
        if (selector & 0x4)
1906 1906
            dt = &env->ldt;
1907 1907
        else
......
1912 1912
        ptr = dt->base + index;
1913 1913
        e1 = ldl_kernel(ptr);
1914 1914
        e2 = ldl_kernel(ptr + 4);
1915
       
1915

  
1916 1916
        if (!(e2 & DESC_S_MASK))
1917 1917
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1918 1918
        rpl = selector & 3;
......
1927 1927
            /* must be readable segment */
1928 1928
            if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
1929 1929
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1930
           
1930

  
1931 1931
            if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1932 1932
                /* if not conforming code, test rights */
1933 1933
                if (dpl < cpl || dpl < rpl)
......
1965 1965
    int new_cs, gate_cs, type;
1966 1966
    uint32_t e1, e2, cpl, dpl, rpl, limit;
1967 1967
    target_ulong new_eip, next_eip;
1968
   
1968

  
1969 1969
    new_cs = T0;
1970 1970
    new_eip = T1;
1971 1971
    if ((new_cs & 0xfffc) == 0)
......
2084 2084
    uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
2085 2085
    uint32_t val, limit, old_sp_mask;
2086 2086
    target_ulong ssp, old_ssp, next_eip, new_eip;
2087
   
2087

  
2088 2088
    new_cs = T0;
2089 2089
    new_eip = T1;
2090 2090
    next_eip = env->eip + next_eip_addend;
......
2151 2151
                PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
2152 2152
                PUSHW(ssp, sp, sp_mask, next_eip);
2153 2153
            }
2154
           
2154

  
2155 2155
            limit = get_seg_limit(e1, e2);
2156 2156
            if (new_eip > limit)
2157 2157
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
......
2228 2228
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2229 2229
            if (!(ss_e2 & DESC_P_MASK))
2230 2230
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
2231
           
2231

  
2232 2232
            //            push_size = ((param_count * 2) + 8) << shift;
2233 2233

  
2234 2234
            old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
2235 2235
            old_ssp = env->segs[R_SS].base;
2236
           
2236

  
2237 2237
            sp_mask = get_sp_mask(ss_e2);
2238 2238
            ssp = get_seg_base(ss_e1, ss_e2);
2239 2239
            if (shift) {
......
2360 2360
    uint32_t e1, e2, ss_e1, ss_e2;
2361 2361
    int cpl, dpl, rpl, eflags_mask, iopl;
2362 2362
    target_ulong ssp, sp, new_eip, new_esp, sp_mask;
2363
   
2363

  
2364 2364
#ifdef TARGET_X86_64
2365 2365
    if (shift == 2)
2366 2366
        sp_mask = -1;
......
2425 2425
    }
2426 2426
    if (!(e2 & DESC_P_MASK))
2427 2427
        raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
2428
   
2428

  
2429 2429
    sp += addend;
2430 2430
    if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||
2431 2431
                       ((env->hflags & HF_CS64_MASK) && !is_iret))) {
......
2539 2539
    POPL(ssp, sp, sp_mask, new_ds);
2540 2540
    POPL(ssp, sp, sp_mask, new_fs);
2541 2541
    POPL(ssp, sp, sp_mask, new_gs);
2542
   
2542

  
2543 2543
    /* modify processor state */
2544 2544
    load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
2545 2545
                IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
......
2559 2559
{
2560 2560
    int tss_selector, type;
2561 2561
    uint32_t e1, e2;
2562
   
2562

  
2563 2563
    /* specific case for TSS */
2564 2564
    if (env->eflags & NT_MASK) {
2565 2565
#ifdef TARGET_X86_64
......
3080 3080
void helper_fyl2x(void)
3081 3081
{
3082 3082
    CPU86_LDouble fptemp;
3083
   
3083

  
3084 3084
    fptemp = ST0;
3085 3085
    if (fptemp>0.0){
3086 3086
        fptemp = log(fptemp)/log(2.0);	 /* log2(ST) */
......
3490 3490
        helper_fstt(tmp, addr);
3491 3491
        addr += 16;
3492 3492
    }
3493
   
3493

  
3494 3494
    if (env->cr[4] & CR4_OSFXSR_MASK) {
3495 3495
        /* XXX: finish it */
3496 3496
        stl(ptr + 0x18, env->mxcsr); /* mxcsr */

Also available in: Unified diff