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

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

unix.superglobalmegacorp.com

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