Annotation of qemu/target-i386/helper.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  *  i386 helpers
                      3:  * 
                      4:  *  Copyright (c) 2003 Fabrice Bellard
                      5:  *
                      6:  * 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.
                     10:  *
                     11:  * 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.
                     15:  *
                     16:  * 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
                     19:  */
                     20: #include "exec.h"
                     21: 
                     22: //#define DEBUG_PCALL
                     23: 
                     24: #if 0
                     25: #define raise_exception_err(a, b)\
                     26: do {\
1.1.1.3 ! root       27:     if (logfile)\
        !            28:         fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
1.1       root       29:     (raise_exception_err)(a, b);\
                     30: } while (0)
                     31: #endif
                     32: 
                     33: const uint8_t parity_table[256] = {
                     34:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     35:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     36:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     37:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     38:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     39:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     40:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     41:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     42:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     43:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     44:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     45:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     46:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     47:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     48:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     49:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     50:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     51:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     52:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     53:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     54:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     55:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     56:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     57:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     58:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     59:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     60:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     61:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     62:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     63:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     64:     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
                     65:     0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
                     66: };
                     67: 
                     68: /* modulo 17 table */
                     69: const uint8_t rclw_table[32] = {
                     70:     0, 1, 2, 3, 4, 5, 6, 7, 
                     71:     8, 9,10,11,12,13,14,15,
                     72:    16, 0, 1, 2, 3, 4, 5, 6,
                     73:     7, 8, 9,10,11,12,13,14,
                     74: };
                     75: 
                     76: /* modulo 9 table */
                     77: const uint8_t rclb_table[32] = {
                     78:     0, 1, 2, 3, 4, 5, 6, 7, 
                     79:     8, 0, 1, 2, 3, 4, 5, 6,
                     80:     7, 8, 0, 1, 2, 3, 4, 5, 
                     81:     6, 7, 8, 0, 1, 2, 3, 4,
                     82: };
                     83: 
                     84: const CPU86_LDouble f15rk[7] =
                     85: {
                     86:     0.00000000000000000000L,
                     87:     1.00000000000000000000L,
                     88:     3.14159265358979323851L,  /*pi*/
                     89:     0.30102999566398119523L,  /*lg2*/
                     90:     0.69314718055994530943L,  /*ln2*/
                     91:     1.44269504088896340739L,  /*l2e*/
                     92:     3.32192809488736234781L,  /*l2t*/
                     93: };
                     94:     
                     95: /* thread support */
                     96: 
                     97: spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
                     98: 
                     99: void cpu_lock(void)
                    100: {
                    101:     spin_lock(&global_cpu_lock);
                    102: }
                    103: 
                    104: void cpu_unlock(void)
                    105: {
                    106:     spin_unlock(&global_cpu_lock);
                    107: }
                    108: 
                    109: void cpu_loop_exit(void)
                    110: {
                    111:     /* NOTE: the register at this point must be saved by hand because
                    112:        longjmp restore them */
                    113:     regs_to_env();
                    114:     longjmp(env->jmp_env, 1);
                    115: }
                    116: 
                    117: /* return non zero if error */
                    118: static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
                    119:                                int selector)
                    120: {
                    121:     SegmentCache *dt;
                    122:     int index;
                    123:     target_ulong ptr;
                    124: 
                    125:     if (selector & 0x4)
                    126:         dt = &env->ldt;
                    127:     else
                    128:         dt = &env->gdt;
                    129:     index = selector & ~7;
                    130:     if ((index + 7) > dt->limit)
                    131:         return -1;
                    132:     ptr = dt->base + index;
                    133:     *e1_ptr = ldl_kernel(ptr);
                    134:     *e2_ptr = ldl_kernel(ptr + 4);
                    135:     return 0;
                    136: }
                    137:                                      
                    138: static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2)
                    139: {
                    140:     unsigned int limit;
                    141:     limit = (e1 & 0xffff) | (e2 & 0x000f0000);
                    142:     if (e2 & DESC_G_MASK)
                    143:         limit = (limit << 12) | 0xfff;
                    144:     return limit;
                    145: }
                    146: 
                    147: static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
                    148: {
                    149:     return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
                    150: }
                    151: 
                    152: static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
                    153: {
                    154:     sc->base = get_seg_base(e1, e2);
                    155:     sc->limit = get_seg_limit(e1, e2);
                    156:     sc->flags = e2;
                    157: }
                    158: 
                    159: /* init the segment cache in vm86 mode. */
                    160: static inline void load_seg_vm(int seg, int selector)
                    161: {
                    162:     selector &= 0xffff;
                    163:     cpu_x86_load_seg_cache(env, seg, selector, 
                    164:                            (selector << 4), 0xffff, 0);
                    165: }
                    166: 
                    167: static inline void get_ss_esp_from_tss(uint32_t *ss_ptr, 
                    168:                                        uint32_t *esp_ptr, int dpl)
                    169: {
                    170:     int type, index, shift;
                    171:     
                    172: #if 0
                    173:     {
                    174:         int i;
                    175:         printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
                    176:         for(i=0;i<env->tr.limit;i++) {
                    177:             printf("%02x ", env->tr.base[i]);
                    178:             if ((i & 7) == 7) printf("\n");
                    179:         }
                    180:         printf("\n");
                    181:     }
                    182: #endif
                    183: 
                    184:     if (!(env->tr.flags & DESC_P_MASK))
                    185:         cpu_abort(env, "invalid tss");
                    186:     type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
                    187:     if ((type & 7) != 1)
                    188:         cpu_abort(env, "invalid tss type");
                    189:     shift = type >> 3;
                    190:     index = (dpl * 4 + 2) << shift;
                    191:     if (index + (4 << shift) - 1 > env->tr.limit)
                    192:         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
                    193:     if (shift == 0) {
                    194:         *esp_ptr = lduw_kernel(env->tr.base + index);
                    195:         *ss_ptr = lduw_kernel(env->tr.base + index + 2);
                    196:     } else {
                    197:         *esp_ptr = ldl_kernel(env->tr.base + index);
                    198:         *ss_ptr = lduw_kernel(env->tr.base + index + 4);
                    199:     }
                    200: }
                    201: 
                    202: /* XXX: merge with load_seg() */
                    203: static void tss_load_seg(int seg_reg, int selector)
                    204: {
                    205:     uint32_t e1, e2;
                    206:     int rpl, dpl, cpl;
                    207: 
                    208:     if ((selector & 0xfffc) != 0) {
                    209:         if (load_segment(&e1, &e2, selector) != 0)
                    210:             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    211:         if (!(e2 & DESC_S_MASK))
                    212:             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    213:         rpl = selector & 3;
                    214:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    215:         cpl = env->hflags & HF_CPL_MASK;
                    216:         if (seg_reg == R_CS) {
                    217:             if (!(e2 & DESC_CS_MASK))
                    218:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
1.1.1.3 ! root      219:             /* XXX: is it correct ? */
1.1       root      220:             if (dpl != rpl)
                    221:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    222:             if ((e2 & DESC_C_MASK) && dpl > rpl)
                    223:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    224:         } else if (seg_reg == R_SS) {
                    225:             /* SS must be writable data */
                    226:             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
                    227:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    228:             if (dpl != cpl || dpl != rpl)
                    229:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    230:         } else {
                    231:             /* not readable code */
                    232:             if ((e2 & DESC_CS_MASK) && !(e2 & DESC_R_MASK))
                    233:                 raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    234:             /* if data or non conforming code, checks the rights */
                    235:             if (((e2 >> DESC_TYPE_SHIFT) & 0xf) < 12) {
                    236:                 if (dpl < cpl || dpl < rpl)
                    237:                     raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    238:             }
                    239:         }
                    240:         if (!(e2 & DESC_P_MASK))
                    241:             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                    242:         cpu_x86_load_seg_cache(env, seg_reg, selector, 
                    243:                        get_seg_base(e1, e2),
                    244:                        get_seg_limit(e1, e2),
                    245:                        e2);
                    246:     } else {
                    247:         if (seg_reg == R_SS || seg_reg == R_CS) 
                    248:             raise_exception_err(EXCP0A_TSS, selector & 0xfffc);
                    249:     }
                    250: }
                    251: 
                    252: #define SWITCH_TSS_JMP  0
                    253: #define SWITCH_TSS_IRET 1
                    254: #define SWITCH_TSS_CALL 2
                    255: 
                    256: /* XXX: restore CPU state in registers (PowerPC case) */
                    257: static void switch_tss(int tss_selector, 
                    258:                        uint32_t e1, uint32_t e2, int source,
                    259:                        uint32_t next_eip)
                    260: {
                    261:     int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
                    262:     target_ulong tss_base;
                    263:     uint32_t new_regs[8], new_segs[6];
                    264:     uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
                    265:     uint32_t old_eflags, eflags_mask;
                    266:     SegmentCache *dt;
                    267:     int index;
                    268:     target_ulong ptr;
                    269: 
                    270:     type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                    271: #ifdef DEBUG_PCALL
                    272:     if (loglevel & CPU_LOG_PCALL)
                    273:         fprintf(logfile, "switch_tss: sel=0x%04x type=%d src=%d\n", tss_selector, type, source);
                    274: #endif
                    275: 
                    276:     /* if task gate, we read the TSS segment and we load it */
                    277:     if (type == 5) {
                    278:         if (!(e2 & DESC_P_MASK))
                    279:             raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
                    280:         tss_selector = e1 >> 16;
                    281:         if (tss_selector & 4)
                    282:             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                    283:         if (load_segment(&e1, &e2, tss_selector) != 0)
                    284:             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
                    285:         if (e2 & DESC_S_MASK)
                    286:             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
                    287:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                    288:         if ((type & 7) != 1)
                    289:             raise_exception_err(EXCP0D_GPF, tss_selector & 0xfffc);
                    290:     }
                    291: 
                    292:     if (!(e2 & DESC_P_MASK))
                    293:         raise_exception_err(EXCP0B_NOSEG, tss_selector & 0xfffc);
                    294: 
                    295:     if (type & 8)
                    296:         tss_limit_max = 103;
                    297:     else
                    298:         tss_limit_max = 43;
                    299:     tss_limit = get_seg_limit(e1, e2);
                    300:     tss_base = get_seg_base(e1, e2);
                    301:     if ((tss_selector & 4) != 0 || 
                    302:         tss_limit < tss_limit_max)
                    303:         raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                    304:     old_type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
                    305:     if (old_type & 8)
                    306:         old_tss_limit_max = 103;
                    307:     else
                    308:         old_tss_limit_max = 43;
                    309: 
                    310:     /* read all the registers from the new TSS */
                    311:     if (type & 8) {
                    312:         /* 32 bit */
                    313:         new_cr3 = ldl_kernel(tss_base + 0x1c);
                    314:         new_eip = ldl_kernel(tss_base + 0x20);
                    315:         new_eflags = ldl_kernel(tss_base + 0x24);
                    316:         for(i = 0; i < 8; i++)
                    317:             new_regs[i] = ldl_kernel(tss_base + (0x28 + i * 4));
                    318:         for(i = 0; i < 6; i++)
                    319:             new_segs[i] = lduw_kernel(tss_base + (0x48 + i * 4));
                    320:         new_ldt = lduw_kernel(tss_base + 0x60);
                    321:         new_trap = ldl_kernel(tss_base + 0x64);
                    322:     } else {
                    323:         /* 16 bit */
                    324:         new_cr3 = 0;
                    325:         new_eip = lduw_kernel(tss_base + 0x0e);
                    326:         new_eflags = lduw_kernel(tss_base + 0x10);
                    327:         for(i = 0; i < 8; i++)
                    328:             new_regs[i] = lduw_kernel(tss_base + (0x12 + i * 2)) | 0xffff0000;
                    329:         for(i = 0; i < 4; i++)
                    330:             new_segs[i] = lduw_kernel(tss_base + (0x22 + i * 4));
                    331:         new_ldt = lduw_kernel(tss_base + 0x2a);
                    332:         new_segs[R_FS] = 0;
                    333:         new_segs[R_GS] = 0;
                    334:         new_trap = 0;
                    335:     }
                    336:     
                    337:     /* NOTE: we must avoid memory exceptions during the task switch,
                    338:        so we make dummy accesses before */
                    339:     /* XXX: it can still fail in some cases, so a bigger hack is
                    340:        necessary to valid the TLB after having done the accesses */
                    341: 
                    342:     v1 = ldub_kernel(env->tr.base);
1.1.1.2   root      343:     v2 = ldub_kernel(env->tr.base + old_tss_limit_max);
1.1       root      344:     stb_kernel(env->tr.base, v1);
                    345:     stb_kernel(env->tr.base + old_tss_limit_max, v2);
                    346:     
                    347:     /* clear busy bit (it is restartable) */
                    348:     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
                    349:         target_ulong ptr;
                    350:         uint32_t e2;
                    351:         ptr = env->gdt.base + (env->tr.selector & ~7);
                    352:         e2 = ldl_kernel(ptr + 4);
                    353:         e2 &= ~DESC_TSS_BUSY_MASK;
                    354:         stl_kernel(ptr + 4, e2);
                    355:     }
                    356:     old_eflags = compute_eflags();
                    357:     if (source == SWITCH_TSS_IRET)
                    358:         old_eflags &= ~NT_MASK;
                    359:     
                    360:     /* save the current state in the old TSS */
                    361:     if (type & 8) {
                    362:         /* 32 bit */
                    363:         stl_kernel(env->tr.base + 0x20, next_eip);
                    364:         stl_kernel(env->tr.base + 0x24, old_eflags);
                    365:         stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
                    366:         stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
                    367:         stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
                    368:         stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
                    369:         stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
                    370:         stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
                    371:         stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
                    372:         stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
                    373:         for(i = 0; i < 6; i++)
                    374:             stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
                    375:     } else {
                    376:         /* 16 bit */
                    377:         stw_kernel(env->tr.base + 0x0e, next_eip);
                    378:         stw_kernel(env->tr.base + 0x10, old_eflags);
                    379:         stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
                    380:         stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
                    381:         stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
                    382:         stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
                    383:         stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
                    384:         stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
                    385:         stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
                    386:         stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
                    387:         for(i = 0; i < 4; i++)
                    388:             stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
                    389:     }
                    390:     
                    391:     /* now if an exception occurs, it will occurs in the next task
                    392:        context */
                    393: 
                    394:     if (source == SWITCH_TSS_CALL) {
                    395:         stw_kernel(tss_base, env->tr.selector);
                    396:         new_eflags |= NT_MASK;
                    397:     }
                    398: 
                    399:     /* set busy bit */
                    400:     if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
                    401:         target_ulong ptr;
                    402:         uint32_t e2;
                    403:         ptr = env->gdt.base + (tss_selector & ~7);
                    404:         e2 = ldl_kernel(ptr + 4);
                    405:         e2 |= DESC_TSS_BUSY_MASK;
                    406:         stl_kernel(ptr + 4, e2);
                    407:     }
                    408: 
                    409:     /* set the new CPU state */
                    410:     /* from this point, any exception which occurs can give problems */
                    411:     env->cr[0] |= CR0_TS_MASK;
                    412:     env->hflags |= HF_TS_MASK;
                    413:     env->tr.selector = tss_selector;
                    414:     env->tr.base = tss_base;
                    415:     env->tr.limit = tss_limit;
                    416:     env->tr.flags = e2 & ~DESC_TSS_BUSY_MASK;
                    417:     
                    418:     if ((type & 8) && (env->cr[0] & CR0_PG_MASK)) {
                    419:         cpu_x86_update_cr3(env, new_cr3);
                    420:     }
                    421:     
                    422:     /* load all registers without an exception, then reload them with
                    423:        possible exception */
                    424:     env->eip = new_eip;
                    425:     eflags_mask = TF_MASK | AC_MASK | ID_MASK | 
                    426:         IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK;
                    427:     if (!(type & 8))
                    428:         eflags_mask &= 0xffff;
                    429:     load_eflags(new_eflags, eflags_mask);
                    430:     /* XXX: what to do in 16 bit case ? */
                    431:     EAX = new_regs[0];
                    432:     ECX = new_regs[1];
                    433:     EDX = new_regs[2];
                    434:     EBX = new_regs[3];
                    435:     ESP = new_regs[4];
                    436:     EBP = new_regs[5];
                    437:     ESI = new_regs[6];
                    438:     EDI = new_regs[7];
                    439:     if (new_eflags & VM_MASK) {
                    440:         for(i = 0; i < 6; i++) 
                    441:             load_seg_vm(i, new_segs[i]);
                    442:         /* in vm86, CPL is always 3 */
                    443:         cpu_x86_set_cpl(env, 3);
                    444:     } else {
                    445:         /* CPL is set the RPL of CS */
                    446:         cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
                    447:         /* first just selectors as the rest may trigger exceptions */
                    448:         for(i = 0; i < 6; i++)
                    449:             cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
                    450:     }
                    451:     
                    452:     env->ldt.selector = new_ldt & ~4;
                    453:     env->ldt.base = 0;
                    454:     env->ldt.limit = 0;
                    455:     env->ldt.flags = 0;
                    456: 
                    457:     /* load the LDT */
                    458:     if (new_ldt & 4)
                    459:         raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
                    460: 
                    461:     if ((new_ldt & 0xfffc) != 0) {
                    462:         dt = &env->gdt;
                    463:         index = new_ldt & ~7;
                    464:         if ((index + 7) > dt->limit)
                    465:             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
                    466:         ptr = dt->base + index;
                    467:         e1 = ldl_kernel(ptr);
                    468:         e2 = ldl_kernel(ptr + 4);
                    469:         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
                    470:             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
                    471:         if (!(e2 & DESC_P_MASK))
                    472:             raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc);
                    473:         load_seg_cache_raw_dt(&env->ldt, e1, e2);
                    474:     }
                    475:     
                    476:     /* load the segments */
                    477:     if (!(new_eflags & VM_MASK)) {
                    478:         tss_load_seg(R_CS, new_segs[R_CS]);
                    479:         tss_load_seg(R_SS, new_segs[R_SS]);
                    480:         tss_load_seg(R_ES, new_segs[R_ES]);
                    481:         tss_load_seg(R_DS, new_segs[R_DS]);
                    482:         tss_load_seg(R_FS, new_segs[R_FS]);
                    483:         tss_load_seg(R_GS, new_segs[R_GS]);
                    484:     }
                    485:     
                    486:     /* check that EIP is in the CS segment limits */
                    487:     if (new_eip > env->segs[R_CS].limit) {
                    488:         /* XXX: different exception if CALL ? */
                    489:         raise_exception_err(EXCP0D_GPF, 0);
                    490:     }
                    491: }
                    492: 
                    493: /* check if Port I/O is allowed in TSS */
                    494: static inline void check_io(int addr, int size)
                    495: {
                    496:     int io_offset, val, mask;
                    497:     
                    498:     /* TSS must be a valid 32 bit one */
                    499:     if (!(env->tr.flags & DESC_P_MASK) ||
                    500:         ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
                    501:         env->tr.limit < 103)
                    502:         goto fail;
                    503:     io_offset = lduw_kernel(env->tr.base + 0x66);
                    504:     io_offset += (addr >> 3);
                    505:     /* Note: the check needs two bytes */
                    506:     if ((io_offset + 1) > env->tr.limit)
                    507:         goto fail;
                    508:     val = lduw_kernel(env->tr.base + io_offset);
                    509:     val >>= (addr & 7);
                    510:     mask = (1 << size) - 1;
                    511:     /* all bits must be zero to allow the I/O */
                    512:     if ((val & mask) != 0) {
                    513:     fail:
                    514:         raise_exception_err(EXCP0D_GPF, 0);
                    515:     }
                    516: }
                    517: 
                    518: void check_iob_T0(void)
                    519: {
                    520:     check_io(T0, 1);
                    521: }
                    522: 
                    523: void check_iow_T0(void)
                    524: {
                    525:     check_io(T0, 2);
                    526: }
                    527: 
                    528: void check_iol_T0(void)
                    529: {
                    530:     check_io(T0, 4);
                    531: }
                    532: 
                    533: void check_iob_DX(void)
                    534: {
                    535:     check_io(EDX & 0xffff, 1);
                    536: }
                    537: 
                    538: void check_iow_DX(void)
                    539: {
                    540:     check_io(EDX & 0xffff, 2);
                    541: }
                    542: 
                    543: void check_iol_DX(void)
                    544: {
                    545:     check_io(EDX & 0xffff, 4);
                    546: }
                    547: 
                    548: static inline unsigned int get_sp_mask(unsigned int e2)
                    549: {
                    550:     if (e2 & DESC_B_MASK)
                    551:         return 0xffffffff;
                    552:     else
                    553:         return 0xffff;
                    554: }
                    555: 
                    556: /* XXX: add a is_user flag to have proper security support */
                    557: #define PUSHW(ssp, sp, sp_mask, val)\
                    558: {\
                    559:     sp -= 2;\
                    560:     stw_kernel((ssp) + (sp & (sp_mask)), (val));\
                    561: }
                    562: 
                    563: #define PUSHL(ssp, sp, sp_mask, val)\
                    564: {\
                    565:     sp -= 4;\
                    566:     stl_kernel((ssp) + (sp & (sp_mask)), (val));\
                    567: }
                    568: 
                    569: #define POPW(ssp, sp, sp_mask, val)\
                    570: {\
                    571:     val = lduw_kernel((ssp) + (sp & (sp_mask)));\
                    572:     sp += 2;\
                    573: }
                    574: 
                    575: #define POPL(ssp, sp, sp_mask, val)\
                    576: {\
                    577:     val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
                    578:     sp += 4;\
                    579: }
                    580: 
                    581: /* protected mode interrupt */
                    582: static void do_interrupt_protected(int intno, int is_int, int error_code,
                    583:                                    unsigned int next_eip, int is_hw)
                    584: {
                    585:     SegmentCache *dt;
                    586:     target_ulong ptr, ssp;
                    587:     int type, dpl, selector, ss_dpl, cpl, sp_mask;
                    588:     int has_error_code, new_stack, shift;
                    589:     uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
                    590:     uint32_t old_eip;
                    591: 
                    592:     has_error_code = 0;
                    593:     if (!is_int && !is_hw) {
                    594:         switch(intno) {
                    595:         case 8:
                    596:         case 10:
                    597:         case 11:
                    598:         case 12:
                    599:         case 13:
                    600:         case 14:
                    601:         case 17:
                    602:             has_error_code = 1;
                    603:             break;
                    604:         }
                    605:     }
                    606:     if (is_int)
                    607:         old_eip = next_eip;
                    608:     else
                    609:         old_eip = env->eip;
                    610: 
                    611:     dt = &env->idt;
                    612:     if (intno * 8 + 7 > dt->limit)
                    613:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                    614:     ptr = dt->base + intno * 8;
                    615:     e1 = ldl_kernel(ptr);
                    616:     e2 = ldl_kernel(ptr + 4);
                    617:     /* check gate type */
                    618:     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
                    619:     switch(type) {
                    620:     case 5: /* task gate */
                    621:         /* must do that check here to return the correct error code */
                    622:         if (!(e2 & DESC_P_MASK))
                    623:             raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
                    624:         switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
                    625:         if (has_error_code) {
                    626:             int mask, type;
                    627:             /* push the error code */
                    628:             type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
                    629:             shift = type >> 3;
                    630:             if (env->segs[R_SS].flags & DESC_B_MASK)
                    631:                 mask = 0xffffffff;
                    632:             else
                    633:                 mask = 0xffff;
                    634:             esp = (ESP - (2 << shift)) & mask;
                    635:             ssp = env->segs[R_SS].base + esp;
                    636:             if (shift)
                    637:                 stl_kernel(ssp, error_code);
                    638:             else
                    639:                 stw_kernel(ssp, error_code);
                    640:             ESP = (esp & mask) | (ESP & ~mask);
                    641:         }
                    642:         return;
                    643:     case 6: /* 286 interrupt gate */
                    644:     case 7: /* 286 trap gate */
                    645:     case 14: /* 386 interrupt gate */
                    646:     case 15: /* 386 trap gate */
                    647:         break;
                    648:     default:
                    649:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                    650:         break;
                    651:     }
                    652:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    653:     cpl = env->hflags & HF_CPL_MASK;
                    654:     /* check privledge if software int */
                    655:     if (is_int && dpl < cpl)
                    656:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                    657:     /* check valid bit */
                    658:     if (!(e2 & DESC_P_MASK))
                    659:         raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
                    660:     selector = e1 >> 16;
                    661:     offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
                    662:     if ((selector & 0xfffc) == 0)
                    663:         raise_exception_err(EXCP0D_GPF, 0);
                    664: 
                    665:     if (load_segment(&e1, &e2, selector) != 0)
                    666:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    667:     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
                    668:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    669:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    670:     if (dpl > cpl)
                    671:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    672:     if (!(e2 & DESC_P_MASK))
                    673:         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                    674:     if (!(e2 & DESC_C_MASK) && dpl < cpl) {
                    675:         /* to inner priviledge */
                    676:         get_ss_esp_from_tss(&ss, &esp, dpl);
                    677:         if ((ss & 0xfffc) == 0)
                    678:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    679:         if ((ss & 3) != dpl)
                    680:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    681:         if (load_segment(&ss_e1, &ss_e2, ss) != 0)
                    682:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    683:         ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
                    684:         if (ss_dpl != dpl)
                    685:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    686:         if (!(ss_e2 & DESC_S_MASK) ||
                    687:             (ss_e2 & DESC_CS_MASK) ||
                    688:             !(ss_e2 & DESC_W_MASK))
                    689:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    690:         if (!(ss_e2 & DESC_P_MASK))
                    691:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    692:         new_stack = 1;
                    693:         sp_mask = get_sp_mask(ss_e2);
                    694:         ssp = get_seg_base(ss_e1, ss_e2);
                    695:     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
                    696:         /* to same priviledge */
                    697:         if (env->eflags & VM_MASK)
                    698:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    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;
                    703:         dpl = cpl;
                    704:     } else {
                    705:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    706:         new_stack = 0; /* avoid warning */
                    707:         sp_mask = 0; /* avoid warning */
                    708:         ssp = 0; /* avoid warning */
                    709:         esp = 0; /* avoid warning */
                    710:     }
                    711: 
                    712:     shift = type >> 3;
                    713: 
                    714: #if 0
                    715:     /* XXX: check that enough room is available */
                    716:     push_size = 6 + (new_stack << 2) + (has_error_code << 1);
                    717:     if (env->eflags & VM_MASK)
                    718:         push_size += 8;
                    719:     push_size <<= shift;
                    720: #endif
                    721:     if (shift == 1) {
                    722:         if (new_stack) {
                    723:             if (env->eflags & VM_MASK) {
                    724:                 PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
                    725:                 PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
                    726:                 PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
                    727:                 PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
                    728:             }
                    729:             PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
                    730:             PUSHL(ssp, esp, sp_mask, ESP);
                    731:         }
                    732:         PUSHL(ssp, esp, sp_mask, compute_eflags());
                    733:         PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
                    734:         PUSHL(ssp, esp, sp_mask, old_eip);
                    735:         if (has_error_code) {
                    736:             PUSHL(ssp, esp, sp_mask, error_code);
                    737:         }
                    738:     } else {
                    739:         if (new_stack) {
                    740:             if (env->eflags & VM_MASK) {
                    741:                 PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
                    742:                 PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
                    743:                 PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
                    744:                 PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
                    745:             }
                    746:             PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
                    747:             PUSHW(ssp, esp, sp_mask, ESP);
                    748:         }
                    749:         PUSHW(ssp, esp, sp_mask, compute_eflags());
                    750:         PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
                    751:         PUSHW(ssp, esp, sp_mask, old_eip);
                    752:         if (has_error_code) {
                    753:             PUSHW(ssp, esp, sp_mask, error_code);
                    754:         }
                    755:     }
                    756:     
                    757:     if (new_stack) {
                    758:         if (env->eflags & VM_MASK) {
                    759:             cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
                    760:             cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
                    761:             cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
                    762:             cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
                    763:         }
                    764:         ss = (ss & ~3) | dpl;
                    765:         cpu_x86_load_seg_cache(env, R_SS, ss, 
                    766:                                ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
                    767:     }
                    768:     ESP = (ESP & ~sp_mask) | (esp & sp_mask);
                    769: 
                    770:     selector = (selector & ~3) | dpl;
                    771:     cpu_x86_load_seg_cache(env, R_CS, selector, 
                    772:                    get_seg_base(e1, e2),
                    773:                    get_seg_limit(e1, e2),
                    774:                    e2);
                    775:     cpu_x86_set_cpl(env, dpl);
                    776:     env->eip = offset;
                    777: 
                    778:     /* interrupt gate clear IF mask */
                    779:     if ((type & 1) == 0) {
                    780:         env->eflags &= ~IF_MASK;
                    781:     }
                    782:     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
                    783: }
                    784: 
                    785: #ifdef TARGET_X86_64
                    786: 
                    787: #define PUSHQ(sp, val)\
                    788: {\
                    789:     sp -= 8;\
                    790:     stq_kernel(sp, (val));\
                    791: }
                    792: 
                    793: #define POPQ(sp, val)\
                    794: {\
                    795:     val = ldq_kernel(sp);\
                    796:     sp += 8;\
                    797: }
                    798: 
                    799: static inline target_ulong get_rsp_from_tss(int level)
                    800: {
                    801:     int index;
                    802:     
                    803: #if 0
                    804:     printf("TR: base=" TARGET_FMT_lx " limit=%x\n", 
                    805:            env->tr.base, env->tr.limit);
                    806: #endif
                    807: 
                    808:     if (!(env->tr.flags & DESC_P_MASK))
                    809:         cpu_abort(env, "invalid tss");
                    810:     index = 8 * level + 4;
                    811:     if ((index + 7) > env->tr.limit)
                    812:         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
                    813:     return ldq_kernel(env->tr.base + index);
                    814: }
                    815: 
                    816: /* 64 bit interrupt */
                    817: static void do_interrupt64(int intno, int is_int, int error_code,
                    818:                            target_ulong next_eip, int is_hw)
                    819: {
                    820:     SegmentCache *dt;
                    821:     target_ulong ptr;
                    822:     int type, dpl, selector, cpl, ist;
                    823:     int has_error_code, new_stack;
                    824:     uint32_t e1, e2, e3, ss;
                    825:     target_ulong old_eip, esp, offset;
                    826: 
                    827:     has_error_code = 0;
                    828:     if (!is_int && !is_hw) {
                    829:         switch(intno) {
                    830:         case 8:
                    831:         case 10:
                    832:         case 11:
                    833:         case 12:
                    834:         case 13:
                    835:         case 14:
                    836:         case 17:
                    837:             has_error_code = 1;
                    838:             break;
                    839:         }
                    840:     }
                    841:     if (is_int)
                    842:         old_eip = next_eip;
                    843:     else
                    844:         old_eip = env->eip;
                    845: 
                    846:     dt = &env->idt;
                    847:     if (intno * 16 + 15 > dt->limit)
                    848:         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
                    849:     ptr = dt->base + intno * 16;
                    850:     e1 = ldl_kernel(ptr);
                    851:     e2 = ldl_kernel(ptr + 4);
                    852:     e3 = ldl_kernel(ptr + 8);
                    853:     /* check gate type */
                    854:     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
                    855:     switch(type) {
                    856:     case 14: /* 386 interrupt gate */
                    857:     case 15: /* 386 trap gate */
                    858:         break;
                    859:     default:
                    860:         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
                    861:         break;
                    862:     }
                    863:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    864:     cpl = env->hflags & HF_CPL_MASK;
                    865:     /* check privledge if software int */
                    866:     if (is_int && dpl < cpl)
                    867:         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
                    868:     /* check valid bit */
                    869:     if (!(e2 & DESC_P_MASK))
                    870:         raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
                    871:     selector = e1 >> 16;
                    872:     offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
                    873:     ist = e2 & 7;
                    874:     if ((selector & 0xfffc) == 0)
                    875:         raise_exception_err(EXCP0D_GPF, 0);
                    876: 
                    877:     if (load_segment(&e1, &e2, selector) != 0)
                    878:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    879:     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
                    880:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    881:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    882:     if (dpl > cpl)
                    883:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    884:     if (!(e2 & DESC_P_MASK))
                    885:         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                    886:     if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
                    887:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    888:     if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
                    889:         /* to inner priviledge */
                    890:         if (ist != 0)
                    891:             esp = get_rsp_from_tss(ist + 3);
                    892:         else
                    893:             esp = get_rsp_from_tss(dpl);
1.1.1.3 ! root      894:         esp &= ~0xfLL; /* align stack */
1.1       root      895:         ss = 0;
                    896:         new_stack = 1;
                    897:     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
                    898:         /* to same priviledge */
                    899:         if (env->eflags & VM_MASK)
                    900:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    901:         new_stack = 0;
1.1.1.3 ! root      902:         if (ist != 0)
        !           903:             esp = get_rsp_from_tss(ist + 3);
        !           904:         else
        !           905:             esp = ESP;
        !           906:         esp &= ~0xfLL; /* align stack */
1.1       root      907:         dpl = cpl;
                    908:     } else {
                    909:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    910:         new_stack = 0; /* avoid warning */
                    911:         esp = 0; /* avoid warning */
                    912:     }
                    913: 
                    914:     PUSHQ(esp, env->segs[R_SS].selector);
                    915:     PUSHQ(esp, ESP);
                    916:     PUSHQ(esp, compute_eflags());
                    917:     PUSHQ(esp, env->segs[R_CS].selector);
                    918:     PUSHQ(esp, old_eip);
                    919:     if (has_error_code) {
                    920:         PUSHQ(esp, error_code);
                    921:     }
                    922:     
                    923:     if (new_stack) {
                    924:         ss = 0 | dpl;
                    925:         cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
                    926:     }
                    927:     ESP = esp;
                    928: 
                    929:     selector = (selector & ~3) | dpl;
                    930:     cpu_x86_load_seg_cache(env, R_CS, selector, 
                    931:                    get_seg_base(e1, e2),
                    932:                    get_seg_limit(e1, e2),
                    933:                    e2);
                    934:     cpu_x86_set_cpl(env, dpl);
                    935:     env->eip = offset;
                    936: 
                    937:     /* interrupt gate clear IF mask */
                    938:     if ((type & 1) == 0) {
                    939:         env->eflags &= ~IF_MASK;
                    940:     }
                    941:     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
                    942: }
                    943: #endif
                    944: 
                    945: void helper_syscall(int next_eip_addend)
                    946: {
                    947:     int selector;
                    948: 
                    949:     if (!(env->efer & MSR_EFER_SCE)) {
                    950:         raise_exception_err(EXCP06_ILLOP, 0);
                    951:     }
                    952:     selector = (env->star >> 32) & 0xffff;
                    953: #ifdef TARGET_X86_64
                    954:     if (env->hflags & HF_LMA_MASK) {
1.1.1.3 ! root      955:         int code64;
        !           956: 
1.1       root      957:         ECX = env->eip + next_eip_addend;
                    958:         env->regs[11] = compute_eflags();
1.1.1.3 ! root      959:         
        !           960:         code64 = env->hflags & HF_CS64_MASK;
1.1       root      961: 
                    962:         cpu_x86_set_cpl(env, 0);
                    963:         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
                    964:                            0, 0xffffffff, 
                    965:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                    966:                                DESC_S_MASK |
                    967:                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
                    968:         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
                    969:                                0, 0xffffffff,
                    970:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                    971:                                DESC_S_MASK |
                    972:                                DESC_W_MASK | DESC_A_MASK);
                    973:         env->eflags &= ~env->fmask;
1.1.1.3 ! root      974:         if (code64)
1.1       root      975:             env->eip = env->lstar;
                    976:         else
                    977:             env->eip = env->cstar;
                    978:     } else 
                    979: #endif
                    980:     {
                    981:         ECX = (uint32_t)(env->eip + next_eip_addend);
                    982:         
                    983:         cpu_x86_set_cpl(env, 0);
                    984:         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
                    985:                            0, 0xffffffff, 
                    986:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                    987:                                DESC_S_MASK |
                    988:                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                    989:         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
                    990:                                0, 0xffffffff,
                    991:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                    992:                                DESC_S_MASK |
                    993:                                DESC_W_MASK | DESC_A_MASK);
                    994:         env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
                    995:         env->eip = (uint32_t)env->star;
                    996:     }
                    997: }
                    998: 
                    999: void helper_sysret(int dflag)
                   1000: {
                   1001:     int cpl, selector;
                   1002: 
                   1003:     if (!(env->efer & MSR_EFER_SCE)) {
                   1004:         raise_exception_err(EXCP06_ILLOP, 0);
                   1005:     }
                   1006:     cpl = env->hflags & HF_CPL_MASK;
                   1007:     if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
                   1008:         raise_exception_err(EXCP0D_GPF, 0);
                   1009:     }
                   1010:     selector = (env->star >> 48) & 0xffff;
                   1011: #ifdef TARGET_X86_64
                   1012:     if (env->hflags & HF_LMA_MASK) {
                   1013:         if (dflag == 2) {
                   1014:             cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, 
                   1015:                                    0, 0xffffffff, 
                   1016:                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1017:                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1018:                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | 
                   1019:                                    DESC_L_MASK);
                   1020:             env->eip = ECX;
                   1021:         } else {
                   1022:             cpu_x86_load_seg_cache(env, R_CS, selector | 3, 
                   1023:                                    0, 0xffffffff, 
                   1024:                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1025:                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1026:                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                   1027:             env->eip = (uint32_t)ECX;
                   1028:         }
                   1029:         cpu_x86_load_seg_cache(env, R_SS, selector + 8, 
                   1030:                                0, 0xffffffff,
                   1031:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1032:                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1033:                                DESC_W_MASK | DESC_A_MASK);
                   1034:         load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK | 
                   1035:                     IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
                   1036:         cpu_x86_set_cpl(env, 3);
                   1037:     } else 
                   1038: #endif
                   1039:     {
                   1040:         cpu_x86_load_seg_cache(env, R_CS, selector | 3, 
                   1041:                                0, 0xffffffff, 
                   1042:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1043:                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1044:                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                   1045:         env->eip = (uint32_t)ECX;
                   1046:         cpu_x86_load_seg_cache(env, R_SS, selector + 8, 
                   1047:                                0, 0xffffffff,
                   1048:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1049:                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1050:                                DESC_W_MASK | DESC_A_MASK);
                   1051:         env->eflags |= IF_MASK;
                   1052:         cpu_x86_set_cpl(env, 3);
                   1053:     }
                   1054: #ifdef USE_KQEMU
                   1055:     if (kqemu_is_ok(env)) {
                   1056:         if (env->hflags & HF_LMA_MASK)
                   1057:             CC_OP = CC_OP_EFLAGS;
                   1058:         env->exception_index = -1;
                   1059:         cpu_loop_exit();
                   1060:     }
                   1061: #endif
                   1062: }
                   1063: 
                   1064: /* real mode interrupt */
                   1065: static void do_interrupt_real(int intno, int is_int, int error_code,
                   1066:                               unsigned int next_eip)
                   1067: {
                   1068:     SegmentCache *dt;
                   1069:     target_ulong ptr, ssp;
                   1070:     int selector;
                   1071:     uint32_t offset, esp;
                   1072:     uint32_t old_cs, old_eip;
                   1073: 
                   1074:     /* real mode (simpler !) */
                   1075:     dt = &env->idt;
                   1076:     if (intno * 4 + 3 > dt->limit)
                   1077:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                   1078:     ptr = dt->base + intno * 4;
                   1079:     offset = lduw_kernel(ptr);
                   1080:     selector = lduw_kernel(ptr + 2);
                   1081:     esp = ESP;
                   1082:     ssp = env->segs[R_SS].base;
                   1083:     if (is_int)
                   1084:         old_eip = next_eip;
                   1085:     else
                   1086:         old_eip = env->eip;
                   1087:     old_cs = env->segs[R_CS].selector;
                   1088:     /* XXX: use SS segment size ? */
                   1089:     PUSHW(ssp, esp, 0xffff, compute_eflags());
                   1090:     PUSHW(ssp, esp, 0xffff, old_cs);
                   1091:     PUSHW(ssp, esp, 0xffff, old_eip);
                   1092:     
                   1093:     /* update processor state */
                   1094:     ESP = (ESP & ~0xffff) | (esp & 0xffff);
                   1095:     env->eip = offset;
                   1096:     env->segs[R_CS].selector = selector;
                   1097:     env->segs[R_CS].base = (selector << 4);
                   1098:     env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
                   1099: }
                   1100: 
                   1101: /* fake user mode interrupt */
                   1102: void do_interrupt_user(int intno, int is_int, int error_code, 
                   1103:                        target_ulong next_eip)
                   1104: {
                   1105:     SegmentCache *dt;
                   1106:     target_ulong ptr;
                   1107:     int dpl, cpl;
                   1108:     uint32_t e2;
                   1109: 
                   1110:     dt = &env->idt;
                   1111:     ptr = dt->base + (intno * 8);
                   1112:     e2 = ldl_kernel(ptr + 4);
                   1113:     
                   1114:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1115:     cpl = env->hflags & HF_CPL_MASK;
                   1116:     /* check privledge if software int */
                   1117:     if (is_int && dpl < cpl)
                   1118:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                   1119: 
                   1120:     /* Since we emulate only user space, we cannot do more than
                   1121:        exiting the emulation with the suitable exception and error
                   1122:        code */
                   1123:     if (is_int)
                   1124:         EIP = next_eip;
                   1125: }
                   1126: 
                   1127: /*
                   1128:  * Begin execution of an interruption. is_int is TRUE if coming from
                   1129:  * the int instruction. next_eip is the EIP value AFTER the interrupt
                   1130:  * instruction. It is only relevant if is_int is TRUE.  
                   1131:  */
                   1132: void do_interrupt(int intno, int is_int, int error_code, 
                   1133:                   target_ulong next_eip, int is_hw)
                   1134: {
1.1.1.3 ! root     1135:     if (loglevel & CPU_LOG_INT) {
1.1       root     1136:         if ((env->cr[0] & CR0_PE_MASK)) {
                   1137:             static int count;
                   1138:             fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
                   1139:                     count, intno, error_code, is_int,
                   1140:                     env->hflags & HF_CPL_MASK,
                   1141:                     env->segs[R_CS].selector, EIP,
                   1142:                     (int)env->segs[R_CS].base + EIP,
                   1143:                     env->segs[R_SS].selector, ESP);
                   1144:             if (intno == 0x0e) {
                   1145:                 fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
                   1146:             } else {
                   1147:                 fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
                   1148:             }
                   1149:             fprintf(logfile, "\n");
                   1150:             cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1.1.1.3 ! root     1151: #if 0
1.1       root     1152:             {
                   1153:                 int i;
                   1154:                 uint8_t *ptr;
                   1155:                 fprintf(logfile, "       code=");
                   1156:                 ptr = env->segs[R_CS].base + env->eip;
                   1157:                 for(i = 0; i < 16; i++) {
                   1158:                     fprintf(logfile, " %02x", ldub(ptr + i));
                   1159:                 }
                   1160:                 fprintf(logfile, "\n");
                   1161:             }
                   1162: #endif
                   1163:             count++;
                   1164:         }
                   1165:     }
                   1166:     if (env->cr[0] & CR0_PE_MASK) {
                   1167: #if TARGET_X86_64
                   1168:         if (env->hflags & HF_LMA_MASK) {
                   1169:             do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
                   1170:         } else
                   1171: #endif
                   1172:         {
                   1173:             do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
                   1174:         }
                   1175:     } else {
                   1176:         do_interrupt_real(intno, is_int, error_code, next_eip);
                   1177:     }
                   1178: }
                   1179: 
                   1180: /*
                   1181:  * Signal an interruption. It is executed in the main CPU loop.
                   1182:  * is_int is TRUE if coming from the int instruction. next_eip is the
                   1183:  * EIP value AFTER the interrupt instruction. It is only relevant if
                   1184:  * is_int is TRUE.  
                   1185:  */
                   1186: void raise_interrupt(int intno, int is_int, int error_code, 
                   1187:                      int next_eip_addend)
                   1188: {
                   1189:     env->exception_index = intno;
                   1190:     env->error_code = error_code;
                   1191:     env->exception_is_int = is_int;
                   1192:     env->exception_next_eip = env->eip + next_eip_addend;
                   1193:     cpu_loop_exit();
                   1194: }
                   1195: 
                   1196: /* same as raise_exception_err, but do not restore global registers */
                   1197: static void raise_exception_err_norestore(int exception_index, int error_code)
                   1198: {
                   1199:     env->exception_index = exception_index;
                   1200:     env->error_code = error_code;
                   1201:     env->exception_is_int = 0;
                   1202:     env->exception_next_eip = 0;
                   1203:     longjmp(env->jmp_env, 1);
                   1204: }
                   1205: 
                   1206: /* shortcuts to generate exceptions */
                   1207: 
                   1208: void (raise_exception_err)(int exception_index, int error_code)
                   1209: {
                   1210:     raise_interrupt(exception_index, 0, error_code, 0);
                   1211: }
                   1212: 
                   1213: void raise_exception(int exception_index)
                   1214: {
                   1215:     raise_interrupt(exception_index, 0, 0, 0);
                   1216: }
                   1217: 
                   1218: #ifdef BUGGY_GCC_DIV64
                   1219: /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
                   1220:    call it from another function */
                   1221: uint32_t div32(uint64_t *q_ptr, uint64_t num, uint32_t den)
                   1222: {
                   1223:     *q_ptr = num / den;
                   1224:     return num % den;
                   1225: }
                   1226: 
                   1227: int32_t idiv32(int64_t *q_ptr, int64_t num, int32_t den)
                   1228: {
                   1229:     *q_ptr = num / den;
                   1230:     return num % den;
                   1231: }
                   1232: #endif
                   1233: 
                   1234: void helper_divl_EAX_T0(void)
                   1235: {
                   1236:     unsigned int den, r;
                   1237:     uint64_t num, q;
                   1238:     
                   1239:     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
                   1240:     den = T0;
                   1241:     if (den == 0) {
                   1242:         raise_exception(EXCP00_DIVZ);
                   1243:     }
                   1244: #ifdef BUGGY_GCC_DIV64
                   1245:     r = div32(&q, num, den);
                   1246: #else
                   1247:     q = (num / den);
                   1248:     r = (num % den);
                   1249: #endif
                   1250:     if (q > 0xffffffff)
                   1251:         raise_exception(EXCP00_DIVZ);
                   1252:     EAX = (uint32_t)q;
                   1253:     EDX = (uint32_t)r;
                   1254: }
                   1255: 
                   1256: void helper_idivl_EAX_T0(void)
                   1257: {
                   1258:     int den, r;
                   1259:     int64_t num, q;
                   1260:     
                   1261:     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
                   1262:     den = T0;
                   1263:     if (den == 0) {
                   1264:         raise_exception(EXCP00_DIVZ);
                   1265:     }
                   1266: #ifdef BUGGY_GCC_DIV64
                   1267:     r = idiv32(&q, num, den);
                   1268: #else
                   1269:     q = (num / den);
                   1270:     r = (num % den);
                   1271: #endif
                   1272:     if (q != (int32_t)q)
                   1273:         raise_exception(EXCP00_DIVZ);
                   1274:     EAX = (uint32_t)q;
                   1275:     EDX = (uint32_t)r;
                   1276: }
                   1277: 
                   1278: void helper_cmpxchg8b(void)
                   1279: {
                   1280:     uint64_t d;
                   1281:     int eflags;
                   1282: 
                   1283:     eflags = cc_table[CC_OP].compute_all();
                   1284:     d = ldq(A0);
                   1285:     if (d == (((uint64_t)EDX << 32) | EAX)) {
                   1286:         stq(A0, ((uint64_t)ECX << 32) | EBX);
                   1287:         eflags |= CC_Z;
                   1288:     } else {
                   1289:         EDX = d >> 32;
                   1290:         EAX = d;
                   1291:         eflags &= ~CC_Z;
                   1292:     }
                   1293:     CC_SRC = eflags;
                   1294: }
                   1295: 
                   1296: void helper_cpuid(void)
                   1297: {
                   1298:     uint32_t index;
                   1299:     index = (uint32_t)EAX;
                   1300:     
                   1301:     /* test if maximum index reached */
                   1302:     if (index & 0x80000000) {
                   1303:         if (index > env->cpuid_xlevel) 
                   1304:             index = env->cpuid_level;
                   1305:     } else {
                   1306:         if (index > env->cpuid_level) 
                   1307:             index = env->cpuid_level;
                   1308:     }
                   1309:         
                   1310:     switch(index) {
                   1311:     case 0:
                   1312:         EAX = env->cpuid_level;
                   1313:         EBX = env->cpuid_vendor1;
                   1314:         EDX = env->cpuid_vendor2;
                   1315:         ECX = env->cpuid_vendor3;
                   1316:         break;
                   1317:     case 1:
                   1318:         EAX = env->cpuid_version;
                   1319:         EBX = 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
                   1320:         ECX = env->cpuid_ext_features;
                   1321:         EDX = env->cpuid_features;
                   1322:         break;
                   1323:     case 2:
                   1324:         /* cache info: needed for Pentium Pro compatibility */
                   1325:         EAX = 0x410601;
                   1326:         EBX = 0;
                   1327:         ECX = 0;
                   1328:         EDX = 0;
                   1329:         break;
                   1330:     case 0x80000000:
                   1331:         EAX = env->cpuid_xlevel;
                   1332:         EBX = env->cpuid_vendor1;
                   1333:         EDX = env->cpuid_vendor2;
                   1334:         ECX = env->cpuid_vendor3;
                   1335:         break;
                   1336:     case 0x80000001:
                   1337:         EAX = env->cpuid_features;
                   1338:         EBX = 0;
                   1339:         ECX = 0;
                   1340:         EDX = env->cpuid_ext2_features;
                   1341:         break;
                   1342:     case 0x80000002:
                   1343:     case 0x80000003:
                   1344:     case 0x80000004:
                   1345:         EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
                   1346:         EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
                   1347:         ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
                   1348:         EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
                   1349:         break;
                   1350:     case 0x80000005:
                   1351:         /* cache info (L1 cache) */
                   1352:         EAX = 0x01ff01ff;
                   1353:         EBX = 0x01ff01ff;
                   1354:         ECX = 0x40020140;
                   1355:         EDX = 0x40020140;
                   1356:         break;
                   1357:     case 0x80000006:
                   1358:         /* cache info (L2 cache) */
                   1359:         EAX = 0;
                   1360:         EBX = 0x42004200;
                   1361:         ECX = 0x02008140;
                   1362:         EDX = 0;
                   1363:         break;
                   1364:     case 0x80000008:
                   1365:         /* virtual & phys address size in low 2 bytes. */
                   1366:         EAX = 0x00003028;
                   1367:         EBX = 0;
                   1368:         ECX = 0;
                   1369:         EDX = 0;
                   1370:         break;
                   1371:     default:
                   1372:         /* reserved values: zero */
                   1373:         EAX = 0;
                   1374:         EBX = 0;
                   1375:         ECX = 0;
                   1376:         EDX = 0;
                   1377:         break;
                   1378:     }
                   1379: }
                   1380: 
                   1381: void helper_enter_level(int level, int data32)
                   1382: {
                   1383:     target_ulong ssp;
                   1384:     uint32_t esp_mask, esp, ebp;
                   1385: 
                   1386:     esp_mask = get_sp_mask(env->segs[R_SS].flags);
                   1387:     ssp = env->segs[R_SS].base;
                   1388:     ebp = EBP;
                   1389:     esp = ESP;
                   1390:     if (data32) {
                   1391:         /* 32 bit */
                   1392:         esp -= 4;
                   1393:         while (--level) {
                   1394:             esp -= 4;
                   1395:             ebp -= 4;
                   1396:             stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
                   1397:         }
                   1398:         esp -= 4;
                   1399:         stl(ssp + (esp & esp_mask), T1);
                   1400:     } else {
                   1401:         /* 16 bit */
                   1402:         esp -= 2;
                   1403:         while (--level) {
                   1404:             esp -= 2;
                   1405:             ebp -= 2;
                   1406:             stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
                   1407:         }
                   1408:         esp -= 2;
                   1409:         stw(ssp + (esp & esp_mask), T1);
                   1410:     }
                   1411: }
                   1412: 
                   1413: #ifdef TARGET_X86_64
                   1414: void helper_enter64_level(int level, int data64)
                   1415: {
                   1416:     target_ulong esp, ebp;
                   1417:     ebp = EBP;
                   1418:     esp = ESP;
                   1419: 
                   1420:     if (data64) {
                   1421:         /* 64 bit */
                   1422:         esp -= 8;
                   1423:         while (--level) {
                   1424:             esp -= 8;
                   1425:             ebp -= 8;
                   1426:             stq(esp, ldq(ebp));
                   1427:         }
                   1428:         esp -= 8;
                   1429:         stq(esp, T1);
                   1430:     } else {
                   1431:         /* 16 bit */
                   1432:         esp -= 2;
                   1433:         while (--level) {
                   1434:             esp -= 2;
                   1435:             ebp -= 2;
                   1436:             stw(esp, lduw(ebp));
                   1437:         }
                   1438:         esp -= 2;
                   1439:         stw(esp, T1);
                   1440:     }
                   1441: }
                   1442: #endif
                   1443: 
                   1444: void helper_lldt_T0(void)
                   1445: {
                   1446:     int selector;
                   1447:     SegmentCache *dt;
                   1448:     uint32_t e1, e2;
                   1449:     int index, entry_limit;
                   1450:     target_ulong ptr;
                   1451:     
                   1452:     selector = T0 & 0xffff;
                   1453:     if ((selector & 0xfffc) == 0) {
                   1454:         /* XXX: NULL selector case: invalid LDT */
                   1455:         env->ldt.base = 0;
                   1456:         env->ldt.limit = 0;
                   1457:     } else {
                   1458:         if (selector & 0x4)
                   1459:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1460:         dt = &env->gdt;
                   1461:         index = selector & ~7;
                   1462: #ifdef TARGET_X86_64
                   1463:         if (env->hflags & HF_LMA_MASK)
                   1464:             entry_limit = 15;
                   1465:         else
                   1466: #endif            
                   1467:             entry_limit = 7;
                   1468:         if ((index + entry_limit) > dt->limit)
                   1469:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1470:         ptr = dt->base + index;
                   1471:         e1 = ldl_kernel(ptr);
                   1472:         e2 = ldl_kernel(ptr + 4);
                   1473:         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
                   1474:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1475:         if (!(e2 & DESC_P_MASK))
                   1476:             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   1477: #ifdef TARGET_X86_64
                   1478:         if (env->hflags & HF_LMA_MASK) {
                   1479:             uint32_t e3;
                   1480:             e3 = ldl_kernel(ptr + 8);
                   1481:             load_seg_cache_raw_dt(&env->ldt, e1, e2);
                   1482:             env->ldt.base |= (target_ulong)e3 << 32;
                   1483:         } else
                   1484: #endif
                   1485:         {
                   1486:             load_seg_cache_raw_dt(&env->ldt, e1, e2);
                   1487:         }
                   1488:     }
                   1489:     env->ldt.selector = selector;
                   1490: }
                   1491: 
                   1492: void helper_ltr_T0(void)
                   1493: {
                   1494:     int selector;
                   1495:     SegmentCache *dt;
                   1496:     uint32_t e1, e2;
                   1497:     int index, type, entry_limit;
                   1498:     target_ulong ptr;
                   1499:     
                   1500:     selector = T0 & 0xffff;
                   1501:     if ((selector & 0xfffc) == 0) {
                   1502:         /* NULL selector case: invalid TR */
                   1503:         env->tr.base = 0;
                   1504:         env->tr.limit = 0;
                   1505:         env->tr.flags = 0;
                   1506:     } else {
                   1507:         if (selector & 0x4)
                   1508:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1509:         dt = &env->gdt;
                   1510:         index = selector & ~7;
                   1511: #ifdef TARGET_X86_64
                   1512:         if (env->hflags & HF_LMA_MASK)
                   1513:             entry_limit = 15;
                   1514:         else
                   1515: #endif            
                   1516:             entry_limit = 7;
                   1517:         if ((index + entry_limit) > dt->limit)
                   1518:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1519:         ptr = dt->base + index;
                   1520:         e1 = ldl_kernel(ptr);
                   1521:         e2 = ldl_kernel(ptr + 4);
                   1522:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                   1523:         if ((e2 & DESC_S_MASK) || 
                   1524:             (type != 1 && type != 9))
                   1525:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1526:         if (!(e2 & DESC_P_MASK))
                   1527:             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   1528: #ifdef TARGET_X86_64
                   1529:         if (env->hflags & HF_LMA_MASK) {
                   1530:             uint32_t e3;
                   1531:             e3 = ldl_kernel(ptr + 8);
                   1532:             load_seg_cache_raw_dt(&env->tr, e1, e2);
                   1533:             env->tr.base |= (target_ulong)e3 << 32;
                   1534:         } else 
                   1535: #endif
                   1536:         {
                   1537:             load_seg_cache_raw_dt(&env->tr, e1, e2);
                   1538:         }
                   1539:         e2 |= DESC_TSS_BUSY_MASK;
                   1540:         stl_kernel(ptr + 4, e2);
                   1541:     }
                   1542:     env->tr.selector = selector;
                   1543: }
                   1544: 
                   1545: /* only works if protected mode and not VM86. seg_reg must be != R_CS */
                   1546: void load_seg(int seg_reg, int selector)
                   1547: {
                   1548:     uint32_t e1, e2;
                   1549:     int cpl, dpl, rpl;
                   1550:     SegmentCache *dt;
                   1551:     int index;
                   1552:     target_ulong ptr;
                   1553: 
                   1554:     selector &= 0xffff;
                   1555:     cpl = env->hflags & HF_CPL_MASK;
                   1556:     if ((selector & 0xfffc) == 0) {
                   1557:         /* null selector case */
                   1558:         if (seg_reg == R_SS
                   1559: #ifdef TARGET_X86_64
                   1560:             && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
                   1561: #endif
                   1562:             )
                   1563:             raise_exception_err(EXCP0D_GPF, 0);
                   1564:         cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
                   1565:     } else {
                   1566:         
                   1567:         if (selector & 0x4)
                   1568:             dt = &env->ldt;
                   1569:         else
                   1570:             dt = &env->gdt;
                   1571:         index = selector & ~7;
                   1572:         if ((index + 7) > dt->limit)
                   1573:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1574:         ptr = dt->base + index;
                   1575:         e1 = ldl_kernel(ptr);
                   1576:         e2 = ldl_kernel(ptr + 4);
                   1577:         
                   1578:         if (!(e2 & DESC_S_MASK))
                   1579:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1580:         rpl = selector & 3;
                   1581:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1582:         if (seg_reg == R_SS) {
                   1583:             /* must be writable segment */
                   1584:             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
                   1585:                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1586:             if (rpl != cpl || dpl != cpl)
                   1587:                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1588:         } else {
                   1589:             /* must be readable segment */
                   1590:             if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
                   1591:                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1592:             
                   1593:             if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
                   1594:                 /* if not conforming code, test rights */
1.1.1.2   root     1595:                 if (dpl < cpl || dpl < rpl) 
1.1       root     1596:                     raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1597:             }
                   1598:         }
                   1599: 
                   1600:         if (!(e2 & DESC_P_MASK)) {
                   1601:             if (seg_reg == R_SS)
                   1602:                 raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
                   1603:             else
                   1604:                 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   1605:         }
                   1606: 
                   1607:         /* set the access bit if not already set */
                   1608:         if (!(e2 & DESC_A_MASK)) {
                   1609:             e2 |= DESC_A_MASK;
                   1610:             stl_kernel(ptr + 4, e2);
                   1611:         }
                   1612: 
                   1613:         cpu_x86_load_seg_cache(env, seg_reg, selector, 
                   1614:                        get_seg_base(e1, e2),
                   1615:                        get_seg_limit(e1, e2),
                   1616:                        e2);
                   1617: #if 0
                   1618:         fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n", 
                   1619:                 selector, (unsigned long)sc->base, sc->limit, sc->flags);
                   1620: #endif
                   1621:     }
                   1622: }
                   1623: 
                   1624: /* protected mode jump */
                   1625: void helper_ljmp_protected_T0_T1(int next_eip_addend)
                   1626: {
                   1627:     int new_cs, gate_cs, type;
                   1628:     uint32_t e1, e2, cpl, dpl, rpl, limit;
                   1629:     target_ulong new_eip, next_eip;
                   1630:     
                   1631:     new_cs = T0;
                   1632:     new_eip = T1;
                   1633:     if ((new_cs & 0xfffc) == 0)
                   1634:         raise_exception_err(EXCP0D_GPF, 0);
                   1635:     if (load_segment(&e1, &e2, new_cs) != 0)
                   1636:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1637:     cpl = env->hflags & HF_CPL_MASK;
                   1638:     if (e2 & DESC_S_MASK) {
                   1639:         if (!(e2 & DESC_CS_MASK))
                   1640:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1641:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1642:         if (e2 & DESC_C_MASK) {
                   1643:             /* conforming code segment */
                   1644:             if (dpl > cpl)
                   1645:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1646:         } else {
                   1647:             /* non conforming code segment */
                   1648:             rpl = new_cs & 3;
                   1649:             if (rpl > cpl)
                   1650:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1651:             if (dpl != cpl)
                   1652:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1653:         }
                   1654:         if (!(e2 & DESC_P_MASK))
                   1655:             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
                   1656:         limit = get_seg_limit(e1, e2);
                   1657:         if (new_eip > limit && 
                   1658:             !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
                   1659:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1660:         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
                   1661:                        get_seg_base(e1, e2), limit, e2);
                   1662:         EIP = new_eip;
                   1663:     } else {
                   1664:         /* jump to call or task gate */
                   1665:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1666:         rpl = new_cs & 3;
                   1667:         cpl = env->hflags & HF_CPL_MASK;
                   1668:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                   1669:         switch(type) {
                   1670:         case 1: /* 286 TSS */
                   1671:         case 9: /* 386 TSS */
                   1672:         case 5: /* task gate */
                   1673:             if (dpl < cpl || dpl < rpl)
                   1674:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1675:             next_eip = env->eip + next_eip_addend;
                   1676:             switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
                   1677:             break;
                   1678:         case 4: /* 286 call gate */
                   1679:         case 12: /* 386 call gate */
                   1680:             if ((dpl < cpl) || (dpl < rpl))
                   1681:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1682:             if (!(e2 & DESC_P_MASK))
                   1683:                 raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
                   1684:             gate_cs = e1 >> 16;
                   1685:             new_eip = (e1 & 0xffff);
                   1686:             if (type == 12)
                   1687:                 new_eip |= (e2 & 0xffff0000);
                   1688:             if (load_segment(&e1, &e2, gate_cs) != 0)
                   1689:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
                   1690:             dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1691:             /* must be code segment */
                   1692:             if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) != 
                   1693:                  (DESC_S_MASK | DESC_CS_MASK)))
                   1694:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
                   1695:             if (((e2 & DESC_C_MASK) && (dpl > cpl)) || 
                   1696:                 (!(e2 & DESC_C_MASK) && (dpl != cpl)))
                   1697:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
                   1698:             if (!(e2 & DESC_P_MASK))
                   1699:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
                   1700:             limit = get_seg_limit(e1, e2);
                   1701:             if (new_eip > limit)
                   1702:                 raise_exception_err(EXCP0D_GPF, 0);
                   1703:             cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
                   1704:                                    get_seg_base(e1, e2), limit, e2);
                   1705:             EIP = new_eip;
                   1706:             break;
                   1707:         default:
                   1708:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1709:             break;
                   1710:         }
                   1711:     }
                   1712: }
                   1713: 
                   1714: /* real mode call */
                   1715: void helper_lcall_real_T0_T1(int shift, int next_eip)
                   1716: {
                   1717:     int new_cs, new_eip;
                   1718:     uint32_t esp, esp_mask;
                   1719:     target_ulong ssp;
                   1720: 
                   1721:     new_cs = T0;
                   1722:     new_eip = T1;
                   1723:     esp = ESP;
                   1724:     esp_mask = get_sp_mask(env->segs[R_SS].flags);
                   1725:     ssp = env->segs[R_SS].base;
                   1726:     if (shift) {
                   1727:         PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
                   1728:         PUSHL(ssp, esp, esp_mask, next_eip);
                   1729:     } else {
                   1730:         PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
                   1731:         PUSHW(ssp, esp, esp_mask, next_eip);
                   1732:     }
                   1733: 
                   1734:     ESP = (ESP & ~esp_mask) | (esp & esp_mask);
                   1735:     env->eip = new_eip;
                   1736:     env->segs[R_CS].selector = new_cs;
                   1737:     env->segs[R_CS].base = (new_cs << 4);
                   1738: }
                   1739: 
                   1740: /* protected mode call */
                   1741: void helper_lcall_protected_T0_T1(int shift, int next_eip_addend)
                   1742: {
1.1.1.2   root     1743:     int new_cs, new_stack, i;
1.1       root     1744:     uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
                   1745:     uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
                   1746:     uint32_t val, limit, old_sp_mask;
1.1.1.2   root     1747:     target_ulong ssp, old_ssp, next_eip, new_eip;
1.1       root     1748:     
                   1749:     new_cs = T0;
                   1750:     new_eip = T1;
                   1751:     next_eip = env->eip + next_eip_addend;
                   1752: #ifdef DEBUG_PCALL
                   1753:     if (loglevel & CPU_LOG_PCALL) {
                   1754:         fprintf(logfile, "lcall %04x:%08x s=%d\n",
1.1.1.2   root     1755:                 new_cs, (uint32_t)new_eip, shift);
1.1       root     1756:         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
                   1757:     }
                   1758: #endif
                   1759:     if ((new_cs & 0xfffc) == 0)
                   1760:         raise_exception_err(EXCP0D_GPF, 0);
                   1761:     if (load_segment(&e1, &e2, new_cs) != 0)
                   1762:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1763:     cpl = env->hflags & HF_CPL_MASK;
                   1764: #ifdef DEBUG_PCALL
                   1765:     if (loglevel & CPU_LOG_PCALL) {
                   1766:         fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
                   1767:     }
                   1768: #endif
                   1769:     if (e2 & DESC_S_MASK) {
                   1770:         if (!(e2 & DESC_CS_MASK))
                   1771:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1772:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1773:         if (e2 & DESC_C_MASK) {
                   1774:             /* conforming code segment */
                   1775:             if (dpl > cpl)
                   1776:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1777:         } else {
                   1778:             /* non conforming code segment */
                   1779:             rpl = new_cs & 3;
                   1780:             if (rpl > cpl)
                   1781:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1782:             if (dpl != cpl)
                   1783:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1784:         }
                   1785:         if (!(e2 & DESC_P_MASK))
                   1786:             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
                   1787: 
                   1788: #ifdef TARGET_X86_64
                   1789:         /* XXX: check 16/32 bit cases in long mode */
                   1790:         if (shift == 2) {
                   1791:             target_ulong rsp;
                   1792:             /* 64 bit case */
                   1793:             rsp = ESP;
                   1794:             PUSHQ(rsp, env->segs[R_CS].selector);
                   1795:             PUSHQ(rsp, next_eip);
                   1796:             /* from this point, not restartable */
                   1797:             ESP = rsp;
                   1798:             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
                   1799:                                    get_seg_base(e1, e2), 
                   1800:                                    get_seg_limit(e1, e2), e2);
                   1801:             EIP = new_eip;
                   1802:         } else 
                   1803: #endif
                   1804:         {
                   1805:             sp = ESP;
                   1806:             sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   1807:             ssp = env->segs[R_SS].base;
                   1808:             if (shift) {
                   1809:                 PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   1810:                 PUSHL(ssp, sp, sp_mask, next_eip);
                   1811:             } else {
                   1812:                 PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   1813:                 PUSHW(ssp, sp, sp_mask, next_eip);
                   1814:             }
                   1815:             
                   1816:             limit = get_seg_limit(e1, e2);
                   1817:             if (new_eip > limit)
                   1818:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1819:             /* from this point, not restartable */
                   1820:             ESP = (ESP & ~sp_mask) | (sp & sp_mask);
                   1821:             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
                   1822:                                    get_seg_base(e1, e2), limit, e2);
                   1823:             EIP = new_eip;
                   1824:         }
                   1825:     } else {
                   1826:         /* check gate type */
                   1827:         type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
                   1828:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1829:         rpl = new_cs & 3;
                   1830:         switch(type) {
                   1831:         case 1: /* available 286 TSS */
                   1832:         case 9: /* available 386 TSS */
                   1833:         case 5: /* task gate */
                   1834:             if (dpl < cpl || dpl < rpl)
                   1835:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1836:             switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
                   1837:             return;
                   1838:         case 4: /* 286 call gate */
                   1839:         case 12: /* 386 call gate */
                   1840:             break;
                   1841:         default:
                   1842:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1843:             break;
                   1844:         }
                   1845:         shift = type >> 3;
                   1846: 
                   1847:         if (dpl < cpl || dpl < rpl)
                   1848:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1849:         /* check valid bit */
                   1850:         if (!(e2 & DESC_P_MASK))
                   1851:             raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
                   1852:         selector = e1 >> 16;
                   1853:         offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
                   1854:         param_count = e2 & 0x1f;
                   1855:         if ((selector & 0xfffc) == 0)
                   1856:             raise_exception_err(EXCP0D_GPF, 0);
                   1857: 
                   1858:         if (load_segment(&e1, &e2, selector) != 0)
                   1859:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1860:         if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
                   1861:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1862:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1863:         if (dpl > cpl)
                   1864:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1865:         if (!(e2 & DESC_P_MASK))
                   1866:             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   1867: 
                   1868:         if (!(e2 & DESC_C_MASK) && dpl < cpl) {
                   1869:             /* to inner priviledge */
                   1870:             get_ss_esp_from_tss(&ss, &sp, dpl);
                   1871: #ifdef DEBUG_PCALL
                   1872:             if (loglevel & CPU_LOG_PCALL)
                   1873:                 fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n", 
                   1874:                         ss, sp, param_count, ESP);
                   1875: #endif
                   1876:             if ((ss & 0xfffc) == 0)
                   1877:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   1878:             if ((ss & 3) != dpl)
                   1879:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   1880:             if (load_segment(&ss_e1, &ss_e2, ss) != 0)
                   1881:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   1882:             ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
                   1883:             if (ss_dpl != dpl)
                   1884:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   1885:             if (!(ss_e2 & DESC_S_MASK) ||
                   1886:                 (ss_e2 & DESC_CS_MASK) ||
                   1887:                 !(ss_e2 & DESC_W_MASK))
                   1888:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   1889:             if (!(ss_e2 & DESC_P_MASK))
                   1890:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   1891:             
                   1892:             //            push_size = ((param_count * 2) + 8) << shift;
                   1893: 
                   1894:             old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   1895:             old_ssp = env->segs[R_SS].base;
                   1896:             
                   1897:             sp_mask = get_sp_mask(ss_e2);
                   1898:             ssp = get_seg_base(ss_e1, ss_e2);
                   1899:             if (shift) {
                   1900:                 PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
                   1901:                 PUSHL(ssp, sp, sp_mask, ESP);
                   1902:                 for(i = param_count - 1; i >= 0; i--) {
                   1903:                     val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
                   1904:                     PUSHL(ssp, sp, sp_mask, val);
                   1905:                 }
                   1906:             } else {
                   1907:                 PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
                   1908:                 PUSHW(ssp, sp, sp_mask, ESP);
                   1909:                 for(i = param_count - 1; i >= 0; i--) {
                   1910:                     val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
                   1911:                     PUSHW(ssp, sp, sp_mask, val);
                   1912:                 }
                   1913:             }
                   1914:             new_stack = 1;
                   1915:         } else {
                   1916:             /* to same priviledge */
                   1917:             sp = ESP;
                   1918:             sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   1919:             ssp = env->segs[R_SS].base;
                   1920:             //            push_size = (4 << shift);
                   1921:             new_stack = 0;
                   1922:         }
                   1923: 
                   1924:         if (shift) {
                   1925:             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   1926:             PUSHL(ssp, sp, sp_mask, next_eip);
                   1927:         } else {
                   1928:             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   1929:             PUSHW(ssp, sp, sp_mask, next_eip);
                   1930:         }
                   1931: 
                   1932:         /* from this point, not restartable */
                   1933: 
                   1934:         if (new_stack) {
                   1935:             ss = (ss & ~3) | dpl;
                   1936:             cpu_x86_load_seg_cache(env, R_SS, ss, 
                   1937:                                    ssp,
                   1938:                                    get_seg_limit(ss_e1, ss_e2),
                   1939:                                    ss_e2);
                   1940:         }
                   1941: 
                   1942:         selector = (selector & ~3) | dpl;
                   1943:         cpu_x86_load_seg_cache(env, R_CS, selector, 
                   1944:                        get_seg_base(e1, e2),
                   1945:                        get_seg_limit(e1, e2),
                   1946:                        e2);
                   1947:         cpu_x86_set_cpl(env, dpl);
                   1948:         ESP = (ESP & ~sp_mask) | (sp & sp_mask);
                   1949:         EIP = offset;
                   1950:     }
                   1951: #ifdef USE_KQEMU
                   1952:     if (kqemu_is_ok(env)) {
                   1953:         env->exception_index = -1;
                   1954:         cpu_loop_exit();
                   1955:     }
                   1956: #endif
                   1957: }
                   1958: 
                   1959: /* real and vm86 mode iret */
                   1960: void helper_iret_real(int shift)
                   1961: {
                   1962:     uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
                   1963:     target_ulong ssp;
                   1964:     int eflags_mask;
                   1965: 
                   1966:     sp_mask = 0xffff; /* XXXX: use SS segment size ? */
                   1967:     sp = ESP;
                   1968:     ssp = env->segs[R_SS].base;
                   1969:     if (shift == 1) {
                   1970:         /* 32 bits */
                   1971:         POPL(ssp, sp, sp_mask, new_eip);
                   1972:         POPL(ssp, sp, sp_mask, new_cs);
                   1973:         new_cs &= 0xffff;
                   1974:         POPL(ssp, sp, sp_mask, new_eflags);
                   1975:     } else {
                   1976:         /* 16 bits */
                   1977:         POPW(ssp, sp, sp_mask, new_eip);
                   1978:         POPW(ssp, sp, sp_mask, new_cs);
                   1979:         POPW(ssp, sp, sp_mask, new_eflags);
                   1980:     }
                   1981:     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
                   1982:     load_seg_vm(R_CS, new_cs);
                   1983:     env->eip = new_eip;
                   1984:     if (env->eflags & VM_MASK)
                   1985:         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
                   1986:     else
                   1987:         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
                   1988:     if (shift == 0)
                   1989:         eflags_mask &= 0xffff;
                   1990:     load_eflags(new_eflags, eflags_mask);
                   1991: }
                   1992: 
                   1993: static inline void validate_seg(int seg_reg, int cpl)
                   1994: {
                   1995:     int dpl;
                   1996:     uint32_t e2;
1.1.1.2   root     1997: 
                   1998:     /* XXX: on x86_64, we do not want to nullify FS and GS because
                   1999:        they may still contain a valid base. I would be interested to
                   2000:        know how a real x86_64 CPU behaves */
                   2001:     if ((seg_reg == R_FS || seg_reg == R_GS) && 
                   2002:         (env->segs[seg_reg].selector & 0xfffc) == 0)
                   2003:         return;
                   2004: 
1.1       root     2005:     e2 = env->segs[seg_reg].flags;
                   2006:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2007:     if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
                   2008:         /* data or non conforming code segment */
                   2009:         if (dpl < cpl) {
                   2010:             cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
                   2011:         }
                   2012:     }
                   2013: }
                   2014: 
                   2015: /* protected mode iret */
                   2016: static inline void helper_ret_protected(int shift, int is_iret, int addend)
                   2017: {
                   2018:     uint32_t new_cs, new_eflags, new_ss;
                   2019:     uint32_t new_es, new_ds, new_fs, new_gs;
                   2020:     uint32_t e1, e2, ss_e1, ss_e2;
                   2021:     int cpl, dpl, rpl, eflags_mask, iopl;
                   2022:     target_ulong ssp, sp, new_eip, new_esp, sp_mask;
                   2023:     
                   2024: #ifdef TARGET_X86_64
                   2025:     if (shift == 2)
                   2026:         sp_mask = -1;
                   2027:     else
                   2028: #endif
                   2029:         sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   2030:     sp = ESP;
                   2031:     ssp = env->segs[R_SS].base;
                   2032:     new_eflags = 0; /* avoid warning */
                   2033: #ifdef TARGET_X86_64
                   2034:     if (shift == 2) {
                   2035:         POPQ(sp, new_eip);
                   2036:         POPQ(sp, new_cs);
                   2037:         new_cs &= 0xffff;
                   2038:         if (is_iret) {
                   2039:             POPQ(sp, new_eflags);
                   2040:         }
                   2041:     } else
                   2042: #endif
                   2043:     if (shift == 1) {
                   2044:         /* 32 bits */
                   2045:         POPL(ssp, sp, sp_mask, new_eip);
                   2046:         POPL(ssp, sp, sp_mask, new_cs);
                   2047:         new_cs &= 0xffff;
                   2048:         if (is_iret) {
                   2049:             POPL(ssp, sp, sp_mask, new_eflags);
                   2050:             if (new_eflags & VM_MASK)
                   2051:                 goto return_to_vm86;
                   2052:         }
                   2053:     } else {
                   2054:         /* 16 bits */
                   2055:         POPW(ssp, sp, sp_mask, new_eip);
                   2056:         POPW(ssp, sp, sp_mask, new_cs);
                   2057:         if (is_iret)
                   2058:             POPW(ssp, sp, sp_mask, new_eflags);
                   2059:     }
                   2060: #ifdef DEBUG_PCALL
                   2061:     if (loglevel & CPU_LOG_PCALL) {
                   2062:         fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
                   2063:                 new_cs, new_eip, shift, addend);
                   2064:         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
                   2065:     }
                   2066: #endif
                   2067:     if ((new_cs & 0xfffc) == 0)
                   2068:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2069:     if (load_segment(&e1, &e2, new_cs) != 0)
                   2070:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2071:     if (!(e2 & DESC_S_MASK) ||
                   2072:         !(e2 & DESC_CS_MASK))
                   2073:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2074:     cpl = env->hflags & HF_CPL_MASK;
                   2075:     rpl = new_cs & 3; 
                   2076:     if (rpl < cpl)
                   2077:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2078:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2079:     if (e2 & DESC_C_MASK) {
                   2080:         if (dpl > rpl)
                   2081:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2082:     } else {
                   2083:         if (dpl != rpl)
                   2084:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2085:     }
                   2086:     if (!(e2 & DESC_P_MASK))
                   2087:         raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
                   2088:     
                   2089:     sp += addend;
                   2090:     if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) || 
                   2091:                        ((env->hflags & HF_CS64_MASK) && !is_iret))) {
                   2092:         /* return to same priledge level */
                   2093:         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
                   2094:                        get_seg_base(e1, e2),
                   2095:                        get_seg_limit(e1, e2),
                   2096:                        e2);
                   2097:     } else {
                   2098:         /* return to different priviledge level */
                   2099: #ifdef TARGET_X86_64
                   2100:         if (shift == 2) {
                   2101:             POPQ(sp, new_esp);
                   2102:             POPQ(sp, new_ss);
                   2103:             new_ss &= 0xffff;
                   2104:         } else
                   2105: #endif
                   2106:         if (shift == 1) {
                   2107:             /* 32 bits */
                   2108:             POPL(ssp, sp, sp_mask, new_esp);
                   2109:             POPL(ssp, sp, sp_mask, new_ss);
                   2110:             new_ss &= 0xffff;
                   2111:         } else {
                   2112:             /* 16 bits */
                   2113:             POPW(ssp, sp, sp_mask, new_esp);
                   2114:             POPW(ssp, sp, sp_mask, new_ss);
                   2115:         }
                   2116: #ifdef DEBUG_PCALL
                   2117:         if (loglevel & CPU_LOG_PCALL) {
                   2118:             fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
                   2119:                     new_ss, new_esp);
                   2120:         }
                   2121: #endif
                   2122:         if ((new_ss & 0xfffc) == 0) {
                   2123: #ifdef TARGET_X86_64
                   2124:             /* NULL ss is allowed in long mode if cpl != 3*/
                   2125:             if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
                   2126:                 cpu_x86_load_seg_cache(env, R_SS, new_ss, 
                   2127:                                        0, 0xffffffff,
                   2128:                                        DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2129:                                        DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
                   2130:                                        DESC_W_MASK | DESC_A_MASK);
                   2131:             } else 
                   2132: #endif
                   2133:             {
                   2134:                 raise_exception_err(EXCP0D_GPF, 0);
                   2135:             }
                   2136:         } else {
                   2137:             if ((new_ss & 3) != rpl)
                   2138:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2139:             if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
                   2140:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2141:             if (!(ss_e2 & DESC_S_MASK) ||
                   2142:                 (ss_e2 & DESC_CS_MASK) ||
                   2143:                 !(ss_e2 & DESC_W_MASK))
                   2144:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2145:             dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
                   2146:             if (dpl != rpl)
                   2147:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2148:             if (!(ss_e2 & DESC_P_MASK))
                   2149:                 raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
                   2150:             cpu_x86_load_seg_cache(env, R_SS, new_ss, 
                   2151:                                    get_seg_base(ss_e1, ss_e2),
                   2152:                                    get_seg_limit(ss_e1, ss_e2),
                   2153:                                    ss_e2);
                   2154:         }
                   2155: 
                   2156:         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
                   2157:                        get_seg_base(e1, e2),
                   2158:                        get_seg_limit(e1, e2),
                   2159:                        e2);
                   2160:         cpu_x86_set_cpl(env, rpl);
                   2161:         sp = new_esp;
                   2162: #ifdef TARGET_X86_64
                   2163:         if (env->hflags & HF_CS64_MASK)
                   2164:             sp_mask = -1;
                   2165:         else
                   2166: #endif
                   2167:             sp_mask = get_sp_mask(ss_e2);
                   2168: 
                   2169:         /* validate data segments */
1.1.1.2   root     2170:         validate_seg(R_ES, rpl);
                   2171:         validate_seg(R_DS, rpl);
                   2172:         validate_seg(R_FS, rpl);
                   2173:         validate_seg(R_GS, rpl);
1.1       root     2174: 
                   2175:         sp += addend;
                   2176:     }
                   2177:     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
                   2178:     env->eip = new_eip;
                   2179:     if (is_iret) {
                   2180:         /* NOTE: 'cpl' is the _old_ CPL */
                   2181:         eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
                   2182:         if (cpl == 0)
                   2183:             eflags_mask |= IOPL_MASK;
                   2184:         iopl = (env->eflags >> IOPL_SHIFT) & 3;
                   2185:         if (cpl <= iopl)
                   2186:             eflags_mask |= IF_MASK;
                   2187:         if (shift == 0)
                   2188:             eflags_mask &= 0xffff;
                   2189:         load_eflags(new_eflags, eflags_mask);
                   2190:     }
                   2191:     return;
                   2192: 
                   2193:  return_to_vm86:
                   2194:     POPL(ssp, sp, sp_mask, new_esp);
                   2195:     POPL(ssp, sp, sp_mask, new_ss);
                   2196:     POPL(ssp, sp, sp_mask, new_es);
                   2197:     POPL(ssp, sp, sp_mask, new_ds);
                   2198:     POPL(ssp, sp, sp_mask, new_fs);
                   2199:     POPL(ssp, sp, sp_mask, new_gs);
                   2200:     
                   2201:     /* modify processor state */
                   2202:     load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | 
                   2203:                 IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
                   2204:     load_seg_vm(R_CS, new_cs & 0xffff);
                   2205:     cpu_x86_set_cpl(env, 3);
                   2206:     load_seg_vm(R_SS, new_ss & 0xffff);
                   2207:     load_seg_vm(R_ES, new_es & 0xffff);
                   2208:     load_seg_vm(R_DS, new_ds & 0xffff);
                   2209:     load_seg_vm(R_FS, new_fs & 0xffff);
                   2210:     load_seg_vm(R_GS, new_gs & 0xffff);
                   2211: 
                   2212:     env->eip = new_eip & 0xffff;
                   2213:     ESP = new_esp;
                   2214: }
                   2215: 
                   2216: void helper_iret_protected(int shift, int next_eip)
                   2217: {
                   2218:     int tss_selector, type;
                   2219:     uint32_t e1, e2;
                   2220:     
                   2221:     /* specific case for TSS */
                   2222:     if (env->eflags & NT_MASK) {
                   2223: #ifdef TARGET_X86_64
                   2224:         if (env->hflags & HF_LMA_MASK)
                   2225:             raise_exception_err(EXCP0D_GPF, 0);
                   2226: #endif
                   2227:         tss_selector = lduw_kernel(env->tr.base + 0);
                   2228:         if (tss_selector & 4)
                   2229:             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                   2230:         if (load_segment(&e1, &e2, tss_selector) != 0)
                   2231:             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                   2232:         type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
                   2233:         /* NOTE: we check both segment and busy TSS */
                   2234:         if (type != 3)
                   2235:             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                   2236:         switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
                   2237:     } else {
                   2238:         helper_ret_protected(shift, 1, 0);
                   2239:     }
                   2240: #ifdef USE_KQEMU
                   2241:     if (kqemu_is_ok(env)) {
                   2242:         CC_OP = CC_OP_EFLAGS;
                   2243:         env->exception_index = -1;
                   2244:         cpu_loop_exit();
                   2245:     }
                   2246: #endif
                   2247: }
                   2248: 
                   2249: void helper_lret_protected(int shift, int addend)
                   2250: {
                   2251:     helper_ret_protected(shift, 0, addend);
                   2252: #ifdef USE_KQEMU
                   2253:     if (kqemu_is_ok(env)) {
                   2254:         env->exception_index = -1;
                   2255:         cpu_loop_exit();
                   2256:     }
                   2257: #endif
                   2258: }
                   2259: 
                   2260: void helper_sysenter(void)
                   2261: {
                   2262:     if (env->sysenter_cs == 0) {
                   2263:         raise_exception_err(EXCP0D_GPF, 0);
                   2264:     }
                   2265:     env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
                   2266:     cpu_x86_set_cpl(env, 0);
                   2267:     cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, 
                   2268:                            0, 0xffffffff, 
                   2269:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2270:                            DESC_S_MASK |
                   2271:                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                   2272:     cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc, 
                   2273:                            0, 0xffffffff,
                   2274:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2275:                            DESC_S_MASK |
                   2276:                            DESC_W_MASK | DESC_A_MASK);
                   2277:     ESP = env->sysenter_esp;
                   2278:     EIP = env->sysenter_eip;
                   2279: }
                   2280: 
                   2281: void helper_sysexit(void)
                   2282: {
                   2283:     int cpl;
                   2284: 
                   2285:     cpl = env->hflags & HF_CPL_MASK;
                   2286:     if (env->sysenter_cs == 0 || cpl != 0) {
                   2287:         raise_exception_err(EXCP0D_GPF, 0);
                   2288:     }
                   2289:     cpu_x86_set_cpl(env, 3);
                   2290:     cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3, 
                   2291:                            0, 0xffffffff, 
                   2292:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2293:                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   2294:                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                   2295:     cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3, 
                   2296:                            0, 0xffffffff,
                   2297:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2298:                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   2299:                            DESC_W_MASK | DESC_A_MASK);
                   2300:     ESP = ECX;
                   2301:     EIP = EDX;
                   2302: #ifdef USE_KQEMU
                   2303:     if (kqemu_is_ok(env)) {
                   2304:         env->exception_index = -1;
                   2305:         cpu_loop_exit();
                   2306:     }
                   2307: #endif
                   2308: }
                   2309: 
                   2310: void helper_movl_crN_T0(int reg)
                   2311: {
                   2312: #if !defined(CONFIG_USER_ONLY) 
                   2313:     switch(reg) {
                   2314:     case 0:
                   2315:         cpu_x86_update_cr0(env, T0);
                   2316:         break;
                   2317:     case 3:
                   2318:         cpu_x86_update_cr3(env, T0);
                   2319:         break;
                   2320:     case 4:
                   2321:         cpu_x86_update_cr4(env, T0);
                   2322:         break;
                   2323:     case 8:
                   2324:         cpu_set_apic_tpr(env, T0);
                   2325:         break;
                   2326:     default:
                   2327:         env->cr[reg] = T0;
                   2328:         break;
                   2329:     }
                   2330: #endif
                   2331: }
                   2332: 
                   2333: /* XXX: do more */
                   2334: void helper_movl_drN_T0(int reg)
                   2335: {
                   2336:     env->dr[reg] = T0;
                   2337: }
                   2338: 
                   2339: void helper_invlpg(target_ulong addr)
                   2340: {
                   2341:     cpu_x86_flush_tlb(env, addr);
                   2342: }
                   2343: 
                   2344: void helper_rdtsc(void)
                   2345: {
                   2346:     uint64_t val;
                   2347: 
                   2348:     if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
                   2349:         raise_exception(EXCP0D_GPF);
                   2350:     }
                   2351:     val = cpu_get_tsc(env);
                   2352:     EAX = (uint32_t)(val);
                   2353:     EDX = (uint32_t)(val >> 32);
                   2354: }
                   2355: 
                   2356: #if defined(CONFIG_USER_ONLY) 
                   2357: void helper_wrmsr(void)
                   2358: {
                   2359: }
                   2360: 
                   2361: void helper_rdmsr(void)
                   2362: {
                   2363: }
                   2364: #else
                   2365: void helper_wrmsr(void)
                   2366: {
                   2367:     uint64_t val;
                   2368: 
                   2369:     val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
                   2370: 
                   2371:     switch((uint32_t)ECX) {
                   2372:     case MSR_IA32_SYSENTER_CS:
                   2373:         env->sysenter_cs = val & 0xffff;
                   2374:         break;
                   2375:     case MSR_IA32_SYSENTER_ESP:
                   2376:         env->sysenter_esp = val;
                   2377:         break;
                   2378:     case MSR_IA32_SYSENTER_EIP:
                   2379:         env->sysenter_eip = val;
                   2380:         break;
                   2381:     case MSR_IA32_APICBASE:
                   2382:         cpu_set_apic_base(env, val);
                   2383:         break;
                   2384:     case MSR_EFER:
                   2385:         {
                   2386:             uint64_t update_mask;
                   2387:             update_mask = 0;
                   2388:             if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
                   2389:                 update_mask |= MSR_EFER_SCE;
                   2390:             if (env->cpuid_ext2_features & CPUID_EXT2_LM)
                   2391:                 update_mask |= MSR_EFER_LME;
                   2392:             if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
                   2393:                 update_mask |= MSR_EFER_FFXSR;
                   2394:             if (env->cpuid_ext2_features & CPUID_EXT2_NX)
                   2395:                 update_mask |= MSR_EFER_NXE;
                   2396:             env->efer = (env->efer & ~update_mask) | 
                   2397:             (val & update_mask);
                   2398:         }
                   2399:         break;
                   2400:     case MSR_STAR:
                   2401:         env->star = val;
                   2402:         break;
                   2403:     case MSR_PAT:
                   2404:         env->pat = val;
                   2405:         break;
                   2406: #ifdef TARGET_X86_64
                   2407:     case MSR_LSTAR:
                   2408:         env->lstar = val;
                   2409:         break;
                   2410:     case MSR_CSTAR:
                   2411:         env->cstar = val;
                   2412:         break;
                   2413:     case MSR_FMASK:
                   2414:         env->fmask = val;
                   2415:         break;
                   2416:     case MSR_FSBASE:
                   2417:         env->segs[R_FS].base = val;
                   2418:         break;
                   2419:     case MSR_GSBASE:
                   2420:         env->segs[R_GS].base = val;
                   2421:         break;
                   2422:     case MSR_KERNELGSBASE:
                   2423:         env->kernelgsbase = val;
                   2424:         break;
                   2425: #endif
                   2426:     default:
                   2427:         /* XXX: exception ? */
                   2428:         break; 
                   2429:     }
                   2430: }
                   2431: 
                   2432: void helper_rdmsr(void)
                   2433: {
                   2434:     uint64_t val;
                   2435:     switch((uint32_t)ECX) {
                   2436:     case MSR_IA32_SYSENTER_CS:
                   2437:         val = env->sysenter_cs;
                   2438:         break;
                   2439:     case MSR_IA32_SYSENTER_ESP:
                   2440:         val = env->sysenter_esp;
                   2441:         break;
                   2442:     case MSR_IA32_SYSENTER_EIP:
                   2443:         val = env->sysenter_eip;
                   2444:         break;
                   2445:     case MSR_IA32_APICBASE:
                   2446:         val = cpu_get_apic_base(env);
                   2447:         break;
                   2448:     case MSR_EFER:
                   2449:         val = env->efer;
                   2450:         break;
                   2451:     case MSR_STAR:
                   2452:         val = env->star;
                   2453:         break;
                   2454:     case MSR_PAT:
                   2455:         val = env->pat;
                   2456:         break;
                   2457: #ifdef TARGET_X86_64
                   2458:     case MSR_LSTAR:
                   2459:         val = env->lstar;
                   2460:         break;
                   2461:     case MSR_CSTAR:
                   2462:         val = env->cstar;
                   2463:         break;
                   2464:     case MSR_FMASK:
                   2465:         val = env->fmask;
                   2466:         break;
                   2467:     case MSR_FSBASE:
                   2468:         val = env->segs[R_FS].base;
                   2469:         break;
                   2470:     case MSR_GSBASE:
                   2471:         val = env->segs[R_GS].base;
                   2472:         break;
                   2473:     case MSR_KERNELGSBASE:
                   2474:         val = env->kernelgsbase;
                   2475:         break;
                   2476: #endif
                   2477:     default:
                   2478:         /* XXX: exception ? */
                   2479:         val = 0;
                   2480:         break; 
                   2481:     }
                   2482:     EAX = (uint32_t)(val);
                   2483:     EDX = (uint32_t)(val >> 32);
                   2484: }
                   2485: #endif
                   2486: 
                   2487: void helper_lsl(void)
                   2488: {
                   2489:     unsigned int selector, limit;
                   2490:     uint32_t e1, e2, eflags;
                   2491:     int rpl, dpl, cpl, type;
                   2492: 
                   2493:     eflags = cc_table[CC_OP].compute_all();
                   2494:     selector = T0 & 0xffff;
                   2495:     if (load_segment(&e1, &e2, selector) != 0)
                   2496:         goto fail;
                   2497:     rpl = selector & 3;
                   2498:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2499:     cpl = env->hflags & HF_CPL_MASK;
                   2500:     if (e2 & DESC_S_MASK) {
                   2501:         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
                   2502:             /* conforming */
                   2503:         } else {
                   2504:             if (dpl < cpl || dpl < rpl)
                   2505:                 goto fail;
                   2506:         }
                   2507:     } else {
                   2508:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                   2509:         switch(type) {
                   2510:         case 1:
                   2511:         case 2:
                   2512:         case 3:
                   2513:         case 9:
                   2514:         case 11:
                   2515:             break;
                   2516:         default:
                   2517:             goto fail;
                   2518:         }
                   2519:         if (dpl < cpl || dpl < rpl) {
                   2520:         fail:
                   2521:             CC_SRC = eflags & ~CC_Z;
                   2522:             return;
                   2523:         }
                   2524:     }
                   2525:     limit = get_seg_limit(e1, e2);
                   2526:     T1 = limit;
                   2527:     CC_SRC = eflags | CC_Z;
                   2528: }
                   2529: 
                   2530: void helper_lar(void)
                   2531: {
                   2532:     unsigned int selector;
                   2533:     uint32_t e1, e2, eflags;
                   2534:     int rpl, dpl, cpl, type;
                   2535: 
                   2536:     eflags = cc_table[CC_OP].compute_all();
                   2537:     selector = T0 & 0xffff;
                   2538:     if ((selector & 0xfffc) == 0)
                   2539:         goto fail;
                   2540:     if (load_segment(&e1, &e2, selector) != 0)
                   2541:         goto fail;
                   2542:     rpl = selector & 3;
                   2543:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2544:     cpl = env->hflags & HF_CPL_MASK;
                   2545:     if (e2 & DESC_S_MASK) {
                   2546:         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
                   2547:             /* conforming */
                   2548:         } else {
                   2549:             if (dpl < cpl || dpl < rpl)
                   2550:                 goto fail;
                   2551:         }
                   2552:     } else {
                   2553:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                   2554:         switch(type) {
                   2555:         case 1:
                   2556:         case 2:
                   2557:         case 3:
                   2558:         case 4:
                   2559:         case 5:
                   2560:         case 9:
                   2561:         case 11:
                   2562:         case 12:
                   2563:             break;
                   2564:         default:
                   2565:             goto fail;
                   2566:         }
                   2567:         if (dpl < cpl || dpl < rpl) {
                   2568:         fail:
                   2569:             CC_SRC = eflags & ~CC_Z;
                   2570:             return;
                   2571:         }
                   2572:     }
                   2573:     T1 = e2 & 0x00f0ff00;
                   2574:     CC_SRC = eflags | CC_Z;
                   2575: }
                   2576: 
                   2577: void helper_verr(void)
                   2578: {
                   2579:     unsigned int selector;
                   2580:     uint32_t e1, e2, eflags;
                   2581:     int rpl, dpl, cpl;
                   2582: 
                   2583:     eflags = cc_table[CC_OP].compute_all();
                   2584:     selector = T0 & 0xffff;
                   2585:     if ((selector & 0xfffc) == 0)
                   2586:         goto fail;
                   2587:     if (load_segment(&e1, &e2, selector) != 0)
                   2588:         goto fail;
                   2589:     if (!(e2 & DESC_S_MASK))
                   2590:         goto fail;
                   2591:     rpl = selector & 3;
                   2592:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2593:     cpl = env->hflags & HF_CPL_MASK;
                   2594:     if (e2 & DESC_CS_MASK) {
                   2595:         if (!(e2 & DESC_R_MASK))
                   2596:             goto fail;
                   2597:         if (!(e2 & DESC_C_MASK)) {
                   2598:             if (dpl < cpl || dpl < rpl)
                   2599:                 goto fail;
                   2600:         }
                   2601:     } else {
                   2602:         if (dpl < cpl || dpl < rpl) {
                   2603:         fail:
                   2604:             CC_SRC = eflags & ~CC_Z;
                   2605:             return;
                   2606:         }
                   2607:     }
                   2608:     CC_SRC = eflags | CC_Z;
                   2609: }
                   2610: 
                   2611: void helper_verw(void)
                   2612: {
                   2613:     unsigned int selector;
                   2614:     uint32_t e1, e2, eflags;
                   2615:     int rpl, dpl, cpl;
                   2616: 
                   2617:     eflags = cc_table[CC_OP].compute_all();
                   2618:     selector = T0 & 0xffff;
                   2619:     if ((selector & 0xfffc) == 0)
                   2620:         goto fail;
                   2621:     if (load_segment(&e1, &e2, selector) != 0)
                   2622:         goto fail;
                   2623:     if (!(e2 & DESC_S_MASK))
                   2624:         goto fail;
                   2625:     rpl = selector & 3;
                   2626:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2627:     cpl = env->hflags & HF_CPL_MASK;
                   2628:     if (e2 & DESC_CS_MASK) {
                   2629:         goto fail;
                   2630:     } else {
                   2631:         if (dpl < cpl || dpl < rpl)
                   2632:             goto fail;
                   2633:         if (!(e2 & DESC_W_MASK)) {
                   2634:         fail:
                   2635:             CC_SRC = eflags & ~CC_Z;
                   2636:             return;
                   2637:         }
                   2638:     }
                   2639:     CC_SRC = eflags | CC_Z;
                   2640: }
                   2641: 
                   2642: /* FPU helpers */
                   2643: 
                   2644: void helper_fldt_ST0_A0(void)
                   2645: {
                   2646:     int new_fpstt;
                   2647:     new_fpstt = (env->fpstt - 1) & 7;
                   2648:     env->fpregs[new_fpstt].d = helper_fldt(A0);
                   2649:     env->fpstt = new_fpstt;
                   2650:     env->fptags[new_fpstt] = 0; /* validate stack entry */
                   2651: }
                   2652: 
                   2653: void helper_fstt_ST0_A0(void)
                   2654: {
                   2655:     helper_fstt(ST0, A0);
                   2656: }
                   2657: 
                   2658: void fpu_set_exception(int mask)
                   2659: {
                   2660:     env->fpus |= mask;
                   2661:     if (env->fpus & (~env->fpuc & FPUC_EM))
                   2662:         env->fpus |= FPUS_SE | FPUS_B;
                   2663: }
                   2664: 
                   2665: CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
                   2666: {
                   2667:     if (b == 0.0) 
                   2668:         fpu_set_exception(FPUS_ZE);
                   2669:     return a / b;
                   2670: }
                   2671: 
                   2672: void fpu_raise_exception(void)
                   2673: {
                   2674:     if (env->cr[0] & CR0_NE_MASK) {
                   2675:         raise_exception(EXCP10_COPR);
                   2676:     } 
                   2677: #if !defined(CONFIG_USER_ONLY) 
                   2678:     else {
                   2679:         cpu_set_ferr(env);
                   2680:     }
                   2681: #endif
                   2682: }
                   2683: 
                   2684: /* BCD ops */
                   2685: 
                   2686: void helper_fbld_ST0_A0(void)
                   2687: {
                   2688:     CPU86_LDouble tmp;
                   2689:     uint64_t val;
                   2690:     unsigned int v;
                   2691:     int i;
                   2692: 
                   2693:     val = 0;
                   2694:     for(i = 8; i >= 0; i--) {
                   2695:         v = ldub(A0 + i);
                   2696:         val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
                   2697:     }
                   2698:     tmp = val;
                   2699:     if (ldub(A0 + 9) & 0x80)
                   2700:         tmp = -tmp;
                   2701:     fpush();
                   2702:     ST0 = tmp;
                   2703: }
                   2704: 
                   2705: void helper_fbst_ST0_A0(void)
                   2706: {
                   2707:     int v;
                   2708:     target_ulong mem_ref, mem_end;
                   2709:     int64_t val;
                   2710: 
                   2711:     val = floatx_to_int64(ST0, &env->fp_status);
                   2712:     mem_ref = A0;
                   2713:     mem_end = mem_ref + 9;
                   2714:     if (val < 0) {
                   2715:         stb(mem_end, 0x80);
                   2716:         val = -val;
                   2717:     } else {
                   2718:         stb(mem_end, 0x00);
                   2719:     }
                   2720:     while (mem_ref < mem_end) {
                   2721:         if (val == 0)
                   2722:             break;
                   2723:         v = val % 100;
                   2724:         val = val / 100;
                   2725:         v = ((v / 10) << 4) | (v % 10);
                   2726:         stb(mem_ref++, v);
                   2727:     }
                   2728:     while (mem_ref < mem_end) {
                   2729:         stb(mem_ref++, 0);
                   2730:     }
                   2731: }
                   2732: 
                   2733: void helper_f2xm1(void)
                   2734: {
                   2735:     ST0 = pow(2.0,ST0) - 1.0;
                   2736: }
                   2737: 
                   2738: void helper_fyl2x(void)
                   2739: {
                   2740:     CPU86_LDouble fptemp;
                   2741:     
                   2742:     fptemp = ST0;
                   2743:     if (fptemp>0.0){
                   2744:         fptemp = log(fptemp)/log(2.0);  /* log2(ST) */
                   2745:         ST1 *= fptemp;
                   2746:         fpop();
                   2747:     } else { 
                   2748:         env->fpus &= (~0x4700);
                   2749:         env->fpus |= 0x400;
                   2750:     }
                   2751: }
                   2752: 
                   2753: void helper_fptan(void)
                   2754: {
                   2755:     CPU86_LDouble fptemp;
                   2756: 
                   2757:     fptemp = ST0;
                   2758:     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   2759:         env->fpus |= 0x400;
                   2760:     } else {
                   2761:         ST0 = tan(fptemp);
                   2762:         fpush();
                   2763:         ST0 = 1.0;
                   2764:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   2765:         /* the above code is for  |arg| < 2**52 only */
                   2766:     }
                   2767: }
                   2768: 
                   2769: void helper_fpatan(void)
                   2770: {
                   2771:     CPU86_LDouble fptemp, fpsrcop;
                   2772: 
                   2773:     fpsrcop = ST1;
                   2774:     fptemp = ST0;
                   2775:     ST1 = atan2(fpsrcop,fptemp);
                   2776:     fpop();
                   2777: }
                   2778: 
                   2779: void helper_fxtract(void)
                   2780: {
                   2781:     CPU86_LDoubleU temp;
                   2782:     unsigned int expdif;
                   2783: 
                   2784:     temp.d = ST0;
                   2785:     expdif = EXPD(temp) - EXPBIAS;
                   2786:     /*DP exponent bias*/
                   2787:     ST0 = expdif;
                   2788:     fpush();
                   2789:     BIASEXPONENT(temp);
                   2790:     ST0 = temp.d;
                   2791: }
                   2792: 
                   2793: void helper_fprem1(void)
                   2794: {
                   2795:     CPU86_LDouble dblq, fpsrcop, fptemp;
                   2796:     CPU86_LDoubleU fpsrcop1, fptemp1;
                   2797:     int expdif;
                   2798:     int q;
                   2799: 
                   2800:     fpsrcop = ST0;
                   2801:     fptemp = ST1;
                   2802:     fpsrcop1.d = fpsrcop;
                   2803:     fptemp1.d = fptemp;
                   2804:     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
                   2805:     if (expdif < 53) {
                   2806:         dblq = fpsrcop / fptemp;
                   2807:         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
                   2808:         ST0 = fpsrcop - fptemp*dblq;
                   2809:         q = (int)dblq; /* cutting off top bits is assumed here */
                   2810:         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
                   2811:                                /* (C0,C1,C3) <-- (q2,q1,q0) */
                   2812:         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
                   2813:         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
                   2814:         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
                   2815:     } else {
                   2816:         env->fpus |= 0x400;  /* C2 <-- 1 */
                   2817:         fptemp = pow(2.0, expdif-50);
                   2818:         fpsrcop = (ST0 / ST1) / fptemp;
                   2819:         /* fpsrcop = integer obtained by rounding to the nearest */
                   2820:         fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
                   2821:             floor(fpsrcop): ceil(fpsrcop);
                   2822:         ST0 -= (ST1 * fpsrcop * fptemp);
                   2823:     }
                   2824: }
                   2825: 
                   2826: void helper_fprem(void)
                   2827: {
                   2828:     CPU86_LDouble dblq, fpsrcop, fptemp;
                   2829:     CPU86_LDoubleU fpsrcop1, fptemp1;
                   2830:     int expdif;
                   2831:     int q;
                   2832:     
                   2833:     fpsrcop = ST0;
                   2834:     fptemp = ST1;
                   2835:     fpsrcop1.d = fpsrcop;
                   2836:     fptemp1.d = fptemp;
                   2837:     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
                   2838:     if ( expdif < 53 ) {
                   2839:         dblq = fpsrcop / fptemp;
                   2840:         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
                   2841:         ST0 = fpsrcop - fptemp*dblq;
                   2842:         q = (int)dblq; /* cutting off top bits is assumed here */
                   2843:         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
                   2844:                                /* (C0,C1,C3) <-- (q2,q1,q0) */
                   2845:         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
                   2846:         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
                   2847:         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
                   2848:     } else {
                   2849:         env->fpus |= 0x400;  /* C2 <-- 1 */
                   2850:         fptemp = pow(2.0, expdif-50);
                   2851:         fpsrcop = (ST0 / ST1) / fptemp;
                   2852:         /* fpsrcop = integer obtained by chopping */
                   2853:         fpsrcop = (fpsrcop < 0.0)?
                   2854:             -(floor(fabs(fpsrcop))): floor(fpsrcop);
                   2855:         ST0 -= (ST1 * fpsrcop * fptemp);
                   2856:     }
                   2857: }
                   2858: 
                   2859: void helper_fyl2xp1(void)
                   2860: {
                   2861:     CPU86_LDouble fptemp;
                   2862: 
                   2863:     fptemp = ST0;
                   2864:     if ((fptemp+1.0)>0.0) {
                   2865:         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
                   2866:         ST1 *= fptemp;
                   2867:         fpop();
                   2868:     } else { 
                   2869:         env->fpus &= (~0x4700);
                   2870:         env->fpus |= 0x400;
                   2871:     }
                   2872: }
                   2873: 
                   2874: void helper_fsqrt(void)
                   2875: {
                   2876:     CPU86_LDouble fptemp;
                   2877: 
                   2878:     fptemp = ST0;
                   2879:     if (fptemp<0.0) { 
                   2880:         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
                   2881:         env->fpus |= 0x400;
                   2882:     }
                   2883:     ST0 = sqrt(fptemp);
                   2884: }
                   2885: 
                   2886: void helper_fsincos(void)
                   2887: {
                   2888:     CPU86_LDouble fptemp;
                   2889: 
                   2890:     fptemp = ST0;
                   2891:     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   2892:         env->fpus |= 0x400;
                   2893:     } else {
                   2894:         ST0 = sin(fptemp);
                   2895:         fpush();
                   2896:         ST0 = cos(fptemp);
                   2897:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   2898:         /* the above code is for  |arg| < 2**63 only */
                   2899:     }
                   2900: }
                   2901: 
                   2902: void helper_frndint(void)
                   2903: {
                   2904:     ST0 = floatx_round_to_int(ST0, &env->fp_status);
                   2905: }
                   2906: 
                   2907: void helper_fscale(void)
                   2908: {
                   2909:     ST0 = ldexp (ST0, (int)(ST1)); 
                   2910: }
                   2911: 
                   2912: void helper_fsin(void)
                   2913: {
                   2914:     CPU86_LDouble fptemp;
                   2915: 
                   2916:     fptemp = ST0;
                   2917:     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   2918:         env->fpus |= 0x400;
                   2919:     } else {
                   2920:         ST0 = sin(fptemp);
                   2921:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   2922:         /* the above code is for  |arg| < 2**53 only */
                   2923:     }
                   2924: }
                   2925: 
                   2926: void helper_fcos(void)
                   2927: {
                   2928:     CPU86_LDouble fptemp;
                   2929: 
                   2930:     fptemp = ST0;
                   2931:     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   2932:         env->fpus |= 0x400;
                   2933:     } else {
                   2934:         ST0 = cos(fptemp);
                   2935:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   2936:         /* the above code is for  |arg5 < 2**63 only */
                   2937:     }
                   2938: }
                   2939: 
                   2940: void helper_fxam_ST0(void)
                   2941: {
                   2942:     CPU86_LDoubleU temp;
                   2943:     int expdif;
                   2944: 
                   2945:     temp.d = ST0;
                   2946: 
                   2947:     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
                   2948:     if (SIGND(temp))
                   2949:         env->fpus |= 0x200; /* C1 <-- 1 */
                   2950: 
                   2951:     expdif = EXPD(temp);
                   2952:     if (expdif == MAXEXPD) {
                   2953:         if (MANTD(temp) == 0)
                   2954:             env->fpus |=  0x500 /*Infinity*/;
                   2955:         else
                   2956:             env->fpus |=  0x100 /*NaN*/;
                   2957:     } else if (expdif == 0) {
                   2958:         if (MANTD(temp) == 0)
                   2959:             env->fpus |=  0x4000 /*Zero*/;
                   2960:         else
                   2961:             env->fpus |= 0x4400 /*Denormal*/;
                   2962:     } else {
                   2963:         env->fpus |= 0x400;
                   2964:     }
                   2965: }
                   2966: 
                   2967: void helper_fstenv(target_ulong ptr, int data32)
                   2968: {
                   2969:     int fpus, fptag, exp, i;
                   2970:     uint64_t mant;
                   2971:     CPU86_LDoubleU tmp;
                   2972: 
                   2973:     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
                   2974:     fptag = 0;
                   2975:     for (i=7; i>=0; i--) {
                   2976:        fptag <<= 2;
                   2977:        if (env->fptags[i]) {
                   2978:             fptag |= 3;
                   2979:        } else {
                   2980:             tmp.d = env->fpregs[i].d;
                   2981:             exp = EXPD(tmp);
                   2982:             mant = MANTD(tmp);
                   2983:             if (exp == 0 && mant == 0) {
                   2984:                 /* zero */
                   2985:                fptag |= 1;
                   2986:            } else if (exp == 0 || exp == MAXEXPD
                   2987: #ifdef USE_X86LDOUBLE
                   2988:                        || (mant & (1LL << 63)) == 0
                   2989: #endif
                   2990:                        ) {
                   2991:                 /* NaNs, infinity, denormal */
                   2992:                 fptag |= 2;
                   2993:             }
                   2994:         }
                   2995:     }
                   2996:     if (data32) {
                   2997:         /* 32 bit */
                   2998:         stl(ptr, env->fpuc);
                   2999:         stl(ptr + 4, fpus);
                   3000:         stl(ptr + 8, fptag);
                   3001:         stl(ptr + 12, 0); /* fpip */
                   3002:         stl(ptr + 16, 0); /* fpcs */
                   3003:         stl(ptr + 20, 0); /* fpoo */
                   3004:         stl(ptr + 24, 0); /* fpos */
                   3005:     } else {
                   3006:         /* 16 bit */
                   3007:         stw(ptr, env->fpuc);
                   3008:         stw(ptr + 2, fpus);
                   3009:         stw(ptr + 4, fptag);
                   3010:         stw(ptr + 6, 0);
                   3011:         stw(ptr + 8, 0);
                   3012:         stw(ptr + 10, 0);
                   3013:         stw(ptr + 12, 0);
                   3014:     }
                   3015: }
                   3016: 
                   3017: void helper_fldenv(target_ulong ptr, int data32)
                   3018: {
                   3019:     int i, fpus, fptag;
                   3020: 
                   3021:     if (data32) {
                   3022:        env->fpuc = lduw(ptr);
                   3023:         fpus = lduw(ptr + 4);
                   3024:         fptag = lduw(ptr + 8);
                   3025:     }
                   3026:     else {
                   3027:        env->fpuc = lduw(ptr);
                   3028:         fpus = lduw(ptr + 2);
                   3029:         fptag = lduw(ptr + 4);
                   3030:     }
                   3031:     env->fpstt = (fpus >> 11) & 7;
                   3032:     env->fpus = fpus & ~0x3800;
                   3033:     for(i = 0;i < 8; i++) {
                   3034:         env->fptags[i] = ((fptag & 3) == 3);
                   3035:         fptag >>= 2;
                   3036:     }
                   3037: }
                   3038: 
                   3039: void helper_fsave(target_ulong ptr, int data32)
                   3040: {
                   3041:     CPU86_LDouble tmp;
                   3042:     int i;
                   3043: 
                   3044:     helper_fstenv(ptr, data32);
                   3045: 
                   3046:     ptr += (14 << data32);
                   3047:     for(i = 0;i < 8; i++) {
                   3048:         tmp = ST(i);
                   3049:         helper_fstt(tmp, ptr);
                   3050:         ptr += 10;
                   3051:     }
                   3052: 
                   3053:     /* fninit */
                   3054:     env->fpus = 0;
                   3055:     env->fpstt = 0;
                   3056:     env->fpuc = 0x37f;
                   3057:     env->fptags[0] = 1;
                   3058:     env->fptags[1] = 1;
                   3059:     env->fptags[2] = 1;
                   3060:     env->fptags[3] = 1;
                   3061:     env->fptags[4] = 1;
                   3062:     env->fptags[5] = 1;
                   3063:     env->fptags[6] = 1;
                   3064:     env->fptags[7] = 1;
                   3065: }
                   3066: 
                   3067: void helper_frstor(target_ulong ptr, int data32)
                   3068: {
                   3069:     CPU86_LDouble tmp;
                   3070:     int i;
                   3071: 
                   3072:     helper_fldenv(ptr, data32);
                   3073:     ptr += (14 << data32);
                   3074: 
                   3075:     for(i = 0;i < 8; i++) {
                   3076:         tmp = helper_fldt(ptr);
                   3077:         ST(i) = tmp;
                   3078:         ptr += 10;
                   3079:     }
                   3080: }
                   3081: 
                   3082: void helper_fxsave(target_ulong ptr, int data64)
                   3083: {
                   3084:     int fpus, fptag, i, nb_xmm_regs;
                   3085:     CPU86_LDouble tmp;
                   3086:     target_ulong addr;
                   3087: 
                   3088:     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
                   3089:     fptag = 0;
                   3090:     for(i = 0; i < 8; i++) {
                   3091:         fptag |= (env->fptags[i] << i);
                   3092:     }
                   3093:     stw(ptr, env->fpuc);
                   3094:     stw(ptr + 2, fpus);
                   3095:     stw(ptr + 4, fptag ^ 0xff);
                   3096: 
                   3097:     addr = ptr + 0x20;
                   3098:     for(i = 0;i < 8; i++) {
                   3099:         tmp = ST(i);
                   3100:         helper_fstt(tmp, addr);
                   3101:         addr += 16;
                   3102:     }
                   3103:     
                   3104:     if (env->cr[4] & CR4_OSFXSR_MASK) {
                   3105:         /* XXX: finish it */
                   3106:         stl(ptr + 0x18, env->mxcsr); /* mxcsr */
                   3107:         stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
                   3108:         nb_xmm_regs = 8 << data64;
                   3109:         addr = ptr + 0xa0;
                   3110:         for(i = 0; i < nb_xmm_regs; i++) {
                   3111:             stq(addr, env->xmm_regs[i].XMM_Q(0));
                   3112:             stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
                   3113:             addr += 16;
                   3114:         }
                   3115:     }
                   3116: }
                   3117: 
                   3118: void helper_fxrstor(target_ulong ptr, int data64)
                   3119: {
                   3120:     int i, fpus, fptag, nb_xmm_regs;
                   3121:     CPU86_LDouble tmp;
                   3122:     target_ulong addr;
                   3123: 
                   3124:     env->fpuc = lduw(ptr);
                   3125:     fpus = lduw(ptr + 2);
                   3126:     fptag = lduw(ptr + 4);
                   3127:     env->fpstt = (fpus >> 11) & 7;
                   3128:     env->fpus = fpus & ~0x3800;
                   3129:     fptag ^= 0xff;
                   3130:     for(i = 0;i < 8; i++) {
                   3131:         env->fptags[i] = ((fptag >> i) & 1);
                   3132:     }
                   3133: 
                   3134:     addr = ptr + 0x20;
                   3135:     for(i = 0;i < 8; i++) {
                   3136:         tmp = helper_fldt(addr);
                   3137:         ST(i) = tmp;
                   3138:         addr += 16;
                   3139:     }
                   3140: 
                   3141:     if (env->cr[4] & CR4_OSFXSR_MASK) {
                   3142:         /* XXX: finish it */
                   3143:         env->mxcsr = ldl(ptr + 0x18);
                   3144:         //ldl(ptr + 0x1c);
                   3145:         nb_xmm_regs = 8 << data64;
                   3146:         addr = ptr + 0xa0;
                   3147:         for(i = 0; i < nb_xmm_regs; i++) {
                   3148:             env->xmm_regs[i].XMM_Q(0) = ldq(addr);
                   3149:             env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
                   3150:             addr += 16;
                   3151:         }
                   3152:     }
                   3153: }
                   3154: 
                   3155: #ifndef USE_X86LDOUBLE
                   3156: 
                   3157: void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
                   3158: {
                   3159:     CPU86_LDoubleU temp;
                   3160:     int e;
                   3161: 
                   3162:     temp.d = f;
                   3163:     /* mantissa */
                   3164:     *pmant = (MANTD(temp) << 11) | (1LL << 63);
                   3165:     /* exponent + sign */
                   3166:     e = EXPD(temp) - EXPBIAS + 16383;
                   3167:     e |= SIGND(temp) >> 16;
                   3168:     *pexp = e;
                   3169: }
                   3170: 
                   3171: CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
                   3172: {
                   3173:     CPU86_LDoubleU temp;
                   3174:     int e;
                   3175:     uint64_t ll;
                   3176: 
                   3177:     /* XXX: handle overflow ? */
                   3178:     e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
                   3179:     e |= (upper >> 4) & 0x800; /* sign */
                   3180:     ll = (mant >> 11) & ((1LL << 52) - 1);
                   3181: #ifdef __arm__
                   3182:     temp.l.upper = (e << 20) | (ll >> 32);
                   3183:     temp.l.lower = ll;
                   3184: #else
                   3185:     temp.ll = ll | ((uint64_t)e << 52);
                   3186: #endif
                   3187:     return temp.d;
                   3188: }
                   3189: 
                   3190: #else
                   3191: 
                   3192: void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
                   3193: {
                   3194:     CPU86_LDoubleU temp;
                   3195: 
                   3196:     temp.d = f;
                   3197:     *pmant = temp.l.lower;
                   3198:     *pexp = temp.l.upper;
                   3199: }
                   3200: 
                   3201: CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
                   3202: {
                   3203:     CPU86_LDoubleU temp;
                   3204: 
                   3205:     temp.l.upper = upper;
                   3206:     temp.l.lower = mant;
                   3207:     return temp.d;
                   3208: }
                   3209: #endif
                   3210: 
                   3211: #ifdef TARGET_X86_64
                   3212: 
                   3213: //#define DEBUG_MULDIV
                   3214: 
                   3215: static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
                   3216: {
                   3217:     *plow += a;
                   3218:     /* carry test */
                   3219:     if (*plow < a)
                   3220:         (*phigh)++;
                   3221:     *phigh += b;
                   3222: }
                   3223: 
                   3224: static void neg128(uint64_t *plow, uint64_t *phigh)
                   3225: {
                   3226:     *plow = ~ *plow;
                   3227:     *phigh = ~ *phigh;
                   3228:     add128(plow, phigh, 1, 0);
                   3229: }
                   3230: 
                   3231: static void mul64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
                   3232: {
                   3233:     uint32_t a0, a1, b0, b1;
                   3234:     uint64_t v;
                   3235: 
                   3236:     a0 = a;
                   3237:     a1 = a >> 32;
                   3238: 
                   3239:     b0 = b;
                   3240:     b1 = b >> 32;
                   3241:     
                   3242:     v = (uint64_t)a0 * (uint64_t)b0;
                   3243:     *plow = v;
                   3244:     *phigh = 0;
                   3245: 
                   3246:     v = (uint64_t)a0 * (uint64_t)b1;
                   3247:     add128(plow, phigh, v << 32, v >> 32);
                   3248:     
                   3249:     v = (uint64_t)a1 * (uint64_t)b0;
                   3250:     add128(plow, phigh, v << 32, v >> 32);
                   3251:     
                   3252:     v = (uint64_t)a1 * (uint64_t)b1;
                   3253:     *phigh += v;
                   3254: #ifdef DEBUG_MULDIV
                   3255:     printf("mul: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
                   3256:            a, b, *phigh, *plow);
                   3257: #endif
                   3258: }
                   3259: 
                   3260: static void imul64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
                   3261: {
                   3262:     int sa, sb;
                   3263:     sa = (a < 0);
                   3264:     if (sa)
                   3265:         a = -a;
                   3266:     sb = (b < 0);
                   3267:     if (sb)
                   3268:         b = -b;
                   3269:     mul64(plow, phigh, a, b);
                   3270:     if (sa ^ sb) {
                   3271:         neg128(plow, phigh);
                   3272:     }
                   3273: }
                   3274: 
                   3275: /* return TRUE if overflow */
                   3276: static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
                   3277: {
                   3278:     uint64_t q, r, a1, a0;
1.1.1.2   root     3279:     int i, qb, ab;
1.1       root     3280: 
                   3281:     a0 = *plow;
                   3282:     a1 = *phigh;
                   3283:     if (a1 == 0) {
                   3284:         q = a0 / b;
                   3285:         r = a0 % b;
                   3286:         *plow = q;
                   3287:         *phigh = r;
                   3288:     } else {
                   3289:         if (a1 >= b)
                   3290:             return 1;
                   3291:         /* XXX: use a better algorithm */
                   3292:         for(i = 0; i < 64; i++) {
1.1.1.2   root     3293:             ab = a1 >> 63;
1.1       root     3294:             a1 = (a1 << 1) | (a0 >> 63);
1.1.1.2   root     3295:             if (ab || a1 >= b) {
1.1       root     3296:                 a1 -= b;
                   3297:                 qb = 1;
                   3298:             } else {
                   3299:                 qb = 0;
                   3300:             }
                   3301:             a0 = (a0 << 1) | qb;
                   3302:         }
                   3303: #if defined(DEBUG_MULDIV)
                   3304:         printf("div: 0x%016llx%016llx / 0x%016llx: q=0x%016llx r=0x%016llx\n",
                   3305:                *phigh, *plow, b, a0, a1);
                   3306: #endif
                   3307:         *plow = a0;
                   3308:         *phigh = a1;
                   3309:     }
                   3310:     return 0;
                   3311: }
                   3312: 
                   3313: /* return TRUE if overflow */
                   3314: static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
                   3315: {
                   3316:     int sa, sb;
                   3317:     sa = ((int64_t)*phigh < 0);
                   3318:     if (sa)
                   3319:         neg128(plow, phigh);
                   3320:     sb = (b < 0);
                   3321:     if (sb)
                   3322:         b = -b;
                   3323:     if (div64(plow, phigh, b) != 0)
                   3324:         return 1;
                   3325:     if (sa ^ sb) {
                   3326:         if (*plow > (1ULL << 63))
                   3327:             return 1;
                   3328:         *plow = - *plow;
                   3329:     } else {
                   3330:         if (*plow >= (1ULL << 63))
                   3331:             return 1;
                   3332:     }
                   3333:     if (sa)
                   3334:         *phigh = - *phigh;
                   3335:     return 0;
                   3336: }
                   3337: 
                   3338: void helper_mulq_EAX_T0(void)
                   3339: {
                   3340:     uint64_t r0, r1;
                   3341: 
                   3342:     mul64(&r0, &r1, EAX, T0);
                   3343:     EAX = r0;
                   3344:     EDX = r1;
                   3345:     CC_DST = r0;
                   3346:     CC_SRC = r1;
                   3347: }
                   3348: 
                   3349: void helper_imulq_EAX_T0(void)
                   3350: {
                   3351:     uint64_t r0, r1;
                   3352: 
                   3353:     imul64(&r0, &r1, EAX, T0);
                   3354:     EAX = r0;
                   3355:     EDX = r1;
                   3356:     CC_DST = r0;
                   3357:     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
                   3358: }
                   3359: 
                   3360: void helper_imulq_T0_T1(void)
                   3361: {
                   3362:     uint64_t r0, r1;
                   3363: 
                   3364:     imul64(&r0, &r1, T0, T1);
                   3365:     T0 = r0;
                   3366:     CC_DST = r0;
                   3367:     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
                   3368: }
                   3369: 
                   3370: void helper_divq_EAX_T0(void)
                   3371: {
                   3372:     uint64_t r0, r1;
                   3373:     if (T0 == 0) {
                   3374:         raise_exception(EXCP00_DIVZ);
                   3375:     }
                   3376:     r0 = EAX;
                   3377:     r1 = EDX;
                   3378:     if (div64(&r0, &r1, T0))
                   3379:         raise_exception(EXCP00_DIVZ);
                   3380:     EAX = r0;
                   3381:     EDX = r1;
                   3382: }
                   3383: 
                   3384: void helper_idivq_EAX_T0(void)
                   3385: {
                   3386:     uint64_t r0, r1;
                   3387:     if (T0 == 0) {
                   3388:         raise_exception(EXCP00_DIVZ);
                   3389:     }
                   3390:     r0 = EAX;
                   3391:     r1 = EDX;
                   3392:     if (idiv64(&r0, &r1, T0))
                   3393:         raise_exception(EXCP00_DIVZ);
                   3394:     EAX = r0;
                   3395:     EDX = r1;
                   3396: }
                   3397: 
1.1.1.3 ! root     3398: void helper_bswapq_T0(void)
        !          3399: {
        !          3400:     T0 = bswap64(T0);
        !          3401: }
1.1       root     3402: #endif
                   3403: 
                   3404: float approx_rsqrt(float a)
                   3405: {
                   3406:     return 1.0 / sqrt(a);
                   3407: }
                   3408: 
                   3409: float approx_rcp(float a)
                   3410: {
                   3411:     return 1.0 / a;
                   3412: }
                   3413: 
                   3414: void update_fp_status(void)
                   3415: {
                   3416:     int rnd_type;
                   3417: 
                   3418:     /* set rounding mode */
                   3419:     switch(env->fpuc & RC_MASK) {
                   3420:     default:
                   3421:     case RC_NEAR:
                   3422:         rnd_type = float_round_nearest_even;
                   3423:         break;
                   3424:     case RC_DOWN:
                   3425:         rnd_type = float_round_down;
                   3426:         break;
                   3427:     case RC_UP:
                   3428:         rnd_type = float_round_up;
                   3429:         break;
                   3430:     case RC_CHOP:
                   3431:         rnd_type = float_round_to_zero;
                   3432:         break;
                   3433:     }
                   3434:     set_float_rounding_mode(rnd_type, &env->fp_status);
                   3435: #ifdef FLOATX80
                   3436:     switch((env->fpuc >> 8) & 3) {
                   3437:     case 0:
                   3438:         rnd_type = 32;
                   3439:         break;
                   3440:     case 2:
                   3441:         rnd_type = 64;
                   3442:         break;
                   3443:     case 3:
                   3444:     default:
                   3445:         rnd_type = 80;
                   3446:         break;
                   3447:     }
                   3448:     set_floatx80_rounding_precision(rnd_type, &env->fp_status);
                   3449: #endif
                   3450: }
                   3451: 
                   3452: #if !defined(CONFIG_USER_ONLY) 
                   3453: 
                   3454: #define MMUSUFFIX _mmu
                   3455: #define GETPC() (__builtin_return_address(0))
                   3456: 
                   3457: #define SHIFT 0
                   3458: #include "softmmu_template.h"
                   3459: 
                   3460: #define SHIFT 1
                   3461: #include "softmmu_template.h"
                   3462: 
                   3463: #define SHIFT 2
                   3464: #include "softmmu_template.h"
                   3465: 
                   3466: #define SHIFT 3
                   3467: #include "softmmu_template.h"
                   3468: 
                   3469: #endif
                   3470: 
                   3471: /* try to fill the TLB and return an exception if error. If retaddr is
                   3472:    NULL, it means that the function was called in C code (i.e. not
                   3473:    from generated code or from helper.c) */
                   3474: /* XXX: fix it to restore all registers */
                   3475: void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
                   3476: {
                   3477:     TranslationBlock *tb;
                   3478:     int ret;
                   3479:     unsigned long pc;
                   3480:     CPUX86State *saved_env;
                   3481: 
                   3482:     /* XXX: hack to restore env in all cases, even if not called from
                   3483:        generated code */
                   3484:     saved_env = env;
                   3485:     env = cpu_single_env;
                   3486: 
                   3487:     ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1);
                   3488:     if (ret) {
                   3489:         if (retaddr) {
                   3490:             /* now we have a real cpu fault */
                   3491:             pc = (unsigned long)retaddr;
                   3492:             tb = tb_find_pc(pc);
                   3493:             if (tb) {
                   3494:                 /* the PC is inside the translated code. It means that we have
                   3495:                    a virtual CPU fault */
                   3496:                 cpu_restore_state(tb, env, pc, NULL);
                   3497:             }
                   3498:         }
                   3499:         if (retaddr)
1.1.1.2   root     3500:             raise_exception_err(env->exception_index, env->error_code);
1.1       root     3501:         else
1.1.1.2   root     3502:             raise_exception_err_norestore(env->exception_index, env->error_code);
1.1       root     3503:     }
                   3504:     env = saved_env;
                   3505: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.