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,19 +78,27 @@ enum {
78 CC_OP_ADDW, 78 CC_OP_ADDW,
79 CC_OP_ADDL, 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 CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ 85 CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
82 CC_OP_SUBW, 86 CC_OP_SUBW,
83 CC_OP_SUBL, 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 CC_OP_LOGICB, /* modify all flags, CC_DST = res */ 93 CC_OP_LOGICB, /* modify all flags, CC_DST = res */
86 CC_OP_LOGICW, 94 CC_OP_LOGICW,
87 CC_OP_LOGICL, 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 CC_OP_INCW, 98 CC_OP_INCW,
91 CC_OP_INCL, 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 CC_OP_DECW, 102 CC_OP_DECW,
95 CC_OP_DECL, 103 CC_OP_DECL,
96 104
@@ -98,6 +106,10 @@ enum { @@ -98,6 +106,10 @@ enum {
98 CC_OP_SHLW, 106 CC_OP_SHLW,
99 CC_OP_SHLL, 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 CC_OP_NB, 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,14 +198,10 @@ void gen_code(const char *name, unsigned long offset, unsigned long size,
198 { 198 {
199 uint8_t *p; 199 uint8_t *p;
200 p = p_end - 1; 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 if (p == p_start) 201 if (p == p_start)
208 error("empty code for %s", name); 202 error("empty code for %s", name);
  203 + if (p[0] != 0xc3)
  204 + error("ret expected at the end of %s", name);
209 copy_size = p - p_start; 205 copy_size = p - p_start;
210 } 206 }
211 break; 207 break;
linux-user/main.c
@@ -128,21 +128,21 @@ int main(int argc, char **argv) @@ -128,21 +128,21 @@ int main(int argc, char **argv)
128 /* Zero out image_info */ 128 /* Zero out image_info */
129 memset(info, 0, sizeof(struct image_info)); 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 printf("Error loading %s\n", filename); 132 printf("Error loading %s\n", filename);
133 exit(1); 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 target_set_brk((char *)info->brk); 147 target_set_brk((char *)info->brk);
148 syscall_init(); 148 syscall_init();
op-i386.c
@@ -10,7 +10,18 @@ typedef signed short int16_t; @@ -10,7 +10,18 @@ typedef signed short int16_t;
10 typedef signed int int32_t; 10 typedef signed int int32_t;
11 typedef signed long long int64_t; 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 #define NULL 0 23 #define NULL 0
  24 +#include <fenv.h>
14 25
15 typedef struct FILE FILE; 26 typedef struct FILE FILE;
16 extern FILE *logfile; 27 extern FILE *logfile;
@@ -18,41 +29,39 @@ extern int loglevel; @@ -18,41 +29,39 @@ extern int loglevel;
18 extern int fprintf(FILE *, const char *, ...); 29 extern int fprintf(FILE *, const char *, ...);
19 30
20 #ifdef __i386__ 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 register struct CPUX86State *env asm("ebp"); 35 register struct CPUX86State *env asm("ebp");
25 -#define FORCE_RET() asm volatile ("ret");  
26 #endif 36 #endif
27 #ifdef __powerpc__ 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 register struct CPUX86State *env asm("r27"); 41 register struct CPUX86State *env asm("r27");
32 -#define FORCE_RET() asm volatile ("blr");  
33 #endif 42 #endif
34 #ifdef __arm__ 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 register struct CPUX86State *env asm("r7"); 47 register struct CPUX86State *env asm("r7");
39 -#define FORCE_RET() asm volatile ("mov pc, lr");  
40 #endif 48 #endif
41 #ifdef __mips__ 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 register struct CPUX86State *env asm("s3"); 53 register struct CPUX86State *env asm("s3");
46 -#define FORCE_RET() asm volatile ("jr $31");  
47 #endif 54 #endif
48 #ifdef __sparc__ 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 register struct CPUX86State *env asm("l3"); 59 register struct CPUX86State *env asm("l3");
53 -#define FORCE_RET() asm volatile ("retl ; nop");  
54 #endif 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 #ifndef OPPROTO 65 #ifndef OPPROTO
57 #define OPPROTO 66 #define OPPROTO
58 #endif 67 #endif
@@ -267,20 +276,6 @@ void OPPROTO op_orl_T0_T1_cc(void) @@ -267,20 +276,6 @@ void OPPROTO op_orl_T0_T1_cc(void)
267 CC_DST = T0; 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 void OPPROTO op_andl_T0_T1_cc(void) 279 void OPPROTO op_andl_T0_T1_cc(void)
285 { 280 {
286 T0 &= T1; 281 T0 &= T1;
@@ -320,12 +315,14 @@ void OPPROTO op_negl_T0_cc(void) @@ -320,12 +315,14 @@ void OPPROTO op_negl_T0_cc(void)
320 315
321 void OPPROTO op_incl_T0_cc(void) 316 void OPPROTO op_incl_T0_cc(void)
322 { 317 {
  318 + CC_SRC = cc_table[CC_OP].compute_c();
323 T0++; 319 T0++;
324 CC_DST = T0; 320 CC_DST = T0;
325 } 321 }
326 322
327 void OPPROTO op_decl_T0_cc(void) 323 void OPPROTO op_decl_T0_cc(void)
328 { 324 {
  325 + CC_SRC = cc_table[CC_OP].compute_c();
329 T0--; 326 T0--;
330 CC_DST = T0; 327 CC_DST = T0;
331 } 328 }
@@ -335,6 +332,11 @@ void OPPROTO op_testl_T0_T1_cc(void) @@ -335,6 +332,11 @@ void OPPROTO op_testl_T0_T1_cc(void)
335 CC_DST = T0 & T1; 332 CC_DST = T0 & T1;
336 } 333 }
337 334
  335 +void OPPROTO op_bswapl_T0(void)
  336 +{
  337 + T0 = bswap32(T0);
  338 +}
  339 +
338 /* multiply/divide */ 340 /* multiply/divide */
339 void OPPROTO op_mulb_AL_T0(void) 341 void OPPROTO op_mulb_AL_T0(void)
340 { 342 {
@@ -399,7 +401,7 @@ void OPPROTO op_imulw_T0_T1(void) @@ -399,7 +401,7 @@ void OPPROTO op_imulw_T0_T1(void)
399 void OPPROTO op_imull_T0_T1(void) 401 void OPPROTO op_imull_T0_T1(void)
400 { 402 {
401 int64_t res; 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 T0 = res; 405 T0 = res;
404 CC_SRC = (res != (int32_t)res); 406 CC_SRC = (res != (int32_t)res);
405 } 407 }
@@ -468,10 +470,10 @@ void OPPROTO op_divl_EAX_T0(void) @@ -468,10 +470,10 @@ void OPPROTO op_divl_EAX_T0(void)
468 void OPPROTO op_idivl_EAX_T0(void) 470 void OPPROTO op_idivl_EAX_T0(void)
469 { 471 {
470 int den, q, r; 472 int den, q, r;
471 - int16_t num; 473 + int64_t num;
472 474
473 num = EAX | ((uint64_t)EDX << 32); 475 num = EAX | ((uint64_t)EDX << 32);
474 - den = (int16_t)T0; 476 + den = T0;
475 q = (num / den); 477 q = (num / den);
476 r = (num % den); 478 r = (num % den);
477 EAX = q; 479 EAX = q;
@@ -495,6 +497,16 @@ void OPPROTO op_movl_A0_im(void) @@ -495,6 +497,16 @@ void OPPROTO op_movl_A0_im(void)
495 A0 = PARAM1; 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 /* memory access */ 510 /* memory access */
499 511
500 void OPPROTO op_ldub_T0_A0(void) 512 void OPPROTO op_ldub_T0_A0(void)
@@ -562,7 +574,17 @@ void OPPROTO op_stl_T0_A0(void) @@ -562,7 +574,17 @@ void OPPROTO op_stl_T0_A0(void)
562 stl((uint8_t *)A0, T0); 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 /* indirect jump */ 589 /* indirect jump */
568 590
@@ -938,25 +960,37 @@ CCTable cc_table[CC_OP_NB] = { @@ -938,25 +960,37 @@ CCTable cc_table[CC_OP_NB] = {
938 [CC_OP_ADDW] = { compute_all_addw, compute_c_addw }, 960 [CC_OP_ADDW] = { compute_all_addw, compute_c_addw },
939 [CC_OP_ADDL] = { compute_all_addl, compute_c_addl }, 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 [CC_OP_SUBB] = { compute_all_subb, compute_c_subb }, 967 [CC_OP_SUBB] = { compute_all_subb, compute_c_subb },
942 [CC_OP_SUBW] = { compute_all_subw, compute_c_subw }, 968 [CC_OP_SUBW] = { compute_all_subw, compute_c_subw },
943 [CC_OP_SUBL] = { compute_all_subl, compute_c_subl }, 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 [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb }, 975 [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb },
946 [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw }, 976 [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw },
947 [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl }, 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 [CC_OP_INCL] = { compute_all_incl, compute_c_incl }, 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 [CC_OP_DECL] = { compute_all_decl, compute_c_incl }, 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 [CC_OP_SHLL] = { compute_all_shll, compute_c_shll }, 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 /* floating point support */ 996 /* floating point support */
@@ -1640,6 +1674,41 @@ void OPPROTO op_fcos(void) @@ -1640,6 +1674,41 @@ void OPPROTO op_fcos(void)
1640 helper_fcos(); 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 /* main execution loop */ 1712 /* main execution loop */
1644 uint8_t code_gen_buffer[65536]; 1713 uint8_t code_gen_buffer[65536];
1645 1714
@@ -1651,9 +1720,15 @@ static const char *cc_op_str[] = { @@ -1651,9 +1720,15 @@ static const char *cc_op_str[] = {
1651 "ADDB", 1720 "ADDB",
1652 "ADDW", 1721 "ADDW",
1653 "ADDL", 1722 "ADDL",
  1723 + "ADCB",
  1724 + "ADCW",
  1725 + "ADCL",
1654 "SUBB", 1726 "SUBB",
1655 "SUBW", 1727 "SUBW",
1656 "SUBL", 1728 "SUBL",
  1729 + "SBBB",
  1730 + "SBBW",
  1731 + "SBBL",
1657 "LOGICB", 1732 "LOGICB",
1658 "LOGICW", 1733 "LOGICW",
1659 "LOGICL", 1734 "LOGICL",
@@ -1666,6 +1741,9 @@ static const char *cc_op_str[] = { @@ -1666,6 +1741,9 @@ static const char *cc_op_str[] = {
1666 "SHLB", 1741 "SHLB",
1667 "SHLW", 1742 "SHLW",
1668 "SHLL", 1743 "SHLL",
  1744 + "SARB",
  1745 + "SARW",
  1746 + "SARL",
1669 }; 1747 };
1670 #endif 1748 #endif
1671 1749
@@ -1688,13 +1766,24 @@ int cpu_x86_exec(CPUX86State *env1) @@ -1688,13 +1766,24 @@ int cpu_x86_exec(CPUX86State *env1)
1688 for(;;) { 1766 for(;;) {
1689 #ifdef DEBUG_EXEC 1767 #ifdef DEBUG_EXEC
1690 if (loglevel) { 1768 if (loglevel) {
  1769 + int eflags;
  1770 + eflags = cc_table[CC_OP].compute_all();
  1771 + eflags |= (DF & DIRECTION_FLAG);
1691 fprintf(logfile, 1772 fprintf(logfile,
1692 "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n" 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 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 1776 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
1696 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 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 #endif 1788 #endif
1700 cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc); 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,7 +33,7 @@ static int glue(compute_all_add, SUFFIX)(void)
33 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1; 33 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
34 pf = parity_table[(uint8_t)CC_DST]; 34 pf = parity_table[(uint8_t)CC_DST];
35 af = (CC_DST ^ src1 ^ src2) & 0x10; 35 af = (CC_DST ^ src1 ^ src2) & 0x10;
36 - zf = ((DATA_TYPE)CC_DST != 0) << 6; 36 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
37 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 37 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
38 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O; 38 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
39 return cf | pf | af | zf | sf | of; 39 return cf | pf | af | zf | sf | of;
@@ -47,6 +47,29 @@ static int glue(compute_c_add, SUFFIX)(void) @@ -47,6 +47,29 @@ static int glue(compute_c_add, SUFFIX)(void)
47 return cf; 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 static int glue(compute_all_sub, SUFFIX)(void) 73 static int glue(compute_all_sub, SUFFIX)(void)
51 { 74 {
52 int cf, pf, af, zf, sf, of; 75 int cf, pf, af, zf, sf, of;
@@ -56,9 +79,9 @@ static int glue(compute_all_sub, SUFFIX)(void) @@ -56,9 +79,9 @@ static int glue(compute_all_sub, SUFFIX)(void)
56 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; 79 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
57 pf = parity_table[(uint8_t)CC_DST]; 80 pf = parity_table[(uint8_t)CC_DST];
58 af = (CC_DST ^ src1 ^ src2) & 0x10; 81 af = (CC_DST ^ src1 ^ src2) & 0x10;
59 - zf = ((DATA_TYPE)CC_DST != 0) << 6; 82 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
60 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 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 return cf | pf | af | zf | sf | of; 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,7 +90,31 @@ static int glue(compute_c_sub, SUFFIX)(void)
67 int src1, src2, cf; 90 int src1, src2, cf;
68 src1 = CC_SRC; 91 src1 = CC_SRC;
69 src2 = CC_SRC - CC_DST; 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 return cf; 118 return cf;
72 } 119 }
73 120
@@ -77,7 +124,7 @@ static int glue(compute_all_logic, SUFFIX)(void) @@ -77,7 +124,7 @@ static int glue(compute_all_logic, SUFFIX)(void)
77 cf = 0; 124 cf = 0;
78 pf = parity_table[(uint8_t)CC_DST]; 125 pf = parity_table[(uint8_t)CC_DST];
79 af = 0; 126 af = 0;
80 - zf = ((DATA_TYPE)CC_DST != 0) << 6; 127 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
81 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 128 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
82 of = 0; 129 of = 0;
83 return cf | pf | af | zf | sf | of; 130 return cf | pf | af | zf | sf | of;
@@ -97,16 +144,18 @@ static int glue(compute_all_inc, SUFFIX)(void) @@ -97,16 +144,18 @@ static int glue(compute_all_inc, SUFFIX)(void)
97 cf = CC_SRC; 144 cf = CC_SRC;
98 pf = parity_table[(uint8_t)CC_DST]; 145 pf = parity_table[(uint8_t)CC_DST];
99 af = (CC_DST ^ src1 ^ src2) & 0x10; 146 af = (CC_DST ^ src1 ^ src2) & 0x10;
100 - zf = ((DATA_TYPE)CC_DST != 0) << 6; 147 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
101 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 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 return cf | pf | af | zf | sf | of; 150 return cf | pf | af | zf | sf | of;
104 } 151 }
105 152
  153 +#if DATA_BITS == 32
106 static int glue(compute_c_inc, SUFFIX)(void) 154 static int glue(compute_c_inc, SUFFIX)(void)
107 { 155 {
108 return CC_SRC; 156 return CC_SRC;
109 } 157 }
  158 +#endif
110 159
111 static int glue(compute_all_dec, SUFFIX)(void) 160 static int glue(compute_all_dec, SUFFIX)(void)
112 { 161 {
@@ -117,9 +166,9 @@ static int glue(compute_all_dec, SUFFIX)(void) @@ -117,9 +166,9 @@ static int glue(compute_all_dec, SUFFIX)(void)
117 cf = CC_SRC; 166 cf = CC_SRC;
118 pf = parity_table[(uint8_t)CC_DST]; 167 pf = parity_table[(uint8_t)CC_DST];
119 af = (CC_DST ^ src1 ^ src2) & 0x10; 168 af = (CC_DST ^ src1 ^ src2) & 0x10;
120 - zf = ((DATA_TYPE)CC_DST != 0) << 6; 169 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
121 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 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 return cf | pf | af | zf | sf | of; 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,16 +178,30 @@ static int glue(compute_all_shl, SUFFIX)(void)
129 cf = CC_SRC & 1; 178 cf = CC_SRC & 1;
130 pf = parity_table[(uint8_t)CC_DST]; 179 pf = parity_table[(uint8_t)CC_DST];
131 af = 0; /* undefined */ 180 af = 0; /* undefined */
132 - zf = ((DATA_TYPE)CC_DST != 0) << 6; 181 + zf = ((DATA_TYPE)CC_DST == 0) << 6;
133 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; 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 return cf | pf | af | zf | sf | of; 184 return cf | pf | af | zf | sf | of;
136 } 185 }
137 186
  187 +#if DATA_BITS == 32
138 static int glue(compute_c_shl, SUFFIX)(void) 188 static int glue(compute_c_shl, SUFFIX)(void)
139 { 189 {
140 return CC_SRC & 1; 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 /* various optimized jumps cases */ 206 /* various optimized jumps cases */
144 207
@@ -157,7 +220,7 @@ void OPPROTO glue(op_jb_sub, SUFFIX)(void) @@ -157,7 +220,7 @@ void OPPROTO glue(op_jb_sub, SUFFIX)(void)
157 220
158 void OPPROTO glue(op_jz_sub, SUFFIX)(void) 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 PC = PARAM1; 224 PC = PARAM1;
162 else 225 else
163 PC = PARAM2; 226 PC = PARAM2;
@@ -225,7 +288,7 @@ void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void) @@ -225,7 +288,7 @@ void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
225 288
226 void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void) 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 void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void) 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,6 +338,7 @@ void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
275 (T0 & CC_C); 338 (T0 & CC_C);
276 CC_OP = CC_OP_EFLAGS; 339 CC_OP = CC_OP_EFLAGS;
277 } 340 }
  341 + FORCE_RET();
278 } 342 }
279 343
280 void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void) 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,6 +354,7 @@ void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
290 ((T0 >> (DATA_BITS - 1)) & CC_C); 354 ((T0 >> (DATA_BITS - 1)) & CC_C);
291 CC_OP = CC_OP_EFLAGS; 355 CC_OP = CC_OP_EFLAGS;
292 } 356 }
  357 + FORCE_RET();
293 } 358 }
294 359
295 void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void) 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,6 +370,7 @@ void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
305 #endif 370 #endif
306 if (count) { 371 if (count) {
307 eflags = cc_table[CC_OP].compute_all(); 372 eflags = cc_table[CC_OP].compute_all();
  373 + T0 &= DATA_MASK;
308 src = T0; 374 src = T0;
309 res = (T0 << count) | ((eflags & CC_C) << (count - 1)); 375 res = (T0 << count) | ((eflags & CC_C) << (count - 1));
310 if (count > 1) 376 if (count > 1)
@@ -315,6 +381,7 @@ void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void) @@ -315,6 +381,7 @@ void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
315 ((src >> (DATA_BITS - count)) & CC_C); 381 ((src >> (DATA_BITS - count)) & CC_C);
316 CC_OP = CC_OP_EFLAGS; 382 CC_OP = CC_OP_EFLAGS;
317 } 383 }
  384 + FORCE_RET();
318 } 385 }
319 386
320 void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void) 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,6 +397,7 @@ void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
330 #endif 397 #endif
331 if (count) { 398 if (count) {
332 eflags = cc_table[CC_OP].compute_all(); 399 eflags = cc_table[CC_OP].compute_all();
  400 + T0 &= DATA_MASK;
333 src = T0; 401 src = T0;
334 res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count)); 402 res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
335 if (count > 1) 403 if (count > 1)
@@ -340,6 +408,7 @@ void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void) @@ -340,6 +408,7 @@ void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
340 ((src >> (count - 1)) & CC_C); 408 ((src >> (count - 1)) & CC_C);
341 CC_OP = CC_OP_EFLAGS; 409 CC_OP = CC_OP_EFLAGS;
342 } 410 }
  411 + FORCE_RET();
343 } 412 }
344 413
345 void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void) 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,11 +421,12 @@ void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
352 CC_DST = T0; 421 CC_DST = T0;
353 CC_OP = CC_OP_ADDB + SHIFT; 422 CC_OP = CC_OP_ADDB + SHIFT;
354 } else if (count) { 423 } else if (count) {
355 - CC_SRC = T0 >> (DATA_BITS - count); 424 + CC_SRC = (DATA_TYPE)T0 >> (DATA_BITS - count);
356 T0 = T0 << count; 425 T0 = T0 << count;
357 CC_DST = T0; 426 CC_DST = T0;
358 CC_OP = CC_OP_SHLB + SHIFT; 427 CC_OP = CC_OP_SHLB + SHIFT;
359 } 428 }
  429 + FORCE_RET();
360 } 430 }
361 431
362 void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void) 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,6 +440,7 @@ void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
370 CC_DST = T0; 440 CC_DST = T0;
371 CC_OP = CC_OP_SHLB + SHIFT; 441 CC_OP = CC_OP_SHLB + SHIFT;
372 } 442 }
  443 + FORCE_RET();
373 } 444 }
374 445
375 void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void) 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,10 +452,69 @@ void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
381 CC_SRC = src >> (count - 1); 452 CC_SRC = src >> (count - 1);
382 T0 = src >> count; 453 T0 = src >> count;
383 CC_DST = T0; 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 /* string operations */ 518 /* string operations */
389 /* XXX: maybe use lower level instructions to ease exception handling */ 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,8 +594,8 @@ void OPPROTO glue(op_scas, SUFFIX)(void)
464 { 594 {
465 int v; 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 CC_SRC = EAX; 599 CC_SRC = EAX;
470 CC_DST = EAX - v; 600 CC_DST = EAX - v;
471 } 601 }
@@ -476,20 +606,14 @@ void OPPROTO glue(op_repz_scas, SUFFIX)(void) @@ -476,20 +606,14 @@ void OPPROTO glue(op_repz_scas, SUFFIX)(void)
476 606
477 if (ECX != 0) { 607 if (ECX != 0) {
478 /* NOTE: the flags are not modified if ECX == 0 */ 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 inc = (DF << SHIFT); 610 inc = (DF << SHIFT);
487 do { 611 do {
488 - v2 = glue(ldu, SUFFIX)((void *)ESI); 612 + v2 = glue(ldu, SUFFIX)((void *)EDI);
  613 + EDI += inc;
  614 + ECX--;
489 if (v1 != v2) 615 if (v1 != v2)
490 break; 616 break;
491 - ESI += inc;  
492 - ECX--;  
493 } while (ECX != 0); 617 } while (ECX != 0);
494 CC_SRC = v1; 618 CC_SRC = v1;
495 CC_DST = v1 - v2; 619 CC_DST = v1 - v2;
@@ -503,20 +627,14 @@ void OPPROTO glue(op_repnz_scas, SUFFIX)(void) @@ -503,20 +627,14 @@ void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
503 627
504 if (ECX != 0) { 628 if (ECX != 0) {
505 /* NOTE: the flags are not modified if ECX == 0 */ 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 inc = (DF << SHIFT); 631 inc = (DF << SHIFT);
514 do { 632 do {
515 - v2 = glue(ldu, SUFFIX)((void *)ESI); 633 + v2 = glue(ldu, SUFFIX)((void *)EDI);
  634 + EDI += inc;
  635 + ECX--;
516 if (v1 == v2) 636 if (v1 == v2)
517 break; 637 break;
518 - ESI += inc;  
519 - ECX--;  
520 } while (ECX != 0); 638 } while (ECX != 0);
521 CC_SRC = v1; 639 CC_SRC = v1;
522 CC_DST = v1 - v2; 640 CC_DST = v1 - v2;
@@ -543,11 +661,11 @@ void OPPROTO glue(op_repz_cmps, SUFFIX)(void) @@ -543,11 +661,11 @@ void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
543 do { 661 do {
544 v1 = glue(ldu, SUFFIX)((void *)ESI); 662 v1 = glue(ldu, SUFFIX)((void *)ESI);
545 v2 = glue(ldu, SUFFIX)((void *)EDI); 663 v2 = glue(ldu, SUFFIX)((void *)EDI);
546 - if (v1 != v2)  
547 - break;  
548 ESI += inc; 664 ESI += inc;
549 EDI += inc; 665 EDI += inc;
550 ECX--; 666 ECX--;
  667 + if (v1 != v2)
  668 + break;
551 } while (ECX != 0); 669 } while (ECX != 0);
552 CC_SRC = v1; 670 CC_SRC = v1;
553 CC_DST = v1 - v2; 671 CC_DST = v1 - v2;
@@ -563,11 +681,11 @@ void OPPROTO glue(op_repnz_cmps, SUFFIX)(void) @@ -563,11 +681,11 @@ void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
563 do { 681 do {
564 v1 = glue(ldu, SUFFIX)((void *)ESI); 682 v1 = glue(ldu, SUFFIX)((void *)ESI);
565 v2 = glue(ldu, SUFFIX)((void *)EDI); 683 v2 = glue(ldu, SUFFIX)((void *)EDI);
566 - if (v1 == v2)  
567 - break;  
568 ESI += inc; 684 ESI += inc;
569 EDI += inc; 685 EDI += inc;
570 ECX--; 686 ECX--;
  687 + if (v1 == v2)
  688 + break;
571 } while (ECX != 0); 689 } while (ECX != 0);
572 CC_SRC = v1; 690 CC_SRC = v1;
573 CC_DST = v1 - v2; 691 CC_DST = v1 - v2;
tests/Makefile
@@ -20,7 +20,7 @@ test2: test2.c @@ -20,7 +20,7 @@ test2: test2.c
20 20
21 # i386 emulation test (dump various opcodes) */ 21 # i386 emulation test (dump various opcodes) */
22 test-i386: test-i386.c test-i386.h test-i386-shift.h 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 test: test-i386 25 test: test-i386
26 ./test-i386 > test-i386.ref 26 ./test-i386 > test-i386.ref
tests/test-i386.c
@@ -14,13 +14,12 @@ @@ -14,13 +14,12 @@
14 #define CC_S 0x0080 14 #define CC_S 0x0080
15 #define CC_O 0x0800 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 #define __init_call __attribute__ ((unused,__section__ (".initcall.init"))) 17 #define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
21 18
22 static void *call_start __init_call = NULL; 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 #define OP add 23 #define OP add
25 #include "test-i386.h" 24 #include "test-i386.h"
26 25
@@ -67,6 +66,9 @@ static void *call_start __init_call = NULL; @@ -67,6 +66,9 @@ static void *call_start __init_call = NULL;
67 #define OP1 66 #define OP1
68 #include "test-i386.h" 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 #define OP shl 72 #define OP shl
71 #include "test-i386-shift.h" 73 #include "test-i386-shift.h"
72 74
@@ -268,18 +270,148 @@ void test_jcc(void) @@ -268,18 +270,148 @@ void test_jcc(void)
268 TEST_JCC("jns", 0, 0); 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 static void *call_end __init_call = NULL; 399 static void *call_end __init_call = NULL;
272 400
273 int main(int argc, char **argv) 401 int main(int argc, char **argv)
274 { 402 {
275 void **ptr; 403 void **ptr;
276 void (*func)(void); 404 void (*func)(void);
  405 +
  406 + test_mul();
  407 +#if 0
277 ptr = &call_start + 1; 408 ptr = &call_start + 1;
278 while (*ptr != NULL) { 409 while (*ptr != NULL) {
279 func = *ptr++; 410 func = *ptr++;
280 func(); 411 func();
281 } 412 }
282 - test_lea();  
283 test_jcc(); 413 test_jcc();
  414 + test_lea();
  415 +#endif
284 return 0; 416 return 0;
285 } 417 }
translate-i386.c
@@ -27,7 +27,9 @@ static void error(const char *fmt, ...) @@ -27,7 +27,9 @@ static void error(const char *fmt, ...)
27 va_list ap; 27 va_list ap;
28 28
29 va_start(ap, fmt); 29 va_start(ap, fmt);
  30 + fprintf(stderr, "\n");
30 vfprintf(stderr, fmt, ap); 31 vfprintf(stderr, fmt, ap);
  32 + fprintf(stderr, "\n");
31 va_end(ap); 33 va_end(ap);
32 exit(1); 34 exit(1);
33 } 35 }
@@ -98,42 +100,13 @@ enum { @@ -98,42 +100,13 @@ enum {
98 OR_EBP, 100 OR_EBP,
99 OR_ESI, 101 OR_ESI,
100 OR_EDI, 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 OR_TMP0, /* temporary operand register */ 103 OR_TMP0, /* temporary operand register */
112 OR_TMP1, 104 OR_TMP1,
113 OR_A0, /* temporary register used when doing address evaluation */ 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 OR_ZERO, /* fixed zero register */ 106 OR_ZERO, /* fixed zero register */
121 - OR_IM, /* dummy immediate value register */  
122 NB_OREGS, 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 typedef void (GenOpFunc)(void); 110 typedef void (GenOpFunc)(void);
138 typedef void (GenOpFunc1)(long); 111 typedef void (GenOpFunc1)(long);
139 typedef void (GenOpFunc2)(long, long); 112 typedef void (GenOpFunc2)(long, long);
@@ -354,14 +327,29 @@ static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = { @@ -354,14 +327,29 @@ static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
354 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { 327 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
355 gen_op_addl_T0_T1_cc, 328 gen_op_addl_T0_T1_cc,
356 gen_op_orl_T0_T1_cc, 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 gen_op_andl_T0_T1_cc, 332 gen_op_andl_T0_T1_cc,
360 gen_op_subl_T0_T1_cc, 333 gen_op_subl_T0_T1_cc,
361 gen_op_xorl_T0_T1_cc, 334 gen_op_xorl_T0_T1_cc,
362 gen_op_cmpl_T0_T1_cc, 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 static const int cc_op_arithb[8] = { 353 static const int cc_op_arithb[8] = {
366 CC_OP_ADDB, 354 CC_OP_ADDB,
367 CC_OP_LOGICB, 355 CC_OP_LOGICB,
@@ -406,6 +394,21 @@ static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = { @@ -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 static GenOpFunc *gen_op_lds_T0_A0[3] = { 412 static GenOpFunc *gen_op_lds_T0_A0[3] = {
410 gen_op_ldsb_T0_A0, 413 gen_op_ldsb_T0_A0,
411 gen_op_ldsw_T0_A0, 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,18 +647,23 @@ static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
644 gen_op_mov_TN_reg[ot][0][d](); 647 gen_op_mov_TN_reg[ot][0][d]();
645 if (s != OR_TMP1) 648 if (s != OR_TMP1)
646 gen_op_mov_TN_reg[ot][1][s](); 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 if (d != OR_TMP0 && op != OP_CMPL) 659 if (d != OR_TMP0 && op != OP_CMPL)
651 gen_op_mov_reg_T0[ot][d](); 660 gen_op_mov_reg_T0[ot][d]();
652 - s1->cc_op = cc_op_arithb[op] + ot;  
653 } 661 }
654 662
655 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c) 663 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
656 { 664 {
657 gen_op_movl_T1_im(c); 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 static void gen_inc(DisasContext *s1, int ot, int d, int c) 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,10 +672,13 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c)
664 gen_op_mov_TN_reg[ot][0][d](); 672 gen_op_mov_TN_reg[ot][0][d]();
665 if (s1->cc_op != CC_OP_DYNAMIC) 673 if (s1->cc_op != CC_OP_DYNAMIC)
666 gen_op_set_cc_op(s1->cc_op); 674 gen_op_set_cc_op(s1->cc_op);
667 - if (c > 0) 675 + if (c > 0) {
668 gen_op_incl_T0_cc(); 676 gen_op_incl_T0_cc();
669 - else 677 + s1->cc_op = CC_OP_INCB + ot;
  678 + } else {
670 gen_op_decl_T0_cc(); 679 gen_op_decl_T0_cc();
  680 + s1->cc_op = CC_OP_DECB + ot;
  681 + }
671 if (d != OR_TMP0) 682 if (d != OR_TMP0)
672 gen_op_mov_reg_T0[ot][d](); 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,20 +689,12 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
678 gen_op_mov_TN_reg[ot][0][d](); 689 gen_op_mov_TN_reg[ot][0][d]();
679 if (s != OR_TMP1) 690 if (s != OR_TMP1)
680 gen_op_mov_TN_reg[ot][1][s](); 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 if (d != OR_TMP0) 698 if (d != OR_TMP0)
696 gen_op_mov_reg_T0[ot][d](); 699 gen_op_mov_reg_T0[ot][d]();
697 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ 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,12 +788,65 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
785 } 788 }
786 gen_op_addl_A0_reg_sN[scale][reg2](); 789 gen_op_addl_A0_reg_sN[scale][reg2]();
787 } 790 }
788 - opreg = OR_A0;  
789 } else { 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 *reg_ptr = opreg; 850 *reg_ptr = opreg;
795 *offset_ptr = disp; 851 *offset_ptr = disp;
796 } 852 }
@@ -870,6 +926,12 @@ static void gen_jcc(DisasContext *s, int b, int val) @@ -870,6 +926,12 @@ static void gen_jcc(DisasContext *s, int b, int val)
870 case CC_OP_ADDB: 926 case CC_OP_ADDB:
871 case CC_OP_ADDW: 927 case CC_OP_ADDW:
872 case CC_OP_ADDL: 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 case CC_OP_LOGICB: 935 case CC_OP_LOGICB:
874 case CC_OP_LOGICW: 936 case CC_OP_LOGICW:
875 case CC_OP_LOGICL: 937 case CC_OP_LOGICL:
@@ -882,6 +944,9 @@ static void gen_jcc(DisasContext *s, int b, int val) @@ -882,6 +944,9 @@ static void gen_jcc(DisasContext *s, int b, int val)
882 case CC_OP_SHLB: 944 case CC_OP_SHLB:
883 case CC_OP_SHLW: 945 case CC_OP_SHLW:
884 case CC_OP_SHLL: 946 case CC_OP_SHLL:
  947 + case CC_OP_SARB:
  948 + case CC_OP_SARW:
  949 + case CC_OP_SARL:
885 switch(jcc_op) { 950 switch(jcc_op) {
886 case JCC_Z: 951 case JCC_Z:
887 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op]; 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,11 +1349,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1284 gen_inc(s, ot, OR_TMP0, 1); 1349 gen_inc(s, ot, OR_TMP0, 1);
1285 if (mod != 3) 1350 if (mod != 3)
1286 gen_op_st_T0_A0[ot](); 1351 gen_op_st_T0_A0[ot]();
  1352 + else
  1353 + gen_op_mov_reg_T0[ot][rm]();
1287 break; 1354 break;
1288 case 1: /* dec Ev */ 1355 case 1: /* dec Ev */
1289 gen_inc(s, ot, OR_TMP0, -1); 1356 gen_inc(s, ot, OR_TMP0, -1);
1290 if (mod != 3) 1357 if (mod != 3)
1291 gen_op_st_T0_A0[ot](); 1358 gen_op_st_T0_A0[ot]();
  1359 + else
  1360 + gen_op_mov_reg_T0[ot][rm]();
1292 break; 1361 break;
1293 case 2: /* call Ev */ 1362 case 2: /* call Ev */
1294 gen_op_movl_T1_im((long)s->pc); 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,7 +1428,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1359 ot = dflag ? OT_LONG : OT_WORD; 1428 ot = dflag ? OT_LONG : OT_WORD;
1360 modrm = ldub(s->pc++); 1429 modrm = ldub(s->pc++);
1361 reg = ((modrm >> 3) & 7) + OR_EAX; 1430 reg = ((modrm >> 3) & 7) + OR_EAX;
1362 -  
1363 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); 1431 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1364 if (b == 0x69) { 1432 if (b == 0x69) {
1365 val = insn_get(s, ot); 1433 val = insn_get(s, ot);
@@ -1372,9 +1440,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -1372,9 +1440,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1372 } 1440 }
1373 1441
1374 if (ot == OT_LONG) { 1442 if (ot == OT_LONG) {
1375 - op_imull_T0_T1(); 1443 + gen_op_imull_T0_T1();
1376 } else { 1444 } else {
1377 - op_imulw_T0_T1(); 1445 + gen_op_imulw_T0_T1();
1378 } 1446 }
1379 gen_op_mov_reg_T0[ot][reg](); 1447 gen_op_mov_reg_T0[ot][reg]();
1380 s->cc_op = CC_OP_MUL; 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,7 +1590,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1522 offset_addr = insn_get(s, OT_LONG); 1590 offset_addr = insn_get(s, OT_LONG);
1523 else 1591 else
1524 offset_addr = insn_get(s, OT_WORD); 1592 offset_addr = insn_get(s, OT_WORD);
1525 - 1593 + gen_op_movl_A0_im(offset_addr);
1526 if ((b & 2) == 0) { 1594 if ((b & 2) == 0) {
1527 gen_op_ld_T0_A0[ot](); 1595 gen_op_ld_T0_A0[ot]();
1528 gen_op_mov_reg_T0[ot][R_EAX](); 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,17 +1785,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1717 break; 1785 break;
1718 } 1786 }
1719 break; 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 case 0x2f: /* fnstsw mem */ 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 break; 1796 break;
1725 -  
1726 case 0x3c: /* fbld */ 1797 case 0x3c: /* fbld */
1727 case 0x3e: /* fbstp */ 1798 case 0x3e: /* fbstp */
1728 error("float BCD not hanlded"); 1799 error("float BCD not hanlded");
1729 return -1; 1800 return -1;
1730 -#endif  
1731 case 0x3d: /* fildll */ 1801 case 0x3d: /* fildll */
1732 gen_op_fpush(); 1802 gen_op_fpush();
1733 gen_op_fildll_ST0_A0(); 1803 gen_op_fildll_ST0_A0();
@@ -1737,7 +1807,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -1737,7 +1807,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1737 gen_op_fpop(); 1807 gen_op_fpop();
1738 break; 1808 break;
1739 default: 1809 default:
1740 - error("unhandled memory FP\n"); 1810 + error("unhandled memory FP [op=0x%02x]\n", op);
1741 return -1; 1811 return -1;
1742 } 1812 }
1743 } else { 1813 } else {
@@ -1987,11 +2057,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -1987,11 +2057,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1987 else 2057 else
1988 ot = dflag ? OT_LONG : OT_WORD; 2058 ot = dflag ? OT_LONG : OT_WORD;
1989 if (prefixes & PREFIX_REPNZ) { 2059 if (prefixes & PREFIX_REPNZ) {
  2060 + if (s->cc_op != CC_OP_DYNAMIC)
  2061 + gen_op_set_cc_op(s->cc_op);
1990 gen_op_scas[6 + ot](); 2062 gen_op_scas[6 + ot]();
  2063 + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1991 } else if (prefixes & PREFIX_REPZ) { 2064 } else if (prefixes & PREFIX_REPZ) {
  2065 + if (s->cc_op != CC_OP_DYNAMIC)
  2066 + gen_op_set_cc_op(s->cc_op);
1992 gen_op_scas[3 + ot](); 2067 gen_op_scas[3 + ot]();
  2068 + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
1993 } else { 2069 } else {
1994 gen_op_scas[ot](); 2070 gen_op_scas[ot]();
  2071 + s->cc_op = CC_OP_SUBB + ot;
1995 } 2072 }
1996 break; 2073 break;
1997 2074
@@ -2002,11 +2079,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -2002,11 +2079,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2002 else 2079 else
2003 ot = dflag ? OT_LONG : OT_WORD; 2080 ot = dflag ? OT_LONG : OT_WORD;
2004 if (prefixes & PREFIX_REPNZ) { 2081 if (prefixes & PREFIX_REPNZ) {
  2082 + if (s->cc_op != CC_OP_DYNAMIC)
  2083 + gen_op_set_cc_op(s->cc_op);
2005 gen_op_cmps[6 + ot](); 2084 gen_op_cmps[6 + ot]();
  2085 + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2006 } else if (prefixes & PREFIX_REPZ) { 2086 } else if (prefixes & PREFIX_REPZ) {
  2087 + if (s->cc_op != CC_OP_DYNAMIC)
  2088 + gen_op_set_cc_op(s->cc_op);
2007 gen_op_cmps[3 + ot](); 2089 gen_op_cmps[3 + ot]();
  2090 + s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2008 } else { 2091 } else {
2009 gen_op_cmps[ot](); 2092 gen_op_cmps[ot]();
  2093 + s->cc_op = CC_OP_SUBB + ot;
2010 } 2094 }
2011 break; 2095 break;
2012 2096
@@ -2187,6 +2271,74 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -2187,6 +2271,74 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2187 break; 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 /* misc */ 2342 /* misc */
2191 case 0x90: /* nop */ 2343 case 0x90: /* nop */
2192 break; 2344 break;
@@ -2206,6 +2358,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -2206,6 +2358,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2206 gen_op_into((long)pc_start, (long)s->pc); 2358 gen_op_into((long)pc_start, (long)s->pc);
2207 *is_jmp_ptr = 1; 2359 *is_jmp_ptr = 1;
2208 break; 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 #if 0 2368 #if 0
2210 case 0x1a2: /* cpuid */ 2369 case 0x1a2: /* cpuid */
2211 gen_insn0(OP_ASM); 2370 gen_insn0(OP_ASM);