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; | ... | ... |