Commit 27362c82e9df7770554943ceda36ec4e5638c49d

Authored by bellard
1 parent 55480af8

added pusha/popa/rdtsc/bcd ops


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@27 c046a42c-6fe2-441c-8c8c-71466251a162
  1 +- daa/das
1 2 - optimize translated cache chaining (DLL PLT like system)
  3 +- segment ops (minimal LDT/GDT support for wine)
  4 +- improved 16 bit support
2 5 - optimize inverse flags propagation (easy by generating intermediate
3 6 micro operation array).
4 7 - signals
... ...
cpu-i386.h
... ... @@ -114,7 +114,7 @@ enum {
114 114 };
115 115  
116 116 #ifdef __i386__
117   -//#define USE_X86LDOUBLE
  117 +#define USE_X86LDOUBLE
118 118 #endif
119 119  
120 120 #ifdef USE_X86LDOUBLE
... ...
linux-user/main.c
... ... @@ -87,7 +87,7 @@ int cpu_x86_inl(int addr)
87 87  
88 88 void usage(void)
89 89 {
90   - printf("gemu version" GEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
  90 + printf("gemu version " GEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
91 91 "usage: gemu [-d] program [arguments...]\n"
92 92 "Linux x86 emulator\n"
93 93 );
... ...
op-i386.c
... ... @@ -628,6 +628,236 @@ void op_addl_ESP_im(void)
628 628 ESP += PARAM1;
629 629 }
630 630  
  631 +void op_pushal(void)
  632 +{
  633 + uint8_t *sp;
  634 + sp = (void *)(ESP - 32);
  635 + stl(sp, EDI);
  636 + stl(sp + 4, ESI);
  637 + stl(sp + 8, EBP);
  638 + stl(sp + 12, ESP);
  639 + stl(sp + 16, EBX);
  640 + stl(sp + 20, EDX);
  641 + stl(sp + 24, ECX);
  642 + stl(sp + 28, EAX);
  643 + ESP = (unsigned long)sp;
  644 +}
  645 +
  646 +void op_pushaw(void)
  647 +{
  648 + uint8_t *sp;
  649 + sp = (void *)(ESP - 16);
  650 + stw(sp, EDI);
  651 + stw(sp + 2, ESI);
  652 + stw(sp + 4, EBP);
  653 + stw(sp + 6, ESP);
  654 + stw(sp + 8, EBX);
  655 + stw(sp + 10, EDX);
  656 + stw(sp + 12, ECX);
  657 + stw(sp + 14, EAX);
  658 + ESP = (unsigned long)sp;
  659 +}
  660 +
  661 +void op_popal(void)
  662 +{
  663 + uint8_t *sp;
  664 + sp = (void *)ESP;
  665 + EDI = ldl(sp);
  666 + ESI = ldl(sp + 4);
  667 + EBP = ldl(sp + 8);
  668 + EBX = ldl(sp + 16);
  669 + EDX = ldl(sp + 20);
  670 + ECX = ldl(sp + 24);
  671 + EAX = ldl(sp + 28);
  672 + ESP = (unsigned long)sp + 32;
  673 +}
  674 +
  675 +void op_popaw(void)
  676 +{
  677 + uint8_t *sp;
  678 + sp = (void *)ESP;
  679 + EDI = ldl(sp);
  680 + ESI = ldl(sp + 2);
  681 + EBP = ldl(sp + 4);
  682 + EBX = ldl(sp + 8);
  683 + EDX = ldl(sp + 10);
  684 + ECX = ldl(sp + 12);
  685 + EAX = ldl(sp + 14);
  686 + ESP = (unsigned long)sp + 16;
  687 +}
  688 +
  689 +void op_enterl(void)
  690 +{
  691 + unsigned int bp, frame_temp, level;
  692 + uint8_t *sp;
  693 +
  694 + sp = (void *)ESP;
  695 + bp = EBP;
  696 + sp -= 4;
  697 + stl(sp, bp);
  698 + frame_temp = (unsigned int)sp;
  699 + level = PARAM2;
  700 + if (level) {
  701 + while (level--) {
  702 + bp -= 4;
  703 + sp -= 4;
  704 + stl(sp, bp);
  705 + }
  706 + sp -= 4;
  707 + stl(sp, frame_temp);
  708 + }
  709 + EBP = frame_temp;
  710 + sp -= PARAM1;
  711 + ESP = (int)sp;
  712 +}
  713 +
  714 +/* rdtsc */
  715 +#ifndef __i386__
  716 +uint64_t emu_time;
  717 +#endif
  718 +void op_rdtsc(void)
  719 +{
  720 + uint64_t val;
  721 +#ifdef __i386__
  722 + asm("rdtsc" : "=A" (val));
  723 +#else
  724 + /* better than nothing: the time increases */
  725 + val = emu_time++;
  726 +#endif
  727 + EAX = val;
  728 + EDX = val >> 32;
  729 +}
  730 +
  731 +/* bcd */
  732 +
  733 +/* XXX: exception */
  734 +void OPPROTO op_aam(void)
  735 +{
  736 + int base = PARAM1;
  737 + int al, ah;
  738 + al = EAX & 0xff;
  739 + ah = al / base;
  740 + al = al % base;
  741 + EAX = (EAX & ~0xffff) | al | (ah << 8);
  742 + CC_DST = al;
  743 +}
  744 +
  745 +void OPPROTO op_aad(void)
  746 +{
  747 + int base = PARAM1;
  748 + int al, ah;
  749 + al = EAX & 0xff;
  750 + ah = (EAX >> 8) & 0xff;
  751 + al = ((ah * base) + al) & 0xff;
  752 + EAX = (EAX & ~0xffff) | al;
  753 + CC_DST = al;
  754 +}
  755 +
  756 +void OPPROTO op_aaa(void)
  757 +{
  758 + int icarry;
  759 + int al, ah, af;
  760 + int eflags;
  761 +
  762 + eflags = cc_table[CC_OP].compute_all();
  763 + af = eflags & CC_A;
  764 + al = EAX & 0xff;
  765 + ah = (EAX >> 8) & 0xff;
  766 +
  767 + icarry = (al > 0xf9);
  768 + if (((al & 0x0f) > 9 ) || af) {
  769 + al = (al + 6) & 0x0f;
  770 + ah = (ah + 1 + icarry) & 0xff;
  771 + eflags |= CC_C | CC_A;
  772 + } else {
  773 + eflags &= ~(CC_C | CC_A);
  774 + al &= 0x0f;
  775 + }
  776 + EAX = (EAX & ~0xffff) | al | (ah << 8);
  777 + CC_SRC = eflags;
  778 +}
  779 +
  780 +void OPPROTO op_aas(void)
  781 +{
  782 + int icarry;
  783 + int al, ah, af;
  784 + int eflags;
  785 +
  786 + eflags = cc_table[CC_OP].compute_all();
  787 + af = eflags & CC_A;
  788 + al = EAX & 0xff;
  789 + ah = (EAX >> 8) & 0xff;
  790 +
  791 + icarry = (al < 6);
  792 + if (((al & 0x0f) > 9 ) || af) {
  793 + al = (al - 6) & 0x0f;
  794 + ah = (ah - 1 - icarry) & 0xff;
  795 + eflags |= CC_C | CC_A;
  796 + } else {
  797 + eflags &= ~(CC_C | CC_A);
  798 + al &= 0x0f;
  799 + }
  800 + EAX = (EAX & ~0xffff) | al | (ah << 8);
  801 + CC_SRC = eflags;
  802 +}
  803 +
  804 +void OPPROTO op_daa(void)
  805 +{
  806 + int al, af, cf;
  807 + int eflags;
  808 +
  809 + eflags = cc_table[CC_OP].compute_all();
  810 + cf = eflags & CC_C;
  811 + af = eflags & CC_A;
  812 + al = EAX & 0xff;
  813 +
  814 + eflags = 0;
  815 + if (((al & 0x0f) > 9 ) || af) {
  816 + al = (al + 6) & 0xff;
  817 + eflags |= CC_A;
  818 + }
  819 + if ((al > 0x9f) || cf) {
  820 + al = (al + 0x60) & 0xff;
  821 + eflags |= CC_C;
  822 + }
  823 + EAX = (EAX & ~0xff) | al;
  824 + /* well, speed is not an issue here, so we compute the flags by hand */
  825 + eflags |= (al == 0) << 6; /* zf */
  826 + eflags |= parity_table[al]; /* pf */
  827 + eflags |= (al & 0x80); /* sf */
  828 + CC_SRC = eflags;
  829 +}
  830 +
  831 +void OPPROTO op_das(void)
  832 +{
  833 + int al, al1, af, cf;
  834 + int eflags;
  835 +
  836 + eflags = cc_table[CC_OP].compute_all();
  837 + cf = eflags & CC_C;
  838 + af = eflags & CC_A;
  839 + al = EAX & 0xff;
  840 +
  841 + eflags = 0;
  842 + al1 = al;
  843 + if (((al & 0x0f) > 9 ) || af) {
  844 + eflags |= CC_A;
  845 + if (al < 6 || cf)
  846 + eflags |= CC_C;
  847 + al = (al - 6) & 0xff;
  848 + }
  849 + if ((al1 > 0x99) || cf) {
  850 + al = (al - 0x60) & 0xff;
  851 + eflags |= CC_C;
  852 + }
  853 + EAX = (EAX & ~0xff) | al;
  854 + /* well, speed is not an issue here, so we compute the flags by hand */
  855 + eflags |= (al == 0) << 6; /* zf */
  856 + eflags |= parity_table[al]; /* pf */
  857 + eflags |= (al & 0x80); /* sf */
  858 + CC_SRC = eflags;
  859 +}
  860 +
631 861 /* flags handling */
632 862  
633 863 /* slow jumps cases (compute x86 flags) */
... ... @@ -836,6 +1066,13 @@ void OPPROTO op_cmc(void)
836 1066 CC_SRC = eflags;
837 1067 }
838 1068  
  1069 +void OPPROTO op_salc(void)
  1070 +{
  1071 + int cf;
  1072 + cf = cc_table[CC_OP].compute_c();
  1073 + EAX = (EAX & ~0xff) | ((-cf) & 0xff);
  1074 +}
  1075 +
839 1076 static int compute_all_eflags(void)
840 1077 {
841 1078 return CC_SRC;
... ...
translate-i386.c
... ... @@ -1511,6 +1511,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1511 1511 gen_op_popl_T0();
1512 1512 gen_op_mov_reg_T0[OT_LONG][b & 7]();
1513 1513 break;
  1514 + case 0x60: /* pusha */
  1515 + if (s->dflag)
  1516 + gen_op_pushal();
  1517 + else
  1518 + gen_op_pushaw();
  1519 + break;
  1520 + case 0x61: /* popa */
  1521 + if (s->dflag)
  1522 + gen_op_popal();
  1523 + else
  1524 + gen_op_popaw();
  1525 + break;
1514 1526 case 0x68: /* push Iv */
1515 1527 case 0x6a:
1516 1528 ot = dflag ? OT_LONG : OT_WORD;
... ... @@ -1527,6 +1539,16 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1527 1539 gen_op_popl_T0();
1528 1540 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1529 1541 break;
  1542 + case 0xc8: /* enter */
  1543 + {
  1544 + int level;
  1545 + val = lduw(s->pc);
  1546 + s->pc += 2;
  1547 + level = ldub(s->pc++);
  1548 + level &= 0x1f;
  1549 + gen_op_enterl(val, level);
  1550 + }
  1551 + break;
1530 1552 case 0xc9: /* leave */
1531 1553 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1532 1554 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
... ... @@ -2485,6 +2507,42 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2485 2507 s->cc_op = CC_OP_LOGICB + ot;
2486 2508 break;
2487 2509 /************************/
  2510 + /* bcd */
  2511 + case 0x27: /* daa */
  2512 + if (s->cc_op != CC_OP_DYNAMIC)
  2513 + gen_op_set_cc_op(s->cc_op);
  2514 + gen_op_daa();
  2515 + s->cc_op = CC_OP_EFLAGS;
  2516 + break;
  2517 + case 0x2f: /* das */
  2518 + if (s->cc_op != CC_OP_DYNAMIC)
  2519 + gen_op_set_cc_op(s->cc_op);
  2520 + gen_op_das();
  2521 + s->cc_op = CC_OP_EFLAGS;
  2522 + break;
  2523 + case 0x37: /* aaa */
  2524 + if (s->cc_op != CC_OP_DYNAMIC)
  2525 + gen_op_set_cc_op(s->cc_op);
  2526 + gen_op_aaa();
  2527 + s->cc_op = CC_OP_EFLAGS;
  2528 + break;
  2529 + case 0x3f: /* aas */
  2530 + if (s->cc_op != CC_OP_DYNAMIC)
  2531 + gen_op_set_cc_op(s->cc_op);
  2532 + gen_op_aas();
  2533 + s->cc_op = CC_OP_EFLAGS;
  2534 + break;
  2535 + case 0xd4: /* aam */
  2536 + val = ldub(s->pc++);
  2537 + gen_op_aam(val);
  2538 + s->cc_op = CC_OP_LOGICB;
  2539 + break;
  2540 + case 0xd5: /* aad */
  2541 + val = ldub(s->pc++);
  2542 + gen_op_aad(val);
  2543 + s->cc_op = CC_OP_LOGICB;
  2544 + break;
  2545 + /************************/
2488 2546 /* misc */
2489 2547 case 0x90: /* nop */
2490 2548 break;
... ... @@ -2505,19 +2563,26 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2505 2563 *is_jmp_ptr = 1;
2506 2564 break;
2507 2565 case 0x1c8 ... 0x1cf: /* bswap reg */
2508   - reg = b & 7;
2509   - gen_op_mov_TN_reg[OT_LONG][0][reg]();
2510   - gen_op_bswapl_T0();
2511   - gen_op_mov_reg_T0[OT_LONG][reg]();
2512   - break;
2513   -
  2566 + reg = b & 7;
  2567 + gen_op_mov_TN_reg[OT_LONG][0][reg]();
  2568 + gen_op_bswapl_T0();
  2569 + gen_op_mov_reg_T0[OT_LONG][reg]();
  2570 + break;
  2571 + case 0xd6: /* salc */
  2572 + if (s->cc_op != CC_OP_DYNAMIC)
  2573 + gen_op_set_cc_op(s->cc_op);
  2574 + gen_op_salc();
  2575 + break;
  2576 + case 0x1a2: /* rdtsc */
  2577 + gen_op_rdtsc();
  2578 + break;
2514 2579 #if 0
2515 2580 case 0x1a2: /* cpuid */
2516 2581 gen_insn0(OP_ASM);
2517 2582 break;
2518 2583 #endif
2519 2584 default:
2520   - error("unknown opcode %x", b);
  2585 + error("unknown opcode 0x%x", b);
2521 2586 return -1;
2522 2587 }
2523 2588 return (long)s->pc;
... ...