Revision 1d2699ae tcg/i386/tcg-target.c
b/tcg/i386/tcg-target.c | ||
---|---|---|
361 | 361 |
} |
362 | 362 |
} |
363 | 363 |
|
364 |
static void tcg_out_brcond(TCGContext *s, int cond, |
|
365 |
TCGArg arg1, TCGArg arg2, int const_arg2, |
|
366 |
int label_index, int small) |
|
364 |
static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2, |
|
365 |
int const_arg2) |
|
367 | 366 |
{ |
368 | 367 |
if (const_arg2) { |
369 | 368 |
if (arg2 == 0) { |
... | ... | |
375 | 374 |
} else { |
376 | 375 |
tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3), arg2, arg1); |
377 | 376 |
} |
377 |
} |
|
378 |
|
|
379 |
static void tcg_out_brcond(TCGContext *s, int cond, |
|
380 |
TCGArg arg1, TCGArg arg2, int const_arg2, |
|
381 |
int label_index, int small) |
|
382 |
{ |
|
383 |
tcg_out_cmp(s, arg1, arg2, const_arg2); |
|
378 | 384 |
tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small); |
379 | 385 |
} |
380 | 386 |
|
... | ... | |
460 | 466 |
tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr); |
461 | 467 |
} |
462 | 468 |
|
469 |
static void tcg_out_setcond(TCGContext *s, int cond, TCGArg dest, |
|
470 |
TCGArg arg1, TCGArg arg2, int const_arg2) |
|
471 |
{ |
|
472 |
tcg_out_cmp(s, arg1, arg2, const_arg2); |
|
473 |
/* setcc */ |
|
474 |
tcg_out_modrm(s, 0x90 | tcg_cond_to_jcc[cond] | P_EXT, 0, dest); |
|
475 |
tgen_arithi(s, ARITH_AND, dest, 0xff, 0); |
|
476 |
} |
|
477 |
|
|
478 |
static void tcg_out_setcond2(TCGContext *s, const TCGArg *args, |
|
479 |
const int *const_args) |
|
480 |
{ |
|
481 |
TCGArg new_args[6]; |
|
482 |
int label_true, label_over; |
|
483 |
|
|
484 |
memcpy(new_args, args+1, 5*sizeof(TCGArg)); |
|
485 |
|
|
486 |
if (args[0] == args[1] || args[0] == args[2] |
|
487 |
|| (!const_args[3] && args[0] == args[3]) |
|
488 |
|| (!const_args[4] && args[0] == args[4])) { |
|
489 |
/* When the destination overlaps with one of the argument |
|
490 |
registers, don't do anything tricky. */ |
|
491 |
label_true = gen_new_label(); |
|
492 |
label_over = gen_new_label(); |
|
493 |
|
|
494 |
new_args[5] = label_true; |
|
495 |
tcg_out_brcond2(s, new_args, const_args+1, 1); |
|
496 |
|
|
497 |
tcg_out_movi(s, TCG_TYPE_I32, args[0], 0); |
|
498 |
tcg_out_jxx(s, JCC_JMP, label_over, 1); |
|
499 |
tcg_out_label(s, label_true, (tcg_target_long)s->code_ptr); |
|
500 |
|
|
501 |
tcg_out_movi(s, TCG_TYPE_I32, args[0], 1); |
|
502 |
tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr); |
|
503 |
} else { |
|
504 |
/* When the destination does not overlap one of the arguments, |
|
505 |
clear the destination first, jump if cond false, and emit an |
|
506 |
increment in the true case. This results in smaller code. */ |
|
507 |
|
|
508 |
tcg_out_movi(s, TCG_TYPE_I32, args[0], 0); |
|
509 |
|
|
510 |
label_over = gen_new_label(); |
|
511 |
new_args[4] = tcg_invert_cond(new_args[4]); |
|
512 |
new_args[5] = label_over; |
|
513 |
tcg_out_brcond2(s, new_args, const_args+1, 1); |
|
514 |
|
|
515 |
tgen_arithi(s, ARITH_ADD, args[0], 1, 0); |
|
516 |
tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr); |
|
517 |
} |
|
518 |
} |
|
519 |
|
|
463 | 520 |
#if defined(CONFIG_SOFTMMU) |
464 | 521 |
|
465 | 522 |
#include "../../softmmu_defs.h" |
... | ... | |
1121 | 1178 |
tcg_out_modrm(s, 0xb7 | P_EXT, args[0], args[1]); |
1122 | 1179 |
break; |
1123 | 1180 |
|
1181 |
case INDEX_op_setcond_i32: |
|
1182 |
tcg_out_setcond(s, args[3], args[0], args[1], args[2], const_args[2]); |
|
1183 |
break; |
|
1184 |
case INDEX_op_setcond2_i32: |
|
1185 |
tcg_out_setcond2(s, args, const_args); |
|
1186 |
break; |
|
1187 |
|
|
1124 | 1188 |
case INDEX_op_qemu_ld8u: |
1125 | 1189 |
tcg_out_qemu_ld(s, args, 0); |
1126 | 1190 |
break; |
... | ... | |
1209 | 1273 |
{ INDEX_op_ext8u_i32, { "r", "q"} }, |
1210 | 1274 |
{ INDEX_op_ext16u_i32, { "r", "r"} }, |
1211 | 1275 |
|
1276 |
{ INDEX_op_setcond_i32, { "q", "r", "ri" } }, |
|
1277 |
{ INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } }, |
|
1278 |
|
|
1212 | 1279 |
#if TARGET_LONG_BITS == 32 |
1213 | 1280 |
{ INDEX_op_qemu_ld8u, { "r", "L" } }, |
1214 | 1281 |
{ INDEX_op_qemu_ld8s, { "r", "L" } }, |
Also available in: Unified diff