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,6 +123,11 @@ typedef struct CCTable {
123 extern CCTable cc_table[]; 123 extern CCTable cc_table[];
124 124
125 void load_seg(int seg_reg, int selector, unsigned cur_eip); 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 void __hidden cpu_lock(void); 131 void __hidden cpu_lock(void);
127 void __hidden cpu_unlock(void); 132 void __hidden cpu_unlock(void);
128 void raise_interrupt(int intno, int is_int, int error_code, 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,7 +157,7 @@ void raise_interrupt(int intno, int is_int, int error_code,
157 break; 157 break;
158 } 158 }
159 dpl = (e2 >> DESC_DPL_SHIFT) & 3; 159 dpl = (e2 >> DESC_DPL_SHIFT) & 3;
160 - cpl = env->segs[R_CS] & 3; 160 + cpl = env->segs[R_CS].selector & 3;
161 /* check privledge if software int */ 161 /* check privledge if software int */
162 if (is_int && dpl < cpl) 162 if (is_int && dpl < cpl)
163 raise_exception_err(EXCP0D_GPF, intno * 8 + 2); 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,7 +176,7 @@ void raise_interrupt(int intno, int is_int, int error_code,
176 void raise_interrupt(int intno, int is_int, int error_code, 176 void raise_interrupt(int intno, int is_int, int error_code,
177 unsigned int next_eip) 177 unsigned int next_eip)
178 { 178 {
179 - SegmentDescriptorTable *dt; 179 + SegmentCache *dt;
180 uint8_t *ptr; 180 uint8_t *ptr;
181 int dpl, cpl; 181 int dpl, cpl;
182 uint32_t e2; 182 uint32_t e2;
@@ -331,21 +331,98 @@ void helper_cpuid(void) @@ -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 /* only works if protected mode and not VM86 */ 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 SegmentCache *sc; 414 SegmentCache *sc;
338 - SegmentDescriptorTable *dt; 415 + SegmentCache *dt;
339 int index; 416 int index;
340 uint32_t e1, e2; 417 uint32_t e1, e2;
341 uint8_t *ptr; 418 uint8_t *ptr;
342 -  
343 - sc = &env->seg_cache[seg_reg]; 419 +
  420 + sc = &env->segs[seg_reg];
344 if ((selector & 0xfffc) == 0) { 421 if ((selector & 0xfffc) == 0) {
345 /* null selector case */ 422 /* null selector case */
346 if (seg_reg == R_SS) { 423 if (seg_reg == R_SS) {
347 EIP = cur_eip; 424 EIP = cur_eip;
348 - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); 425 + raise_exception_err(EXCP0D_GPF, 0);
349 } else { 426 } else {
350 /* XXX: each access should trigger an exception */ 427 /* XXX: each access should trigger an exception */
351 sc->base = NULL; 428 sc->base = NULL;
@@ -390,18 +467,93 @@ void load_seg(int seg_reg, int selector, unsigned cur_eip) @@ -390,18 +467,93 @@ void load_seg(int seg_reg, int selector, unsigned cur_eip)
390 else 467 else
391 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); 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 #if 0 471 #if 0
400 fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n", 472 fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n",
401 selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit); 473 selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);
402 #endif 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 /* rdtsc */ 559 /* rdtsc */
@@ -425,7 +577,7 @@ void helper_rdtsc(void) @@ -425,7 +577,7 @@ void helper_rdtsc(void)
425 void helper_lsl(void) 577 void helper_lsl(void)
426 { 578 {
427 unsigned int selector, limit; 579 unsigned int selector, limit;
428 - SegmentDescriptorTable *dt; 580 + SegmentCache *dt;
429 int index; 581 int index;
430 uint32_t e1, e2; 582 uint32_t e1, e2;
431 uint8_t *ptr; 583 uint8_t *ptr;
@@ -452,7 +604,7 @@ void helper_lsl(void) @@ -452,7 +604,7 @@ void helper_lsl(void)
452 void helper_lar(void) 604 void helper_lar(void)
453 { 605 {
454 unsigned int selector; 606 unsigned int selector;
455 - SegmentDescriptorTable *dt; 607 + SegmentCache *dt;
456 int index; 608 int index;
457 uint32_t e2; 609 uint32_t e2;
458 uint8_t *ptr; 610 uint8_t *ptr;
op-i386.c
@@ -357,6 +357,11 @@ void OPPROTO op_andl_T0_ffff(void) @@ -357,6 +357,11 @@ void OPPROTO op_andl_T0_ffff(void)
357 T0 = T0 & 0xffff; 357 T0 = T0 & 0xffff;
358 } 358 }
359 359
  360 +void OPPROTO op_andl_T0_im(void)
  361 +{
  362 + T0 = T0 & PARAM1;
  363 +}
  364 +
360 void OPPROTO op_movl_T0_T1(void) 365 void OPPROTO op_movl_T0_T1(void)
361 { 366 {
362 T0 = T1; 367 T0 = T1;
@@ -665,7 +670,7 @@ void op_pushl_ss32_T0(void) @@ -665,7 +670,7 @@ void op_pushl_ss32_T0(void)
665 { 670 {
666 uint32_t offset; 671 uint32_t offset;
667 offset = ESP - 4; 672 offset = ESP - 4;
668 - stl(env->seg_cache[R_SS].base + offset, T0); 673 + stl(env->segs[R_SS].base + offset, T0);
669 /* modify ESP after to handle exceptions correctly */ 674 /* modify ESP after to handle exceptions correctly */
670 ESP = offset; 675 ESP = offset;
671 } 676 }
@@ -674,7 +679,7 @@ void op_pushw_ss32_T0(void) @@ -674,7 +679,7 @@ void op_pushw_ss32_T0(void)
674 { 679 {
675 uint32_t offset; 680 uint32_t offset;
676 offset = ESP - 2; 681 offset = ESP - 2;
677 - stw(env->seg_cache[R_SS].base + offset, T0); 682 + stw(env->segs[R_SS].base + offset, T0);
678 /* modify ESP after to handle exceptions correctly */ 683 /* modify ESP after to handle exceptions correctly */
679 ESP = offset; 684 ESP = offset;
680 } 685 }
@@ -683,7 +688,7 @@ void op_pushl_ss16_T0(void) @@ -683,7 +688,7 @@ void op_pushl_ss16_T0(void)
683 { 688 {
684 uint32_t offset; 689 uint32_t offset;
685 offset = (ESP - 4) & 0xffff; 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 /* modify ESP after to handle exceptions correctly */ 692 /* modify ESP after to handle exceptions correctly */
688 ESP = (ESP & ~0xffff) | offset; 693 ESP = (ESP & ~0xffff) | offset;
689 } 694 }
@@ -692,7 +697,7 @@ void op_pushw_ss16_T0(void) @@ -692,7 +697,7 @@ void op_pushw_ss16_T0(void)
692 { 697 {
693 uint32_t offset; 698 uint32_t offset;
694 offset = (ESP - 2) & 0xffff; 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 /* modify ESP after to handle exceptions correctly */ 701 /* modify ESP after to handle exceptions correctly */
697 ESP = (ESP & ~0xffff) | offset; 702 ESP = (ESP & ~0xffff) | offset;
698 } 703 }
@@ -710,22 +715,22 @@ void op_popw_T0(void) @@ -710,22 +715,22 @@ void op_popw_T0(void)
710 715
711 void op_popl_ss32_T0(void) 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 void op_popw_ss32_T0(void) 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 void op_popl_ss16_T0(void) 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 void op_popw_ss16_T0(void) 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 void op_addl_ESP_4(void) 736 void op_addl_ESP_4(void)
@@ -909,17 +914,18 @@ void OPPROTO op_movl_seg_T0(void) @@ -909,17 +914,18 @@ void OPPROTO op_movl_seg_T0(void)
909 void OPPROTO op_movl_seg_T0_vm(void) 914 void OPPROTO op_movl_seg_T0_vm(void)
910 { 915 {
911 int selector; 916 int selector;
  917 + SegmentCache *sc;
912 918
913 selector = T0 & 0xffff; 919 selector = T0 & 0xffff;
914 /* env->segs[] access */ 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 void OPPROTO op_movl_T0_seg(void) 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 void OPPROTO op_movl_A0_seg(void) 931 void OPPROTO op_movl_A0_seg(void)
@@ -942,6 +948,61 @@ void OPPROTO op_lar(void) @@ -942,6 +948,61 @@ void OPPROTO op_lar(void)
942 helper_lar(); 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 /* flags handling */ 1006 /* flags handling */
946 1007
947 /* slow jumps cases : in order to avoid calling a function with a 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,7 +575,7 @@ static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
575 if (s->addseg && override < 0) 575 if (s->addseg && override < 0)
576 override = R_DS; 576 override = R_DS;
577 if (override >= 0) { 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 index = 3 + ot; 579 index = 3 + ot;
580 } else { 580 } else {
581 index = ot; 581 index = ot;
@@ -583,7 +583,7 @@ static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func) @@ -583,7 +583,7 @@ static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
583 } else { 583 } else {
584 if (override < 0) 584 if (override < 0)
585 override = R_DS; 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 /* 16 address, always override */ 587 /* 16 address, always override */
588 index = 6 + ot; 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,7 +878,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
878 else 878 else
879 override = R_DS; 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 } else { 883 } else {
884 switch (mod) { 884 switch (mod) {
@@ -944,7 +944,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ @@ -944,7 +944,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
944 else 944 else
945 override = R_DS; 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,8 +1146,7 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1146 if (!s->vm86) 1146 if (!s->vm86)
1147 gen_op_movl_seg_T0(seg_reg, cur_eip); 1147 gen_op_movl_seg_T0(seg_reg, cur_eip);
1148 else 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 if (!s->addseg && seg_reg < R_FS) 1150 if (!s->addseg && seg_reg < R_FS)
1152 s->is_jmp = 2; /* abort translation because the register may 1151 s->is_jmp = 2; /* abort translation because the register may
1153 have a non zero base */ 1152 have a non zero base */
@@ -1230,7 +1229,7 @@ static void gen_stack_A0(DisasContext *s) @@ -1230,7 +1229,7 @@ static void gen_stack_A0(DisasContext *s)
1230 gen_op_andl_A0_ffff(); 1229 gen_op_andl_A0_ffff();
1231 gen_op_movl_T1_A0(); 1230 gen_op_movl_T1_A0();
1232 if (s->addseg) 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 /* NOTE: wrap around in 16 bit not fully handled */ 1235 /* NOTE: wrap around in 16 bit not fully handled */
@@ -1243,7 +1242,7 @@ static void gen_pusha(DisasContext *s) @@ -1243,7 +1242,7 @@ static void gen_pusha(DisasContext *s)
1243 gen_op_andl_A0_ffff(); 1242 gen_op_andl_A0_ffff();
1244 gen_op_movl_T1_A0(); 1243 gen_op_movl_T1_A0();
1245 if (s->addseg) 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 for(i = 0;i < 8; i++) { 1246 for(i = 0;i < 8; i++) {
1248 gen_op_mov_TN_reg[OT_LONG][0][7 - i](); 1247 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1249 gen_op_st_T0_A0[OT_WORD + s->dflag](); 1248 gen_op_st_T0_A0[OT_WORD + s->dflag]();
@@ -1262,7 +1261,7 @@ static void gen_popa(DisasContext *s) @@ -1262,7 +1261,7 @@ static void gen_popa(DisasContext *s)
1262 gen_op_movl_T1_A0(); 1261 gen_op_movl_T1_A0();
1263 gen_op_addl_T1_im(16 << s->dflag); 1262 gen_op_addl_T1_im(16 << s->dflag);
1264 if (s->addseg) 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 for(i = 0;i < 8; i++) { 1265 for(i = 0;i < 8; i++) {
1267 /* ESP is not reloaded */ 1266 /* ESP is not reloaded */
1268 if (i != 3) { 1267 if (i != 3) {
@@ -1291,7 +1290,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) @@ -1291,7 +1290,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
1291 gen_op_andl_A0_ffff(); 1290 gen_op_andl_A0_ffff();
1292 gen_op_movl_T1_A0(); 1291 gen_op_movl_T1_A0();
1293 if (s->addseg) 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 /* push bp */ 1294 /* push bp */
1296 gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); 1295 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1297 gen_op_st_T0_A0[ot](); 1296 gen_op_st_T0_A0[ot]();
@@ -1714,9 +1713,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1714,9 +1713,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1714 gen_op_ld_T1_A0[ot](); 1713 gen_op_ld_T1_A0[ot]();
1715 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); 1714 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1716 gen_op_lduw_T0_A0(); 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 s->is_jmp = 1; 1725 s->is_jmp = 1;
1721 break; 1726 break;
1722 case 6: /* push Ev */ 1727 case 6: /* push Ev */
@@ -2085,7 +2090,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2085,7 +2090,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2085 override = R_DS; 2090 override = R_DS;
2086 } 2091 }
2087 if (must_add_seg) { 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 if ((b & 2) == 0) { 2096 if ((b & 2) == 0) {
@@ -2113,7 +2118,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2113,7 +2118,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2113 override = R_DS; 2118 override = R_DS;
2114 } 2119 }
2115 if (must_add_seg) { 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 gen_op_ldub_T0_A0(); 2124 gen_op_ldub_T0_A0();
@@ -2619,12 +2624,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2619,12 +2624,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2619 break; 2624 break;
2620 case 0x1c: 2625 case 0x1c:
2621 switch(rm) { 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 case 2: /* fclex */ 2631 case 2: /* fclex */
2623 gen_op_fclex(); 2632 gen_op_fclex();
2624 break; 2633 break;
2625 case 3: /* fninit */ 2634 case 3: /* fninit */
2626 gen_op_fninit(); 2635 gen_op_fninit();
2627 break; 2636 break;
  2637 + case 4: /* fsetpm (287 only, just do nop here) */
  2638 + break;
2628 default: 2639 default:
2629 goto illegal_op; 2640 goto illegal_op;
2630 } 2641 }
@@ -3011,8 +3022,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3011,8 +3022,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3011 3022
3012 /* change cs and pc */ 3023 /* change cs and pc */
3013 gen_op_movl_T0_im(selector); 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 s->is_jmp = 1; 3034 s->is_jmp = 1;
3017 } 3035 }
3018 break; 3036 break;
@@ -3343,6 +3361,111 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3343,6 +3361,111 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3343 /* XXX: if cpl == 0, then should do something else */ 3361 /* XXX: if cpl == 0, then should do something else */
3344 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 3362 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3345 break; 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 case 0x102: /* lar */ 3469 case 0x102: /* lar */
3347 case 0x103: /* lsl */ 3470 case 0x103: /* lsl */
3348 if (s->vm86) 3471 if (s->vm86)
@@ -3361,6 +3484,83 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3361,6 +3484,83 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3361 s->cc_op = CC_OP_EFLAGS; 3484 s->cc_op = CC_OP_EFLAGS;
3362 gen_op_mov_reg_T1[ot][reg](); 3485 gen_op_mov_reg_T1[ot][reg]();
3363 break; 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 default: 3564 default:
3365 goto illegal_op; 3565 goto illegal_op;
3366 } 3566 }
@@ -3859,12 +4059,12 @@ void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags) @@ -3859,12 +4059,12 @@ void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
3859 eflags & CC_P ? 'P' : '-', 4059 eflags & CC_P ? 'P' : '-',
3860 eflags & CC_C ? 'C' : '-'); 4060 eflags & CC_C ? 'C' : '-');
3861 fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n", 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 if (flags & X86_DUMP_CCOP) { 4068 if (flags & X86_DUMP_CCOP) {
3869 if ((unsigned)env->cc_op < CC_OP_NB) 4069 if ((unsigned)env->cc_op < CC_OP_NB)
3870 strcpy(cc_op_name, cc_op_str[env->cc_op]); 4070 strcpy(cc_op_name, cc_op_str[env->cc_op]);