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

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

unix.superglobalmegacorp.com

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