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

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: 
1.1.1.5 ! root      556: #ifdef TARGET_X86_64
        !           557: #define SET_ESP(val, sp_mask)\
        !           558: do {\
        !           559:     if ((sp_mask) == 0xffff)\
        !           560:         ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
        !           561:     else if ((sp_mask) == 0xffffffffLL)\
        !           562:         ESP = (uint32_t)(val);\
        !           563:     else\
        !           564:         ESP = (val);\
        !           565: } while (0)
        !           566: #else
        !           567: #define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
        !           568: #endif
        !           569: 
1.1       root      570: /* XXX: add a is_user flag to have proper security support */
                    571: #define PUSHW(ssp, sp, sp_mask, val)\
                    572: {\
                    573:     sp -= 2;\
                    574:     stw_kernel((ssp) + (sp & (sp_mask)), (val));\
                    575: }
                    576: 
                    577: #define PUSHL(ssp, sp, sp_mask, val)\
                    578: {\
                    579:     sp -= 4;\
                    580:     stl_kernel((ssp) + (sp & (sp_mask)), (val));\
                    581: }
                    582: 
                    583: #define POPW(ssp, sp, sp_mask, val)\
                    584: {\
                    585:     val = lduw_kernel((ssp) + (sp & (sp_mask)));\
                    586:     sp += 2;\
                    587: }
                    588: 
                    589: #define POPL(ssp, sp, sp_mask, val)\
                    590: {\
                    591:     val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
                    592:     sp += 4;\
                    593: }
                    594: 
                    595: /* protected mode interrupt */
                    596: static void do_interrupt_protected(int intno, int is_int, int error_code,
                    597:                                    unsigned int next_eip, int is_hw)
                    598: {
                    599:     SegmentCache *dt;
                    600:     target_ulong ptr, ssp;
1.1.1.5 ! root      601:     int type, dpl, selector, ss_dpl, cpl;
1.1       root      602:     int has_error_code, new_stack, shift;
                    603:     uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
1.1.1.5 ! root      604:     uint32_t old_eip, sp_mask;
1.1       root      605: 
                    606:     has_error_code = 0;
                    607:     if (!is_int && !is_hw) {
                    608:         switch(intno) {
                    609:         case 8:
                    610:         case 10:
                    611:         case 11:
                    612:         case 12:
                    613:         case 13:
                    614:         case 14:
                    615:         case 17:
                    616:             has_error_code = 1;
                    617:             break;
                    618:         }
                    619:     }
                    620:     if (is_int)
                    621:         old_eip = next_eip;
                    622:     else
                    623:         old_eip = env->eip;
                    624: 
                    625:     dt = &env->idt;
                    626:     if (intno * 8 + 7 > dt->limit)
                    627:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                    628:     ptr = dt->base + intno * 8;
                    629:     e1 = ldl_kernel(ptr);
                    630:     e2 = ldl_kernel(ptr + 4);
                    631:     /* check gate type */
                    632:     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
                    633:     switch(type) {
                    634:     case 5: /* task gate */
                    635:         /* must do that check here to return the correct error code */
                    636:         if (!(e2 & DESC_P_MASK))
                    637:             raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
                    638:         switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
                    639:         if (has_error_code) {
1.1.1.5 ! root      640:             int type;
        !           641:             uint32_t mask;
1.1       root      642:             /* push the error code */
                    643:             type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
                    644:             shift = type >> 3;
                    645:             if (env->segs[R_SS].flags & DESC_B_MASK)
                    646:                 mask = 0xffffffff;
                    647:             else
                    648:                 mask = 0xffff;
                    649:             esp = (ESP - (2 << shift)) & mask;
                    650:             ssp = env->segs[R_SS].base + esp;
                    651:             if (shift)
                    652:                 stl_kernel(ssp, error_code);
                    653:             else
                    654:                 stw_kernel(ssp, error_code);
1.1.1.5 ! root      655:             SET_ESP(esp, mask);
1.1       root      656:         }
                    657:         return;
                    658:     case 6: /* 286 interrupt gate */
                    659:     case 7: /* 286 trap gate */
                    660:     case 14: /* 386 interrupt gate */
                    661:     case 15: /* 386 trap gate */
                    662:         break;
                    663:     default:
                    664:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                    665:         break;
                    666:     }
                    667:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    668:     cpl = env->hflags & HF_CPL_MASK;
                    669:     /* check privledge if software int */
                    670:     if (is_int && dpl < cpl)
                    671:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                    672:     /* check valid bit */
                    673:     if (!(e2 & DESC_P_MASK))
                    674:         raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
                    675:     selector = e1 >> 16;
                    676:     offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
                    677:     if ((selector & 0xfffc) == 0)
                    678:         raise_exception_err(EXCP0D_GPF, 0);
                    679: 
                    680:     if (load_segment(&e1, &e2, selector) != 0)
                    681:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    682:     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
                    683:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    684:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    685:     if (dpl > cpl)
                    686:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    687:     if (!(e2 & DESC_P_MASK))
                    688:         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                    689:     if (!(e2 & DESC_C_MASK) && dpl < cpl) {
                    690:         /* to inner priviledge */
                    691:         get_ss_esp_from_tss(&ss, &esp, dpl);
                    692:         if ((ss & 0xfffc) == 0)
                    693:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    694:         if ((ss & 3) != dpl)
                    695:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    696:         if (load_segment(&ss_e1, &ss_e2, ss) != 0)
                    697:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    698:         ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
                    699:         if (ss_dpl != dpl)
                    700:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    701:         if (!(ss_e2 & DESC_S_MASK) ||
                    702:             (ss_e2 & DESC_CS_MASK) ||
                    703:             !(ss_e2 & DESC_W_MASK))
                    704:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    705:         if (!(ss_e2 & DESC_P_MASK))
                    706:             raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                    707:         new_stack = 1;
                    708:         sp_mask = get_sp_mask(ss_e2);
                    709:         ssp = get_seg_base(ss_e1, ss_e2);
                    710:     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
                    711:         /* to same priviledge */
                    712:         if (env->eflags & VM_MASK)
                    713:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    714:         new_stack = 0;
                    715:         sp_mask = get_sp_mask(env->segs[R_SS].flags);
                    716:         ssp = env->segs[R_SS].base;
                    717:         esp = ESP;
                    718:         dpl = cpl;
                    719:     } else {
                    720:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    721:         new_stack = 0; /* avoid warning */
                    722:         sp_mask = 0; /* avoid warning */
                    723:         ssp = 0; /* avoid warning */
                    724:         esp = 0; /* avoid warning */
                    725:     }
                    726: 
                    727:     shift = type >> 3;
                    728: 
                    729: #if 0
                    730:     /* XXX: check that enough room is available */
                    731:     push_size = 6 + (new_stack << 2) + (has_error_code << 1);
                    732:     if (env->eflags & VM_MASK)
                    733:         push_size += 8;
                    734:     push_size <<= shift;
                    735: #endif
                    736:     if (shift == 1) {
                    737:         if (new_stack) {
                    738:             if (env->eflags & VM_MASK) {
                    739:                 PUSHL(ssp, esp, sp_mask, env->segs[R_GS].selector);
                    740:                 PUSHL(ssp, esp, sp_mask, env->segs[R_FS].selector);
                    741:                 PUSHL(ssp, esp, sp_mask, env->segs[R_DS].selector);
                    742:                 PUSHL(ssp, esp, sp_mask, env->segs[R_ES].selector);
                    743:             }
                    744:             PUSHL(ssp, esp, sp_mask, env->segs[R_SS].selector);
                    745:             PUSHL(ssp, esp, sp_mask, ESP);
                    746:         }
                    747:         PUSHL(ssp, esp, sp_mask, compute_eflags());
                    748:         PUSHL(ssp, esp, sp_mask, env->segs[R_CS].selector);
                    749:         PUSHL(ssp, esp, sp_mask, old_eip);
                    750:         if (has_error_code) {
                    751:             PUSHL(ssp, esp, sp_mask, error_code);
                    752:         }
                    753:     } else {
                    754:         if (new_stack) {
                    755:             if (env->eflags & VM_MASK) {
                    756:                 PUSHW(ssp, esp, sp_mask, env->segs[R_GS].selector);
                    757:                 PUSHW(ssp, esp, sp_mask, env->segs[R_FS].selector);
                    758:                 PUSHW(ssp, esp, sp_mask, env->segs[R_DS].selector);
                    759:                 PUSHW(ssp, esp, sp_mask, env->segs[R_ES].selector);
                    760:             }
                    761:             PUSHW(ssp, esp, sp_mask, env->segs[R_SS].selector);
                    762:             PUSHW(ssp, esp, sp_mask, ESP);
                    763:         }
                    764:         PUSHW(ssp, esp, sp_mask, compute_eflags());
                    765:         PUSHW(ssp, esp, sp_mask, env->segs[R_CS].selector);
                    766:         PUSHW(ssp, esp, sp_mask, old_eip);
                    767:         if (has_error_code) {
                    768:             PUSHW(ssp, esp, sp_mask, error_code);
                    769:         }
                    770:     }
                    771:     
                    772:     if (new_stack) {
                    773:         if (env->eflags & VM_MASK) {
                    774:             cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
                    775:             cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
                    776:             cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
                    777:             cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
                    778:         }
                    779:         ss = (ss & ~3) | dpl;
                    780:         cpu_x86_load_seg_cache(env, R_SS, ss, 
                    781:                                ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
                    782:     }
1.1.1.5 ! root      783:     SET_ESP(esp, sp_mask);
1.1       root      784: 
                    785:     selector = (selector & ~3) | dpl;
                    786:     cpu_x86_load_seg_cache(env, R_CS, selector, 
                    787:                    get_seg_base(e1, e2),
                    788:                    get_seg_limit(e1, e2),
                    789:                    e2);
                    790:     cpu_x86_set_cpl(env, dpl);
                    791:     env->eip = offset;
                    792: 
                    793:     /* interrupt gate clear IF mask */
                    794:     if ((type & 1) == 0) {
                    795:         env->eflags &= ~IF_MASK;
                    796:     }
                    797:     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
                    798: }
                    799: 
                    800: #ifdef TARGET_X86_64
                    801: 
                    802: #define PUSHQ(sp, val)\
                    803: {\
                    804:     sp -= 8;\
                    805:     stq_kernel(sp, (val));\
                    806: }
                    807: 
                    808: #define POPQ(sp, val)\
                    809: {\
                    810:     val = ldq_kernel(sp);\
                    811:     sp += 8;\
                    812: }
                    813: 
                    814: static inline target_ulong get_rsp_from_tss(int level)
                    815: {
                    816:     int index;
                    817:     
                    818: #if 0
                    819:     printf("TR: base=" TARGET_FMT_lx " limit=%x\n", 
                    820:            env->tr.base, env->tr.limit);
                    821: #endif
                    822: 
                    823:     if (!(env->tr.flags & DESC_P_MASK))
                    824:         cpu_abort(env, "invalid tss");
                    825:     index = 8 * level + 4;
                    826:     if ((index + 7) > env->tr.limit)
                    827:         raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
                    828:     return ldq_kernel(env->tr.base + index);
                    829: }
                    830: 
                    831: /* 64 bit interrupt */
                    832: static void do_interrupt64(int intno, int is_int, int error_code,
                    833:                            target_ulong next_eip, int is_hw)
                    834: {
                    835:     SegmentCache *dt;
                    836:     target_ulong ptr;
                    837:     int type, dpl, selector, cpl, ist;
                    838:     int has_error_code, new_stack;
                    839:     uint32_t e1, e2, e3, ss;
                    840:     target_ulong old_eip, esp, offset;
                    841: 
                    842:     has_error_code = 0;
                    843:     if (!is_int && !is_hw) {
                    844:         switch(intno) {
                    845:         case 8:
                    846:         case 10:
                    847:         case 11:
                    848:         case 12:
                    849:         case 13:
                    850:         case 14:
                    851:         case 17:
                    852:             has_error_code = 1;
                    853:             break;
                    854:         }
                    855:     }
                    856:     if (is_int)
                    857:         old_eip = next_eip;
                    858:     else
                    859:         old_eip = env->eip;
                    860: 
                    861:     dt = &env->idt;
                    862:     if (intno * 16 + 15 > dt->limit)
                    863:         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
                    864:     ptr = dt->base + intno * 16;
                    865:     e1 = ldl_kernel(ptr);
                    866:     e2 = ldl_kernel(ptr + 4);
                    867:     e3 = ldl_kernel(ptr + 8);
                    868:     /* check gate type */
                    869:     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
                    870:     switch(type) {
                    871:     case 14: /* 386 interrupt gate */
                    872:     case 15: /* 386 trap gate */
                    873:         break;
                    874:     default:
                    875:         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
                    876:         break;
                    877:     }
                    878:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    879:     cpl = env->hflags & HF_CPL_MASK;
                    880:     /* check privledge if software int */
                    881:     if (is_int && dpl < cpl)
                    882:         raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
                    883:     /* check valid bit */
                    884:     if (!(e2 & DESC_P_MASK))
                    885:         raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
                    886:     selector = e1 >> 16;
                    887:     offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
                    888:     ist = e2 & 7;
                    889:     if ((selector & 0xfffc) == 0)
                    890:         raise_exception_err(EXCP0D_GPF, 0);
                    891: 
                    892:     if (load_segment(&e1, &e2, selector) != 0)
                    893:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    894:     if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
                    895:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    896:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                    897:     if (dpl > cpl)
                    898:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    899:     if (!(e2 & DESC_P_MASK))
                    900:         raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                    901:     if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
                    902:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    903:     if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
                    904:         /* to inner priviledge */
                    905:         if (ist != 0)
                    906:             esp = get_rsp_from_tss(ist + 3);
                    907:         else
                    908:             esp = get_rsp_from_tss(dpl);
1.1.1.3   root      909:         esp &= ~0xfLL; /* align stack */
1.1       root      910:         ss = 0;
                    911:         new_stack = 1;
                    912:     } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
                    913:         /* to same priviledge */
                    914:         if (env->eflags & VM_MASK)
                    915:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    916:         new_stack = 0;
1.1.1.3   root      917:         if (ist != 0)
                    918:             esp = get_rsp_from_tss(ist + 3);
                    919:         else
                    920:             esp = ESP;
                    921:         esp &= ~0xfLL; /* align stack */
1.1       root      922:         dpl = cpl;
                    923:     } else {
                    924:         raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                    925:         new_stack = 0; /* avoid warning */
                    926:         esp = 0; /* avoid warning */
                    927:     }
                    928: 
                    929:     PUSHQ(esp, env->segs[R_SS].selector);
                    930:     PUSHQ(esp, ESP);
                    931:     PUSHQ(esp, compute_eflags());
                    932:     PUSHQ(esp, env->segs[R_CS].selector);
                    933:     PUSHQ(esp, old_eip);
                    934:     if (has_error_code) {
                    935:         PUSHQ(esp, error_code);
                    936:     }
                    937:     
                    938:     if (new_stack) {
                    939:         ss = 0 | dpl;
                    940:         cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
                    941:     }
                    942:     ESP = esp;
                    943: 
                    944:     selector = (selector & ~3) | dpl;
                    945:     cpu_x86_load_seg_cache(env, R_CS, selector, 
                    946:                    get_seg_base(e1, e2),
                    947:                    get_seg_limit(e1, e2),
                    948:                    e2);
                    949:     cpu_x86_set_cpl(env, dpl);
                    950:     env->eip = offset;
                    951: 
                    952:     /* interrupt gate clear IF mask */
                    953:     if ((type & 1) == 0) {
                    954:         env->eflags &= ~IF_MASK;
                    955:     }
                    956:     env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
                    957: }
                    958: #endif
                    959: 
                    960: void helper_syscall(int next_eip_addend)
                    961: {
                    962:     int selector;
                    963: 
                    964:     if (!(env->efer & MSR_EFER_SCE)) {
                    965:         raise_exception_err(EXCP06_ILLOP, 0);
                    966:     }
                    967:     selector = (env->star >> 32) & 0xffff;
                    968: #ifdef TARGET_X86_64
                    969:     if (env->hflags & HF_LMA_MASK) {
1.1.1.3   root      970:         int code64;
                    971: 
1.1       root      972:         ECX = env->eip + next_eip_addend;
                    973:         env->regs[11] = compute_eflags();
1.1.1.3   root      974:         
                    975:         code64 = env->hflags & HF_CS64_MASK;
1.1       root      976: 
                    977:         cpu_x86_set_cpl(env, 0);
                    978:         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
                    979:                            0, 0xffffffff, 
1.1.1.5 ! root      980:                                DESC_G_MASK | DESC_P_MASK |
1.1       root      981:                                DESC_S_MASK |
                    982:                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
                    983:         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
                    984:                                0, 0xffffffff,
                    985:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                    986:                                DESC_S_MASK |
                    987:                                DESC_W_MASK | DESC_A_MASK);
                    988:         env->eflags &= ~env->fmask;
1.1.1.3   root      989:         if (code64)
1.1       root      990:             env->eip = env->lstar;
                    991:         else
                    992:             env->eip = env->cstar;
                    993:     } else 
                    994: #endif
                    995:     {
                    996:         ECX = (uint32_t)(env->eip + next_eip_addend);
                    997:         
                    998:         cpu_x86_set_cpl(env, 0);
                    999:         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
                   1000:                            0, 0xffffffff, 
                   1001:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1002:                                DESC_S_MASK |
                   1003:                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                   1004:         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
                   1005:                                0, 0xffffffff,
                   1006:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1007:                                DESC_S_MASK |
                   1008:                                DESC_W_MASK | DESC_A_MASK);
                   1009:         env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
                   1010:         env->eip = (uint32_t)env->star;
                   1011:     }
                   1012: }
                   1013: 
                   1014: void helper_sysret(int dflag)
                   1015: {
                   1016:     int cpl, selector;
                   1017: 
                   1018:     if (!(env->efer & MSR_EFER_SCE)) {
                   1019:         raise_exception_err(EXCP06_ILLOP, 0);
                   1020:     }
                   1021:     cpl = env->hflags & HF_CPL_MASK;
                   1022:     if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
                   1023:         raise_exception_err(EXCP0D_GPF, 0);
                   1024:     }
                   1025:     selector = (env->star >> 48) & 0xffff;
                   1026: #ifdef TARGET_X86_64
                   1027:     if (env->hflags & HF_LMA_MASK) {
                   1028:         if (dflag == 2) {
                   1029:             cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, 
                   1030:                                    0, 0xffffffff, 
1.1.1.5 ! root     1031:                                    DESC_G_MASK | DESC_P_MASK |
1.1       root     1032:                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1033:                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | 
                   1034:                                    DESC_L_MASK);
                   1035:             env->eip = ECX;
                   1036:         } else {
                   1037:             cpu_x86_load_seg_cache(env, R_CS, selector | 3, 
                   1038:                                    0, 0xffffffff, 
                   1039:                                    DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1040:                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1041:                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                   1042:             env->eip = (uint32_t)ECX;
                   1043:         }
                   1044:         cpu_x86_load_seg_cache(env, R_SS, selector + 8, 
                   1045:                                0, 0xffffffff,
                   1046:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1047:                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1048:                                DESC_W_MASK | DESC_A_MASK);
                   1049:         load_eflags((uint32_t)(env->regs[11]), TF_MASK | AC_MASK | ID_MASK | 
                   1050:                     IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK);
                   1051:         cpu_x86_set_cpl(env, 3);
                   1052:     } else 
                   1053: #endif
                   1054:     {
                   1055:         cpu_x86_load_seg_cache(env, R_CS, selector | 3, 
                   1056:                                0, 0xffffffff, 
                   1057:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1058:                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1059:                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                   1060:         env->eip = (uint32_t)ECX;
                   1061:         cpu_x86_load_seg_cache(env, R_SS, selector + 8, 
                   1062:                                0, 0xffffffff,
                   1063:                                DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   1064:                                DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   1065:                                DESC_W_MASK | DESC_A_MASK);
                   1066:         env->eflags |= IF_MASK;
                   1067:         cpu_x86_set_cpl(env, 3);
                   1068:     }
                   1069: #ifdef USE_KQEMU
                   1070:     if (kqemu_is_ok(env)) {
                   1071:         if (env->hflags & HF_LMA_MASK)
                   1072:             CC_OP = CC_OP_EFLAGS;
                   1073:         env->exception_index = -1;
                   1074:         cpu_loop_exit();
                   1075:     }
                   1076: #endif
                   1077: }
                   1078: 
                   1079: /* real mode interrupt */
                   1080: static void do_interrupt_real(int intno, int is_int, int error_code,
                   1081:                               unsigned int next_eip)
                   1082: {
                   1083:     SegmentCache *dt;
                   1084:     target_ulong ptr, ssp;
                   1085:     int selector;
                   1086:     uint32_t offset, esp;
                   1087:     uint32_t old_cs, old_eip;
                   1088: 
                   1089:     /* real mode (simpler !) */
                   1090:     dt = &env->idt;
                   1091:     if (intno * 4 + 3 > dt->limit)
                   1092:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                   1093:     ptr = dt->base + intno * 4;
                   1094:     offset = lduw_kernel(ptr);
                   1095:     selector = lduw_kernel(ptr + 2);
                   1096:     esp = ESP;
                   1097:     ssp = env->segs[R_SS].base;
                   1098:     if (is_int)
                   1099:         old_eip = next_eip;
                   1100:     else
                   1101:         old_eip = env->eip;
                   1102:     old_cs = env->segs[R_CS].selector;
                   1103:     /* XXX: use SS segment size ? */
                   1104:     PUSHW(ssp, esp, 0xffff, compute_eflags());
                   1105:     PUSHW(ssp, esp, 0xffff, old_cs);
                   1106:     PUSHW(ssp, esp, 0xffff, old_eip);
                   1107:     
                   1108:     /* update processor state */
                   1109:     ESP = (ESP & ~0xffff) | (esp & 0xffff);
                   1110:     env->eip = offset;
                   1111:     env->segs[R_CS].selector = selector;
                   1112:     env->segs[R_CS].base = (selector << 4);
                   1113:     env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
                   1114: }
                   1115: 
                   1116: /* fake user mode interrupt */
                   1117: void do_interrupt_user(int intno, int is_int, int error_code, 
                   1118:                        target_ulong next_eip)
                   1119: {
                   1120:     SegmentCache *dt;
                   1121:     target_ulong ptr;
                   1122:     int dpl, cpl;
                   1123:     uint32_t e2;
                   1124: 
                   1125:     dt = &env->idt;
                   1126:     ptr = dt->base + (intno * 8);
                   1127:     e2 = ldl_kernel(ptr + 4);
                   1128:     
                   1129:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1130:     cpl = env->hflags & HF_CPL_MASK;
                   1131:     /* check privledge if software int */
                   1132:     if (is_int && dpl < cpl)
                   1133:         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
                   1134: 
                   1135:     /* Since we emulate only user space, we cannot do more than
                   1136:        exiting the emulation with the suitable exception and error
                   1137:        code */
                   1138:     if (is_int)
                   1139:         EIP = next_eip;
                   1140: }
                   1141: 
                   1142: /*
                   1143:  * Begin execution of an interruption. is_int is TRUE if coming from
                   1144:  * the int instruction. next_eip is the EIP value AFTER the interrupt
                   1145:  * instruction. It is only relevant if is_int is TRUE.  
                   1146:  */
                   1147: void do_interrupt(int intno, int is_int, int error_code, 
                   1148:                   target_ulong next_eip, int is_hw)
                   1149: {
1.1.1.3   root     1150:     if (loglevel & CPU_LOG_INT) {
1.1       root     1151:         if ((env->cr[0] & CR0_PE_MASK)) {
                   1152:             static int count;
                   1153:             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,
                   1154:                     count, intno, error_code, is_int,
                   1155:                     env->hflags & HF_CPL_MASK,
                   1156:                     env->segs[R_CS].selector, EIP,
                   1157:                     (int)env->segs[R_CS].base + EIP,
                   1158:                     env->segs[R_SS].selector, ESP);
                   1159:             if (intno == 0x0e) {
                   1160:                 fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
                   1161:             } else {
                   1162:                 fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
                   1163:             }
                   1164:             fprintf(logfile, "\n");
                   1165:             cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1.1.1.3   root     1166: #if 0
1.1       root     1167:             {
                   1168:                 int i;
                   1169:                 uint8_t *ptr;
                   1170:                 fprintf(logfile, "       code=");
                   1171:                 ptr = env->segs[R_CS].base + env->eip;
                   1172:                 for(i = 0; i < 16; i++) {
                   1173:                     fprintf(logfile, " %02x", ldub(ptr + i));
                   1174:                 }
                   1175:                 fprintf(logfile, "\n");
                   1176:             }
                   1177: #endif
                   1178:             count++;
                   1179:         }
                   1180:     }
                   1181:     if (env->cr[0] & CR0_PE_MASK) {
                   1182: #if TARGET_X86_64
                   1183:         if (env->hflags & HF_LMA_MASK) {
                   1184:             do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
                   1185:         } else
                   1186: #endif
                   1187:         {
                   1188:             do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
                   1189:         }
                   1190:     } else {
                   1191:         do_interrupt_real(intno, is_int, error_code, next_eip);
                   1192:     }
                   1193: }
                   1194: 
                   1195: /*
                   1196:  * Signal an interruption. It is executed in the main CPU loop.
                   1197:  * is_int is TRUE if coming from the int instruction. next_eip is the
                   1198:  * EIP value AFTER the interrupt instruction. It is only relevant if
                   1199:  * is_int is TRUE.  
                   1200:  */
                   1201: void raise_interrupt(int intno, int is_int, int error_code, 
                   1202:                      int next_eip_addend)
                   1203: {
                   1204:     env->exception_index = intno;
                   1205:     env->error_code = error_code;
                   1206:     env->exception_is_int = is_int;
                   1207:     env->exception_next_eip = env->eip + next_eip_addend;
                   1208:     cpu_loop_exit();
                   1209: }
                   1210: 
                   1211: /* same as raise_exception_err, but do not restore global registers */
                   1212: static void raise_exception_err_norestore(int exception_index, int error_code)
                   1213: {
                   1214:     env->exception_index = exception_index;
                   1215:     env->error_code = error_code;
                   1216:     env->exception_is_int = 0;
                   1217:     env->exception_next_eip = 0;
                   1218:     longjmp(env->jmp_env, 1);
                   1219: }
                   1220: 
                   1221: /* shortcuts to generate exceptions */
                   1222: 
                   1223: void (raise_exception_err)(int exception_index, int error_code)
                   1224: {
                   1225:     raise_interrupt(exception_index, 0, error_code, 0);
                   1226: }
                   1227: 
                   1228: void raise_exception(int exception_index)
                   1229: {
                   1230:     raise_interrupt(exception_index, 0, 0, 0);
                   1231: }
                   1232: 
1.1.1.5 ! root     1233: /* SMM support */
        !          1234: 
        !          1235: #if defined(CONFIG_USER_ONLY) 
        !          1236: 
        !          1237: void do_smm_enter(void)
        !          1238: {
        !          1239: }
        !          1240: 
        !          1241: void helper_rsm(void)
        !          1242: {
        !          1243: }
        !          1244: 
        !          1245: #else
        !          1246: 
        !          1247: #ifdef TARGET_X86_64
        !          1248: #define SMM_REVISION_ID 0x00020064
        !          1249: #else
        !          1250: #define SMM_REVISION_ID 0x00020000
        !          1251: #endif
        !          1252: 
        !          1253: void do_smm_enter(void)
        !          1254: {
        !          1255:     target_ulong sm_state;
        !          1256:     SegmentCache *dt;
        !          1257:     int i, offset;
        !          1258: 
        !          1259:     if (loglevel & CPU_LOG_INT) {
        !          1260:         fprintf(logfile, "SMM: enter\n");
        !          1261:         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
        !          1262:     }
        !          1263: 
        !          1264:     env->hflags |= HF_SMM_MASK;
        !          1265:     cpu_smm_update(env);
        !          1266: 
        !          1267:     sm_state = env->smbase + 0x8000;
        !          1268:     
        !          1269: #ifdef TARGET_X86_64
        !          1270:     for(i = 0; i < 6; i++) {
        !          1271:         dt = &env->segs[i];
        !          1272:         offset = 0x7e00 + i * 16;
        !          1273:         stw_phys(sm_state + offset, dt->selector);
        !          1274:         stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
        !          1275:         stl_phys(sm_state + offset + 4, dt->limit);
        !          1276:         stq_phys(sm_state + offset + 8, dt->base);
        !          1277:     }
        !          1278: 
        !          1279:     stq_phys(sm_state + 0x7e68, env->gdt.base);
        !          1280:     stl_phys(sm_state + 0x7e64, env->gdt.limit);
        !          1281: 
        !          1282:     stw_phys(sm_state + 0x7e70, env->ldt.selector);
        !          1283:     stq_phys(sm_state + 0x7e78, env->ldt.base);
        !          1284:     stl_phys(sm_state + 0x7e74, env->ldt.limit);
        !          1285:     stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
        !          1286:     
        !          1287:     stq_phys(sm_state + 0x7e88, env->idt.base);
        !          1288:     stl_phys(sm_state + 0x7e84, env->idt.limit);
        !          1289: 
        !          1290:     stw_phys(sm_state + 0x7e90, env->tr.selector);
        !          1291:     stq_phys(sm_state + 0x7e98, env->tr.base);
        !          1292:     stl_phys(sm_state + 0x7e94, env->tr.limit);
        !          1293:     stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
        !          1294:     
        !          1295:     stq_phys(sm_state + 0x7ed0, env->efer);
        !          1296: 
        !          1297:     stq_phys(sm_state + 0x7ff8, EAX);
        !          1298:     stq_phys(sm_state + 0x7ff0, ECX);
        !          1299:     stq_phys(sm_state + 0x7fe8, EDX);
        !          1300:     stq_phys(sm_state + 0x7fe0, EBX);
        !          1301:     stq_phys(sm_state + 0x7fd8, ESP);
        !          1302:     stq_phys(sm_state + 0x7fd0, EBP);
        !          1303:     stq_phys(sm_state + 0x7fc8, ESI);
        !          1304:     stq_phys(sm_state + 0x7fc0, EDI);
        !          1305:     for(i = 8; i < 16; i++) 
        !          1306:         stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
        !          1307:     stq_phys(sm_state + 0x7f78, env->eip);
        !          1308:     stl_phys(sm_state + 0x7f70, compute_eflags());
        !          1309:     stl_phys(sm_state + 0x7f68, env->dr[6]);
        !          1310:     stl_phys(sm_state + 0x7f60, env->dr[7]);
        !          1311: 
        !          1312:     stl_phys(sm_state + 0x7f48, env->cr[4]);
        !          1313:     stl_phys(sm_state + 0x7f50, env->cr[3]);
        !          1314:     stl_phys(sm_state + 0x7f58, env->cr[0]);
        !          1315: 
        !          1316:     stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
        !          1317:     stl_phys(sm_state + 0x7f00, env->smbase);
        !          1318: #else
        !          1319:     stl_phys(sm_state + 0x7ffc, env->cr[0]);
        !          1320:     stl_phys(sm_state + 0x7ff8, env->cr[3]);
        !          1321:     stl_phys(sm_state + 0x7ff4, compute_eflags());
        !          1322:     stl_phys(sm_state + 0x7ff0, env->eip);
        !          1323:     stl_phys(sm_state + 0x7fec, EDI);
        !          1324:     stl_phys(sm_state + 0x7fe8, ESI);
        !          1325:     stl_phys(sm_state + 0x7fe4, EBP);
        !          1326:     stl_phys(sm_state + 0x7fe0, ESP);
        !          1327:     stl_phys(sm_state + 0x7fdc, EBX);
        !          1328:     stl_phys(sm_state + 0x7fd8, EDX);
        !          1329:     stl_phys(sm_state + 0x7fd4, ECX);
        !          1330:     stl_phys(sm_state + 0x7fd0, EAX);
        !          1331:     stl_phys(sm_state + 0x7fcc, env->dr[6]);
        !          1332:     stl_phys(sm_state + 0x7fc8, env->dr[7]);
        !          1333:     
        !          1334:     stl_phys(sm_state + 0x7fc4, env->tr.selector);
        !          1335:     stl_phys(sm_state + 0x7f64, env->tr.base);
        !          1336:     stl_phys(sm_state + 0x7f60, env->tr.limit);
        !          1337:     stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
        !          1338:     
        !          1339:     stl_phys(sm_state + 0x7fc0, env->ldt.selector);
        !          1340:     stl_phys(sm_state + 0x7f80, env->ldt.base);
        !          1341:     stl_phys(sm_state + 0x7f7c, env->ldt.limit);
        !          1342:     stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
        !          1343:     
        !          1344:     stl_phys(sm_state + 0x7f74, env->gdt.base);
        !          1345:     stl_phys(sm_state + 0x7f70, env->gdt.limit);
        !          1346: 
        !          1347:     stl_phys(sm_state + 0x7f58, env->idt.base);
        !          1348:     stl_phys(sm_state + 0x7f54, env->idt.limit);
        !          1349: 
        !          1350:     for(i = 0; i < 6; i++) {
        !          1351:         dt = &env->segs[i];
        !          1352:         if (i < 3)
        !          1353:             offset = 0x7f84 + i * 12;
        !          1354:         else
        !          1355:             offset = 0x7f2c + (i - 3) * 12;
        !          1356:         stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
        !          1357:         stl_phys(sm_state + offset + 8, dt->base);
        !          1358:         stl_phys(sm_state + offset + 4, dt->limit);
        !          1359:         stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
        !          1360:     }
        !          1361:     stl_phys(sm_state + 0x7f14, env->cr[4]);
        !          1362: 
        !          1363:     stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
        !          1364:     stl_phys(sm_state + 0x7ef8, env->smbase);
        !          1365: #endif
        !          1366:     /* init SMM cpu state */
        !          1367: 
        !          1368: #ifdef TARGET_X86_64
        !          1369:     env->efer = 0;
        !          1370:     env->hflags &= ~HF_LMA_MASK;
        !          1371: #endif
        !          1372:     load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
        !          1373:     env->eip = 0x00008000;
        !          1374:     cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
        !          1375:                            0xffffffff, 0);
        !          1376:     cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
        !          1377:     cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
        !          1378:     cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
        !          1379:     cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
        !          1380:     cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
        !          1381:     
        !          1382:     cpu_x86_update_cr0(env, 
        !          1383:                        env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
        !          1384:     cpu_x86_update_cr4(env, 0);
        !          1385:     env->dr[7] = 0x00000400;
        !          1386:     CC_OP = CC_OP_EFLAGS;
        !          1387: }
        !          1388: 
        !          1389: void helper_rsm(void)
        !          1390: {
        !          1391:     target_ulong sm_state;
        !          1392:     int i, offset;
        !          1393:     uint32_t val;
        !          1394: 
        !          1395:     sm_state = env->smbase + 0x8000;
        !          1396: #ifdef TARGET_X86_64
        !          1397:     env->efer = ldq_phys(sm_state + 0x7ed0);
        !          1398:     if (env->efer & MSR_EFER_LMA)
        !          1399:         env->hflags |= HF_LMA_MASK;
        !          1400:     else
        !          1401:         env->hflags &= ~HF_LMA_MASK;
        !          1402: 
        !          1403:     for(i = 0; i < 6; i++) {
        !          1404:         offset = 0x7e00 + i * 16;
        !          1405:         cpu_x86_load_seg_cache(env, i, 
        !          1406:                                lduw_phys(sm_state + offset),
        !          1407:                                ldq_phys(sm_state + offset + 8),
        !          1408:                                ldl_phys(sm_state + offset + 4),
        !          1409:                                (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
        !          1410:     }
        !          1411: 
        !          1412:     env->gdt.base = ldq_phys(sm_state + 0x7e68);
        !          1413:     env->gdt.limit = ldl_phys(sm_state + 0x7e64);
        !          1414: 
        !          1415:     env->ldt.selector = lduw_phys(sm_state + 0x7e70);
        !          1416:     env->ldt.base = ldq_phys(sm_state + 0x7e78);
        !          1417:     env->ldt.limit = ldl_phys(sm_state + 0x7e74);
        !          1418:     env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
        !          1419:     
        !          1420:     env->idt.base = ldq_phys(sm_state + 0x7e88);
        !          1421:     env->idt.limit = ldl_phys(sm_state + 0x7e84);
        !          1422: 
        !          1423:     env->tr.selector = lduw_phys(sm_state + 0x7e90);
        !          1424:     env->tr.base = ldq_phys(sm_state + 0x7e98);
        !          1425:     env->tr.limit = ldl_phys(sm_state + 0x7e94);
        !          1426:     env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
        !          1427:     
        !          1428:     EAX = ldq_phys(sm_state + 0x7ff8);
        !          1429:     ECX = ldq_phys(sm_state + 0x7ff0);
        !          1430:     EDX = ldq_phys(sm_state + 0x7fe8);
        !          1431:     EBX = ldq_phys(sm_state + 0x7fe0);
        !          1432:     ESP = ldq_phys(sm_state + 0x7fd8);
        !          1433:     EBP = ldq_phys(sm_state + 0x7fd0);
        !          1434:     ESI = ldq_phys(sm_state + 0x7fc8);
        !          1435:     EDI = ldq_phys(sm_state + 0x7fc0);
        !          1436:     for(i = 8; i < 16; i++) 
        !          1437:         env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
        !          1438:     env->eip = ldq_phys(sm_state + 0x7f78);
        !          1439:     load_eflags(ldl_phys(sm_state + 0x7f70), 
        !          1440:                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
        !          1441:     env->dr[6] = ldl_phys(sm_state + 0x7f68);
        !          1442:     env->dr[7] = ldl_phys(sm_state + 0x7f60);
        !          1443: 
        !          1444:     cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
        !          1445:     cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
        !          1446:     cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
        !          1447: 
        !          1448:     val = ldl_phys(sm_state + 0x7efc); /* revision ID */
        !          1449:     if (val & 0x20000) {
        !          1450:         env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
        !          1451:     }
        !          1452: #else
        !          1453:     cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
        !          1454:     cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
        !          1455:     load_eflags(ldl_phys(sm_state + 0x7ff4), 
        !          1456:                 ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
        !          1457:     env->eip = ldl_phys(sm_state + 0x7ff0);
        !          1458:     EDI = ldl_phys(sm_state + 0x7fec);
        !          1459:     ESI = ldl_phys(sm_state + 0x7fe8);
        !          1460:     EBP = ldl_phys(sm_state + 0x7fe4);
        !          1461:     ESP = ldl_phys(sm_state + 0x7fe0);
        !          1462:     EBX = ldl_phys(sm_state + 0x7fdc);
        !          1463:     EDX = ldl_phys(sm_state + 0x7fd8);
        !          1464:     ECX = ldl_phys(sm_state + 0x7fd4);
        !          1465:     EAX = ldl_phys(sm_state + 0x7fd0);
        !          1466:     env->dr[6] = ldl_phys(sm_state + 0x7fcc);
        !          1467:     env->dr[7] = ldl_phys(sm_state + 0x7fc8);
        !          1468:     
        !          1469:     env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
        !          1470:     env->tr.base = ldl_phys(sm_state + 0x7f64);
        !          1471:     env->tr.limit = ldl_phys(sm_state + 0x7f60);
        !          1472:     env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
        !          1473:     
        !          1474:     env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
        !          1475:     env->ldt.base = ldl_phys(sm_state + 0x7f80);
        !          1476:     env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
        !          1477:     env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
        !          1478:     
        !          1479:     env->gdt.base = ldl_phys(sm_state + 0x7f74);
        !          1480:     env->gdt.limit = ldl_phys(sm_state + 0x7f70);
        !          1481: 
        !          1482:     env->idt.base = ldl_phys(sm_state + 0x7f58);
        !          1483:     env->idt.limit = ldl_phys(sm_state + 0x7f54);
        !          1484: 
        !          1485:     for(i = 0; i < 6; i++) {
        !          1486:         if (i < 3)
        !          1487:             offset = 0x7f84 + i * 12;
        !          1488:         else
        !          1489:             offset = 0x7f2c + (i - 3) * 12;
        !          1490:         cpu_x86_load_seg_cache(env, i, 
        !          1491:                                ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
        !          1492:                                ldl_phys(sm_state + offset + 8),
        !          1493:                                ldl_phys(sm_state + offset + 4),
        !          1494:                                (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
        !          1495:     }
        !          1496:     cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
        !          1497: 
        !          1498:     val = ldl_phys(sm_state + 0x7efc); /* revision ID */
        !          1499:     if (val & 0x20000) {
        !          1500:         env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
        !          1501:     }
        !          1502: #endif
        !          1503:     CC_OP = CC_OP_EFLAGS;
        !          1504:     env->hflags &= ~HF_SMM_MASK;
        !          1505:     cpu_smm_update(env);
        !          1506: 
        !          1507:     if (loglevel & CPU_LOG_INT) {
        !          1508:         fprintf(logfile, "SMM: after RSM\n");
        !          1509:         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
        !          1510:     }
        !          1511: }
        !          1512: 
        !          1513: #endif /* !CONFIG_USER_ONLY */
        !          1514: 
        !          1515: 
1.1       root     1516: #ifdef BUGGY_GCC_DIV64
                   1517: /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
                   1518:    call it from another function */
                   1519: uint32_t div32(uint64_t *q_ptr, uint64_t num, uint32_t den)
                   1520: {
                   1521:     *q_ptr = num / den;
                   1522:     return num % den;
                   1523: }
                   1524: 
                   1525: int32_t idiv32(int64_t *q_ptr, int64_t num, int32_t den)
                   1526: {
                   1527:     *q_ptr = num / den;
                   1528:     return num % den;
                   1529: }
                   1530: #endif
                   1531: 
                   1532: void helper_divl_EAX_T0(void)
                   1533: {
                   1534:     unsigned int den, r;
                   1535:     uint64_t num, q;
                   1536:     
                   1537:     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
                   1538:     den = T0;
                   1539:     if (den == 0) {
                   1540:         raise_exception(EXCP00_DIVZ);
                   1541:     }
                   1542: #ifdef BUGGY_GCC_DIV64
                   1543:     r = div32(&q, num, den);
                   1544: #else
                   1545:     q = (num / den);
                   1546:     r = (num % den);
                   1547: #endif
                   1548:     if (q > 0xffffffff)
                   1549:         raise_exception(EXCP00_DIVZ);
                   1550:     EAX = (uint32_t)q;
                   1551:     EDX = (uint32_t)r;
                   1552: }
                   1553: 
                   1554: void helper_idivl_EAX_T0(void)
                   1555: {
                   1556:     int den, r;
                   1557:     int64_t num, q;
                   1558:     
                   1559:     num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
                   1560:     den = T0;
                   1561:     if (den == 0) {
                   1562:         raise_exception(EXCP00_DIVZ);
                   1563:     }
                   1564: #ifdef BUGGY_GCC_DIV64
                   1565:     r = idiv32(&q, num, den);
                   1566: #else
                   1567:     q = (num / den);
                   1568:     r = (num % den);
                   1569: #endif
                   1570:     if (q != (int32_t)q)
                   1571:         raise_exception(EXCP00_DIVZ);
                   1572:     EAX = (uint32_t)q;
                   1573:     EDX = (uint32_t)r;
                   1574: }
                   1575: 
                   1576: void helper_cmpxchg8b(void)
                   1577: {
                   1578:     uint64_t d;
                   1579:     int eflags;
                   1580: 
                   1581:     eflags = cc_table[CC_OP].compute_all();
                   1582:     d = ldq(A0);
                   1583:     if (d == (((uint64_t)EDX << 32) | EAX)) {
                   1584:         stq(A0, ((uint64_t)ECX << 32) | EBX);
                   1585:         eflags |= CC_Z;
                   1586:     } else {
                   1587:         EDX = d >> 32;
                   1588:         EAX = d;
                   1589:         eflags &= ~CC_Z;
                   1590:     }
                   1591:     CC_SRC = eflags;
                   1592: }
                   1593: 
                   1594: void helper_cpuid(void)
                   1595: {
                   1596:     uint32_t index;
                   1597:     index = (uint32_t)EAX;
                   1598:     
                   1599:     /* test if maximum index reached */
                   1600:     if (index & 0x80000000) {
                   1601:         if (index > env->cpuid_xlevel) 
                   1602:             index = env->cpuid_level;
                   1603:     } else {
                   1604:         if (index > env->cpuid_level) 
                   1605:             index = env->cpuid_level;
                   1606:     }
                   1607:         
                   1608:     switch(index) {
                   1609:     case 0:
                   1610:         EAX = env->cpuid_level;
                   1611:         EBX = env->cpuid_vendor1;
                   1612:         EDX = env->cpuid_vendor2;
                   1613:         ECX = env->cpuid_vendor3;
                   1614:         break;
                   1615:     case 1:
                   1616:         EAX = env->cpuid_version;
                   1617:         EBX = 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
                   1618:         ECX = env->cpuid_ext_features;
                   1619:         EDX = env->cpuid_features;
                   1620:         break;
                   1621:     case 2:
                   1622:         /* cache info: needed for Pentium Pro compatibility */
                   1623:         EAX = 0x410601;
                   1624:         EBX = 0;
                   1625:         ECX = 0;
                   1626:         EDX = 0;
                   1627:         break;
                   1628:     case 0x80000000:
                   1629:         EAX = env->cpuid_xlevel;
                   1630:         EBX = env->cpuid_vendor1;
                   1631:         EDX = env->cpuid_vendor2;
                   1632:         ECX = env->cpuid_vendor3;
                   1633:         break;
                   1634:     case 0x80000001:
                   1635:         EAX = env->cpuid_features;
                   1636:         EBX = 0;
                   1637:         ECX = 0;
                   1638:         EDX = env->cpuid_ext2_features;
                   1639:         break;
                   1640:     case 0x80000002:
                   1641:     case 0x80000003:
                   1642:     case 0x80000004:
                   1643:         EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];
                   1644:         EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];
                   1645:         ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];
                   1646:         EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];
                   1647:         break;
                   1648:     case 0x80000005:
                   1649:         /* cache info (L1 cache) */
                   1650:         EAX = 0x01ff01ff;
                   1651:         EBX = 0x01ff01ff;
                   1652:         ECX = 0x40020140;
                   1653:         EDX = 0x40020140;
                   1654:         break;
                   1655:     case 0x80000006:
                   1656:         /* cache info (L2 cache) */
                   1657:         EAX = 0;
                   1658:         EBX = 0x42004200;
                   1659:         ECX = 0x02008140;
                   1660:         EDX = 0;
                   1661:         break;
                   1662:     case 0x80000008:
                   1663:         /* virtual & phys address size in low 2 bytes. */
                   1664:         EAX = 0x00003028;
                   1665:         EBX = 0;
                   1666:         ECX = 0;
                   1667:         EDX = 0;
                   1668:         break;
                   1669:     default:
                   1670:         /* reserved values: zero */
                   1671:         EAX = 0;
                   1672:         EBX = 0;
                   1673:         ECX = 0;
                   1674:         EDX = 0;
                   1675:         break;
                   1676:     }
                   1677: }
                   1678: 
                   1679: void helper_enter_level(int level, int data32)
                   1680: {
                   1681:     target_ulong ssp;
                   1682:     uint32_t esp_mask, esp, ebp;
                   1683: 
                   1684:     esp_mask = get_sp_mask(env->segs[R_SS].flags);
                   1685:     ssp = env->segs[R_SS].base;
                   1686:     ebp = EBP;
                   1687:     esp = ESP;
                   1688:     if (data32) {
                   1689:         /* 32 bit */
                   1690:         esp -= 4;
                   1691:         while (--level) {
                   1692:             esp -= 4;
                   1693:             ebp -= 4;
                   1694:             stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
                   1695:         }
                   1696:         esp -= 4;
                   1697:         stl(ssp + (esp & esp_mask), T1);
                   1698:     } else {
                   1699:         /* 16 bit */
                   1700:         esp -= 2;
                   1701:         while (--level) {
                   1702:             esp -= 2;
                   1703:             ebp -= 2;
                   1704:             stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
                   1705:         }
                   1706:         esp -= 2;
                   1707:         stw(ssp + (esp & esp_mask), T1);
                   1708:     }
                   1709: }
                   1710: 
                   1711: #ifdef TARGET_X86_64
                   1712: void helper_enter64_level(int level, int data64)
                   1713: {
                   1714:     target_ulong esp, ebp;
                   1715:     ebp = EBP;
                   1716:     esp = ESP;
                   1717: 
                   1718:     if (data64) {
                   1719:         /* 64 bit */
                   1720:         esp -= 8;
                   1721:         while (--level) {
                   1722:             esp -= 8;
                   1723:             ebp -= 8;
                   1724:             stq(esp, ldq(ebp));
                   1725:         }
                   1726:         esp -= 8;
                   1727:         stq(esp, T1);
                   1728:     } else {
                   1729:         /* 16 bit */
                   1730:         esp -= 2;
                   1731:         while (--level) {
                   1732:             esp -= 2;
                   1733:             ebp -= 2;
                   1734:             stw(esp, lduw(ebp));
                   1735:         }
                   1736:         esp -= 2;
                   1737:         stw(esp, T1);
                   1738:     }
                   1739: }
                   1740: #endif
                   1741: 
                   1742: void helper_lldt_T0(void)
                   1743: {
                   1744:     int selector;
                   1745:     SegmentCache *dt;
                   1746:     uint32_t e1, e2;
                   1747:     int index, entry_limit;
                   1748:     target_ulong ptr;
                   1749:     
                   1750:     selector = T0 & 0xffff;
                   1751:     if ((selector & 0xfffc) == 0) {
                   1752:         /* XXX: NULL selector case: invalid LDT */
                   1753:         env->ldt.base = 0;
                   1754:         env->ldt.limit = 0;
                   1755:     } else {
                   1756:         if (selector & 0x4)
                   1757:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1758:         dt = &env->gdt;
                   1759:         index = selector & ~7;
                   1760: #ifdef TARGET_X86_64
                   1761:         if (env->hflags & HF_LMA_MASK)
                   1762:             entry_limit = 15;
                   1763:         else
                   1764: #endif            
                   1765:             entry_limit = 7;
                   1766:         if ((index + entry_limit) > dt->limit)
                   1767:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1768:         ptr = dt->base + index;
                   1769:         e1 = ldl_kernel(ptr);
                   1770:         e2 = ldl_kernel(ptr + 4);
                   1771:         if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
                   1772:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1773:         if (!(e2 & DESC_P_MASK))
                   1774:             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   1775: #ifdef TARGET_X86_64
                   1776:         if (env->hflags & HF_LMA_MASK) {
                   1777:             uint32_t e3;
                   1778:             e3 = ldl_kernel(ptr + 8);
                   1779:             load_seg_cache_raw_dt(&env->ldt, e1, e2);
                   1780:             env->ldt.base |= (target_ulong)e3 << 32;
                   1781:         } else
                   1782: #endif
                   1783:         {
                   1784:             load_seg_cache_raw_dt(&env->ldt, e1, e2);
                   1785:         }
                   1786:     }
                   1787:     env->ldt.selector = selector;
                   1788: }
                   1789: 
                   1790: void helper_ltr_T0(void)
                   1791: {
                   1792:     int selector;
                   1793:     SegmentCache *dt;
                   1794:     uint32_t e1, e2;
                   1795:     int index, type, entry_limit;
                   1796:     target_ulong ptr;
                   1797:     
                   1798:     selector = T0 & 0xffff;
                   1799:     if ((selector & 0xfffc) == 0) {
                   1800:         /* NULL selector case: invalid TR */
                   1801:         env->tr.base = 0;
                   1802:         env->tr.limit = 0;
                   1803:         env->tr.flags = 0;
                   1804:     } else {
                   1805:         if (selector & 0x4)
                   1806:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1807:         dt = &env->gdt;
                   1808:         index = selector & ~7;
                   1809: #ifdef TARGET_X86_64
                   1810:         if (env->hflags & HF_LMA_MASK)
                   1811:             entry_limit = 15;
                   1812:         else
                   1813: #endif            
                   1814:             entry_limit = 7;
                   1815:         if ((index + entry_limit) > dt->limit)
                   1816:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1817:         ptr = dt->base + index;
                   1818:         e1 = ldl_kernel(ptr);
                   1819:         e2 = ldl_kernel(ptr + 4);
                   1820:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                   1821:         if ((e2 & DESC_S_MASK) || 
                   1822:             (type != 1 && type != 9))
                   1823:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1824:         if (!(e2 & DESC_P_MASK))
                   1825:             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   1826: #ifdef TARGET_X86_64
                   1827:         if (env->hflags & HF_LMA_MASK) {
                   1828:             uint32_t e3;
                   1829:             e3 = ldl_kernel(ptr + 8);
                   1830:             load_seg_cache_raw_dt(&env->tr, e1, e2);
                   1831:             env->tr.base |= (target_ulong)e3 << 32;
                   1832:         } else 
                   1833: #endif
                   1834:         {
                   1835:             load_seg_cache_raw_dt(&env->tr, e1, e2);
                   1836:         }
                   1837:         e2 |= DESC_TSS_BUSY_MASK;
                   1838:         stl_kernel(ptr + 4, e2);
                   1839:     }
                   1840:     env->tr.selector = selector;
                   1841: }
                   1842: 
                   1843: /* only works if protected mode and not VM86. seg_reg must be != R_CS */
                   1844: void load_seg(int seg_reg, int selector)
                   1845: {
                   1846:     uint32_t e1, e2;
                   1847:     int cpl, dpl, rpl;
                   1848:     SegmentCache *dt;
                   1849:     int index;
                   1850:     target_ulong ptr;
                   1851: 
                   1852:     selector &= 0xffff;
                   1853:     cpl = env->hflags & HF_CPL_MASK;
                   1854:     if ((selector & 0xfffc) == 0) {
                   1855:         /* null selector case */
                   1856:         if (seg_reg == R_SS
                   1857: #ifdef TARGET_X86_64
                   1858:             && (!(env->hflags & HF_CS64_MASK) || cpl == 3)
                   1859: #endif
                   1860:             )
                   1861:             raise_exception_err(EXCP0D_GPF, 0);
                   1862:         cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
                   1863:     } else {
                   1864:         
                   1865:         if (selector & 0x4)
                   1866:             dt = &env->ldt;
                   1867:         else
                   1868:             dt = &env->gdt;
                   1869:         index = selector & ~7;
                   1870:         if ((index + 7) > dt->limit)
                   1871:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1872:         ptr = dt->base + index;
                   1873:         e1 = ldl_kernel(ptr);
                   1874:         e2 = ldl_kernel(ptr + 4);
                   1875:         
                   1876:         if (!(e2 & DESC_S_MASK))
                   1877:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1878:         rpl = selector & 3;
                   1879:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1880:         if (seg_reg == R_SS) {
                   1881:             /* must be writable segment */
                   1882:             if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK))
                   1883:                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1884:             if (rpl != cpl || dpl != cpl)
                   1885:                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1886:         } else {
                   1887:             /* must be readable segment */
                   1888:             if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK)
                   1889:                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1890:             
                   1891:             if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
                   1892:                 /* if not conforming code, test rights */
1.1.1.2   root     1893:                 if (dpl < cpl || dpl < rpl) 
1.1       root     1894:                     raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   1895:             }
                   1896:         }
                   1897: 
                   1898:         if (!(e2 & DESC_P_MASK)) {
                   1899:             if (seg_reg == R_SS)
                   1900:                 raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
                   1901:             else
                   1902:                 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   1903:         }
                   1904: 
                   1905:         /* set the access bit if not already set */
                   1906:         if (!(e2 & DESC_A_MASK)) {
                   1907:             e2 |= DESC_A_MASK;
                   1908:             stl_kernel(ptr + 4, e2);
                   1909:         }
                   1910: 
                   1911:         cpu_x86_load_seg_cache(env, seg_reg, selector, 
                   1912:                        get_seg_base(e1, e2),
                   1913:                        get_seg_limit(e1, e2),
                   1914:                        e2);
                   1915: #if 0
                   1916:         fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n", 
                   1917:                 selector, (unsigned long)sc->base, sc->limit, sc->flags);
                   1918: #endif
                   1919:     }
                   1920: }
                   1921: 
                   1922: /* protected mode jump */
                   1923: void helper_ljmp_protected_T0_T1(int next_eip_addend)
                   1924: {
                   1925:     int new_cs, gate_cs, type;
                   1926:     uint32_t e1, e2, cpl, dpl, rpl, limit;
                   1927:     target_ulong new_eip, next_eip;
                   1928:     
                   1929:     new_cs = T0;
                   1930:     new_eip = T1;
                   1931:     if ((new_cs & 0xfffc) == 0)
                   1932:         raise_exception_err(EXCP0D_GPF, 0);
                   1933:     if (load_segment(&e1, &e2, new_cs) != 0)
                   1934:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1935:     cpl = env->hflags & HF_CPL_MASK;
                   1936:     if (e2 & DESC_S_MASK) {
                   1937:         if (!(e2 & DESC_CS_MASK))
                   1938:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1939:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1940:         if (e2 & DESC_C_MASK) {
                   1941:             /* conforming code segment */
                   1942:             if (dpl > cpl)
                   1943:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1944:         } else {
                   1945:             /* non conforming code segment */
                   1946:             rpl = new_cs & 3;
                   1947:             if (rpl > cpl)
                   1948:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1949:             if (dpl != cpl)
                   1950:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1951:         }
                   1952:         if (!(e2 & DESC_P_MASK))
                   1953:             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
                   1954:         limit = get_seg_limit(e1, e2);
                   1955:         if (new_eip > limit && 
                   1956:             !(env->hflags & HF_LMA_MASK) && !(e2 & DESC_L_MASK))
                   1957:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1958:         cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
                   1959:                        get_seg_base(e1, e2), limit, e2);
                   1960:         EIP = new_eip;
                   1961:     } else {
                   1962:         /* jump to call or task gate */
                   1963:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1964:         rpl = new_cs & 3;
                   1965:         cpl = env->hflags & HF_CPL_MASK;
                   1966:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                   1967:         switch(type) {
                   1968:         case 1: /* 286 TSS */
                   1969:         case 9: /* 386 TSS */
                   1970:         case 5: /* task gate */
                   1971:             if (dpl < cpl || dpl < rpl)
                   1972:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1973:             next_eip = env->eip + next_eip_addend;
                   1974:             switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip);
1.1.1.4   root     1975:             CC_OP = CC_OP_EFLAGS;
1.1       root     1976:             break;
                   1977:         case 4: /* 286 call gate */
                   1978:         case 12: /* 386 call gate */
                   1979:             if ((dpl < cpl) || (dpl < rpl))
                   1980:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   1981:             if (!(e2 & DESC_P_MASK))
                   1982:                 raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
                   1983:             gate_cs = e1 >> 16;
                   1984:             new_eip = (e1 & 0xffff);
                   1985:             if (type == 12)
                   1986:                 new_eip |= (e2 & 0xffff0000);
                   1987:             if (load_segment(&e1, &e2, gate_cs) != 0)
                   1988:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
                   1989:             dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   1990:             /* must be code segment */
                   1991:             if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) != 
                   1992:                  (DESC_S_MASK | DESC_CS_MASK)))
                   1993:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
                   1994:             if (((e2 & DESC_C_MASK) && (dpl > cpl)) || 
                   1995:                 (!(e2 & DESC_C_MASK) && (dpl != cpl)))
                   1996:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
                   1997:             if (!(e2 & DESC_P_MASK))
                   1998:                 raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
                   1999:             limit = get_seg_limit(e1, e2);
                   2000:             if (new_eip > limit)
                   2001:                 raise_exception_err(EXCP0D_GPF, 0);
                   2002:             cpu_x86_load_seg_cache(env, R_CS, (gate_cs & 0xfffc) | cpl,
                   2003:                                    get_seg_base(e1, e2), limit, e2);
                   2004:             EIP = new_eip;
                   2005:             break;
                   2006:         default:
                   2007:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2008:             break;
                   2009:         }
                   2010:     }
                   2011: }
                   2012: 
                   2013: /* real mode call */
                   2014: void helper_lcall_real_T0_T1(int shift, int next_eip)
                   2015: {
                   2016:     int new_cs, new_eip;
                   2017:     uint32_t esp, esp_mask;
                   2018:     target_ulong ssp;
                   2019: 
                   2020:     new_cs = T0;
                   2021:     new_eip = T1;
                   2022:     esp = ESP;
                   2023:     esp_mask = get_sp_mask(env->segs[R_SS].flags);
                   2024:     ssp = env->segs[R_SS].base;
                   2025:     if (shift) {
                   2026:         PUSHL(ssp, esp, esp_mask, env->segs[R_CS].selector);
                   2027:         PUSHL(ssp, esp, esp_mask, next_eip);
                   2028:     } else {
                   2029:         PUSHW(ssp, esp, esp_mask, env->segs[R_CS].selector);
                   2030:         PUSHW(ssp, esp, esp_mask, next_eip);
                   2031:     }
                   2032: 
1.1.1.5 ! root     2033:     SET_ESP(esp, esp_mask);
1.1       root     2034:     env->eip = new_eip;
                   2035:     env->segs[R_CS].selector = new_cs;
                   2036:     env->segs[R_CS].base = (new_cs << 4);
                   2037: }
                   2038: 
                   2039: /* protected mode call */
                   2040: void helper_lcall_protected_T0_T1(int shift, int next_eip_addend)
                   2041: {
1.1.1.2   root     2042:     int new_cs, new_stack, i;
1.1       root     2043:     uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
                   2044:     uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
                   2045:     uint32_t val, limit, old_sp_mask;
1.1.1.2   root     2046:     target_ulong ssp, old_ssp, next_eip, new_eip;
1.1       root     2047:     
                   2048:     new_cs = T0;
                   2049:     new_eip = T1;
                   2050:     next_eip = env->eip + next_eip_addend;
                   2051: #ifdef DEBUG_PCALL
                   2052:     if (loglevel & CPU_LOG_PCALL) {
                   2053:         fprintf(logfile, "lcall %04x:%08x s=%d\n",
1.1.1.2   root     2054:                 new_cs, (uint32_t)new_eip, shift);
1.1       root     2055:         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
                   2056:     }
                   2057: #endif
                   2058:     if ((new_cs & 0xfffc) == 0)
                   2059:         raise_exception_err(EXCP0D_GPF, 0);
                   2060:     if (load_segment(&e1, &e2, new_cs) != 0)
                   2061:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2062:     cpl = env->hflags & HF_CPL_MASK;
                   2063: #ifdef DEBUG_PCALL
                   2064:     if (loglevel & CPU_LOG_PCALL) {
                   2065:         fprintf(logfile, "desc=%08x:%08x\n", e1, e2);
                   2066:     }
                   2067: #endif
                   2068:     if (e2 & DESC_S_MASK) {
                   2069:         if (!(e2 & DESC_CS_MASK))
                   2070:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2071:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2072:         if (e2 & DESC_C_MASK) {
                   2073:             /* conforming code segment */
                   2074:             if (dpl > cpl)
                   2075:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2076:         } else {
                   2077:             /* non conforming code segment */
                   2078:             rpl = new_cs & 3;
                   2079:             if (rpl > cpl)
                   2080:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2081:             if (dpl != cpl)
                   2082:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2083:         }
                   2084:         if (!(e2 & DESC_P_MASK))
                   2085:             raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
                   2086: 
                   2087: #ifdef TARGET_X86_64
                   2088:         /* XXX: check 16/32 bit cases in long mode */
                   2089:         if (shift == 2) {
                   2090:             target_ulong rsp;
                   2091:             /* 64 bit case */
                   2092:             rsp = ESP;
                   2093:             PUSHQ(rsp, env->segs[R_CS].selector);
                   2094:             PUSHQ(rsp, next_eip);
                   2095:             /* from this point, not restartable */
                   2096:             ESP = rsp;
                   2097:             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
                   2098:                                    get_seg_base(e1, e2), 
                   2099:                                    get_seg_limit(e1, e2), e2);
                   2100:             EIP = new_eip;
                   2101:         } else 
                   2102: #endif
                   2103:         {
                   2104:             sp = ESP;
                   2105:             sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   2106:             ssp = env->segs[R_SS].base;
                   2107:             if (shift) {
                   2108:                 PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   2109:                 PUSHL(ssp, sp, sp_mask, next_eip);
                   2110:             } else {
                   2111:                 PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   2112:                 PUSHW(ssp, sp, sp_mask, next_eip);
                   2113:             }
                   2114:             
                   2115:             limit = get_seg_limit(e1, e2);
                   2116:             if (new_eip > limit)
                   2117:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2118:             /* from this point, not restartable */
1.1.1.5 ! root     2119:             SET_ESP(sp, sp_mask);
1.1       root     2120:             cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
                   2121:                                    get_seg_base(e1, e2), limit, e2);
                   2122:             EIP = new_eip;
                   2123:         }
                   2124:     } else {
                   2125:         /* check gate type */
                   2126:         type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
                   2127:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2128:         rpl = new_cs & 3;
                   2129:         switch(type) {
                   2130:         case 1: /* available 286 TSS */
                   2131:         case 9: /* available 386 TSS */
                   2132:         case 5: /* task gate */
                   2133:             if (dpl < cpl || dpl < rpl)
                   2134:                 raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2135:             switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL, next_eip);
1.1.1.4   root     2136:             CC_OP = CC_OP_EFLAGS;
1.1       root     2137:             return;
                   2138:         case 4: /* 286 call gate */
                   2139:         case 12: /* 386 call gate */
                   2140:             break;
                   2141:         default:
                   2142:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2143:             break;
                   2144:         }
                   2145:         shift = type >> 3;
                   2146: 
                   2147:         if (dpl < cpl || dpl < rpl)
                   2148:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2149:         /* check valid bit */
                   2150:         if (!(e2 & DESC_P_MASK))
                   2151:             raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
                   2152:         selector = e1 >> 16;
                   2153:         offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
                   2154:         param_count = e2 & 0x1f;
                   2155:         if ((selector & 0xfffc) == 0)
                   2156:             raise_exception_err(EXCP0D_GPF, 0);
                   2157: 
                   2158:         if (load_segment(&e1, &e2, selector) != 0)
                   2159:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   2160:         if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
                   2161:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   2162:         dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2163:         if (dpl > cpl)
                   2164:             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
                   2165:         if (!(e2 & DESC_P_MASK))
                   2166:             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
                   2167: 
                   2168:         if (!(e2 & DESC_C_MASK) && dpl < cpl) {
                   2169:             /* to inner priviledge */
                   2170:             get_ss_esp_from_tss(&ss, &sp, dpl);
                   2171: #ifdef DEBUG_PCALL
                   2172:             if (loglevel & CPU_LOG_PCALL)
                   2173:                 fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n", 
                   2174:                         ss, sp, param_count, ESP);
                   2175: #endif
                   2176:             if ((ss & 0xfffc) == 0)
                   2177:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   2178:             if ((ss & 3) != dpl)
                   2179:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   2180:             if (load_segment(&ss_e1, &ss_e2, ss) != 0)
                   2181:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   2182:             ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
                   2183:             if (ss_dpl != dpl)
                   2184:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   2185:             if (!(ss_e2 & DESC_S_MASK) ||
                   2186:                 (ss_e2 & DESC_CS_MASK) ||
                   2187:                 !(ss_e2 & DESC_W_MASK))
                   2188:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   2189:             if (!(ss_e2 & DESC_P_MASK))
                   2190:                 raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
                   2191:             
                   2192:             //            push_size = ((param_count * 2) + 8) << shift;
                   2193: 
                   2194:             old_sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   2195:             old_ssp = env->segs[R_SS].base;
                   2196:             
                   2197:             sp_mask = get_sp_mask(ss_e2);
                   2198:             ssp = get_seg_base(ss_e1, ss_e2);
                   2199:             if (shift) {
                   2200:                 PUSHL(ssp, sp, sp_mask, env->segs[R_SS].selector);
                   2201:                 PUSHL(ssp, sp, sp_mask, ESP);
                   2202:                 for(i = param_count - 1; i >= 0; i--) {
                   2203:                     val = ldl_kernel(old_ssp + ((ESP + i * 4) & old_sp_mask));
                   2204:                     PUSHL(ssp, sp, sp_mask, val);
                   2205:                 }
                   2206:             } else {
                   2207:                 PUSHW(ssp, sp, sp_mask, env->segs[R_SS].selector);
                   2208:                 PUSHW(ssp, sp, sp_mask, ESP);
                   2209:                 for(i = param_count - 1; i >= 0; i--) {
                   2210:                     val = lduw_kernel(old_ssp + ((ESP + i * 2) & old_sp_mask));
                   2211:                     PUSHW(ssp, sp, sp_mask, val);
                   2212:                 }
                   2213:             }
                   2214:             new_stack = 1;
                   2215:         } else {
                   2216:             /* to same priviledge */
                   2217:             sp = ESP;
                   2218:             sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   2219:             ssp = env->segs[R_SS].base;
                   2220:             //            push_size = (4 << shift);
                   2221:             new_stack = 0;
                   2222:         }
                   2223: 
                   2224:         if (shift) {
                   2225:             PUSHL(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   2226:             PUSHL(ssp, sp, sp_mask, next_eip);
                   2227:         } else {
                   2228:             PUSHW(ssp, sp, sp_mask, env->segs[R_CS].selector);
                   2229:             PUSHW(ssp, sp, sp_mask, next_eip);
                   2230:         }
                   2231: 
                   2232:         /* from this point, not restartable */
                   2233: 
                   2234:         if (new_stack) {
                   2235:             ss = (ss & ~3) | dpl;
                   2236:             cpu_x86_load_seg_cache(env, R_SS, ss, 
                   2237:                                    ssp,
                   2238:                                    get_seg_limit(ss_e1, ss_e2),
                   2239:                                    ss_e2);
                   2240:         }
                   2241: 
                   2242:         selector = (selector & ~3) | dpl;
                   2243:         cpu_x86_load_seg_cache(env, R_CS, selector, 
                   2244:                        get_seg_base(e1, e2),
                   2245:                        get_seg_limit(e1, e2),
                   2246:                        e2);
                   2247:         cpu_x86_set_cpl(env, dpl);
1.1.1.5 ! root     2248:         SET_ESP(sp, sp_mask);
1.1       root     2249:         EIP = offset;
                   2250:     }
                   2251: #ifdef USE_KQEMU
                   2252:     if (kqemu_is_ok(env)) {
                   2253:         env->exception_index = -1;
                   2254:         cpu_loop_exit();
                   2255:     }
                   2256: #endif
                   2257: }
                   2258: 
                   2259: /* real and vm86 mode iret */
                   2260: void helper_iret_real(int shift)
                   2261: {
                   2262:     uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
                   2263:     target_ulong ssp;
                   2264:     int eflags_mask;
                   2265: 
                   2266:     sp_mask = 0xffff; /* XXXX: use SS segment size ? */
                   2267:     sp = ESP;
                   2268:     ssp = env->segs[R_SS].base;
                   2269:     if (shift == 1) {
                   2270:         /* 32 bits */
                   2271:         POPL(ssp, sp, sp_mask, new_eip);
                   2272:         POPL(ssp, sp, sp_mask, new_cs);
                   2273:         new_cs &= 0xffff;
                   2274:         POPL(ssp, sp, sp_mask, new_eflags);
                   2275:     } else {
                   2276:         /* 16 bits */
                   2277:         POPW(ssp, sp, sp_mask, new_eip);
                   2278:         POPW(ssp, sp, sp_mask, new_cs);
                   2279:         POPW(ssp, sp, sp_mask, new_eflags);
                   2280:     }
                   2281:     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
                   2282:     load_seg_vm(R_CS, new_cs);
                   2283:     env->eip = new_eip;
                   2284:     if (env->eflags & VM_MASK)
                   2285:         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
                   2286:     else
                   2287:         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK;
                   2288:     if (shift == 0)
                   2289:         eflags_mask &= 0xffff;
                   2290:     load_eflags(new_eflags, eflags_mask);
                   2291: }
                   2292: 
                   2293: static inline void validate_seg(int seg_reg, int cpl)
                   2294: {
                   2295:     int dpl;
                   2296:     uint32_t e2;
1.1.1.2   root     2297: 
                   2298:     /* XXX: on x86_64, we do not want to nullify FS and GS because
                   2299:        they may still contain a valid base. I would be interested to
                   2300:        know how a real x86_64 CPU behaves */
                   2301:     if ((seg_reg == R_FS || seg_reg == R_GS) && 
                   2302:         (env->segs[seg_reg].selector & 0xfffc) == 0)
                   2303:         return;
                   2304: 
1.1       root     2305:     e2 = env->segs[seg_reg].flags;
                   2306:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2307:     if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
                   2308:         /* data or non conforming code segment */
                   2309:         if (dpl < cpl) {
                   2310:             cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
                   2311:         }
                   2312:     }
                   2313: }
                   2314: 
                   2315: /* protected mode iret */
                   2316: static inline void helper_ret_protected(int shift, int is_iret, int addend)
                   2317: {
                   2318:     uint32_t new_cs, new_eflags, new_ss;
                   2319:     uint32_t new_es, new_ds, new_fs, new_gs;
                   2320:     uint32_t e1, e2, ss_e1, ss_e2;
                   2321:     int cpl, dpl, rpl, eflags_mask, iopl;
                   2322:     target_ulong ssp, sp, new_eip, new_esp, sp_mask;
                   2323:     
                   2324: #ifdef TARGET_X86_64
                   2325:     if (shift == 2)
                   2326:         sp_mask = -1;
                   2327:     else
                   2328: #endif
                   2329:         sp_mask = get_sp_mask(env->segs[R_SS].flags);
                   2330:     sp = ESP;
                   2331:     ssp = env->segs[R_SS].base;
                   2332:     new_eflags = 0; /* avoid warning */
                   2333: #ifdef TARGET_X86_64
                   2334:     if (shift == 2) {
                   2335:         POPQ(sp, new_eip);
                   2336:         POPQ(sp, new_cs);
                   2337:         new_cs &= 0xffff;
                   2338:         if (is_iret) {
                   2339:             POPQ(sp, new_eflags);
                   2340:         }
                   2341:     } else
                   2342: #endif
                   2343:     if (shift == 1) {
                   2344:         /* 32 bits */
                   2345:         POPL(ssp, sp, sp_mask, new_eip);
                   2346:         POPL(ssp, sp, sp_mask, new_cs);
                   2347:         new_cs &= 0xffff;
                   2348:         if (is_iret) {
                   2349:             POPL(ssp, sp, sp_mask, new_eflags);
                   2350:             if (new_eflags & VM_MASK)
                   2351:                 goto return_to_vm86;
                   2352:         }
                   2353:     } else {
                   2354:         /* 16 bits */
                   2355:         POPW(ssp, sp, sp_mask, new_eip);
                   2356:         POPW(ssp, sp, sp_mask, new_cs);
                   2357:         if (is_iret)
                   2358:             POPW(ssp, sp, sp_mask, new_eflags);
                   2359:     }
                   2360: #ifdef DEBUG_PCALL
                   2361:     if (loglevel & CPU_LOG_PCALL) {
                   2362:         fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
                   2363:                 new_cs, new_eip, shift, addend);
                   2364:         cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
                   2365:     }
                   2366: #endif
                   2367:     if ((new_cs & 0xfffc) == 0)
                   2368:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2369:     if (load_segment(&e1, &e2, new_cs) != 0)
                   2370:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2371:     if (!(e2 & DESC_S_MASK) ||
                   2372:         !(e2 & DESC_CS_MASK))
                   2373:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2374:     cpl = env->hflags & HF_CPL_MASK;
                   2375:     rpl = new_cs & 3; 
                   2376:     if (rpl < cpl)
                   2377:         raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2378:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2379:     if (e2 & DESC_C_MASK) {
                   2380:         if (dpl > rpl)
                   2381:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2382:     } else {
                   2383:         if (dpl != rpl)
                   2384:             raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
                   2385:     }
                   2386:     if (!(e2 & DESC_P_MASK))
                   2387:         raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
                   2388:     
                   2389:     sp += addend;
                   2390:     if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) || 
                   2391:                        ((env->hflags & HF_CS64_MASK) && !is_iret))) {
                   2392:         /* return to same priledge level */
                   2393:         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
                   2394:                        get_seg_base(e1, e2),
                   2395:                        get_seg_limit(e1, e2),
                   2396:                        e2);
                   2397:     } else {
                   2398:         /* return to different priviledge level */
                   2399: #ifdef TARGET_X86_64
                   2400:         if (shift == 2) {
                   2401:             POPQ(sp, new_esp);
                   2402:             POPQ(sp, new_ss);
                   2403:             new_ss &= 0xffff;
                   2404:         } else
                   2405: #endif
                   2406:         if (shift == 1) {
                   2407:             /* 32 bits */
                   2408:             POPL(ssp, sp, sp_mask, new_esp);
                   2409:             POPL(ssp, sp, sp_mask, new_ss);
                   2410:             new_ss &= 0xffff;
                   2411:         } else {
                   2412:             /* 16 bits */
                   2413:             POPW(ssp, sp, sp_mask, new_esp);
                   2414:             POPW(ssp, sp, sp_mask, new_ss);
                   2415:         }
                   2416: #ifdef DEBUG_PCALL
                   2417:         if (loglevel & CPU_LOG_PCALL) {
                   2418:             fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
                   2419:                     new_ss, new_esp);
                   2420:         }
                   2421: #endif
                   2422:         if ((new_ss & 0xfffc) == 0) {
                   2423: #ifdef TARGET_X86_64
                   2424:             /* NULL ss is allowed in long mode if cpl != 3*/
1.1.1.5 ! root     2425:             /* XXX: test CS64 ? */
1.1       root     2426:             if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
                   2427:                 cpu_x86_load_seg_cache(env, R_SS, new_ss, 
                   2428:                                        0, 0xffffffff,
                   2429:                                        DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2430:                                        DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
                   2431:                                        DESC_W_MASK | DESC_A_MASK);
1.1.1.5 ! root     2432:                 ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
1.1       root     2433:             } else 
                   2434: #endif
                   2435:             {
                   2436:                 raise_exception_err(EXCP0D_GPF, 0);
                   2437:             }
                   2438:         } else {
                   2439:             if ((new_ss & 3) != rpl)
                   2440:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2441:             if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
                   2442:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2443:             if (!(ss_e2 & DESC_S_MASK) ||
                   2444:                 (ss_e2 & DESC_CS_MASK) ||
                   2445:                 !(ss_e2 & DESC_W_MASK))
                   2446:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2447:             dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
                   2448:             if (dpl != rpl)
                   2449:                 raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
                   2450:             if (!(ss_e2 & DESC_P_MASK))
                   2451:                 raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
                   2452:             cpu_x86_load_seg_cache(env, R_SS, new_ss, 
                   2453:                                    get_seg_base(ss_e1, ss_e2),
                   2454:                                    get_seg_limit(ss_e1, ss_e2),
                   2455:                                    ss_e2);
                   2456:         }
                   2457: 
                   2458:         cpu_x86_load_seg_cache(env, R_CS, new_cs, 
                   2459:                        get_seg_base(e1, e2),
                   2460:                        get_seg_limit(e1, e2),
                   2461:                        e2);
                   2462:         cpu_x86_set_cpl(env, rpl);
                   2463:         sp = new_esp;
                   2464: #ifdef TARGET_X86_64
                   2465:         if (env->hflags & HF_CS64_MASK)
                   2466:             sp_mask = -1;
                   2467:         else
                   2468: #endif
                   2469:             sp_mask = get_sp_mask(ss_e2);
                   2470: 
                   2471:         /* validate data segments */
1.1.1.2   root     2472:         validate_seg(R_ES, rpl);
                   2473:         validate_seg(R_DS, rpl);
                   2474:         validate_seg(R_FS, rpl);
                   2475:         validate_seg(R_GS, rpl);
1.1       root     2476: 
                   2477:         sp += addend;
                   2478:     }
1.1.1.5 ! root     2479:     SET_ESP(sp, sp_mask);
1.1       root     2480:     env->eip = new_eip;
                   2481:     if (is_iret) {
                   2482:         /* NOTE: 'cpl' is the _old_ CPL */
                   2483:         eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;
                   2484:         if (cpl == 0)
                   2485:             eflags_mask |= IOPL_MASK;
                   2486:         iopl = (env->eflags >> IOPL_SHIFT) & 3;
                   2487:         if (cpl <= iopl)
                   2488:             eflags_mask |= IF_MASK;
                   2489:         if (shift == 0)
                   2490:             eflags_mask &= 0xffff;
                   2491:         load_eflags(new_eflags, eflags_mask);
                   2492:     }
                   2493:     return;
                   2494: 
                   2495:  return_to_vm86:
                   2496:     POPL(ssp, sp, sp_mask, new_esp);
                   2497:     POPL(ssp, sp, sp_mask, new_ss);
                   2498:     POPL(ssp, sp, sp_mask, new_es);
                   2499:     POPL(ssp, sp, sp_mask, new_ds);
                   2500:     POPL(ssp, sp, sp_mask, new_fs);
                   2501:     POPL(ssp, sp, sp_mask, new_gs);
                   2502:     
                   2503:     /* modify processor state */
                   2504:     load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | 
                   2505:                 IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK);
                   2506:     load_seg_vm(R_CS, new_cs & 0xffff);
                   2507:     cpu_x86_set_cpl(env, 3);
                   2508:     load_seg_vm(R_SS, new_ss & 0xffff);
                   2509:     load_seg_vm(R_ES, new_es & 0xffff);
                   2510:     load_seg_vm(R_DS, new_ds & 0xffff);
                   2511:     load_seg_vm(R_FS, new_fs & 0xffff);
                   2512:     load_seg_vm(R_GS, new_gs & 0xffff);
                   2513: 
                   2514:     env->eip = new_eip & 0xffff;
                   2515:     ESP = new_esp;
                   2516: }
                   2517: 
                   2518: void helper_iret_protected(int shift, int next_eip)
                   2519: {
                   2520:     int tss_selector, type;
                   2521:     uint32_t e1, e2;
                   2522:     
                   2523:     /* specific case for TSS */
                   2524:     if (env->eflags & NT_MASK) {
                   2525: #ifdef TARGET_X86_64
                   2526:         if (env->hflags & HF_LMA_MASK)
                   2527:             raise_exception_err(EXCP0D_GPF, 0);
                   2528: #endif
                   2529:         tss_selector = lduw_kernel(env->tr.base + 0);
                   2530:         if (tss_selector & 4)
                   2531:             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                   2532:         if (load_segment(&e1, &e2, tss_selector) != 0)
                   2533:             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                   2534:         type = (e2 >> DESC_TYPE_SHIFT) & 0x17;
                   2535:         /* NOTE: we check both segment and busy TSS */
                   2536:         if (type != 3)
                   2537:             raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
                   2538:         switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip);
                   2539:     } else {
                   2540:         helper_ret_protected(shift, 1, 0);
                   2541:     }
                   2542: #ifdef USE_KQEMU
                   2543:     if (kqemu_is_ok(env)) {
                   2544:         CC_OP = CC_OP_EFLAGS;
                   2545:         env->exception_index = -1;
                   2546:         cpu_loop_exit();
                   2547:     }
                   2548: #endif
                   2549: }
                   2550: 
                   2551: void helper_lret_protected(int shift, int addend)
                   2552: {
                   2553:     helper_ret_protected(shift, 0, addend);
                   2554: #ifdef USE_KQEMU
                   2555:     if (kqemu_is_ok(env)) {
                   2556:         env->exception_index = -1;
                   2557:         cpu_loop_exit();
                   2558:     }
                   2559: #endif
                   2560: }
                   2561: 
                   2562: void helper_sysenter(void)
                   2563: {
                   2564:     if (env->sysenter_cs == 0) {
                   2565:         raise_exception_err(EXCP0D_GPF, 0);
                   2566:     }
                   2567:     env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
                   2568:     cpu_x86_set_cpl(env, 0);
                   2569:     cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, 
                   2570:                            0, 0xffffffff, 
                   2571:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2572:                            DESC_S_MASK |
                   2573:                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                   2574:     cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc, 
                   2575:                            0, 0xffffffff,
                   2576:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2577:                            DESC_S_MASK |
                   2578:                            DESC_W_MASK | DESC_A_MASK);
                   2579:     ESP = env->sysenter_esp;
                   2580:     EIP = env->sysenter_eip;
                   2581: }
                   2582: 
                   2583: void helper_sysexit(void)
                   2584: {
                   2585:     int cpl;
                   2586: 
                   2587:     cpl = env->hflags & HF_CPL_MASK;
                   2588:     if (env->sysenter_cs == 0 || cpl != 0) {
                   2589:         raise_exception_err(EXCP0D_GPF, 0);
                   2590:     }
                   2591:     cpu_x86_set_cpl(env, 3);
                   2592:     cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3, 
                   2593:                            0, 0xffffffff, 
                   2594:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2595:                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   2596:                            DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
                   2597:     cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3, 
                   2598:                            0, 0xffffffff,
                   2599:                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                   2600:                            DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                   2601:                            DESC_W_MASK | DESC_A_MASK);
                   2602:     ESP = ECX;
                   2603:     EIP = EDX;
                   2604: #ifdef USE_KQEMU
                   2605:     if (kqemu_is_ok(env)) {
                   2606:         env->exception_index = -1;
                   2607:         cpu_loop_exit();
                   2608:     }
                   2609: #endif
                   2610: }
                   2611: 
                   2612: void helper_movl_crN_T0(int reg)
                   2613: {
                   2614: #if !defined(CONFIG_USER_ONLY) 
                   2615:     switch(reg) {
                   2616:     case 0:
                   2617:         cpu_x86_update_cr0(env, T0);
                   2618:         break;
                   2619:     case 3:
                   2620:         cpu_x86_update_cr3(env, T0);
                   2621:         break;
                   2622:     case 4:
                   2623:         cpu_x86_update_cr4(env, T0);
                   2624:         break;
                   2625:     case 8:
                   2626:         cpu_set_apic_tpr(env, T0);
                   2627:         break;
                   2628:     default:
                   2629:         env->cr[reg] = T0;
                   2630:         break;
                   2631:     }
                   2632: #endif
                   2633: }
                   2634: 
                   2635: /* XXX: do more */
                   2636: void helper_movl_drN_T0(int reg)
                   2637: {
                   2638:     env->dr[reg] = T0;
                   2639: }
                   2640: 
                   2641: void helper_invlpg(target_ulong addr)
                   2642: {
                   2643:     cpu_x86_flush_tlb(env, addr);
                   2644: }
                   2645: 
                   2646: void helper_rdtsc(void)
                   2647: {
                   2648:     uint64_t val;
                   2649: 
                   2650:     if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
                   2651:         raise_exception(EXCP0D_GPF);
                   2652:     }
                   2653:     val = cpu_get_tsc(env);
                   2654:     EAX = (uint32_t)(val);
                   2655:     EDX = (uint32_t)(val >> 32);
                   2656: }
                   2657: 
                   2658: #if defined(CONFIG_USER_ONLY) 
                   2659: void helper_wrmsr(void)
                   2660: {
                   2661: }
                   2662: 
                   2663: void helper_rdmsr(void)
                   2664: {
                   2665: }
                   2666: #else
                   2667: void helper_wrmsr(void)
                   2668: {
                   2669:     uint64_t val;
                   2670: 
                   2671:     val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
                   2672: 
                   2673:     switch((uint32_t)ECX) {
                   2674:     case MSR_IA32_SYSENTER_CS:
                   2675:         env->sysenter_cs = val & 0xffff;
                   2676:         break;
                   2677:     case MSR_IA32_SYSENTER_ESP:
                   2678:         env->sysenter_esp = val;
                   2679:         break;
                   2680:     case MSR_IA32_SYSENTER_EIP:
                   2681:         env->sysenter_eip = val;
                   2682:         break;
                   2683:     case MSR_IA32_APICBASE:
                   2684:         cpu_set_apic_base(env, val);
                   2685:         break;
                   2686:     case MSR_EFER:
                   2687:         {
                   2688:             uint64_t update_mask;
                   2689:             update_mask = 0;
                   2690:             if (env->cpuid_ext2_features & CPUID_EXT2_SYSCALL)
                   2691:                 update_mask |= MSR_EFER_SCE;
                   2692:             if (env->cpuid_ext2_features & CPUID_EXT2_LM)
                   2693:                 update_mask |= MSR_EFER_LME;
                   2694:             if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
                   2695:                 update_mask |= MSR_EFER_FFXSR;
                   2696:             if (env->cpuid_ext2_features & CPUID_EXT2_NX)
                   2697:                 update_mask |= MSR_EFER_NXE;
                   2698:             env->efer = (env->efer & ~update_mask) | 
                   2699:             (val & update_mask);
                   2700:         }
                   2701:         break;
                   2702:     case MSR_STAR:
                   2703:         env->star = val;
                   2704:         break;
                   2705:     case MSR_PAT:
                   2706:         env->pat = val;
                   2707:         break;
                   2708: #ifdef TARGET_X86_64
                   2709:     case MSR_LSTAR:
                   2710:         env->lstar = val;
                   2711:         break;
                   2712:     case MSR_CSTAR:
                   2713:         env->cstar = val;
                   2714:         break;
                   2715:     case MSR_FMASK:
                   2716:         env->fmask = val;
                   2717:         break;
                   2718:     case MSR_FSBASE:
                   2719:         env->segs[R_FS].base = val;
                   2720:         break;
                   2721:     case MSR_GSBASE:
                   2722:         env->segs[R_GS].base = val;
                   2723:         break;
                   2724:     case MSR_KERNELGSBASE:
                   2725:         env->kernelgsbase = val;
                   2726:         break;
                   2727: #endif
                   2728:     default:
                   2729:         /* XXX: exception ? */
                   2730:         break; 
                   2731:     }
                   2732: }
                   2733: 
                   2734: void helper_rdmsr(void)
                   2735: {
                   2736:     uint64_t val;
                   2737:     switch((uint32_t)ECX) {
                   2738:     case MSR_IA32_SYSENTER_CS:
                   2739:         val = env->sysenter_cs;
                   2740:         break;
                   2741:     case MSR_IA32_SYSENTER_ESP:
                   2742:         val = env->sysenter_esp;
                   2743:         break;
                   2744:     case MSR_IA32_SYSENTER_EIP:
                   2745:         val = env->sysenter_eip;
                   2746:         break;
                   2747:     case MSR_IA32_APICBASE:
                   2748:         val = cpu_get_apic_base(env);
                   2749:         break;
                   2750:     case MSR_EFER:
                   2751:         val = env->efer;
                   2752:         break;
                   2753:     case MSR_STAR:
                   2754:         val = env->star;
                   2755:         break;
                   2756:     case MSR_PAT:
                   2757:         val = env->pat;
                   2758:         break;
                   2759: #ifdef TARGET_X86_64
                   2760:     case MSR_LSTAR:
                   2761:         val = env->lstar;
                   2762:         break;
                   2763:     case MSR_CSTAR:
                   2764:         val = env->cstar;
                   2765:         break;
                   2766:     case MSR_FMASK:
                   2767:         val = env->fmask;
                   2768:         break;
                   2769:     case MSR_FSBASE:
                   2770:         val = env->segs[R_FS].base;
                   2771:         break;
                   2772:     case MSR_GSBASE:
                   2773:         val = env->segs[R_GS].base;
                   2774:         break;
                   2775:     case MSR_KERNELGSBASE:
                   2776:         val = env->kernelgsbase;
                   2777:         break;
                   2778: #endif
                   2779:     default:
                   2780:         /* XXX: exception ? */
                   2781:         val = 0;
                   2782:         break; 
                   2783:     }
                   2784:     EAX = (uint32_t)(val);
                   2785:     EDX = (uint32_t)(val >> 32);
                   2786: }
                   2787: #endif
                   2788: 
                   2789: void helper_lsl(void)
                   2790: {
                   2791:     unsigned int selector, limit;
                   2792:     uint32_t e1, e2, eflags;
                   2793:     int rpl, dpl, cpl, type;
                   2794: 
                   2795:     eflags = cc_table[CC_OP].compute_all();
                   2796:     selector = T0 & 0xffff;
                   2797:     if (load_segment(&e1, &e2, selector) != 0)
                   2798:         goto fail;
                   2799:     rpl = selector & 3;
                   2800:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2801:     cpl = env->hflags & HF_CPL_MASK;
                   2802:     if (e2 & DESC_S_MASK) {
                   2803:         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
                   2804:             /* conforming */
                   2805:         } else {
                   2806:             if (dpl < cpl || dpl < rpl)
                   2807:                 goto fail;
                   2808:         }
                   2809:     } else {
                   2810:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                   2811:         switch(type) {
                   2812:         case 1:
                   2813:         case 2:
                   2814:         case 3:
                   2815:         case 9:
                   2816:         case 11:
                   2817:             break;
                   2818:         default:
                   2819:             goto fail;
                   2820:         }
                   2821:         if (dpl < cpl || dpl < rpl) {
                   2822:         fail:
                   2823:             CC_SRC = eflags & ~CC_Z;
                   2824:             return;
                   2825:         }
                   2826:     }
                   2827:     limit = get_seg_limit(e1, e2);
                   2828:     T1 = limit;
                   2829:     CC_SRC = eflags | CC_Z;
                   2830: }
                   2831: 
                   2832: void helper_lar(void)
                   2833: {
                   2834:     unsigned int selector;
                   2835:     uint32_t e1, e2, eflags;
                   2836:     int rpl, dpl, cpl, type;
                   2837: 
                   2838:     eflags = cc_table[CC_OP].compute_all();
                   2839:     selector = T0 & 0xffff;
                   2840:     if ((selector & 0xfffc) == 0)
                   2841:         goto fail;
                   2842:     if (load_segment(&e1, &e2, selector) != 0)
                   2843:         goto fail;
                   2844:     rpl = selector & 3;
                   2845:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2846:     cpl = env->hflags & HF_CPL_MASK;
                   2847:     if (e2 & DESC_S_MASK) {
                   2848:         if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
                   2849:             /* conforming */
                   2850:         } else {
                   2851:             if (dpl < cpl || dpl < rpl)
                   2852:                 goto fail;
                   2853:         }
                   2854:     } else {
                   2855:         type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
                   2856:         switch(type) {
                   2857:         case 1:
                   2858:         case 2:
                   2859:         case 3:
                   2860:         case 4:
                   2861:         case 5:
                   2862:         case 9:
                   2863:         case 11:
                   2864:         case 12:
                   2865:             break;
                   2866:         default:
                   2867:             goto fail;
                   2868:         }
                   2869:         if (dpl < cpl || dpl < rpl) {
                   2870:         fail:
                   2871:             CC_SRC = eflags & ~CC_Z;
                   2872:             return;
                   2873:         }
                   2874:     }
                   2875:     T1 = e2 & 0x00f0ff00;
                   2876:     CC_SRC = eflags | CC_Z;
                   2877: }
                   2878: 
                   2879: void helper_verr(void)
                   2880: {
                   2881:     unsigned int selector;
                   2882:     uint32_t e1, e2, eflags;
                   2883:     int rpl, dpl, cpl;
                   2884: 
                   2885:     eflags = cc_table[CC_OP].compute_all();
                   2886:     selector = T0 & 0xffff;
                   2887:     if ((selector & 0xfffc) == 0)
                   2888:         goto fail;
                   2889:     if (load_segment(&e1, &e2, selector) != 0)
                   2890:         goto fail;
                   2891:     if (!(e2 & DESC_S_MASK))
                   2892:         goto fail;
                   2893:     rpl = selector & 3;
                   2894:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2895:     cpl = env->hflags & HF_CPL_MASK;
                   2896:     if (e2 & DESC_CS_MASK) {
                   2897:         if (!(e2 & DESC_R_MASK))
                   2898:             goto fail;
                   2899:         if (!(e2 & DESC_C_MASK)) {
                   2900:             if (dpl < cpl || dpl < rpl)
                   2901:                 goto fail;
                   2902:         }
                   2903:     } else {
                   2904:         if (dpl < cpl || dpl < rpl) {
                   2905:         fail:
                   2906:             CC_SRC = eflags & ~CC_Z;
                   2907:             return;
                   2908:         }
                   2909:     }
                   2910:     CC_SRC = eflags | CC_Z;
                   2911: }
                   2912: 
                   2913: void helper_verw(void)
                   2914: {
                   2915:     unsigned int selector;
                   2916:     uint32_t e1, e2, eflags;
                   2917:     int rpl, dpl, cpl;
                   2918: 
                   2919:     eflags = cc_table[CC_OP].compute_all();
                   2920:     selector = T0 & 0xffff;
                   2921:     if ((selector & 0xfffc) == 0)
                   2922:         goto fail;
                   2923:     if (load_segment(&e1, &e2, selector) != 0)
                   2924:         goto fail;
                   2925:     if (!(e2 & DESC_S_MASK))
                   2926:         goto fail;
                   2927:     rpl = selector & 3;
                   2928:     dpl = (e2 >> DESC_DPL_SHIFT) & 3;
                   2929:     cpl = env->hflags & HF_CPL_MASK;
                   2930:     if (e2 & DESC_CS_MASK) {
                   2931:         goto fail;
                   2932:     } else {
                   2933:         if (dpl < cpl || dpl < rpl)
                   2934:             goto fail;
                   2935:         if (!(e2 & DESC_W_MASK)) {
                   2936:         fail:
                   2937:             CC_SRC = eflags & ~CC_Z;
                   2938:             return;
                   2939:         }
                   2940:     }
                   2941:     CC_SRC = eflags | CC_Z;
                   2942: }
                   2943: 
                   2944: /* FPU helpers */
                   2945: 
                   2946: void helper_fldt_ST0_A0(void)
                   2947: {
                   2948:     int new_fpstt;
                   2949:     new_fpstt = (env->fpstt - 1) & 7;
                   2950:     env->fpregs[new_fpstt].d = helper_fldt(A0);
                   2951:     env->fpstt = new_fpstt;
                   2952:     env->fptags[new_fpstt] = 0; /* validate stack entry */
                   2953: }
                   2954: 
                   2955: void helper_fstt_ST0_A0(void)
                   2956: {
                   2957:     helper_fstt(ST0, A0);
                   2958: }
                   2959: 
                   2960: void fpu_set_exception(int mask)
                   2961: {
                   2962:     env->fpus |= mask;
                   2963:     if (env->fpus & (~env->fpuc & FPUC_EM))
                   2964:         env->fpus |= FPUS_SE | FPUS_B;
                   2965: }
                   2966: 
                   2967: CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
                   2968: {
                   2969:     if (b == 0.0) 
                   2970:         fpu_set_exception(FPUS_ZE);
                   2971:     return a / b;
                   2972: }
                   2973: 
                   2974: void fpu_raise_exception(void)
                   2975: {
                   2976:     if (env->cr[0] & CR0_NE_MASK) {
                   2977:         raise_exception(EXCP10_COPR);
                   2978:     } 
                   2979: #if !defined(CONFIG_USER_ONLY) 
                   2980:     else {
                   2981:         cpu_set_ferr(env);
                   2982:     }
                   2983: #endif
                   2984: }
                   2985: 
                   2986: /* BCD ops */
                   2987: 
                   2988: void helper_fbld_ST0_A0(void)
                   2989: {
                   2990:     CPU86_LDouble tmp;
                   2991:     uint64_t val;
                   2992:     unsigned int v;
                   2993:     int i;
                   2994: 
                   2995:     val = 0;
                   2996:     for(i = 8; i >= 0; i--) {
                   2997:         v = ldub(A0 + i);
                   2998:         val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
                   2999:     }
                   3000:     tmp = val;
                   3001:     if (ldub(A0 + 9) & 0x80)
                   3002:         tmp = -tmp;
                   3003:     fpush();
                   3004:     ST0 = tmp;
                   3005: }
                   3006: 
                   3007: void helper_fbst_ST0_A0(void)
                   3008: {
                   3009:     int v;
                   3010:     target_ulong mem_ref, mem_end;
                   3011:     int64_t val;
                   3012: 
                   3013:     val = floatx_to_int64(ST0, &env->fp_status);
                   3014:     mem_ref = A0;
                   3015:     mem_end = mem_ref + 9;
                   3016:     if (val < 0) {
                   3017:         stb(mem_end, 0x80);
                   3018:         val = -val;
                   3019:     } else {
                   3020:         stb(mem_end, 0x00);
                   3021:     }
                   3022:     while (mem_ref < mem_end) {
                   3023:         if (val == 0)
                   3024:             break;
                   3025:         v = val % 100;
                   3026:         val = val / 100;
                   3027:         v = ((v / 10) << 4) | (v % 10);
                   3028:         stb(mem_ref++, v);
                   3029:     }
                   3030:     while (mem_ref < mem_end) {
                   3031:         stb(mem_ref++, 0);
                   3032:     }
                   3033: }
                   3034: 
                   3035: void helper_f2xm1(void)
                   3036: {
                   3037:     ST0 = pow(2.0,ST0) - 1.0;
                   3038: }
                   3039: 
                   3040: void helper_fyl2x(void)
                   3041: {
                   3042:     CPU86_LDouble fptemp;
                   3043:     
                   3044:     fptemp = ST0;
                   3045:     if (fptemp>0.0){
                   3046:         fptemp = log(fptemp)/log(2.0);  /* log2(ST) */
                   3047:         ST1 *= fptemp;
                   3048:         fpop();
                   3049:     } else { 
                   3050:         env->fpus &= (~0x4700);
                   3051:         env->fpus |= 0x400;
                   3052:     }
                   3053: }
                   3054: 
                   3055: void helper_fptan(void)
                   3056: {
                   3057:     CPU86_LDouble fptemp;
                   3058: 
                   3059:     fptemp = ST0;
                   3060:     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   3061:         env->fpus |= 0x400;
                   3062:     } else {
                   3063:         ST0 = tan(fptemp);
                   3064:         fpush();
                   3065:         ST0 = 1.0;
                   3066:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   3067:         /* the above code is for  |arg| < 2**52 only */
                   3068:     }
                   3069: }
                   3070: 
                   3071: void helper_fpatan(void)
                   3072: {
                   3073:     CPU86_LDouble fptemp, fpsrcop;
                   3074: 
                   3075:     fpsrcop = ST1;
                   3076:     fptemp = ST0;
                   3077:     ST1 = atan2(fpsrcop,fptemp);
                   3078:     fpop();
                   3079: }
                   3080: 
                   3081: void helper_fxtract(void)
                   3082: {
                   3083:     CPU86_LDoubleU temp;
                   3084:     unsigned int expdif;
                   3085: 
                   3086:     temp.d = ST0;
                   3087:     expdif = EXPD(temp) - EXPBIAS;
                   3088:     /*DP exponent bias*/
                   3089:     ST0 = expdif;
                   3090:     fpush();
                   3091:     BIASEXPONENT(temp);
                   3092:     ST0 = temp.d;
                   3093: }
                   3094: 
                   3095: void helper_fprem1(void)
                   3096: {
                   3097:     CPU86_LDouble dblq, fpsrcop, fptemp;
                   3098:     CPU86_LDoubleU fpsrcop1, fptemp1;
                   3099:     int expdif;
                   3100:     int q;
                   3101: 
                   3102:     fpsrcop = ST0;
                   3103:     fptemp = ST1;
                   3104:     fpsrcop1.d = fpsrcop;
                   3105:     fptemp1.d = fptemp;
                   3106:     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
                   3107:     if (expdif < 53) {
                   3108:         dblq = fpsrcop / fptemp;
                   3109:         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
                   3110:         ST0 = fpsrcop - fptemp*dblq;
                   3111:         q = (int)dblq; /* cutting off top bits is assumed here */
                   3112:         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
                   3113:                                /* (C0,C1,C3) <-- (q2,q1,q0) */
                   3114:         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
                   3115:         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
                   3116:         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
                   3117:     } else {
                   3118:         env->fpus |= 0x400;  /* C2 <-- 1 */
                   3119:         fptemp = pow(2.0, expdif-50);
                   3120:         fpsrcop = (ST0 / ST1) / fptemp;
                   3121:         /* fpsrcop = integer obtained by rounding to the nearest */
                   3122:         fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
                   3123:             floor(fpsrcop): ceil(fpsrcop);
                   3124:         ST0 -= (ST1 * fpsrcop * fptemp);
                   3125:     }
                   3126: }
                   3127: 
                   3128: void helper_fprem(void)
                   3129: {
                   3130:     CPU86_LDouble dblq, fpsrcop, fptemp;
                   3131:     CPU86_LDoubleU fpsrcop1, fptemp1;
                   3132:     int expdif;
                   3133:     int q;
                   3134:     
                   3135:     fpsrcop = ST0;
                   3136:     fptemp = ST1;
                   3137:     fpsrcop1.d = fpsrcop;
                   3138:     fptemp1.d = fptemp;
                   3139:     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
                   3140:     if ( expdif < 53 ) {
                   3141:         dblq = fpsrcop / fptemp;
                   3142:         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
                   3143:         ST0 = fpsrcop - fptemp*dblq;
                   3144:         q = (int)dblq; /* cutting off top bits is assumed here */
                   3145:         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
                   3146:                                /* (C0,C1,C3) <-- (q2,q1,q0) */
                   3147:         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
                   3148:         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
                   3149:         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
                   3150:     } else {
                   3151:         env->fpus |= 0x400;  /* C2 <-- 1 */
                   3152:         fptemp = pow(2.0, expdif-50);
                   3153:         fpsrcop = (ST0 / ST1) / fptemp;
                   3154:         /* fpsrcop = integer obtained by chopping */
                   3155:         fpsrcop = (fpsrcop < 0.0)?
                   3156:             -(floor(fabs(fpsrcop))): floor(fpsrcop);
                   3157:         ST0 -= (ST1 * fpsrcop * fptemp);
                   3158:     }
                   3159: }
                   3160: 
                   3161: void helper_fyl2xp1(void)
                   3162: {
                   3163:     CPU86_LDouble fptemp;
                   3164: 
                   3165:     fptemp = ST0;
                   3166:     if ((fptemp+1.0)>0.0) {
                   3167:         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
                   3168:         ST1 *= fptemp;
                   3169:         fpop();
                   3170:     } else { 
                   3171:         env->fpus &= (~0x4700);
                   3172:         env->fpus |= 0x400;
                   3173:     }
                   3174: }
                   3175: 
                   3176: void helper_fsqrt(void)
                   3177: {
                   3178:     CPU86_LDouble fptemp;
                   3179: 
                   3180:     fptemp = ST0;
                   3181:     if (fptemp<0.0) { 
                   3182:         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
                   3183:         env->fpus |= 0x400;
                   3184:     }
                   3185:     ST0 = sqrt(fptemp);
                   3186: }
                   3187: 
                   3188: void helper_fsincos(void)
                   3189: {
                   3190:     CPU86_LDouble fptemp;
                   3191: 
                   3192:     fptemp = ST0;
                   3193:     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   3194:         env->fpus |= 0x400;
                   3195:     } else {
                   3196:         ST0 = sin(fptemp);
                   3197:         fpush();
                   3198:         ST0 = cos(fptemp);
                   3199:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   3200:         /* the above code is for  |arg| < 2**63 only */
                   3201:     }
                   3202: }
                   3203: 
                   3204: void helper_frndint(void)
                   3205: {
                   3206:     ST0 = floatx_round_to_int(ST0, &env->fp_status);
                   3207: }
                   3208: 
                   3209: void helper_fscale(void)
                   3210: {
                   3211:     ST0 = ldexp (ST0, (int)(ST1)); 
                   3212: }
                   3213: 
                   3214: void helper_fsin(void)
                   3215: {
                   3216:     CPU86_LDouble fptemp;
                   3217: 
                   3218:     fptemp = ST0;
                   3219:     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   3220:         env->fpus |= 0x400;
                   3221:     } else {
                   3222:         ST0 = sin(fptemp);
                   3223:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   3224:         /* the above code is for  |arg| < 2**53 only */
                   3225:     }
                   3226: }
                   3227: 
                   3228: void helper_fcos(void)
                   3229: {
                   3230:     CPU86_LDouble fptemp;
                   3231: 
                   3232:     fptemp = ST0;
                   3233:     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
                   3234:         env->fpus |= 0x400;
                   3235:     } else {
                   3236:         ST0 = cos(fptemp);
                   3237:         env->fpus &= (~0x400);  /* C2 <-- 0 */
                   3238:         /* the above code is for  |arg5 < 2**63 only */
                   3239:     }
                   3240: }
                   3241: 
                   3242: void helper_fxam_ST0(void)
                   3243: {
                   3244:     CPU86_LDoubleU temp;
                   3245:     int expdif;
                   3246: 
                   3247:     temp.d = ST0;
                   3248: 
                   3249:     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */
                   3250:     if (SIGND(temp))
                   3251:         env->fpus |= 0x200; /* C1 <-- 1 */
                   3252: 
1.1.1.4   root     3253:     /* XXX: test fptags too */
1.1       root     3254:     expdif = EXPD(temp);
                   3255:     if (expdif == MAXEXPD) {
1.1.1.4   root     3256: #ifdef USE_X86LDOUBLE
                   3257:         if (MANTD(temp) == 0x8000000000000000ULL)
                   3258: #else
1.1       root     3259:         if (MANTD(temp) == 0)
1.1.1.4   root     3260: #endif
1.1       root     3261:             env->fpus |=  0x500 /*Infinity*/;
                   3262:         else
                   3263:             env->fpus |=  0x100 /*NaN*/;
                   3264:     } else if (expdif == 0) {
                   3265:         if (MANTD(temp) == 0)
                   3266:             env->fpus |=  0x4000 /*Zero*/;
                   3267:         else
                   3268:             env->fpus |= 0x4400 /*Denormal*/;
                   3269:     } else {
                   3270:         env->fpus |= 0x400;
                   3271:     }
                   3272: }
                   3273: 
                   3274: void helper_fstenv(target_ulong ptr, int data32)
                   3275: {
                   3276:     int fpus, fptag, exp, i;
                   3277:     uint64_t mant;
                   3278:     CPU86_LDoubleU tmp;
                   3279: 
                   3280:     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
                   3281:     fptag = 0;
                   3282:     for (i=7; i>=0; i--) {
                   3283:        fptag <<= 2;
                   3284:        if (env->fptags[i]) {
                   3285:             fptag |= 3;
                   3286:        } else {
                   3287:             tmp.d = env->fpregs[i].d;
                   3288:             exp = EXPD(tmp);
                   3289:             mant = MANTD(tmp);
                   3290:             if (exp == 0 && mant == 0) {
                   3291:                 /* zero */
                   3292:                fptag |= 1;
                   3293:            } else if (exp == 0 || exp == MAXEXPD
                   3294: #ifdef USE_X86LDOUBLE
                   3295:                        || (mant & (1LL << 63)) == 0
                   3296: #endif
                   3297:                        ) {
                   3298:                 /* NaNs, infinity, denormal */
                   3299:                 fptag |= 2;
                   3300:             }
                   3301:         }
                   3302:     }
                   3303:     if (data32) {
                   3304:         /* 32 bit */
                   3305:         stl(ptr, env->fpuc);
                   3306:         stl(ptr + 4, fpus);
                   3307:         stl(ptr + 8, fptag);
                   3308:         stl(ptr + 12, 0); /* fpip */
                   3309:         stl(ptr + 16, 0); /* fpcs */
                   3310:         stl(ptr + 20, 0); /* fpoo */
                   3311:         stl(ptr + 24, 0); /* fpos */
                   3312:     } else {
                   3313:         /* 16 bit */
                   3314:         stw(ptr, env->fpuc);
                   3315:         stw(ptr + 2, fpus);
                   3316:         stw(ptr + 4, fptag);
                   3317:         stw(ptr + 6, 0);
                   3318:         stw(ptr + 8, 0);
                   3319:         stw(ptr + 10, 0);
                   3320:         stw(ptr + 12, 0);
                   3321:     }
                   3322: }
                   3323: 
                   3324: void helper_fldenv(target_ulong ptr, int data32)
                   3325: {
                   3326:     int i, fpus, fptag;
                   3327: 
                   3328:     if (data32) {
                   3329:        env->fpuc = lduw(ptr);
                   3330:         fpus = lduw(ptr + 4);
                   3331:         fptag = lduw(ptr + 8);
                   3332:     }
                   3333:     else {
                   3334:        env->fpuc = lduw(ptr);
                   3335:         fpus = lduw(ptr + 2);
                   3336:         fptag = lduw(ptr + 4);
                   3337:     }
                   3338:     env->fpstt = (fpus >> 11) & 7;
                   3339:     env->fpus = fpus & ~0x3800;
                   3340:     for(i = 0;i < 8; i++) {
                   3341:         env->fptags[i] = ((fptag & 3) == 3);
                   3342:         fptag >>= 2;
                   3343:     }
                   3344: }
                   3345: 
                   3346: void helper_fsave(target_ulong ptr, int data32)
                   3347: {
                   3348:     CPU86_LDouble tmp;
                   3349:     int i;
                   3350: 
                   3351:     helper_fstenv(ptr, data32);
                   3352: 
                   3353:     ptr += (14 << data32);
                   3354:     for(i = 0;i < 8; i++) {
                   3355:         tmp = ST(i);
                   3356:         helper_fstt(tmp, ptr);
                   3357:         ptr += 10;
                   3358:     }
                   3359: 
                   3360:     /* fninit */
                   3361:     env->fpus = 0;
                   3362:     env->fpstt = 0;
                   3363:     env->fpuc = 0x37f;
                   3364:     env->fptags[0] = 1;
                   3365:     env->fptags[1] = 1;
                   3366:     env->fptags[2] = 1;
                   3367:     env->fptags[3] = 1;
                   3368:     env->fptags[4] = 1;
                   3369:     env->fptags[5] = 1;
                   3370:     env->fptags[6] = 1;
                   3371:     env->fptags[7] = 1;
                   3372: }
                   3373: 
                   3374: void helper_frstor(target_ulong ptr, int data32)
                   3375: {
                   3376:     CPU86_LDouble tmp;
                   3377:     int i;
                   3378: 
                   3379:     helper_fldenv(ptr, data32);
                   3380:     ptr += (14 << data32);
                   3381: 
                   3382:     for(i = 0;i < 8; i++) {
                   3383:         tmp = helper_fldt(ptr);
                   3384:         ST(i) = tmp;
                   3385:         ptr += 10;
                   3386:     }
                   3387: }
                   3388: 
                   3389: void helper_fxsave(target_ulong ptr, int data64)
                   3390: {
                   3391:     int fpus, fptag, i, nb_xmm_regs;
                   3392:     CPU86_LDouble tmp;
                   3393:     target_ulong addr;
                   3394: 
                   3395:     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
                   3396:     fptag = 0;
                   3397:     for(i = 0; i < 8; i++) {
                   3398:         fptag |= (env->fptags[i] << i);
                   3399:     }
                   3400:     stw(ptr, env->fpuc);
                   3401:     stw(ptr + 2, fpus);
                   3402:     stw(ptr + 4, fptag ^ 0xff);
                   3403: 
                   3404:     addr = ptr + 0x20;
                   3405:     for(i = 0;i < 8; i++) {
                   3406:         tmp = ST(i);
                   3407:         helper_fstt(tmp, addr);
                   3408:         addr += 16;
                   3409:     }
                   3410:     
                   3411:     if (env->cr[4] & CR4_OSFXSR_MASK) {
                   3412:         /* XXX: finish it */
                   3413:         stl(ptr + 0x18, env->mxcsr); /* mxcsr */
                   3414:         stl(ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */
                   3415:         nb_xmm_regs = 8 << data64;
                   3416:         addr = ptr + 0xa0;
                   3417:         for(i = 0; i < nb_xmm_regs; i++) {
                   3418:             stq(addr, env->xmm_regs[i].XMM_Q(0));
                   3419:             stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
                   3420:             addr += 16;
                   3421:         }
                   3422:     }
                   3423: }
                   3424: 
                   3425: void helper_fxrstor(target_ulong ptr, int data64)
                   3426: {
                   3427:     int i, fpus, fptag, nb_xmm_regs;
                   3428:     CPU86_LDouble tmp;
                   3429:     target_ulong addr;
                   3430: 
                   3431:     env->fpuc = lduw(ptr);
                   3432:     fpus = lduw(ptr + 2);
                   3433:     fptag = lduw(ptr + 4);
                   3434:     env->fpstt = (fpus >> 11) & 7;
                   3435:     env->fpus = fpus & ~0x3800;
                   3436:     fptag ^= 0xff;
                   3437:     for(i = 0;i < 8; i++) {
                   3438:         env->fptags[i] = ((fptag >> i) & 1);
                   3439:     }
                   3440: 
                   3441:     addr = ptr + 0x20;
                   3442:     for(i = 0;i < 8; i++) {
                   3443:         tmp = helper_fldt(addr);
                   3444:         ST(i) = tmp;
                   3445:         addr += 16;
                   3446:     }
                   3447: 
                   3448:     if (env->cr[4] & CR4_OSFXSR_MASK) {
                   3449:         /* XXX: finish it */
                   3450:         env->mxcsr = ldl(ptr + 0x18);
                   3451:         //ldl(ptr + 0x1c);
                   3452:         nb_xmm_regs = 8 << data64;
                   3453:         addr = ptr + 0xa0;
                   3454:         for(i = 0; i < nb_xmm_regs; i++) {
                   3455:             env->xmm_regs[i].XMM_Q(0) = ldq(addr);
                   3456:             env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
                   3457:             addr += 16;
                   3458:         }
                   3459:     }
                   3460: }
                   3461: 
                   3462: #ifndef USE_X86LDOUBLE
                   3463: 
                   3464: void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
                   3465: {
                   3466:     CPU86_LDoubleU temp;
                   3467:     int e;
                   3468: 
                   3469:     temp.d = f;
                   3470:     /* mantissa */
                   3471:     *pmant = (MANTD(temp) << 11) | (1LL << 63);
                   3472:     /* exponent + sign */
                   3473:     e = EXPD(temp) - EXPBIAS + 16383;
                   3474:     e |= SIGND(temp) >> 16;
                   3475:     *pexp = e;
                   3476: }
                   3477: 
                   3478: CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
                   3479: {
                   3480:     CPU86_LDoubleU temp;
                   3481:     int e;
                   3482:     uint64_t ll;
                   3483: 
                   3484:     /* XXX: handle overflow ? */
                   3485:     e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
                   3486:     e |= (upper >> 4) & 0x800; /* sign */
                   3487:     ll = (mant >> 11) & ((1LL << 52) - 1);
                   3488: #ifdef __arm__
                   3489:     temp.l.upper = (e << 20) | (ll >> 32);
                   3490:     temp.l.lower = ll;
                   3491: #else
                   3492:     temp.ll = ll | ((uint64_t)e << 52);
                   3493: #endif
                   3494:     return temp.d;
                   3495: }
                   3496: 
                   3497: #else
                   3498: 
                   3499: void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f)
                   3500: {
                   3501:     CPU86_LDoubleU temp;
                   3502: 
                   3503:     temp.d = f;
                   3504:     *pmant = temp.l.lower;
                   3505:     *pexp = temp.l.upper;
                   3506: }
                   3507: 
                   3508: CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper)
                   3509: {
                   3510:     CPU86_LDoubleU temp;
                   3511: 
                   3512:     temp.l.upper = upper;
                   3513:     temp.l.lower = mant;
                   3514:     return temp.d;
                   3515: }
                   3516: #endif
                   3517: 
                   3518: #ifdef TARGET_X86_64
                   3519: 
                   3520: //#define DEBUG_MULDIV
                   3521: 
                   3522: static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
                   3523: {
                   3524:     *plow += a;
                   3525:     /* carry test */
                   3526:     if (*plow < a)
                   3527:         (*phigh)++;
                   3528:     *phigh += b;
                   3529: }
                   3530: 
                   3531: static void neg128(uint64_t *plow, uint64_t *phigh)
                   3532: {
                   3533:     *plow = ~ *plow;
                   3534:     *phigh = ~ *phigh;
                   3535:     add128(plow, phigh, 1, 0);
                   3536: }
                   3537: 
                   3538: static void mul64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
                   3539: {
                   3540:     uint32_t a0, a1, b0, b1;
                   3541:     uint64_t v;
                   3542: 
                   3543:     a0 = a;
                   3544:     a1 = a >> 32;
                   3545: 
                   3546:     b0 = b;
                   3547:     b1 = b >> 32;
                   3548:     
                   3549:     v = (uint64_t)a0 * (uint64_t)b0;
                   3550:     *plow = v;
                   3551:     *phigh = 0;
                   3552: 
                   3553:     v = (uint64_t)a0 * (uint64_t)b1;
                   3554:     add128(plow, phigh, v << 32, v >> 32);
                   3555:     
                   3556:     v = (uint64_t)a1 * (uint64_t)b0;
                   3557:     add128(plow, phigh, v << 32, v >> 32);
                   3558:     
                   3559:     v = (uint64_t)a1 * (uint64_t)b1;
                   3560:     *phigh += v;
                   3561: #ifdef DEBUG_MULDIV
1.1.1.4   root     3562:     printf("mul: 0x%016" PRIx64 " * 0x%016" PRIx64 " = 0x%016" PRIx64 "%016" PRIx64 "\n",
1.1       root     3563:            a, b, *phigh, *plow);
                   3564: #endif
                   3565: }
                   3566: 
                   3567: static void imul64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
                   3568: {
                   3569:     int sa, sb;
                   3570:     sa = (a < 0);
                   3571:     if (sa)
                   3572:         a = -a;
                   3573:     sb = (b < 0);
                   3574:     if (sb)
                   3575:         b = -b;
                   3576:     mul64(plow, phigh, a, b);
                   3577:     if (sa ^ sb) {
                   3578:         neg128(plow, phigh);
                   3579:     }
                   3580: }
                   3581: 
                   3582: /* return TRUE if overflow */
                   3583: static int div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
                   3584: {
                   3585:     uint64_t q, r, a1, a0;
1.1.1.2   root     3586:     int i, qb, ab;
1.1       root     3587: 
                   3588:     a0 = *plow;
                   3589:     a1 = *phigh;
                   3590:     if (a1 == 0) {
                   3591:         q = a0 / b;
                   3592:         r = a0 % b;
                   3593:         *plow = q;
                   3594:         *phigh = r;
                   3595:     } else {
                   3596:         if (a1 >= b)
                   3597:             return 1;
                   3598:         /* XXX: use a better algorithm */
                   3599:         for(i = 0; i < 64; i++) {
1.1.1.2   root     3600:             ab = a1 >> 63;
1.1       root     3601:             a1 = (a1 << 1) | (a0 >> 63);
1.1.1.2   root     3602:             if (ab || a1 >= b) {
1.1       root     3603:                 a1 -= b;
                   3604:                 qb = 1;
                   3605:             } else {
                   3606:                 qb = 0;
                   3607:             }
                   3608:             a0 = (a0 << 1) | qb;
                   3609:         }
                   3610: #if defined(DEBUG_MULDIV)
1.1.1.4   root     3611:         printf("div: 0x%016" PRIx64 "%016" PRIx64 " / 0x%016" PRIx64 ": q=0x%016" PRIx64 " r=0x%016" PRIx64 "\n",
1.1       root     3612:                *phigh, *plow, b, a0, a1);
                   3613: #endif
                   3614:         *plow = a0;
                   3615:         *phigh = a1;
                   3616:     }
                   3617:     return 0;
                   3618: }
                   3619: 
                   3620: /* return TRUE if overflow */
                   3621: static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b)
                   3622: {
                   3623:     int sa, sb;
                   3624:     sa = ((int64_t)*phigh < 0);
                   3625:     if (sa)
                   3626:         neg128(plow, phigh);
                   3627:     sb = (b < 0);
                   3628:     if (sb)
                   3629:         b = -b;
                   3630:     if (div64(plow, phigh, b) != 0)
                   3631:         return 1;
                   3632:     if (sa ^ sb) {
                   3633:         if (*plow > (1ULL << 63))
                   3634:             return 1;
                   3635:         *plow = - *plow;
                   3636:     } else {
                   3637:         if (*plow >= (1ULL << 63))
                   3638:             return 1;
                   3639:     }
                   3640:     if (sa)
                   3641:         *phigh = - *phigh;
                   3642:     return 0;
                   3643: }
                   3644: 
                   3645: void helper_mulq_EAX_T0(void)
                   3646: {
                   3647:     uint64_t r0, r1;
                   3648: 
                   3649:     mul64(&r0, &r1, EAX, T0);
                   3650:     EAX = r0;
                   3651:     EDX = r1;
                   3652:     CC_DST = r0;
                   3653:     CC_SRC = r1;
                   3654: }
                   3655: 
                   3656: void helper_imulq_EAX_T0(void)
                   3657: {
                   3658:     uint64_t r0, r1;
                   3659: 
                   3660:     imul64(&r0, &r1, EAX, T0);
                   3661:     EAX = r0;
                   3662:     EDX = r1;
                   3663:     CC_DST = r0;
                   3664:     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
                   3665: }
                   3666: 
                   3667: void helper_imulq_T0_T1(void)
                   3668: {
                   3669:     uint64_t r0, r1;
                   3670: 
                   3671:     imul64(&r0, &r1, T0, T1);
                   3672:     T0 = r0;
                   3673:     CC_DST = r0;
                   3674:     CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
                   3675: }
                   3676: 
                   3677: void helper_divq_EAX_T0(void)
                   3678: {
                   3679:     uint64_t r0, r1;
                   3680:     if (T0 == 0) {
                   3681:         raise_exception(EXCP00_DIVZ);
                   3682:     }
                   3683:     r0 = EAX;
                   3684:     r1 = EDX;
                   3685:     if (div64(&r0, &r1, T0))
                   3686:         raise_exception(EXCP00_DIVZ);
                   3687:     EAX = r0;
                   3688:     EDX = r1;
                   3689: }
                   3690: 
                   3691: void helper_idivq_EAX_T0(void)
                   3692: {
                   3693:     uint64_t r0, r1;
                   3694:     if (T0 == 0) {
                   3695:         raise_exception(EXCP00_DIVZ);
                   3696:     }
                   3697:     r0 = EAX;
                   3698:     r1 = EDX;
                   3699:     if (idiv64(&r0, &r1, T0))
                   3700:         raise_exception(EXCP00_DIVZ);
                   3701:     EAX = r0;
                   3702:     EDX = r1;
                   3703: }
                   3704: 
1.1.1.3   root     3705: void helper_bswapq_T0(void)
                   3706: {
                   3707:     T0 = bswap64(T0);
                   3708: }
1.1       root     3709: #endif
                   3710: 
1.1.1.4   root     3711: void helper_hlt(void)
                   3712: {
                   3713:     env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
                   3714:     env->hflags |= HF_HALTED_MASK;
                   3715:     env->exception_index = EXCP_HLT;
                   3716:     cpu_loop_exit();
                   3717: }
                   3718: 
                   3719: void helper_monitor(void)
                   3720: {
1.1.1.5 ! root     3721:     if ((uint32_t)ECX != 0)
1.1.1.4   root     3722:         raise_exception(EXCP0D_GPF);
                   3723:     /* XXX: store address ? */
                   3724: }
                   3725: 
                   3726: void helper_mwait(void)
                   3727: {
1.1.1.5 ! root     3728:     if ((uint32_t)ECX != 0)
1.1.1.4   root     3729:         raise_exception(EXCP0D_GPF);
                   3730:     /* XXX: not complete but not completely erroneous */
                   3731:     if (env->cpu_index != 0 || env->next_cpu != NULL) {
                   3732:         /* more than one CPU: do not sleep because another CPU may
                   3733:            wake this one */
                   3734:     } else {
                   3735:         helper_hlt();
                   3736:     }
                   3737: }
                   3738: 
1.1       root     3739: float approx_rsqrt(float a)
                   3740: {
                   3741:     return 1.0 / sqrt(a);
                   3742: }
                   3743: 
                   3744: float approx_rcp(float a)
                   3745: {
                   3746:     return 1.0 / a;
                   3747: }
                   3748: 
                   3749: void update_fp_status(void)
                   3750: {
                   3751:     int rnd_type;
                   3752: 
                   3753:     /* set rounding mode */
                   3754:     switch(env->fpuc & RC_MASK) {
                   3755:     default:
                   3756:     case RC_NEAR:
                   3757:         rnd_type = float_round_nearest_even;
                   3758:         break;
                   3759:     case RC_DOWN:
                   3760:         rnd_type = float_round_down;
                   3761:         break;
                   3762:     case RC_UP:
                   3763:         rnd_type = float_round_up;
                   3764:         break;
                   3765:     case RC_CHOP:
                   3766:         rnd_type = float_round_to_zero;
                   3767:         break;
                   3768:     }
                   3769:     set_float_rounding_mode(rnd_type, &env->fp_status);
                   3770: #ifdef FLOATX80
                   3771:     switch((env->fpuc >> 8) & 3) {
                   3772:     case 0:
                   3773:         rnd_type = 32;
                   3774:         break;
                   3775:     case 2:
                   3776:         rnd_type = 64;
                   3777:         break;
                   3778:     case 3:
                   3779:     default:
                   3780:         rnd_type = 80;
                   3781:         break;
                   3782:     }
                   3783:     set_floatx80_rounding_precision(rnd_type, &env->fp_status);
                   3784: #endif
                   3785: }
                   3786: 
                   3787: #if !defined(CONFIG_USER_ONLY) 
                   3788: 
                   3789: #define MMUSUFFIX _mmu
                   3790: #define GETPC() (__builtin_return_address(0))
                   3791: 
                   3792: #define SHIFT 0
                   3793: #include "softmmu_template.h"
                   3794: 
                   3795: #define SHIFT 1
                   3796: #include "softmmu_template.h"
                   3797: 
                   3798: #define SHIFT 2
                   3799: #include "softmmu_template.h"
                   3800: 
                   3801: #define SHIFT 3
                   3802: #include "softmmu_template.h"
                   3803: 
                   3804: #endif
                   3805: 
                   3806: /* try to fill the TLB and return an exception if error. If retaddr is
                   3807:    NULL, it means that the function was called in C code (i.e. not
                   3808:    from generated code or from helper.c) */
                   3809: /* XXX: fix it to restore all registers */
                   3810: void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
                   3811: {
                   3812:     TranslationBlock *tb;
                   3813:     int ret;
                   3814:     unsigned long pc;
                   3815:     CPUX86State *saved_env;
                   3816: 
                   3817:     /* XXX: hack to restore env in all cases, even if not called from
                   3818:        generated code */
                   3819:     saved_env = env;
                   3820:     env = cpu_single_env;
                   3821: 
                   3822:     ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1);
                   3823:     if (ret) {
                   3824:         if (retaddr) {
                   3825:             /* now we have a real cpu fault */
                   3826:             pc = (unsigned long)retaddr;
                   3827:             tb = tb_find_pc(pc);
                   3828:             if (tb) {
                   3829:                 /* the PC is inside the translated code. It means that we have
                   3830:                    a virtual CPU fault */
                   3831:                 cpu_restore_state(tb, env, pc, NULL);
                   3832:             }
                   3833:         }
                   3834:         if (retaddr)
1.1.1.2   root     3835:             raise_exception_err(env->exception_index, env->error_code);
1.1       root     3836:         else
1.1.1.2   root     3837:             raise_exception_err_norestore(env->exception_index, env->error_code);
1.1       root     3838:     }
                   3839:     env = saved_env;
                   3840: }

unix.superglobalmegacorp.com

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