Commit 4b74fe1f0013c622693b26141c0ed031a284a45a

Authored by bellard
1 parent 586314f2

many fixes


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@19 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-i386.h
... ... @@ -78,19 +78,27 @@ enum {
78 78 CC_OP_ADDW,
79 79 CC_OP_ADDL,
80 80  
  81 + CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
  82 + CC_OP_ADCW,
  83 + CC_OP_ADCL,
  84 +
81 85 CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
82 86 CC_OP_SUBW,
83 87 CC_OP_SUBL,
84 88  
  89 + CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
  90 + CC_OP_SBBW,
  91 + CC_OP_SBBL,
  92 +
85 93 CC_OP_LOGICB, /* modify all flags, CC_DST = res */
86 94 CC_OP_LOGICW,
87 95 CC_OP_LOGICL,
88 96  
89   - CC_OP_INCB, /* modify all flags except, CC_DST = res */
  97 + CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */
90 98 CC_OP_INCW,
91 99 CC_OP_INCL,
92 100  
93   - CC_OP_DECB, /* modify all flags except, CC_DST = res */
  101 + CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C */
94 102 CC_OP_DECW,
95 103 CC_OP_DECL,
96 104  
... ... @@ -98,6 +106,10 @@ enum {
98 106 CC_OP_SHLW,
99 107 CC_OP_SHLL,
100 108  
  109 + CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
  110 + CC_OP_SARW,
  111 + CC_OP_SARL,
  112 +
101 113 CC_OP_NB,
102 114 };
103 115  
... ...
dyngen.c
... ... @@ -198,14 +198,10 @@ void gen_code(const char *name, unsigned long offset, unsigned long size,
198 198 {
199 199 uint8_t *p;
200 200 p = p_end - 1;
201   - /* find ret */
202   - while (p > p_start && *p != 0xc3)
203   - p--;
204   - /* skip double ret */
205   - if (p > p_start && p[-1] == 0xc3)
206   - p--;
207 201 if (p == p_start)
208 202 error("empty code for %s", name);
  203 + if (p[0] != 0xc3)
  204 + error("ret expected at the end of %s", name);
209 205 copy_size = p - p_start;
210 206 }
211 207 break;
... ...
linux-user/main.c
... ... @@ -128,21 +128,21 @@ int main(int argc, char **argv)
128 128 /* Zero out image_info */
129 129 memset(info, 0, sizeof(struct image_info));
130 130  
131   - if(elf_exec(filename, argv+1, environ, regs, info) != 0) {
  131 + if(elf_exec(filename, argv+optind, environ, regs, info) != 0) {
132 132 printf("Error loading %s\n", filename);
133 133 exit(1);
134 134 }
135 135  
136   -#if 0
137   - printf("start_brk 0x%08lx\n" , info->start_brk);
138   - printf("end_code 0x%08lx\n" , info->end_code);
139   - printf("start_code 0x%08lx\n" , info->start_code);
140   - printf("end_data 0x%08lx\n" , info->end_data);
141   - printf("start_stack 0x%08lx\n" , info->start_stack);
142   - printf("brk 0x%08lx\n" , info->brk);
143   - printf("esp 0x%08lx\n" , regs->esp);
144   - printf("eip 0x%08lx\n" , regs->eip);
145   -#endif
  136 + if (loglevel) {
  137 + fprintf(logfile, "start_brk 0x%08lx\n" , info->start_brk);
  138 + fprintf(logfile, "end_code 0x%08lx\n" , info->end_code);
  139 + fprintf(logfile, "start_code 0x%08lx\n" , info->start_code);
  140 + fprintf(logfile, "end_data 0x%08lx\n" , info->end_data);
  141 + fprintf(logfile, "start_stack 0x%08lx\n" , info->start_stack);
  142 + fprintf(logfile, "brk 0x%08lx\n" , info->brk);
  143 + fprintf(logfile, "esp 0x%08lx\n" , regs->esp);
  144 + fprintf(logfile, "eip 0x%08lx\n" , regs->eip);
  145 + }
146 146  
147 147 target_set_brk((char *)info->brk);
148 148 syscall_init();
... ...
op-i386.c
... ... @@ -10,7 +10,18 @@ typedef signed short int16_t;
10 10 typedef signed int int32_t;
11 11 typedef signed long long int64_t;
12 12  
  13 +#define bswap32(x) \
  14 +({ \
  15 + uint32_t __x = (x); \
  16 + ((uint32_t)( \
  17 + (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
  18 + (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
  19 + (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
  20 + (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
  21 +})
  22 +
13 23 #define NULL 0
  24 +#include <fenv.h>
14 25  
15 26 typedef struct FILE FILE;
16 27 extern FILE *logfile;
... ... @@ -18,41 +29,39 @@ extern int loglevel;
18 29 extern int fprintf(FILE *, const char *, ...);
19 30  
20 31 #ifdef __i386__
21   -register int T0 asm("esi");
22   -register int T1 asm("ebx");
23   -register int A0 asm("edi");
  32 +register unsigned int T0 asm("ebx");
  33 +register unsigned int T1 asm("esi");
  34 +register unsigned int A0 asm("edi");
24 35 register struct CPUX86State *env asm("ebp");
25   -#define FORCE_RET() asm volatile ("ret");
26 36 #endif
27 37 #ifdef __powerpc__
28   -register int T0 asm("r24");
29   -register int T1 asm("r25");
30   -register int A0 asm("r26");
  38 +register unsigned int T0 asm("r24");
  39 +register unsigned int T1 asm("r25");
  40 +register unsigned int A0 asm("r26");
31 41 register struct CPUX86State *env asm("r27");
32   -#define FORCE_RET() asm volatile ("blr");
33 42 #endif
34 43 #ifdef __arm__
35   -register int T0 asm("r4");
36   -register int T1 asm("r5");
37   -register int A0 asm("r6");
  44 +register unsigned int T0 asm("r4");
  45 +register unsigned int T1 asm("r5");
  46 +register unsigned int A0 asm("r6");
38 47 register struct CPUX86State *env asm("r7");
39   -#define FORCE_RET() asm volatile ("mov pc, lr");
40 48 #endif
41 49 #ifdef __mips__
42   -register int T0 asm("s0");
43   -register int T1 asm("s1");
44   -register int A0 asm("s2");
  50 +register unsigned int T0 asm("s0");
  51 +register unsigned int T1 asm("s1");
  52 +register unsigned int A0 asm("s2");
45 53 register struct CPUX86State *env asm("s3");
46   -#define FORCE_RET() asm volatile ("jr $31");
47 54 #endif
48 55 #ifdef __sparc__
49   -register int T0 asm("l0");
50   -register int T1 asm("l1");
51   -register int A0 asm("l2");
  56 +register unsigned int T0 asm("l0");
  57 +register unsigned int T1 asm("l1");
  58 +register unsigned int A0 asm("l2");
52 59 register struct CPUX86State *env asm("l3");
53   -#define FORCE_RET() asm volatile ("retl ; nop");
54 60 #endif
55 61  
  62 +/* force GCC to generate only one epilog at the end of the function */
  63 +#define FORCE_RET() asm volatile ("");
  64 +
56 65 #ifndef OPPROTO
57 66 #define OPPROTO
58 67 #endif
... ... @@ -267,20 +276,6 @@ void OPPROTO op_orl_T0_T1_cc(void)
267 276 CC_DST = T0;
268 277 }
269 278  
270   -void OPPROTO op_adcl_T0_T1_cc(void)
271   -{
272   - CC_SRC = T0;
273   - T0 = T0 + T1 + cc_table[CC_OP].compute_c();
274   - CC_DST = T0;
275   -}
276   -
277   -void OPPROTO op_sbbl_T0_T1_cc(void)
278   -{
279   - CC_SRC = T0;
280   - T0 = T0 - T1 - cc_table[CC_OP].compute_c();
281   - CC_DST = T0;
282   -}
283   -
284 279 void OPPROTO op_andl_T0_T1_cc(void)
285 280 {
286 281 T0 &= T1;
... ... @@ -320,12 +315,14 @@ void OPPROTO op_negl_T0_cc(void)
320 315  
321 316 void OPPROTO op_incl_T0_cc(void)
322 317 {
  318 + CC_SRC = cc_table[CC_OP].compute_c();
323 319 T0++;
324 320 CC_DST = T0;
325 321 }
326 322  
327 323 void OPPROTO op_decl_T0_cc(void)
328 324 {
  325 + CC_SRC = cc_table[CC_OP].compute_c();
329 326 T0--;
330 327 CC_DST = T0;
331 328 }
... ... @@ -335,6 +332,11 @@ void OPPROTO op_testl_T0_T1_cc(void)
335 332 CC_DST = T0 & T1;
336 333 }
337 334  
  335 +void OPPROTO op_bswapl_T0(void)
  336 +{
  337 + T0 = bswap32(T0);
  338 +}
  339 +
338 340 /* multiply/divide */
339 341 void OPPROTO op_mulb_AL_T0(void)
340 342 {
... ... @@ -399,7 +401,7 @@ void OPPROTO op_imulw_T0_T1(void)
399 401 void OPPROTO op_imull_T0_T1(void)
400 402 {
401 403 int64_t res;
402   - res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T1);
  404 + res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
403 405 T0 = res;
404 406 CC_SRC = (res != (int32_t)res);
405 407 }
... ... @@ -468,10 +470,10 @@ void OPPROTO op_divl_EAX_T0(void)
468 470 void OPPROTO op_idivl_EAX_T0(void)
469 471 {
470 472 int den, q, r;
471   - int16_t num;
  473 + int64_t num;
472 474  
473 475 num = EAX | ((uint64_t)EDX << 32);
474   - den = (int16_t)T0;
  476 + den = T0;
475 477 q = (num / den);
476 478 r = (num % den);
477 479 EAX = q;
... ... @@ -495,6 +497,16 @@ void OPPROTO op_movl_A0_im(void)
495 497 A0 = PARAM1;
496 498 }
497 499  
  500 +void OPPROTO op_addl_A0_im(void)
  501 +{
  502 + A0 += PARAM1;
  503 +}
  504 +
  505 +void OPPROTO op_andl_A0_ffff(void)
  506 +{
  507 + A0 = A0 & 0xffff;
  508 +}
  509 +
498 510 /* memory access */
499 511  
500 512 void OPPROTO op_ldub_T0_A0(void)
... ... @@ -562,7 +574,17 @@ void OPPROTO op_stl_T0_A0(void)
562 574 stl((uint8_t *)A0, T0);
563 575 }
564 576  
565   -/* jumps */
  577 +/* used for bit operations */
  578 +
  579 +void OPPROTO op_add_bitw_A0_T1(void)
  580 +{
  581 + A0 += ((int32_t)T1 >> 4) << 1;
  582 +}
  583 +
  584 +void OPPROTO op_add_bitl_A0_T1(void)
  585 +{
  586 + A0 += ((int32_t)T1 >> 5) << 2;
  587 +}
566 588  
567 589 /* indirect jump */
568 590  
... ... @@ -938,25 +960,37 @@ CCTable cc_table[CC_OP_NB] = {
938 960 [CC_OP_ADDW] = { compute_all_addw, compute_c_addw },
939 961 [CC_OP_ADDL] = { compute_all_addl, compute_c_addl },
940 962  
  963 + [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb },
  964 + [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw },
  965 + [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl },
  966 +
941 967 [CC_OP_SUBB] = { compute_all_subb, compute_c_subb },
942 968 [CC_OP_SUBW] = { compute_all_subw, compute_c_subw },
943 969 [CC_OP_SUBL] = { compute_all_subl, compute_c_subl },
944 970  
  971 + [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb },
  972 + [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw },
  973 + [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl },
  974 +
945 975 [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
946 976 [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
947 977 [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl },
948 978  
949   - [CC_OP_INCB] = { compute_all_incb, compute_c_incb },
950   - [CC_OP_INCW] = { compute_all_incw, compute_c_incw },
  979 + [CC_OP_INCB] = { compute_all_incb, compute_c_incl },
  980 + [CC_OP_INCW] = { compute_all_incw, compute_c_incl },
951 981 [CC_OP_INCL] = { compute_all_incl, compute_c_incl },
952 982  
953   - [CC_OP_DECB] = { compute_all_decb, compute_c_incb },
954   - [CC_OP_DECW] = { compute_all_decw, compute_c_incw },
  983 + [CC_OP_DECB] = { compute_all_decb, compute_c_incl },
  984 + [CC_OP_DECW] = { compute_all_decw, compute_c_incl },
955 985 [CC_OP_DECL] = { compute_all_decl, compute_c_incl },
956 986  
957   - [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
958   - [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
  987 + [CC_OP_SHLB] = { compute_all_shlb, compute_c_shll },
  988 + [CC_OP_SHLW] = { compute_all_shlw, compute_c_shll },
959 989 [CC_OP_SHLL] = { compute_all_shll, compute_c_shll },
  990 +
  991 + [CC_OP_SARB] = { compute_all_sarb, compute_c_shll },
  992 + [CC_OP_SARW] = { compute_all_sarw, compute_c_shll },
  993 + [CC_OP_SARL] = { compute_all_sarl, compute_c_shll },
960 994 };
961 995  
962 996 /* floating point support */
... ... @@ -1640,6 +1674,41 @@ void OPPROTO op_fcos(void)
1640 1674 helper_fcos();
1641 1675 }
1642 1676  
  1677 +void OPPROTO op_fnstsw_A0(void)
  1678 +{
  1679 + int fpus;
  1680 + fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
  1681 + stw((void *)A0, fpus);
  1682 +}
  1683 +
  1684 +void OPPROTO op_fnstcw_A0(void)
  1685 +{
  1686 + stw((void *)A0, env->fpuc);
  1687 +}
  1688 +
  1689 +void OPPROTO op_fldcw_A0(void)
  1690 +{
  1691 + int rnd_type;
  1692 + env->fpuc = lduw((void *)A0);
  1693 + /* set rounding mode */
  1694 + switch(env->fpuc & RC_MASK) {
  1695 + default:
  1696 + case RC_NEAR:
  1697 + rnd_type = FE_TONEAREST;
  1698 + break;
  1699 + case RC_DOWN:
  1700 + rnd_type = FE_DOWNWARD;
  1701 + break;
  1702 + case RC_UP:
  1703 + rnd_type = FE_UPWARD;
  1704 + break;
  1705 + case RC_CHOP:
  1706 + rnd_type = FE_TOWARDZERO;
  1707 + break;
  1708 + }
  1709 + fesetround(rnd_type);
  1710 +}
  1711 +
1643 1712 /* main execution loop */
1644 1713 uint8_t code_gen_buffer[65536];
1645 1714  
... ... @@ -1651,9 +1720,15 @@ static const char *cc_op_str[] = {
1651 1720 "ADDB",
1652 1721 "ADDW",
1653 1722 "ADDL",
  1723 + "ADCB",
  1724 + "ADCW",
  1725 + "ADCL",
1654 1726 "SUBB",
1655 1727 "SUBW",
1656 1728 "SUBL",
  1729 + "SBBB",
  1730 + "SBBW",
  1731 + "SBBL",
1657 1732 "LOGICB",
1658 1733 "LOGICW",
1659 1734 "LOGICL",
... ... @@ -1666,6 +1741,9 @@ static const char *cc_op_str[] = {
1666 1741 "SHLB",
1667 1742 "SHLW",
1668 1743 "SHLL",
  1744 + "SARB",
  1745 + "SARW",
  1746 + "SARL",
1669 1747 };
1670 1748 #endif
1671 1749  
... ... @@ -1688,13 +1766,24 @@ int cpu_x86_exec(CPUX86State *env1)
1688 1766 for(;;) {
1689 1767 #ifdef DEBUG_EXEC
1690 1768 if (loglevel) {
  1769 + int eflags;
  1770 + eflags = cc_table[CC_OP].compute_all();
  1771 + eflags |= (DF & DIRECTION_FLAG);
1691 1772 fprintf(logfile,
1692 1773 "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
1693   - "ESI=%08x ESI=%08X EBP=%08x ESP=%08x\n"
1694   - "CCS=%08x CCD=%08x CCOP=%s\n",
  1774 + "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
  1775 + "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",
1695 1776 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
1696 1777 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
1697   - env->cc_src, env->cc_dst, cc_op_str[env->cc_op]);
  1778 + env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
  1779 + eflags & DIRECTION_FLAG ? 'D' : '-',
  1780 + eflags & CC_O ? 'O' : '-',
  1781 + eflags & CC_S ? 'S' : '-',
  1782 + eflags & CC_Z ? 'Z' : '-',
  1783 + eflags & CC_A ? 'A' : '-',
  1784 + eflags & CC_P ? 'P' : '-',
  1785 + eflags & CC_C ? 'C' : '-'
  1786 + );
1698 1787 }
1699 1788 #endif
1700 1789 cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc);
... ...
ops_template.h
... ... @@ -33,7 +33,7 @@ static int glue(compute_all_add, SUFFIX)(void)
33 33 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
34 34 pf = parity_table[(uint8_t)CC_DST];
35 35 af = (CC_DST ^ src1 ^ src2) & 0x10;
36   - zf = ((DATA_TYPE)CC_DST != 0) << 6;
  36 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
37 37 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
38 38 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
39 39 return cf | pf | af | zf | sf | of;
... ... @@ -47,6 +47,29 @@ static int glue(compute_c_add, SUFFIX)(void)
47 47 return cf;
48 48 }
49 49  
  50 +static int glue(compute_all_adc, SUFFIX)(void)
  51 +{
  52 + int cf, pf, af, zf, sf, of;
  53 + int src1, src2;
  54 + src1 = CC_SRC;
  55 + src2 = CC_DST - CC_SRC - 1;
  56 + cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
  57 + pf = parity_table[(uint8_t)CC_DST];
  58 + af = (CC_DST ^ src1 ^ src2) & 0x10;
  59 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
  60 + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
  61 + of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
  62 + return cf | pf | af | zf | sf | of;
  63 +}
  64 +
  65 +static int glue(compute_c_adc, SUFFIX)(void)
  66 +{
  67 + int src1, cf;
  68 + src1 = CC_SRC;
  69 + cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
  70 + return cf;
  71 +}
  72 +
50 73 static int glue(compute_all_sub, SUFFIX)(void)
51 74 {
52 75 int cf, pf, af, zf, sf, of;
... ... @@ -56,9 +79,9 @@ static int glue(compute_all_sub, SUFFIX)(void)
56 79 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
57 80 pf = parity_table[(uint8_t)CC_DST];
58 81 af = (CC_DST ^ src1 ^ src2) & 0x10;
59   - zf = ((DATA_TYPE)CC_DST != 0) << 6;
  82 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
60 83 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
61   - of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
  84 + of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
62 85 return cf | pf | af | zf | sf | of;
63 86 }
64 87  
... ... @@ -67,7 +90,31 @@ static int glue(compute_c_sub, SUFFIX)(void)
67 90 int src1, src2, cf;
68 91 src1 = CC_SRC;
69 92 src2 = CC_SRC - CC_DST;
70   - cf = (DATA_TYPE)src1 < (DATA_TYPE)src1;
  93 + cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
  94 + return cf;
  95 +}
  96 +
  97 +static int glue(compute_all_sbb, SUFFIX)(void)
  98 +{
  99 + int cf, pf, af, zf, sf, of;
  100 + int src1, src2;
  101 + src1 = CC_SRC;
  102 + src2 = CC_SRC - CC_DST - 1;
  103 + cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
  104 + pf = parity_table[(uint8_t)CC_DST];
  105 + af = (CC_DST ^ src1 ^ src2) & 0x10;
  106 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
  107 + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
  108 + of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
  109 + return cf | pf | af | zf | sf | of;
  110 +}
  111 +
  112 +static int glue(compute_c_sbb, SUFFIX)(void)
  113 +{
  114 + int src1, src2, cf;
  115 + src1 = CC_SRC;
  116 + src2 = CC_SRC - CC_DST - 1;
  117 + cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
71 118 return cf;
72 119 }
73 120  
... ... @@ -77,7 +124,7 @@ static int glue(compute_all_logic, SUFFIX)(void)
77 124 cf = 0;
78 125 pf = parity_table[(uint8_t)CC_DST];
79 126 af = 0;
80   - zf = ((DATA_TYPE)CC_DST != 0) << 6;
  127 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
81 128 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
82 129 of = 0;
83 130 return cf | pf | af | zf | sf | of;
... ... @@ -97,16 +144,18 @@ static int glue(compute_all_inc, SUFFIX)(void)
97 144 cf = CC_SRC;
98 145 pf = parity_table[(uint8_t)CC_DST];
99 146 af = (CC_DST ^ src1 ^ src2) & 0x10;
100   - zf = ((DATA_TYPE)CC_DST != 0) << 6;
  147 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
101 148 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
102   - of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
  149 + of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
103 150 return cf | pf | af | zf | sf | of;
104 151 }
105 152  
  153 +#if DATA_BITS == 32
106 154 static int glue(compute_c_inc, SUFFIX)(void)
107 155 {
108 156 return CC_SRC;
109 157 }
  158 +#endif
110 159  
111 160 static int glue(compute_all_dec, SUFFIX)(void)
112 161 {
... ... @@ -117,9 +166,9 @@ static int glue(compute_all_dec, SUFFIX)(void)
117 166 cf = CC_SRC;
118 167 pf = parity_table[(uint8_t)CC_DST];
119 168 af = (CC_DST ^ src1 ^ src2) & 0x10;
120   - zf = ((DATA_TYPE)CC_DST != 0) << 6;
  169 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
121 170 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
122   - of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
  171 + of = ((CC_DST & DATA_MASK) == ((uint32_t)SIGN_MASK - 1)) << 11;
123 172 return cf | pf | af | zf | sf | of;
124 173 }
125 174  
... ... @@ -129,16 +178,30 @@ static int glue(compute_all_shl, SUFFIX)(void)
129 178 cf = CC_SRC & 1;
130 179 pf = parity_table[(uint8_t)CC_DST];
131 180 af = 0; /* undefined */
132   - zf = ((DATA_TYPE)CC_DST != 0) << 6;
  181 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
133 182 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
134   - of = sf << 4; /* only meaniful for shr with count == 1 */
  183 + of = lshift(CC_SRC, 12 - DATA_BITS) & CC_O; /* only meaniful for shr with count == 1 */
135 184 return cf | pf | af | zf | sf | of;
136 185 }
137 186  
  187 +#if DATA_BITS == 32
138 188 static int glue(compute_c_shl, SUFFIX)(void)
139 189 {
140 190 return CC_SRC & 1;
141 191 }
  192 +#endif
  193 +
  194 +static int glue(compute_all_sar, SUFFIX)(void)
  195 +{
  196 + int cf, pf, af, zf, sf, of;
  197 + cf = CC_SRC & 1;
  198 + pf = parity_table[(uint8_t)CC_DST];
  199 + af = 0; /* undefined */
  200 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
  201 + sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
  202 + of = 0; /* only meaniful for shr with count == 1 */
  203 + return cf | pf | af | zf | sf | of;
  204 +}
142 205  
143 206 /* various optimized jumps cases */
144 207  
... ... @@ -157,7 +220,7 @@ void OPPROTO glue(op_jb_sub, SUFFIX)(void)
157 220  
158 221 void OPPROTO glue(op_jz_sub, SUFFIX)(void)
159 222 {
160   - if ((DATA_TYPE)CC_DST != 0)
  223 + if ((DATA_TYPE)CC_DST == 0)
161 224 PC = PARAM1;
162 225 else
163 226 PC = PARAM2;
... ... @@ -225,7 +288,7 @@ void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
225 288  
226 289 void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
227 290 {
228   - T0 = ((DATA_TYPE)CC_DST != 0);
  291 + T0 = ((DATA_TYPE)CC_DST == 0);
229 292 }
230 293  
231 294 void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
... ... @@ -275,6 +338,7 @@ void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
275 338 (T0 & CC_C);
276 339 CC_OP = CC_OP_EFLAGS;
277 340 }
  341 + FORCE_RET();
278 342 }
279 343  
280 344 void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
... ... @@ -290,6 +354,7 @@ void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
290 354 ((T0 >> (DATA_BITS - 1)) & CC_C);
291 355 CC_OP = CC_OP_EFLAGS;
292 356 }
  357 + FORCE_RET();
293 358 }
294 359  
295 360 void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
... ... @@ -305,6 +370,7 @@ void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
305 370 #endif
306 371 if (count) {
307 372 eflags = cc_table[CC_OP].compute_all();
  373 + T0 &= DATA_MASK;
308 374 src = T0;
309 375 res = (T0 << count) | ((eflags & CC_C) << (count - 1));
310 376 if (count > 1)
... ... @@ -315,6 +381,7 @@ void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
315 381 ((src >> (DATA_BITS - count)) & CC_C);
316 382 CC_OP = CC_OP_EFLAGS;
317 383 }
  384 + FORCE_RET();
318 385 }
319 386  
320 387 void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
... ... @@ -330,6 +397,7 @@ void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
330 397 #endif
331 398 if (count) {
332 399 eflags = cc_table[CC_OP].compute_all();
  400 + T0 &= DATA_MASK;
333 401 src = T0;
334 402 res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
335 403 if (count > 1)
... ... @@ -340,6 +408,7 @@ void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
340 408 ((src >> (count - 1)) & CC_C);
341 409 CC_OP = CC_OP_EFLAGS;
342 410 }
  411 + FORCE_RET();
343 412 }
344 413  
345 414 void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
... ... @@ -352,11 +421,12 @@ void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
352 421 CC_DST = T0;
353 422 CC_OP = CC_OP_ADDB + SHIFT;
354 423 } else if (count) {
355   - CC_SRC = T0 >> (DATA_BITS - count);
  424 + CC_SRC = (DATA_TYPE)T0 >> (DATA_BITS - count);
356 425 T0 = T0 << count;
357 426 CC_DST = T0;
358 427 CC_OP = CC_OP_SHLB + SHIFT;
359 428 }
  429 + FORCE_RET();
360 430 }
361 431  
362 432 void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
... ... @@ -370,6 +440,7 @@ void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
370 440 CC_DST = T0;
371 441 CC_OP = CC_OP_SHLB + SHIFT;
372 442 }
  443 + FORCE_RET();
373 444 }
374 445  
375 446 void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
... ... @@ -381,10 +452,69 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
381 452 CC_SRC = src >> (count - 1);
382 453 T0 = src >> count;
383 454 CC_DST = T0;
384   - CC_OP = CC_OP_SHLB + SHIFT;
  455 + CC_OP = CC_OP_SARB + SHIFT;
385 456 }
  457 + FORCE_RET();
386 458 }
387 459  
  460 +/* carry add/sub (we only need to set CC_OP differently) */
  461 +
  462 +void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
  463 +{
  464 + int cf;
  465 + cf = cc_table[CC_OP].compute_c();
  466 + CC_SRC = T0;
  467 + T0 = T0 + T1 + cf;
  468 + CC_DST = T0;
  469 + CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
  470 +}
  471 +
  472 +void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
  473 +{
  474 + int cf;
  475 + cf = cc_table[CC_OP].compute_c();
  476 + CC_SRC = T0;
  477 + T0 = T0 - T1 - cf;
  478 + CC_DST = T0;
  479 + CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
  480 +}
  481 +
  482 +/* bit operations */
  483 +#if DATA_BITS >= 16
  484 +
  485 +void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
  486 +{
  487 + int count;
  488 + count = T1 & SHIFT_MASK;
  489 + CC_SRC = T0 >> count;
  490 +}
  491 +
  492 +void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
  493 +{
  494 + int count;
  495 + count = T1 & SHIFT_MASK;
  496 + CC_SRC = T0 >> count;
  497 + T0 |= (1 << count);
  498 +}
  499 +
  500 +void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
  501 +{
  502 + int count;
  503 + count = T1 & SHIFT_MASK;
  504 + CC_SRC = T0 >> count;
  505 + T0 &= ~(1 << count);
  506 +}
  507 +
  508 +void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
  509 +{
  510 + int count;
  511 + count = T1 & SHIFT_MASK;
  512 + CC_SRC = T0 >> count;
  513 + T0 ^= (1 << count);
  514 +}
  515 +
  516 +#endif
  517 +
388 518 /* string operations */
389 519 /* XXX: maybe use lower level instructions to ease exception handling */
390 520  
... ... @@ -464,8 +594,8 @@ void OPPROTO glue(op_scas, SUFFIX)(void)
464 594 {
465 595 int v;
466 596  
467   - v = glue(ldu, SUFFIX)((void *)ESI);
468   - ESI += (DF << SHIFT);
  597 + v = glue(ldu, SUFFIX)((void *)EDI);
  598 + EDI += (DF << SHIFT);
469 599 CC_SRC = EAX;
470 600 CC_DST = EAX - v;
471 601 }
... ... @@ -476,20 +606,14 @@ void OPPROTO glue(op_repz_scas, SUFFIX)(void)
476 606  
477 607 if (ECX != 0) {
478 608 /* NOTE: the flags are not modified if ECX == 0 */
479   -#if SHIFT == 0
480   - v1 = EAX & 0xff;
481   -#elif SHIFT == 1
482   - v1 = EAX & 0xffff;
483   -#else
484   - v1 = EAX;
485   -#endif
  609 + v1 = EAX & DATA_MASK;
486 610 inc = (DF << SHIFT);
487 611 do {
488   - v2 = glue(ldu, SUFFIX)((void *)ESI);
  612 + v2 = glue(ldu, SUFFIX)((void *)EDI);
  613 + EDI += inc;
  614 + ECX--;
489 615 if (v1 != v2)
490 616 break;
491   - ESI += inc;
492   - ECX--;
493 617 } while (ECX != 0);
494 618 CC_SRC = v1;
495 619 CC_DST = v1 - v2;
... ... @@ -503,20 +627,14 @@ void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
503 627  
504 628 if (ECX != 0) {
505 629 /* NOTE: the flags are not modified if ECX == 0 */
506   -#if SHIFT == 0
507   - v1 = EAX & 0xff;
508   -#elif SHIFT == 1
509   - v1 = EAX & 0xffff;
510   -#else
511   - v1 = EAX;
512   -#endif
  630 + v1 = EAX & DATA_MASK;
513 631 inc = (DF << SHIFT);
514 632 do {
515   - v2 = glue(ldu, SUFFIX)((void *)ESI);
  633 + v2 = glue(ldu, SUFFIX)((void *)EDI);
  634 + EDI += inc;
  635 + ECX--;
516 636 if (v1 == v2)
517 637 break;
518   - ESI += inc;
519   - ECX--;
520 638 } while (ECX != 0);
521 639 CC_SRC = v1;
522 640 CC_DST = v1 - v2;
... ... @@ -543,11 +661,11 @@ void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
543 661 do {
544 662 v1 = glue(ldu, SUFFIX)((void *)ESI);
545 663 v2 = glue(ldu, SUFFIX)((void *)EDI);
546   - if (v1 != v2)
547   - break;
548 664 ESI += inc;
549 665 EDI += inc;
550 666 ECX--;
  667 + if (v1 != v2)
  668 + break;
551 669 } while (ECX != 0);
552 670 CC_SRC = v1;
553 671 CC_DST = v1 - v2;
... ... @@ -563,11 +681,11 @@ void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
563 681 do {
564 682 v1 = glue(ldu, SUFFIX)((void *)ESI);
565 683 v2 = glue(ldu, SUFFIX)((void *)EDI);
566   - if (v1 == v2)
567   - break;
568 684 ESI += inc;
569 685 EDI += inc;
570 686 ECX--;
  687 + if (v1 == v2)
  688 + break;
571 689 } while (ECX != 0);
572 690 CC_SRC = v1;
573 691 CC_DST = v1 - v2;
... ...
tests/Makefile
... ... @@ -20,7 +20,7 @@ test2: test2.c
20 20  
21 21 # i386 emulation test (dump various opcodes) */
22 22 test-i386: test-i386.c test-i386.h test-i386-shift.h
23   - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
  23 + $(CC) $(CFLAGS) $(LDFLAGS) -static -o $@ $<
24 24  
25 25 test: test-i386
26 26 ./test-i386 > test-i386.ref
... ...
tests/test-i386.c
... ... @@ -14,13 +14,12 @@
14 14 #define CC_S 0x0080
15 15 #define CC_O 0x0800
16 16  
17   -/* XXX: currently no A flag */
18   -#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
19   -
20 17 #define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
21 18  
22 19 static void *call_start __init_call = NULL;
23 20  
  21 +#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
  22 +
24 23 #define OP add
25 24 #include "test-i386.h"
26 25  
... ... @@ -67,6 +66,9 @@ static void *call_start __init_call = NULL;
67 66 #define OP1
68 67 #include "test-i386.h"
69 68  
  69 +#undef CC_MASK
  70 +#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
  71 +
70 72 #define OP shl
71 73 #include "test-i386-shift.h"
72 74  
... ... @@ -268,18 +270,148 @@ void test_jcc(void)
268 270 TEST_JCC("jns", 0, 0);
269 271 }
270 272  
  273 +#undef CC_MASK
  274 +#define CC_MASK (CC_O | CC_C)
  275 +
  276 +#define OP mul
  277 +#include "test-i386-muldiv.h"
  278 +
  279 +#define OP imul
  280 +#include "test-i386-muldiv.h"
  281 +
  282 +#undef CC_MASK
  283 +#define CC_MASK (0)
  284 +
  285 +#define OP div
  286 +#include "test-i386-muldiv.h"
  287 +
  288 +#define OP idiv
  289 +#include "test-i386-muldiv.h"
  290 +
  291 +void test_imulw2(int op0, int op1)
  292 +{
  293 + int res, s1, s0, flags;
  294 + s0 = op0;
  295 + s1 = op1;
  296 + res = s0;
  297 + flags = 0;
  298 + asm ("push %4\n\t"
  299 + "popf\n\t"
  300 + "imulw %w2, %w0\n\t"
  301 + "pushf\n\t"
  302 + "popl %1\n\t"
  303 + : "=q" (res), "=g" (flags)
  304 + : "q" (s1), "0" (res), "1" (flags));
  305 + printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
  306 + "imulw", s0, s1, res, flags & CC_MASK);
  307 +}
  308 +
  309 +void test_imull2(int op0, int op1)
  310 +{
  311 + int res, s1, s0, flags;
  312 + s0 = op0;
  313 + s1 = op1;
  314 + res = s0;
  315 + flags = 0;
  316 + asm ("push %4\n\t"
  317 + "popf\n\t"
  318 + "imull %2, %0\n\t"
  319 + "pushf\n\t"
  320 + "popl %1\n\t"
  321 + : "=q" (res), "=g" (flags)
  322 + : "q" (s1), "0" (res), "1" (flags));
  323 + printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
  324 + "imull", s0, s1, res, flags & CC_MASK);
  325 +}
  326 +
  327 +void test_mul(void)
  328 +{
  329 + test_imulb(0x1234561d, 4);
  330 + test_imulb(3, -4);
  331 + test_imulb(0x80, 0x80);
  332 + test_imulb(0x10, 0x10);
  333 +
  334 + test_imulw(0, 0x1234001d, 45);
  335 + test_imulw(0, 23, -45);
  336 + test_imulw(0, 0x8000, 0x8000);
  337 + test_imulw(0, 0x100, 0x100);
  338 +
  339 + test_imull(0, 0x1234001d, 45);
  340 + test_imull(0, 23, -45);
  341 + test_imull(0, 0x80000000, 0x80000000);
  342 + test_imull(0, 0x10000, 0x10000);
  343 +
  344 + test_mulb(0x1234561d, 4);
  345 + test_mulb(3, -4);
  346 + test_mulb(0x80, 0x80);
  347 + test_mulb(0x10, 0x10);
  348 +
  349 + test_mulw(0, 0x1234001d, 45);
  350 + test_mulw(0, 23, -45);
  351 + test_mulw(0, 0x8000, 0x8000);
  352 + test_mulw(0, 0x100, 0x100);
  353 +
  354 + test_mull(0, 0x1234001d, 45);
  355 + test_mull(0, 23, -45);
  356 + test_mull(0, 0x80000000, 0x80000000);
  357 + test_mull(0, 0x10000, 0x10000);
  358 +
  359 + test_imulw2(0x1234001d, 45);
  360 + test_imulw2(23, -45);
  361 + test_imulw2(0x8000, 0x8000);
  362 + test_imulw2(0x100, 0x100);
  363 +
  364 + test_imull2(0x1234001d, 45);
  365 + test_imull2(23, -45);
  366 + test_imull2(0x80000000, 0x80000000);
  367 + test_imull2(0x10000, 0x10000);
  368 +
  369 + test_idivb(0x12341678, 0x127e);
  370 + test_idivb(0x43210123, -5);
  371 + test_idivb(0x12340004, -1);
  372 +
  373 + test_idivw(0, 0x12345678, 12347);
  374 + test_idivw(0, -23223, -45);
  375 + test_idivw(0, 0x12348000, -1);
  376 + test_idivw(0x12343, 0x12345678, 0x81238567);
  377 +
  378 + test_idivl(0, 0x12345678, 12347);
  379 + test_idivl(0, -233223, -45);
  380 + test_idivl(0, 0x80000000, -1);
  381 + test_idivl(0x12343, 0x12345678, 0x81234567);
  382 +
  383 + test_divb(0x12341678, 0x127e);
  384 + test_divb(0x43210123, -5);
  385 + test_divb(0x12340004, -1);
  386 +
  387 + test_divw(0, 0x12345678, 12347);
  388 + test_divw(0, -23223, -45);
  389 + test_divw(0, 0x12348000, -1);
  390 + test_divw(0x12343, 0x12345678, 0x81238567);
  391 +
  392 + test_divl(0, 0x12345678, 12347);
  393 + test_divl(0, -233223, -45);
  394 + test_divl(0, 0x80000000, -1);
  395 + test_divl(0x12343, 0x12345678, 0x81234567);
  396 +}
  397 +
  398 +
271 399 static void *call_end __init_call = NULL;
272 400  
273 401 int main(int argc, char **argv)
274 402 {
275 403 void **ptr;
276 404 void (*func)(void);
  405 +
  406 + test_mul();
  407 +#if 0
277 408 ptr = &call_start + 1;
278 409 while (*ptr != NULL) {
279 410 func = *ptr++;
280 411 func();
281 412 }
282   - test_lea();
283 413 test_jcc();
  414 + test_lea();
  415 +#endif
284 416 return 0;
285 417 }
... ...
translate-i386.c
... ... @@ -27,7 +27,9 @@ static void error(const char *fmt, ...)
27 27 va_list ap;
28 28  
29 29 va_start(ap, fmt);
  30 + fprintf(stderr, "\n");
30 31 vfprintf(stderr, fmt, ap);
  32 + fprintf(stderr, "\n");
31 33 va_end(ap);
32 34 exit(1);
33 35 }
... ... @@ -98,42 +100,13 @@ enum {
98 100 OR_EBP,
99 101 OR_ESI,
100 102 OR_EDI,
101   -
102   - /* I386 float registers */
103   - OR_ST0,
104   - OR_ST1,
105   - OR_ST2,
106   - OR_ST3,
107   - OR_ST4,
108   - OR_ST5,
109   - OR_ST6,
110   - OR_ST7,
111 103 OR_TMP0, /* temporary operand register */
112 104 OR_TMP1,
113 105 OR_A0, /* temporary register used when doing address evaluation */
114   - OR_EFLAGS, /* cpu flags */
115   - OR_ITMP0, /* used for byte/word insertion */
116   - OR_ITMP1, /* used for byte/word insertion */
117   - OR_ITMP2, /* used for byte/word insertion */
118   - OR_FTMP0, /* float temporary */
119   - OR_DF, /* D flag, for string ops */
120 106 OR_ZERO, /* fixed zero register */
121   - OR_IM, /* dummy immediate value register */
122 107 NB_OREGS,
123 108 };
124 109  
125   -#if 0
126   -static const double tab_const[7] = {
127   - 1.0,
128   - 3.32192809488736234789, /* log2(10) */
129   - M_LOG2E,
130   - M_PI,
131   - 0.30102999566398119521, /* log10(2) */
132   - M_LN2,
133   - 0.0
134   -};
135   -#endif
136   -
137 110 typedef void (GenOpFunc)(void);
138 111 typedef void (GenOpFunc1)(long);
139 112 typedef void (GenOpFunc2)(long, long);
... ... @@ -354,14 +327,29 @@ static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
354 327 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
355 328 gen_op_addl_T0_T1_cc,
356 329 gen_op_orl_T0_T1_cc,
357   - gen_op_adcl_T0_T1_cc,
358   - gen_op_sbbl_T0_T1_cc,
  330 + NULL,
  331 + NULL,
359 332 gen_op_andl_T0_T1_cc,
360 333 gen_op_subl_T0_T1_cc,
361 334 gen_op_xorl_T0_T1_cc,
362 335 gen_op_cmpl_T0_T1_cc,
363 336 };
364 337  
  338 +static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
  339 + [OT_BYTE] = {
  340 + gen_op_adcb_T0_T1_cc,
  341 + gen_op_sbbb_T0_T1_cc,
  342 + },
  343 + [OT_WORD] = {
  344 + gen_op_adcw_T0_T1_cc,
  345 + gen_op_sbbw_T0_T1_cc,
  346 + },
  347 + [OT_LONG] = {
  348 + gen_op_adcl_T0_T1_cc,
  349 + gen_op_sbbl_T0_T1_cc,
  350 + },
  351 +};
  352 +
365 353 static const int cc_op_arithb[8] = {
366 354 CC_OP_ADDB,
367 355 CC_OP_LOGICB,
... ... @@ -406,6 +394,21 @@ static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
406 394 },
407 395 };
408 396  
  397 +static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
  398 + [0] = {
  399 + gen_op_btw_T0_T1_cc,
  400 + gen_op_btsw_T0_T1_cc,
  401 + gen_op_btrw_T0_T1_cc,
  402 + gen_op_btcw_T0_T1_cc,
  403 + },
  404 + [1] = {
  405 + gen_op_btl_T0_T1_cc,
  406 + gen_op_btsl_T0_T1_cc,
  407 + gen_op_btrl_T0_T1_cc,
  408 + gen_op_btcl_T0_T1_cc,
  409 + },
  410 +};
  411 +
409 412 static GenOpFunc *gen_op_lds_T0_A0[3] = {
410 413 gen_op_ldsb_T0_A0,
411 414 gen_op_ldsw_T0_A0,
... ... @@ -644,18 +647,23 @@ static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
644 647 gen_op_mov_TN_reg[ot][0][d]();
645 648 if (s != OR_TMP1)
646 649 gen_op_mov_TN_reg[ot][1][s]();
647   - if ((op == OP_ADCL || op == OP_SBBL) && s1->cc_op != CC_OP_DYNAMIC)
648   - gen_op_set_cc_op(s1->cc_op);
649   - gen_op_arith_T0_T1_cc[op]();
  650 + if (op == OP_ADCL || op == OP_SBBL) {
  651 + if (s1->cc_op != CC_OP_DYNAMIC)
  652 + gen_op_set_cc_op(s1->cc_op);
  653 + gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
  654 + s1->cc_op = CC_OP_DYNAMIC;
  655 + } else {
  656 + gen_op_arith_T0_T1_cc[op]();
  657 + s1->cc_op = cc_op_arithb[op] + ot;
  658 + }
650 659 if (d != OR_TMP0 && op != OP_CMPL)
651 660 gen_op_mov_reg_T0[ot][d]();
652   - s1->cc_op = cc_op_arithb[op] + ot;
653 661 }
654 662  
655 663 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
656 664 {
657 665 gen_op_movl_T1_im(c);
658   - gen_op(s1, op, ot, d, OR_TMP0);
  666 + gen_op(s1, op, ot, d, OR_TMP1);
659 667 }
660 668  
661 669 static void gen_inc(DisasContext *s1, int ot, int d, int c)
... ... @@ -664,10 +672,13 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c)
664 672 gen_op_mov_TN_reg[ot][0][d]();
665 673 if (s1->cc_op != CC_OP_DYNAMIC)
666 674 gen_op_set_cc_op(s1->cc_op);
667   - if (c > 0)
  675 + if (c > 0) {
668 676 gen_op_incl_T0_cc();
669   - else
  677 + s1->cc_op = CC_OP_INCB + ot;
  678 + } else {
670 679 gen_op_decl_T0_cc();
  680 + s1->cc_op = CC_OP_DECB + ot;
  681 + }
671 682 if (d != OR_TMP0)
672 683 gen_op_mov_reg_T0[ot][d]();
673 684 }
... ... @@ -678,20 +689,12 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
678 689 gen_op_mov_TN_reg[ot][0][d]();
679 690 if (s != OR_TMP1)
680 691 gen_op_mov_TN_reg[ot][1][s]();
681   - switch(op) {
682   - case OP_ROL:
683   - case OP_ROR:
684   - case OP_RCL:
685   - case OP_RCR:
686   - /* only C and O are modified, so we must update flags dynamically */
687   - if (s1->cc_op != CC_OP_DYNAMIC)
688   - gen_op_set_cc_op(s1->cc_op);
689   - gen_op_shift_T0_T1_cc[ot][op]();
690   - break;
691   - default:
692   - gen_op_shift_T0_T1_cc[ot][op]();
693   - break;
694   - }
  692 + /* for zero counts, flags are not updated, so must do it dynamically */
  693 + if (s1->cc_op != CC_OP_DYNAMIC)
  694 + gen_op_set_cc_op(s1->cc_op);
  695 +
  696 + gen_op_shift_T0_T1_cc[ot][op]();
  697 +
695 698 if (d != OR_TMP0)
696 699 gen_op_mov_reg_T0[ot][d]();
697 700 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
... ... @@ -785,12 +788,65 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
785 788 }
786 789 gen_op_addl_A0_reg_sN[scale][reg2]();
787 790 }
788   - opreg = OR_A0;
789 791 } else {
790   - fprintf(stderr, "16 bit addressing not supported\n");
791   - disp = 0;
792   - opreg = 0;
  792 + switch (mod) {
  793 + case 0:
  794 + if (rm == 6) {
  795 + disp = lduw(s->pc);
  796 + s->pc += 2;
  797 + gen_op_movl_A0_im(disp);
  798 + goto no_rm;
  799 + } else {
  800 + disp = 0;
  801 + }
  802 + break;
  803 + case 1:
  804 + disp = (int8_t)ldub(s->pc++);
  805 + break;
  806 + default:
  807 + case 2:
  808 + disp = lduw(s->pc);
  809 + s->pc += 2;
  810 + break;
  811 + }
  812 + switch(rm) {
  813 + case 0:
  814 + gen_op_movl_A0_reg[R_EBX]();
  815 + gen_op_addl_A0_reg_sN[0][R_ESI]();
  816 + break;
  817 + case 1:
  818 + gen_op_movl_A0_reg[R_EBX]();
  819 + gen_op_addl_A0_reg_sN[0][R_EDI]();
  820 + break;
  821 + case 2:
  822 + gen_op_movl_A0_reg[R_EBP]();
  823 + gen_op_addl_A0_reg_sN[0][R_ESI]();
  824 + break;
  825 + case 3:
  826 + gen_op_movl_A0_reg[R_EBP]();
  827 + gen_op_addl_A0_reg_sN[0][R_EDI]();
  828 + break;
  829 + case 4:
  830 + gen_op_movl_A0_reg[R_ESI]();
  831 + break;
  832 + case 5:
  833 + gen_op_movl_A0_reg[R_EDI]();
  834 + break;
  835 + case 6:
  836 + gen_op_movl_A0_reg[R_EBP]();
  837 + break;
  838 + default:
  839 + case 7:
  840 + gen_op_movl_A0_reg[R_EBX]();
  841 + break;
  842 + }
  843 + if (disp != 0)
  844 + gen_op_addl_A0_im(disp);
  845 + gen_op_andl_A0_ffff();
  846 + no_rm: ;
793 847 }
  848 + opreg = OR_A0;
  849 + disp = 0;
794 850 *reg_ptr = opreg;
795 851 *offset_ptr = disp;
796 852 }
... ... @@ -870,6 +926,12 @@ static void gen_jcc(DisasContext *s, int b, int val)
870 926 case CC_OP_ADDB:
871 927 case CC_OP_ADDW:
872 928 case CC_OP_ADDL:
  929 + case CC_OP_ADCB:
  930 + case CC_OP_ADCW:
  931 + case CC_OP_ADCL:
  932 + case CC_OP_SBBB:
  933 + case CC_OP_SBBW:
  934 + case CC_OP_SBBL:
873 935 case CC_OP_LOGICB:
874 936 case CC_OP_LOGICW:
875 937 case CC_OP_LOGICL:
... ... @@ -882,6 +944,9 @@ static void gen_jcc(DisasContext *s, int b, int val)
882 944 case CC_OP_SHLB:
883 945 case CC_OP_SHLW:
884 946 case CC_OP_SHLL:
  947 + case CC_OP_SARB:
  948 + case CC_OP_SARW:
  949 + case CC_OP_SARL:
885 950 switch(jcc_op) {
886 951 case JCC_Z:
887 952 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
... ... @@ -1284,11 +1349,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1284 1349 gen_inc(s, ot, OR_TMP0, 1);
1285 1350 if (mod != 3)
1286 1351 gen_op_st_T0_A0[ot]();
  1352 + else
  1353 + gen_op_mov_reg_T0[ot][rm]();
1287 1354 break;
1288 1355 case 1: /* dec Ev */
1289 1356 gen_inc(s, ot, OR_TMP0, -1);
1290 1357 if (mod != 3)
1291 1358 gen_op_st_T0_A0[ot]();
  1359 + else
  1360 + gen_op_mov_reg_T0[ot][rm]();
1292 1361 break;
1293 1362 case 2: /* call Ev */
1294 1363 gen_op_movl_T1_im((long)s->pc);
... ... @@ -1359,7 +1428,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1359 1428 ot = dflag ? OT_LONG : OT_WORD;
1360 1429 modrm = ldub(s->pc++);
1361 1430 reg = ((modrm >> 3) & 7) + OR_EAX;
1362   -
1363 1431 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1364 1432 if (b == 0x69) {
1365 1433 val = insn_get(s, ot);
... ... @@ -1372,9 +1440,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1372 1440 }
1373 1441  
1374 1442 if (ot == OT_LONG) {
1375   - op_imull_T0_T1();
  1443 + gen_op_imull_T0_T1();
1376 1444 } else {
1377   - op_imulw_T0_T1();
  1445 + gen_op_imulw_T0_T1();
1378 1446 }
1379 1447 gen_op_mov_reg_T0[ot][reg]();
1380 1448 s->cc_op = CC_OP_MUL;
... ... @@ -1522,7 +1590,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1522 1590 offset_addr = insn_get(s, OT_LONG);
1523 1591 else
1524 1592 offset_addr = insn_get(s, OT_WORD);
1525   -
  1593 + gen_op_movl_A0_im(offset_addr);
1526 1594 if ((b & 2) == 0) {
1527 1595 gen_op_ld_T0_A0[ot]();
1528 1596 gen_op_mov_reg_T0[ot][R_EAX]();
... ... @@ -1717,17 +1785,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1717 1785 break;
1718 1786 }
1719 1787 break;
1720   -#if 0
  1788 + case 0x0d: /* fldcw mem */
  1789 + gen_op_fldcw_A0();
  1790 + break;
  1791 + case 0x0f: /* fnstcw mem */
  1792 + gen_op_fnstcw_A0();
  1793 + break;
1721 1794 case 0x2f: /* fnstsw mem */
1722   - gen_insn3(OP_FNSTS, OR_TMP0, OR_ZERO, OR_ZERO);
1723   - gen_st(OP_STW, OR_TMP0, reg_addr, offset_addr);
  1795 + gen_op_fnstsw_A0();
1724 1796 break;
1725   -
1726 1797 case 0x3c: /* fbld */
1727 1798 case 0x3e: /* fbstp */
1728 1799 error("float BCD not hanlded");
1729 1800 return -1;
1730   -#endif
1731 1801 case 0x3d: /* fildll */
1732 1802 gen_op_fpush();
1733 1803 gen_op_fildll_ST0_A0();
... ... @@ -1737,7 +1807,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1737 1807 gen_op_fpop();
1738 1808 break;
1739 1809 default:
1740   - error("unhandled memory FP\n");
  1810 + error("unhandled memory FP [op=0x%02x]\n", op);
1741 1811 return -1;
1742 1812 }
1743 1813 } else {
... ... @@ -1987,11 +2057,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1987 2057 else
1988 2058 ot = dflag ? OT_LONG : OT_WORD;
1989 2059 if (prefixes & PREFIX_REPNZ) {
  2060 + if (s->cc_op != CC_OP_DYNAMIC)
  2061 + gen_op_set_cc_op(s->cc_op);
1990 2062 gen_op_scas[6 + ot]();
  2063 + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1991 2064 } else if (prefixes & PREFIX_REPZ) {
  2065 + if (s->cc_op != CC_OP_DYNAMIC)
  2066 + gen_op_set_cc_op(s->cc_op);
1992 2067 gen_op_scas[3 + ot]();
  2068 + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1993 2069 } else {
1994 2070 gen_op_scas[ot]();
  2071 + s->cc_op = CC_OP_SUBB + ot;
1995 2072 }
1996 2073 break;
1997 2074  
... ... @@ -2002,11 +2079,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2002 2079 else
2003 2080 ot = dflag ? OT_LONG : OT_WORD;
2004 2081 if (prefixes & PREFIX_REPNZ) {
  2082 + if (s->cc_op != CC_OP_DYNAMIC)
  2083 + gen_op_set_cc_op(s->cc_op);
2005 2084 gen_op_cmps[6 + ot]();
  2085 + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2006 2086 } else if (prefixes & PREFIX_REPZ) {
  2087 + if (s->cc_op != CC_OP_DYNAMIC)
  2088 + gen_op_set_cc_op(s->cc_op);
2007 2089 gen_op_cmps[3 + ot]();
  2090 + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2008 2091 } else {
2009 2092 gen_op_cmps[ot]();
  2093 + s->cc_op = CC_OP_SUBB + ot;
2010 2094 }
2011 2095 break;
2012 2096  
... ... @@ -2187,6 +2271,74 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2187 2271 break;
2188 2272  
2189 2273 /************************/
  2274 + /* bit operations */
  2275 + case 0x1ba: /* bt/bts/btr/btc Gv, im */
  2276 + ot = dflag ? OT_LONG : OT_WORD;
  2277 + modrm = ldub(s->pc++);
  2278 + op = (modrm >> 3) & 7;
  2279 + mod = (modrm >> 6) & 3;
  2280 + rm = modrm & 7;
  2281 + if (mod != 3) {
  2282 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  2283 + gen_op_ld_T0_A0[ot]();
  2284 + } else {
  2285 + gen_op_mov_TN_reg[ot][0][rm]();
  2286 + }
  2287 + /* load shift */
  2288 + val = ldub(s->pc++);
  2289 + gen_op_movl_T1_im(val);
  2290 + if (op < 4)
  2291 + return -1;
  2292 + op -= 4;
  2293 + gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
  2294 + s->cc_op = CC_OP_SHLB + ot;
  2295 + if (op != 0) {
  2296 + if (mod != 3)
  2297 + gen_op_st_T0_A0[ot]();
  2298 + else
  2299 + gen_op_mov_reg_T0[ot][rm]();
  2300 + }
  2301 + break;
  2302 + case 0x1a3: /* bt Gv, Ev */
  2303 + op = 0;
  2304 + goto do_btx;
  2305 + case 0x1ab: /* bts */
  2306 + op = 1;
  2307 + goto do_btx;
  2308 + case 0x1b3: /* btr */
  2309 + op = 2;
  2310 + goto do_btx;
  2311 + case 0x1bb: /* btc */
  2312 + op = 3;
  2313 + do_btx:
  2314 + ot = dflag ? OT_LONG : OT_WORD;
  2315 + modrm = ldub(s->pc++);
  2316 + reg = (modrm >> 3) & 7;
  2317 + mod = (modrm >> 6) & 3;
  2318 + rm = modrm & 7;
  2319 + gen_op_mov_TN_reg[OT_LONG][1][reg]();
  2320 + if (mod != 3) {
  2321 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  2322 + /* specific case: we need to add a displacement */
  2323 + if (ot == OT_WORD)
  2324 + gen_op_add_bitw_A0_T1();
  2325 + else
  2326 + gen_op_add_bitl_A0_T1();
  2327 + gen_op_ld_T0_A0[ot]();
  2328 + } else {
  2329 + gen_op_mov_TN_reg[ot][0][rm]();
  2330 + }
  2331 + gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
  2332 + s->cc_op = CC_OP_SHLB + ot;
  2333 + if (op != 0) {
  2334 + if (mod != 3)
  2335 + gen_op_st_T0_A0[ot]();
  2336 + else
  2337 + gen_op_mov_reg_T0[ot][rm]();
  2338 + }
  2339 + break;
  2340 +
  2341 + /************************/
2190 2342 /* misc */
2191 2343 case 0x90: /* nop */
2192 2344 break;
... ... @@ -2206,6 +2358,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2206 2358 gen_op_into((long)pc_start, (long)s->pc);
2207 2359 *is_jmp_ptr = 1;
2208 2360 break;
  2361 + case 0x1c8 ... 0x1cf: /* bswap reg */
  2362 + reg = b & 7;
  2363 + gen_op_mov_TN_reg[OT_LONG][0][reg]();
  2364 + gen_op_bswapl_T0();
  2365 + gen_op_mov_reg_T0[OT_LONG][reg]();
  2366 + break;
  2367 +
2209 2368 #if 0
2210 2369 case 0x1a2: /* cpuid */
2211 2370 gen_insn0(OP_ASM);
... ...