Commit d8bc1fd0aeb0423074b5063c8dc94dddd7285321
1 parent
7501267e
ring 0 ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@254 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
469 additions
and
51 deletions
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, ®_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, ®_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, ®_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]); |