Commit 5dd9488c09081a76ff86e0d74e56a9d98d666d64
1 parent
60cd49d5
added cmov instruction
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@32 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
125 additions
and
65 deletions
TODO
opreg_template.h
... | ... | @@ -60,6 +60,19 @@ void OPPROTO glue(glue(op_movl,REGNAME),_A0)(void) |
60 | 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 | 76 | /* NOTE: T0 high order bits are ignored */ |
64 | 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 | 385 | void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void) |
386 | 386 | { |
387 | 387 | int count, src; |
388 | + /* XXX: testing */ | |
388 | 389 | count = T1 & SHIFT_MASK; |
389 | 390 | if (count) { |
390 | 391 | CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C); | ... | ... |
tests/test-i386.c
... | ... | @@ -3,6 +3,8 @@ |
3 | 3 | #include <inttypes.h> |
4 | 4 | #include <math.h> |
5 | 5 | |
6 | +#define TEST_CMOV 0 | |
7 | + | |
6 | 8 | #define xglue(x, y) x ## y |
7 | 9 | #define glue(x, y) xglue(x, y) |
8 | 10 | #define stringify(s) tostring(s) |
... | ... | @@ -225,79 +227,99 @@ void test_lea(void) |
225 | 227 | |
226 | 228 | #define TEST_JCC(JCC, v1, v2)\ |
227 | 229 | {\ |
230 | + int res;\ | |
228 | 231 | asm("movl $1, %0\n\t"\ |
229 | 232 | "cmpl %2, %1\n\t"\ |
230 | - JCC " 1f\n\t"\ | |
233 | + "j" JCC " 1f\n\t"\ | |
231 | 234 | "movl $0, %0\n\t"\ |
232 | 235 | "1:\n\t"\ |
233 | 236 | : "=r" (res)\ |
234 | 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 | 262 | /* various jump tests */ |
239 | 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 | 325 | #undef CC_MASK | ... | ... |
translate-i386.c
... | ... | @@ -44,19 +44,6 @@ int __op_param1, __op_param2, __op_param3; |
44 | 44 | extern FILE *logfile; |
45 | 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 | 47 | #define PREFIX_REPZ 1 |
61 | 48 | #define PREFIX_REPNZ 2 |
62 | 49 | #define PREFIX_LOCK 4 |
... | ... | @@ -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 | 365 | static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { |
356 | 366 | gen_op_addl_T0_T1_cc, |
357 | 367 | gen_op_orl_T0_T1_cc, |
... | ... | @@ -2586,12 +2596,27 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2586 | 2596 | s->is_jmp = 1; |
2587 | 2597 | break; |
2588 | 2598 | |
2589 | - case 0x190 ... 0x19f: | |
2599 | + case 0x190 ... 0x19f: /* setcc Gv */ | |
2590 | 2600 | modrm = ldub(s->pc++); |
2591 | 2601 | gen_setcc(s, b); |
2592 | 2602 | gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); |
2593 | 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, ®_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 | 2621 | /* flags */ |
2597 | 2622 | case 0x9c: /* pushf */ |
... | ... | @@ -2801,7 +2826,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2801 | 2826 | gen_op_loop[s->aflag][b & 3](val, (long)s->pc); |
2802 | 2827 | s->is_jmp = 1; |
2803 | 2828 | break; |
2804 | - case 0x1a2: /* rdtsc */ | |
2829 | + case 0x131: /* rdtsc */ | |
2805 | 2830 | gen_op_rdtsc(); |
2806 | 2831 | break; |
2807 | 2832 | #if 0 |
... | ... | @@ -2841,8 +2866,8 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, |
2841 | 2866 | do { |
2842 | 2867 | ret = disas_insn(dc, pc_ptr); |
2843 | 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 | 2871 | abort(); |
2847 | 2872 | } |
2848 | 2873 | pc_ptr = (void *)ret; | ... | ... |