Revision 1d2699ae

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