Commit 5dd9488c09081a76ff86e0d74e56a9d98d666d64

Authored by bellard
1 parent 60cd49d5

added cmov instruction


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@32 c046a42c-6fe2-441c-8c8c-71466251a162
1 -- segment ops (minimal LDT/GDT support for wine)  
2 - optimize translated cache chaining (DLL PLT like system) 1 - optimize translated cache chaining (DLL PLT like system)
3 - improved 16 bit support 2 - improved 16 bit support
4 - optimize inverse flags propagation (easy by generating intermediate 3 - optimize inverse flags propagation (easy by generating intermediate
opreg_template.h
@@ -60,6 +60,19 @@ void OPPROTO glue(glue(op_movl,REGNAME),_A0)(void) @@ -60,6 +60,19 @@ void OPPROTO glue(glue(op_movl,REGNAME),_A0)(void)
60 REG = A0; 60 REG = A0;
61 } 61 }
62 62
  63 +/* mov T1 to REG if T0 is true */
  64 +void OPPROTO glue(glue(op_cmovw,REGNAME),_T1_T0)(void)
  65 +{
  66 + if (T0)
  67 + REG = (REG & 0xffff0000) | (T1 & 0xffff);
  68 +}
  69 +
  70 +void OPPROTO glue(glue(op_cmovl,REGNAME),_T1_T0)(void)
  71 +{
  72 + if (T0)
  73 + REG = T1;
  74 +}
  75 +
63 /* NOTE: T0 high order bits are ignored */ 76 /* NOTE: T0 high order bits are ignored */
64 void OPPROTO glue(glue(op_movw,REGNAME),_T0)(void) 77 void OPPROTO glue(glue(op_movw,REGNAME),_T0)(void)
65 { 78 {
ops_template.h
@@ -385,6 +385,7 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) @@ -385,6 +385,7 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
385 void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void) 385 void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
386 { 386 {
387 int count, src; 387 int count, src;
  388 + /* XXX: testing */
388 count = T1 & SHIFT_MASK; 389 count = T1 & SHIFT_MASK;
389 if (count) { 390 if (count) {
390 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C); 391 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
tests/test-i386.c
@@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
3 #include <inttypes.h> 3 #include <inttypes.h>
4 #include <math.h> 4 #include <math.h>
5 5
  6 +#define TEST_CMOV 0
  7 +
6 #define xglue(x, y) x ## y 8 #define xglue(x, y) x ## y
7 #define glue(x, y) xglue(x, y) 9 #define glue(x, y) xglue(x, y)
8 #define stringify(s) tostring(s) 10 #define stringify(s) tostring(s)
@@ -225,79 +227,99 @@ void test_lea(void) @@ -225,79 +227,99 @@ void test_lea(void)
225 227
226 #define TEST_JCC(JCC, v1, v2)\ 228 #define TEST_JCC(JCC, v1, v2)\
227 {\ 229 {\
  230 + int res;\
228 asm("movl $1, %0\n\t"\ 231 asm("movl $1, %0\n\t"\
229 "cmpl %2, %1\n\t"\ 232 "cmpl %2, %1\n\t"\
230 - JCC " 1f\n\t"\ 233 + "j" JCC " 1f\n\t"\
231 "movl $0, %0\n\t"\ 234 "movl $0, %0\n\t"\
232 "1:\n\t"\ 235 "1:\n\t"\
233 : "=r" (res)\ 236 : "=r" (res)\
234 : "r" (v1), "r" (v2));\ 237 : "r" (v1), "r" (v2));\
235 - printf("%-10s %d\n", JCC, res);\ 238 + printf("%-10s %d\n", "j" JCC, res);\
  239 +\
  240 + asm("movl $0, %0\n\t"\
  241 + "cmpl %2, %1\n\t"\
  242 + "set" JCC " %b0\n\t"\
  243 + : "=r" (res)\
  244 + : "r" (v1), "r" (v2));\
  245 + printf("%-10s %d\n", "set" JCC, res);\
  246 + if (TEST_CMOV) {\
  247 + asm("movl $0x12345678, %0\n\t"\
  248 + "cmpl %2, %1\n\t"\
  249 + "cmov" JCC "l %3, %0\n\t"\
  250 + : "=r" (res)\
  251 + : "r" (v1), "r" (v2), "m" (1));\
  252 + printf("%-10s R=0x%08x\n", "cmov" JCC "l", res);\
  253 + asm("movl $0x12345678, %0\n\t"\
  254 + "cmpl %2, %1\n\t"\
  255 + "cmov" JCC "w %w3, %w0\n\t"\
  256 + : "=r" (res)\
  257 + : "r" (v1), "r" (v2), "r" (1));\
  258 + printf("%-10s R=0x%08x\n", "cmov" JCC "w", res);\
  259 + } \
236 } 260 }
237 261
238 /* various jump tests */ 262 /* various jump tests */
239 void test_jcc(void) 263 void test_jcc(void)
240 { 264 {
241 - int res;  
242 -  
243 - TEST_JCC("jne", 1, 1);  
244 - TEST_JCC("jne", 1, 0); 265 + TEST_JCC("ne", 1, 1);
  266 + TEST_JCC("ne", 1, 0);
245 267
246 - TEST_JCC("je", 1, 1);  
247 - TEST_JCC("je", 1, 0); 268 + TEST_JCC("e", 1, 1);
  269 + TEST_JCC("e", 1, 0);
248 270
249 - TEST_JCC("jl", 1, 1);  
250 - TEST_JCC("jl", 1, 0);  
251 - TEST_JCC("jl", 1, -1); 271 + TEST_JCC("l", 1, 1);
  272 + TEST_JCC("l", 1, 0);
  273 + TEST_JCC("l", 1, -1);
252 274
253 - TEST_JCC("jle", 1, 1);  
254 - TEST_JCC("jle", 1, 0);  
255 - TEST_JCC("jle", 1, -1); 275 + TEST_JCC("le", 1, 1);
  276 + TEST_JCC("le", 1, 0);
  277 + TEST_JCC("le", 1, -1);
256 278
257 - TEST_JCC("jge", 1, 1);  
258 - TEST_JCC("jge", 1, 0);  
259 - TEST_JCC("jge", -1, 1); 279 + TEST_JCC("ge", 1, 1);
  280 + TEST_JCC("ge", 1, 0);
  281 + TEST_JCC("ge", -1, 1);
260 282
261 - TEST_JCC("jg", 1, 1);  
262 - TEST_JCC("jg", 1, 0);  
263 - TEST_JCC("jg", 1, -1); 283 + TEST_JCC("g", 1, 1);
  284 + TEST_JCC("g", 1, 0);
  285 + TEST_JCC("g", 1, -1);
264 286
265 - TEST_JCC("jb", 1, 1);  
266 - TEST_JCC("jb", 1, 0);  
267 - TEST_JCC("jb", 1, -1); 287 + TEST_JCC("b", 1, 1);
  288 + TEST_JCC("b", 1, 0);
  289 + TEST_JCC("b", 1, -1);
268 290
269 - TEST_JCC("jbe", 1, 1);  
270 - TEST_JCC("jbe", 1, 0);  
271 - TEST_JCC("jbe", 1, -1); 291 + TEST_JCC("be", 1, 1);
  292 + TEST_JCC("be", 1, 0);
  293 + TEST_JCC("be", 1, -1);
272 294
273 - TEST_JCC("jae", 1, 1);  
274 - TEST_JCC("jae", 1, 0);  
275 - TEST_JCC("jae", 1, -1); 295 + TEST_JCC("ae", 1, 1);
  296 + TEST_JCC("ae", 1, 0);
  297 + TEST_JCC("ae", 1, -1);
276 298
277 - TEST_JCC("ja", 1, 1);  
278 - TEST_JCC("ja", 1, 0);  
279 - TEST_JCC("ja", 1, -1); 299 + TEST_JCC("a", 1, 1);
  300 + TEST_JCC("a", 1, 0);
  301 + TEST_JCC("a", 1, -1);
280 302
281 303
282 - TEST_JCC("jp", 1, 1);  
283 - TEST_JCC("jp", 1, 0); 304 + TEST_JCC("p", 1, 1);
  305 + TEST_JCC("p", 1, 0);
284 306
285 - TEST_JCC("jnp", 1, 1);  
286 - TEST_JCC("jnp", 1, 0); 307 + TEST_JCC("np", 1, 1);
  308 + TEST_JCC("np", 1, 0);
287 309
288 - TEST_JCC("jo", 0x7fffffff, 0);  
289 - TEST_JCC("jo", 0x7fffffff, -1); 310 + TEST_JCC("o", 0x7fffffff, 0);
  311 + TEST_JCC("o", 0x7fffffff, -1);
290 312
291 - TEST_JCC("jno", 0x7fffffff, 0);  
292 - TEST_JCC("jno", 0x7fffffff, -1); 313 + TEST_JCC("no", 0x7fffffff, 0);
  314 + TEST_JCC("no", 0x7fffffff, -1);
293 315
294 - TEST_JCC("js", 0, 1);  
295 - TEST_JCC("js", 0, -1);  
296 - TEST_JCC("js", 0, 0); 316 + TEST_JCC("s", 0, 1);
  317 + TEST_JCC("s", 0, -1);
  318 + TEST_JCC("s", 0, 0);
297 319
298 - TEST_JCC("jns", 0, 1);  
299 - TEST_JCC("jns", 0, -1);  
300 - TEST_JCC("jns", 0, 0); 320 + TEST_JCC("ns", 0, 1);
  321 + TEST_JCC("ns", 0, -1);
  322 + TEST_JCC("ns", 0, 0);
301 } 323 }
302 324
303 #undef CC_MASK 325 #undef CC_MASK
translate-i386.c
@@ -44,19 +44,6 @@ int __op_param1, __op_param2, __op_param3; @@ -44,19 +44,6 @@ int __op_param1, __op_param2, __op_param3;
44 extern FILE *logfile; 44 extern FILE *logfile;
45 extern int loglevel; 45 extern int loglevel;
46 46
47 -/* supress that */  
48 -static void error(const char *fmt, ...)  
49 -{  
50 - va_list ap;  
51 -  
52 - va_start(ap, fmt);  
53 - fprintf(stderr, "\n");  
54 - vfprintf(stderr, fmt, ap);  
55 - fprintf(stderr, "\n");  
56 - va_end(ap);  
57 - exit(1);  
58 -}  
59 -  
60 #define PREFIX_REPZ 1 47 #define PREFIX_REPZ 1
61 #define PREFIX_REPNZ 2 48 #define PREFIX_REPNZ 2
62 #define PREFIX_LOCK 4 49 #define PREFIX_LOCK 4
@@ -352,6 +339,29 @@ static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = { @@ -352,6 +339,29 @@ static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
352 }, 339 },
353 }; 340 };
354 341
  342 +static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
  343 + [0] = {
  344 + gen_op_cmovw_EAX_T1_T0,
  345 + gen_op_cmovw_ECX_T1_T0,
  346 + gen_op_cmovw_EDX_T1_T0,
  347 + gen_op_cmovw_EBX_T1_T0,
  348 + gen_op_cmovw_ESP_T1_T0,
  349 + gen_op_cmovw_EBP_T1_T0,
  350 + gen_op_cmovw_ESI_T1_T0,
  351 + gen_op_cmovw_EDI_T1_T0,
  352 + },
  353 + [1] = {
  354 + gen_op_cmovl_EAX_T1_T0,
  355 + gen_op_cmovl_ECX_T1_T0,
  356 + gen_op_cmovl_EDX_T1_T0,
  357 + gen_op_cmovl_EBX_T1_T0,
  358 + gen_op_cmovl_ESP_T1_T0,
  359 + gen_op_cmovl_EBP_T1_T0,
  360 + gen_op_cmovl_ESI_T1_T0,
  361 + gen_op_cmovl_EDI_T1_T0,
  362 + },
  363 +};
  364 +
355 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { 365 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
356 gen_op_addl_T0_T1_cc, 366 gen_op_addl_T0_T1_cc,
357 gen_op_orl_T0_T1_cc, 367 gen_op_orl_T0_T1_cc,
@@ -2586,12 +2596,27 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2586,12 +2596,27 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2586 s->is_jmp = 1; 2596 s->is_jmp = 1;
2587 break; 2597 break;
2588 2598
2589 - case 0x190 ... 0x19f: 2599 + case 0x190 ... 0x19f: /* setcc Gv */
2590 modrm = ldub(s->pc++); 2600 modrm = ldub(s->pc++);
2591 gen_setcc(s, b); 2601 gen_setcc(s, b);
2592 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); 2602 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
2593 break; 2603 break;
2594 - 2604 + case 0x140 ... 0x14f: /* cmov Gv, Ev */
  2605 + ot = dflag ? OT_LONG : OT_WORD;
  2606 + modrm = ldub(s->pc++);
  2607 + reg = (modrm >> 3) & 7;
  2608 + mod = (modrm >> 6) & 3;
  2609 + gen_setcc(s, b);
  2610 + if (mod != 3) {
  2611 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  2612 + gen_op_ld_T1_A0[ot]();
  2613 + } else {
  2614 + rm = modrm & 7;
  2615 + gen_op_mov_TN_reg[ot][1][rm]();
  2616 + }
  2617 + gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
  2618 + break;
  2619 +
2595 /************************/ 2620 /************************/
2596 /* flags */ 2621 /* flags */
2597 case 0x9c: /* pushf */ 2622 case 0x9c: /* pushf */
@@ -2801,7 +2826,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2801,7 +2826,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2801 gen_op_loop[s->aflag][b & 3](val, (long)s->pc); 2826 gen_op_loop[s->aflag][b & 3](val, (long)s->pc);
2802 s->is_jmp = 1; 2827 s->is_jmp = 1;
2803 break; 2828 break;
2804 - case 0x1a2: /* rdtsc */ 2829 + case 0x131: /* rdtsc */
2805 gen_op_rdtsc(); 2830 gen_op_rdtsc();
2806 break; 2831 break;
2807 #if 0 2832 #if 0
@@ -2841,8 +2866,8 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, @@ -2841,8 +2866,8 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
2841 do { 2866 do {
2842 ret = disas_insn(dc, pc_ptr); 2867 ret = disas_insn(dc, pc_ptr);
2843 if (ret == -1) { 2868 if (ret == -1) {
2844 - error("unknown instruction at PC=0x%x B=%02x %02x %02x",  
2845 - pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]); 2869 + fprintf(stderr, "unknown instruction at PC=0x%08lx B=%02x %02x %02x",
  2870 + (long)pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]);
2846 abort(); 2871 abort();
2847 } 2872 }
2848 pc_ptr = (void *)ret; 2873 pc_ptr = (void *)ret;