Commit d8bc1fd0aeb0423074b5063c8dc94dddd7285321

Authored by bellard
1 parent 7501267e

ring 0 ops


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@254 c046a42c-6fe2-441c-8c8c-71466251a162
exec-i386.h
... ... @@ -123,6 +123,11 @@ typedef struct CCTable {
123 123 extern CCTable cc_table[];
124 124  
125 125 void load_seg(int seg_reg, int selector, unsigned cur_eip);
  126 +void jmp_seg(int selector, unsigned int new_eip);
  127 +void helper_lldt_T0(void);
  128 +void helper_ltr_T0(void);
  129 +void helper_movl_crN_T0(int reg);
  130 +void helper_movl_drN_T0(int reg);
126 131 void __hidden cpu_lock(void);
127 132 void __hidden cpu_unlock(void);
128 133 void raise_interrupt(int intno, int is_int, int error_code,
... ...
helper-i386.c
... ... @@ -157,7 +157,7 @@ void raise_interrupt(int intno, int is_int, int error_code,
157 157 break;
158 158 }
159 159 dpl = (e2 >> DESC_DPL_SHIFT) & 3;
160   - cpl = env->segs[R_CS] & 3;
  160 + cpl = env->segs[R_CS].selector & 3;
161 161 /* check privledge if software int */
162 162 if (is_int && dpl < cpl)
163 163 raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
... ... @@ -176,7 +176,7 @@ void raise_interrupt(int intno, int is_int, int error_code,
176 176 void raise_interrupt(int intno, int is_int, int error_code,
177 177 unsigned int next_eip)
178 178 {
179   - SegmentDescriptorTable *dt;
  179 + SegmentCache *dt;
180 180 uint8_t *ptr;
181 181 int dpl, cpl;
182 182 uint32_t e2;
... ... @@ -331,21 +331,98 @@ void helper_cpuid(void)
331 331 }
332 332 }
333 333  
  334 +static inline void load_seg_cache(SegmentCache *sc, uint32_t e1, uint32_t e2)
  335 +{
  336 + sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
  337 + sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
  338 + if (e2 & (1 << 23))
  339 + sc->limit = (sc->limit << 12) | 0xfff;
  340 + sc->seg_32bit = (e2 >> 22) & 1;
  341 +}
  342 +
  343 +void helper_lldt_T0(void)
  344 +{
  345 + int selector;
  346 + SegmentCache *dt;
  347 + uint32_t e1, e2;
  348 + int index;
  349 + uint8_t *ptr;
  350 +
  351 + selector = T0 & 0xffff;
  352 + if ((selector & 0xfffc) == 0) {
  353 + /* XXX: NULL selector case: invalid LDT */
  354 + env->ldt.base = NULL;
  355 + env->ldt.limit = 0;
  356 + } else {
  357 + if (selector & 0x4)
  358 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  359 + dt = &env->gdt;
  360 + index = selector & ~7;
  361 + if ((index + 7) > dt->limit)
  362 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  363 + ptr = dt->base + index;
  364 + e1 = ldl(ptr);
  365 + e2 = ldl(ptr + 4);
  366 + if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)
  367 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  368 + if (!(e2 & DESC_P_MASK))
  369 + raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
  370 + load_seg_cache(&env->ldt, e1, e2);
  371 + }
  372 + env->ldt.selector = selector;
  373 +}
  374 +
  375 +void helper_ltr_T0(void)
  376 +{
  377 + int selector;
  378 + SegmentCache *dt;
  379 + uint32_t e1, e2;
  380 + int index, type;
  381 + uint8_t *ptr;
  382 +
  383 + selector = T0 & 0xffff;
  384 + if ((selector & 0xfffc) == 0) {
  385 + /* XXX: NULL selector case: invalid LDT */
  386 + env->tr.base = NULL;
  387 + env->tr.limit = 0;
  388 + } else {
  389 + if (selector & 0x4)
  390 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  391 + dt = &env->gdt;
  392 + index = selector & ~7;
  393 + if ((index + 7) > dt->limit)
  394 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  395 + ptr = dt->base + index;
  396 + e1 = ldl(ptr);
  397 + e2 = ldl(ptr + 4);
  398 + type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
  399 + if ((e2 & DESC_S_MASK) ||
  400 + (type != 2 && type != 9))
  401 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  402 + if (!(e2 & DESC_P_MASK))
  403 + raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
  404 + load_seg_cache(&env->tr, e1, e2);
  405 + e2 |= 0x00000200; /* set the busy bit */
  406 + stl(ptr + 4, e2);
  407 + }
  408 + env->tr.selector = selector;
  409 +}
  410 +
334 411 /* only works if protected mode and not VM86 */
335   -void load_seg(int seg_reg, int selector, unsigned cur_eip)
  412 +void load_seg(int seg_reg, int selector, unsigned int cur_eip)
336 413 {
337 414 SegmentCache *sc;
338   - SegmentDescriptorTable *dt;
  415 + SegmentCache *dt;
339 416 int index;
340 417 uint32_t e1, e2;
341 418 uint8_t *ptr;
342   -
343   - sc = &env->seg_cache[seg_reg];
  419 +
  420 + sc = &env->segs[seg_reg];
344 421 if ((selector & 0xfffc) == 0) {
345 422 /* null selector case */
346 423 if (seg_reg == R_SS) {
347 424 EIP = cur_eip;
348   - raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  425 + raise_exception_err(EXCP0D_GPF, 0);
349 426 } else {
350 427 /* XXX: each access should trigger an exception */
351 428 sc->base = NULL;
... ... @@ -390,18 +467,93 @@ void load_seg(int seg_reg, int selector, unsigned cur_eip)
390 467 else
391 468 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
392 469 }
393   -
394   - sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
395   - sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
396   - if (e2 & (1 << 23))
397   - sc->limit = (sc->limit << 12) | 0xfff;
398   - sc->seg_32bit = (e2 >> 22) & 1;
  470 + load_seg_cache(sc, e1, e2);
399 471 #if 0
400 472 fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n",
401 473 selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);
402 474 #endif
403 475 }
404   - env->segs[seg_reg] = selector;
  476 + sc->selector = selector;
  477 +}
  478 +
  479 +/* protected mode jump */
  480 +void jmp_seg(int selector, unsigned int new_eip)
  481 +{
  482 + SegmentCache sc1;
  483 + SegmentCache *dt;
  484 + int index;
  485 + uint32_t e1, e2, cpl, dpl, rpl;
  486 + uint8_t *ptr;
  487 +
  488 + if ((selector & 0xfffc) == 0) {
  489 + raise_exception_err(EXCP0D_GPF, 0);
  490 + }
  491 +
  492 + if (selector & 0x4)
  493 + dt = &env->ldt;
  494 + else
  495 + dt = &env->gdt;
  496 + index = selector & ~7;
  497 + if ((index + 7) > dt->limit)
  498 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  499 + ptr = dt->base + index;
  500 + e1 = ldl(ptr);
  501 + e2 = ldl(ptr + 4);
  502 + cpl = env->segs[R_CS].selector & 3;
  503 + if (e2 & DESC_S_MASK) {
  504 + if (!(e2 & DESC_CS_MASK))
  505 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  506 + dpl = (e2 >> DESC_DPL_SHIFT) & 3;
  507 + if (e2 & DESC_CS_MASK) {
  508 + /* conforming code segment */
  509 + if (dpl > cpl)
  510 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  511 + } else {
  512 + /* non conforming code segment */
  513 + rpl = selector & 3;
  514 + if (rpl > cpl)
  515 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  516 + if (dpl != cpl)
  517 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  518 + }
  519 + if (!(e2 & DESC_P_MASK))
  520 + raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
  521 + load_seg_cache(&sc1, e1, e2);
  522 + if (new_eip > sc1.limit)
  523 + raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
  524 + env->segs[R_CS] = sc1;
  525 + env->segs[R_CS].selector = (selector & 0xfffc) | cpl;
  526 + EIP = new_eip;
  527 + } else {
  528 + cpu_abort(env, "jmp to call/task gate not supported 0x%04x:0x%08x",
  529 + selector, new_eip);
  530 + }
  531 +}
  532 +
  533 +/* XXX: do more */
  534 +void helper_movl_crN_T0(int reg)
  535 +{
  536 + switch(reg) {
  537 + case 0:
  538 + default:
  539 + env->cr[0] = reg;
  540 + break;
  541 + case 2:
  542 + env->cr[2] = reg;
  543 + break;
  544 + case 3:
  545 + env->cr[3] = reg;
  546 + break;
  547 + case 4:
  548 + env->cr[4] = reg;
  549 + break;
  550 + }
  551 +}
  552 +
  553 +/* XXX: do more */
  554 +void helper_movl_drN_T0(int reg)
  555 +{
  556 + env->dr[reg] = T0;
405 557 }
406 558  
407 559 /* rdtsc */
... ... @@ -425,7 +577,7 @@ void helper_rdtsc(void)
425 577 void helper_lsl(void)
426 578 {
427 579 unsigned int selector, limit;
428   - SegmentDescriptorTable *dt;
  580 + SegmentCache *dt;
429 581 int index;
430 582 uint32_t e1, e2;
431 583 uint8_t *ptr;
... ... @@ -452,7 +604,7 @@ void helper_lsl(void)
452 604 void helper_lar(void)
453 605 {
454 606 unsigned int selector;
455   - SegmentDescriptorTable *dt;
  607 + SegmentCache *dt;
456 608 int index;
457 609 uint32_t e2;
458 610 uint8_t *ptr;
... ...
op-i386.c
... ... @@ -357,6 +357,11 @@ void OPPROTO op_andl_T0_ffff(void)
357 357 T0 = T0 & 0xffff;
358 358 }
359 359  
  360 +void OPPROTO op_andl_T0_im(void)
  361 +{
  362 + T0 = T0 & PARAM1;
  363 +}
  364 +
360 365 void OPPROTO op_movl_T0_T1(void)
361 366 {
362 367 T0 = T1;
... ... @@ -665,7 +670,7 @@ void op_pushl_ss32_T0(void)
665 670 {
666 671 uint32_t offset;
667 672 offset = ESP - 4;
668   - stl(env->seg_cache[R_SS].base + offset, T0);
  673 + stl(env->segs[R_SS].base + offset, T0);
669 674 /* modify ESP after to handle exceptions correctly */
670 675 ESP = offset;
671 676 }
... ... @@ -674,7 +679,7 @@ void op_pushw_ss32_T0(void)
674 679 {
675 680 uint32_t offset;
676 681 offset = ESP - 2;
677   - stw(env->seg_cache[R_SS].base + offset, T0);
  682 + stw(env->segs[R_SS].base + offset, T0);
678 683 /* modify ESP after to handle exceptions correctly */
679 684 ESP = offset;
680 685 }
... ... @@ -683,7 +688,7 @@ void op_pushl_ss16_T0(void)
683 688 {
684 689 uint32_t offset;
685 690 offset = (ESP - 4) & 0xffff;
686   - stl(env->seg_cache[R_SS].base + offset, T0);
  691 + stl(env->segs[R_SS].base + offset, T0);
687 692 /* modify ESP after to handle exceptions correctly */
688 693 ESP = (ESP & ~0xffff) | offset;
689 694 }
... ... @@ -692,7 +697,7 @@ void op_pushw_ss16_T0(void)
692 697 {
693 698 uint32_t offset;
694 699 offset = (ESP - 2) & 0xffff;
695   - stw(env->seg_cache[R_SS].base + offset, T0);
  700 + stw(env->segs[R_SS].base + offset, T0);
696 701 /* modify ESP after to handle exceptions correctly */
697 702 ESP = (ESP & ~0xffff) | offset;
698 703 }
... ... @@ -710,22 +715,22 @@ void op_popw_T0(void)
710 715  
711 716 void op_popl_ss32_T0(void)
712 717 {
713   - T0 = ldl(env->seg_cache[R_SS].base + ESP);
  718 + T0 = ldl(env->segs[R_SS].base + ESP);
714 719 }
715 720  
716 721 void op_popw_ss32_T0(void)
717 722 {
718   - T0 = lduw(env->seg_cache[R_SS].base + ESP);
  723 + T0 = lduw(env->segs[R_SS].base + ESP);
719 724 }
720 725  
721 726 void op_popl_ss16_T0(void)
722 727 {
723   - T0 = ldl(env->seg_cache[R_SS].base + (ESP & 0xffff));
  728 + T0 = ldl(env->segs[R_SS].base + (ESP & 0xffff));
724 729 }
725 730  
726 731 void op_popw_ss16_T0(void)
727 732 {
728   - T0 = lduw(env->seg_cache[R_SS].base + (ESP & 0xffff));
  733 + T0 = lduw(env->segs[R_SS].base + (ESP & 0xffff));
729 734 }
730 735  
731 736 void op_addl_ESP_4(void)
... ... @@ -909,17 +914,18 @@ void OPPROTO op_movl_seg_T0(void)
909 914 void OPPROTO op_movl_seg_T0_vm(void)
910 915 {
911 916 int selector;
  917 + SegmentCache *sc;
912 918  
913 919 selector = T0 & 0xffff;
914 920 /* env->segs[] access */
915   - *(uint32_t *)((char *)env + PARAM1) = selector;
916   - /* env->seg_cache[] access */
917   - ((SegmentCache *)((char *)env + PARAM2))->base = (void *)(selector << 4);
  921 + sc = (SegmentCache *)((char *)env + PARAM1);
  922 + sc->selector = selector;
  923 + sc->base = (void *)(selector << 4);
918 924 }
919 925  
920 926 void OPPROTO op_movl_T0_seg(void)
921 927 {
922   - T0 = env->segs[PARAM1];
  928 + T0 = env->segs[PARAM1].selector;
923 929 }
924 930  
925 931 void OPPROTO op_movl_A0_seg(void)
... ... @@ -942,6 +948,61 @@ void OPPROTO op_lar(void)
942 948 helper_lar();
943 949 }
944 950  
  951 +/* T0: segment, T1:eip */
  952 +void OPPROTO op_ljmp_T0_T1(void)
  953 +{
  954 + jmp_seg(T0 & 0xffff, T1);
  955 +}
  956 +
  957 +void OPPROTO op_lldt_T0(void)
  958 +{
  959 + helper_lldt_T0();
  960 +}
  961 +
  962 +void OPPROTO op_ltr_T0(void)
  963 +{
  964 + helper_ltr_T0();
  965 +}
  966 +
  967 +/* CR registers access */
  968 +void OPPROTO op_movl_crN_T0(void)
  969 +{
  970 + helper_movl_crN_T0(PARAM1);
  971 +}
  972 +
  973 +/* DR registers access */
  974 +void OPPROTO op_movl_drN_T0(void)
  975 +{
  976 + helper_movl_drN_T0(PARAM1);
  977 +}
  978 +
  979 +void OPPROTO op_lmsw_T0(void)
  980 +{
  981 + /* only 4 lower bits of CR0 are modified */
  982 + T0 = (env->cr[0] & ~0xf) | (T0 & 0xf);
  983 + helper_movl_crN_T0(0);
  984 +}
  985 +
  986 +void OPPROTO op_movl_T0_env(void)
  987 +{
  988 + T0 = *(uint32_t *)((char *)env + PARAM1);
  989 +}
  990 +
  991 +void OPPROTO op_movl_env_T0(void)
  992 +{
  993 + *(uint32_t *)((char *)env + PARAM1) = T0;
  994 +}
  995 +
  996 +void OPPROTO op_movl_env_T1(void)
  997 +{
  998 + *(uint32_t *)((char *)env + PARAM1) = T1;
  999 +}
  1000 +
  1001 +void OPPROTO op_clts(void)
  1002 +{
  1003 + env->cr[0] &= ~CR0_TS_MASK;
  1004 +}
  1005 +
945 1006 /* flags handling */
946 1007  
947 1008 /* slow jumps cases : in order to avoid calling a function with a
... ...
translate-i386.c
... ... @@ -575,7 +575,7 @@ static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
575 575 if (s->addseg && override < 0)
576 576 override = R_DS;
577 577 if (override >= 0) {
578   - gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
  578 + gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
579 579 index = 3 + ot;
580 580 } else {
581 581 index = ot;
... ... @@ -583,7 +583,7 @@ static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
583 583 } else {
584 584 if (override < 0)
585 585 override = R_DS;
586   - gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
  586 + gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
587 587 /* 16 address, always override */
588 588 index = 6 + ot;
589 589 }
... ... @@ -878,7 +878,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
878 878 else
879 879 override = R_DS;
880 880 }
881   - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
  881 + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
882 882 }
883 883 } else {
884 884 switch (mod) {
... ... @@ -944,7 +944,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
944 944 else
945 945 override = R_DS;
946 946 }
947   - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
  947 + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
948 948 }
949 949 }
950 950  
... ... @@ -1146,8 +1146,7 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1146 1146 if (!s->vm86)
1147 1147 gen_op_movl_seg_T0(seg_reg, cur_eip);
1148 1148 else
1149   - gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]),
1150   - offsetof(CPUX86State,seg_cache[seg_reg].base));
  1149 + gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
1151 1150 if (!s->addseg && seg_reg < R_FS)
1152 1151 s->is_jmp = 2; /* abort translation because the register may
1153 1152 have a non zero base */
... ... @@ -1230,7 +1229,7 @@ static void gen_stack_A0(DisasContext *s)
1230 1229 gen_op_andl_A0_ffff();
1231 1230 gen_op_movl_T1_A0();
1232 1231 if (s->addseg)
1233   - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
  1232 + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1234 1233 }
1235 1234  
1236 1235 /* NOTE: wrap around in 16 bit not fully handled */
... ... @@ -1243,7 +1242,7 @@ static void gen_pusha(DisasContext *s)
1243 1242 gen_op_andl_A0_ffff();
1244 1243 gen_op_movl_T1_A0();
1245 1244 if (s->addseg)
1246   - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
  1245 + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1247 1246 for(i = 0;i < 8; i++) {
1248 1247 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1249 1248 gen_op_st_T0_A0[OT_WORD + s->dflag]();
... ... @@ -1262,7 +1261,7 @@ static void gen_popa(DisasContext *s)
1262 1261 gen_op_movl_T1_A0();
1263 1262 gen_op_addl_T1_im(16 << s->dflag);
1264 1263 if (s->addseg)
1265   - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
  1264 + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1266 1265 for(i = 0;i < 8; i++) {
1267 1266 /* ESP is not reloaded */
1268 1267 if (i != 3) {
... ... @@ -1291,7 +1290,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
1291 1290 gen_op_andl_A0_ffff();
1292 1291 gen_op_movl_T1_A0();
1293 1292 if (s->addseg)
1294   - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
  1293 + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base));
1295 1294 /* push bp */
1296 1295 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1297 1296 gen_op_st_T0_A0[ot]();
... ... @@ -1714,9 +1713,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1714 1713 gen_op_ld_T1_A0[ot]();
1715 1714 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1716 1715 gen_op_lduw_T0_A0();
1717   - gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1718   - gen_op_movl_T0_T1();
1719   - gen_op_jmp_T0();
  1716 + if (!s->vm86) {
  1717 + /* we compute EIP to handle the exception case */
  1718 + gen_op_jmp_im(pc_start - s->cs_base);
  1719 + gen_op_ljmp_T0_T1();
  1720 + } else {
  1721 + gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
  1722 + gen_op_movl_T0_T1();
  1723 + gen_op_jmp_T0();
  1724 + }
1720 1725 s->is_jmp = 1;
1721 1726 break;
1722 1727 case 6: /* push Ev */
... ... @@ -2085,7 +2090,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2085 2090 override = R_DS;
2086 2091 }
2087 2092 if (must_add_seg) {
2088   - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
  2093 + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2089 2094 }
2090 2095 }
2091 2096 if ((b & 2) == 0) {
... ... @@ -2113,7 +2118,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2113 2118 override = R_DS;
2114 2119 }
2115 2120 if (must_add_seg) {
2116   - gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
  2121 + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base));
2117 2122 }
2118 2123 }
2119 2124 gen_op_ldub_T0_A0();
... ... @@ -2619,12 +2624,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2619 2624 break;
2620 2625 case 0x1c:
2621 2626 switch(rm) {
  2627 + case 0: /* feni (287 only, just do nop here) */
  2628 + break;
  2629 + case 1: /* fdisi (287 only, just do nop here) */
  2630 + break;
2622 2631 case 2: /* fclex */
2623 2632 gen_op_fclex();
2624 2633 break;
2625 2634 case 3: /* fninit */
2626 2635 gen_op_fninit();
2627 2636 break;
  2637 + case 4: /* fsetpm (287 only, just do nop here) */
  2638 + break;
2628 2639 default:
2629 2640 goto illegal_op;
2630 2641 }
... ... @@ -3011,8 +3022,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3011 3022  
3012 3023 /* change cs and pc */
3013 3024 gen_op_movl_T0_im(selector);
3014   - gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3015   - gen_op_jmp_im((unsigned long)offset);
  3025 + if (!s->vm86) {
  3026 + /* we compute EIP to handle the exception case */
  3027 + gen_op_jmp_im(pc_start - s->cs_base);
  3028 + gen_op_movl_T1_im(offset);
  3029 + gen_op_ljmp_T0_T1();
  3030 + } else {
  3031 + gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
  3032 + gen_op_jmp_im((unsigned long)offset);
  3033 + }
3016 3034 s->is_jmp = 1;
3017 3035 }
3018 3036 break;
... ... @@ -3343,6 +3361,111 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3343 3361 /* XXX: if cpl == 0, then should do something else */
3344 3362 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3345 3363 break;
  3364 + case 0x100:
  3365 + modrm = ldub(s->pc++);
  3366 + mod = (modrm >> 6) & 3;
  3367 + op = (modrm >> 3) & 7;
  3368 + switch(op) {
  3369 + case 0: /* sldt */
  3370 + gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
  3371 + ot = OT_WORD;
  3372 + if (mod == 3)
  3373 + ot += s->dflag;
  3374 + gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
  3375 + break;
  3376 + case 2: /* lldt */
  3377 + if (s->cpl != 0) {
  3378 + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
  3379 + } else {
  3380 + gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
  3381 + gen_op_jmp_im(pc_start - s->cs_base);
  3382 + gen_op_lldt_T0();
  3383 + }
  3384 + break;
  3385 + case 1: /* str */
  3386 + gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
  3387 + ot = OT_WORD;
  3388 + if (mod == 3)
  3389 + ot += s->dflag;
  3390 + gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
  3391 + break;
  3392 + case 3: /* ltr */
  3393 + if (s->cpl != 0) {
  3394 + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
  3395 + } else {
  3396 + gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
  3397 + gen_op_jmp_im(pc_start - s->cs_base);
  3398 + gen_op_ltr_T0();
  3399 + }
  3400 + break;
  3401 + case 4: /* verr */
  3402 + case 5: /* verw */
  3403 + default:
  3404 + goto illegal_op;
  3405 + }
  3406 + break;
  3407 + case 0x101:
  3408 + modrm = ldub(s->pc++);
  3409 + mod = (modrm >> 6) & 3;
  3410 + op = (modrm >> 3) & 7;
  3411 + switch(op) {
  3412 + case 0: /* sgdt */
  3413 + case 1: /* sidt */
  3414 + if (mod == 3)
  3415 + goto illegal_op;
  3416 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  3417 + if (op == 0)
  3418 + gen_op_movl_T0_env(offsetof(CPUX86State,gdt.limit));
  3419 + else
  3420 + gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit));
  3421 + gen_op_stw_T0_A0();
  3422 + gen_op_addl_A0_im(2);
  3423 + if (op == 0)
  3424 + gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base));
  3425 + else
  3426 + gen_op_movl_T0_env(offsetof(CPUX86State,idt.base));
  3427 + if (!s->dflag)
  3428 + gen_op_andl_T0_im(0xffffff);
  3429 + gen_op_stl_T0_A0();
  3430 + break;
  3431 + case 2: /* lgdt */
  3432 + case 3: /* lidt */
  3433 + if (mod == 3)
  3434 + goto illegal_op;
  3435 + if (s->cpl != 0) {
  3436 + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
  3437 + } else {
  3438 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  3439 + gen_op_lduw_T1_A0();
  3440 + gen_op_addl_A0_im(2);
  3441 + gen_op_ldl_T0_A0();
  3442 + if (!s->dflag)
  3443 + gen_op_andl_T0_im(0xffffff);
  3444 + if (op == 2) {
  3445 + gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base));
  3446 + gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit));
  3447 + } else {
  3448 + gen_op_movl_env_T0(offsetof(CPUX86State,idt.base));
  3449 + gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit));
  3450 + }
  3451 + }
  3452 + break;
  3453 + case 4: /* smsw */
  3454 + gen_op_movl_T0_env(offsetof(CPUX86State,cr[0]));
  3455 + gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 1);
  3456 + break;
  3457 + case 6: /* lmsw */
  3458 + if (s->cpl != 0) {
  3459 + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
  3460 + } else {
  3461 + gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0);
  3462 + gen_op_lmsw_T0();
  3463 + }
  3464 + break;
  3465 + default:
  3466 + goto illegal_op;
  3467 + }
  3468 + break;
3346 3469 case 0x102: /* lar */
3347 3470 case 0x103: /* lsl */
3348 3471 if (s->vm86)
... ... @@ -3361,6 +3484,83 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3361 3484 s->cc_op = CC_OP_EFLAGS;
3362 3485 gen_op_mov_reg_T1[ot][reg]();
3363 3486 break;
  3487 + case 0x118:
  3488 + modrm = ldub(s->pc++);
  3489 + mod = (modrm >> 6) & 3;
  3490 + op = (modrm >> 3) & 7;
  3491 + switch(op) {
  3492 + case 0: /* prefetchnta */
  3493 + case 1: /* prefetchnt0 */
  3494 + case 2: /* prefetchnt0 */
  3495 + case 3: /* prefetchnt0 */
  3496 + if (mod == 3)
  3497 + goto illegal_op;
  3498 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  3499 + /* nothing more to do */
  3500 + break;
  3501 + default:
  3502 + goto illegal_op;
  3503 + }
  3504 + break;
  3505 + case 0x120: /* mov reg, crN */
  3506 + case 0x122: /* mov crN, reg */
  3507 + if (s->cpl != 0) {
  3508 + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
  3509 + } else {
  3510 + modrm = ldub(s->pc++);
  3511 + if ((modrm & 0xc0) != 0xc0)
  3512 + goto illegal_op;
  3513 + rm = modrm & 7;
  3514 + reg = (modrm >> 3) & 7;
  3515 + switch(reg) {
  3516 + case 0:
  3517 + case 2:
  3518 + case 3:
  3519 + case 4:
  3520 + if (b & 2) {
  3521 + gen_op_mov_TN_reg[OT_LONG][0][rm]();
  3522 + gen_op_movl_crN_T0(reg);
  3523 + s->is_jmp = 2;
  3524 + } else {
  3525 + gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
  3526 + gen_op_mov_reg_T0[OT_LONG][rm]();
  3527 + }
  3528 + break;
  3529 + default:
  3530 + goto illegal_op;
  3531 + }
  3532 + }
  3533 + break;
  3534 + case 0x121: /* mov reg, drN */
  3535 + case 0x123: /* mov drN, reg */
  3536 + if (s->cpl != 0) {
  3537 + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
  3538 + } else {
  3539 + modrm = ldub(s->pc++);
  3540 + if ((modrm & 0xc0) != 0xc0)
  3541 + goto illegal_op;
  3542 + rm = modrm & 7;
  3543 + reg = (modrm >> 3) & 7;
  3544 + /* XXX: do it dynamically with CR4.DE bit */
  3545 + if (reg == 4 || reg == 5)
  3546 + goto illegal_op;
  3547 + if (b & 2) {
  3548 + gen_op_mov_TN_reg[OT_LONG][0][rm]();
  3549 + gen_op_movl_drN_T0(reg);
  3550 + s->is_jmp = 2;
  3551 + } else {
  3552 + gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
  3553 + gen_op_mov_reg_T0[OT_LONG][rm]();
  3554 + }
  3555 + }
  3556 + break;
  3557 + case 0x106: /* clts */
  3558 + if (s->cpl != 0) {
  3559 + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
  3560 + } else {
  3561 + gen_op_clts();
  3562 + }
  3563 + break;
3364 3564 default:
3365 3565 goto illegal_op;
3366 3566 }
... ... @@ -3859,12 +4059,12 @@ void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
3859 4059 eflags & CC_P ? 'P' : '-',
3860 4060 eflags & CC_C ? 'C' : '-');
3861 4061 fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
3862   - env->segs[R_CS],
3863   - env->segs[R_SS],
3864   - env->segs[R_DS],
3865   - env->segs[R_ES],
3866   - env->segs[R_FS],
3867   - env->segs[R_GS]);
  4062 + env->segs[R_CS].selector,
  4063 + env->segs[R_SS].selector,
  4064 + env->segs[R_DS].selector,
  4065 + env->segs[R_ES].selector,
  4066 + env->segs[R_FS].selector,
  4067 + env->segs[R_GS].selector);
3868 4068 if (flags & X86_DUMP_CCOP) {
3869 4069 if ((unsigned)env->cc_op < CC_OP_NB)
3870 4070 strcpy(cc_op_name, cc_op_str[env->cc_op]);
... ...