Revision 102bf2c6 target-s390x/translate.c

b/target-s390x/translate.c
620 620
    case CC_OP_COMP_64:
621 621
    case CC_OP_NZ_F32:
622 622
    case CC_OP_NZ_F64:
623
    case CC_OP_FLOGR:
623 624
        /* 1 argument */
624 625
        gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
625 626
        break;
......
852 853
        account_inline_branch(s, old_cc_op);
853 854
        break;
854 855

  
856
    case CC_OP_FLOGR:
857
        switch (mask & 0xa) {
858
        case 8: /* src == 0 -> no one bit found */
859
            cond = TCG_COND_EQ;
860
            break;
861
        case 2: /* src != 0 -> one bit found */
862
            cond = TCG_COND_NE;
863
            break;
864
        default:
865
            goto do_dynamic;
866
        }
867
        account_inline_branch(s, old_cc_op);
868
        break;
869

  
855 870
    default:
856 871
    do_dynamic:
857 872
        /* Calculate cc value.  */
......
888 903

  
889 904
    case CC_OP_LTGT0_64:
890 905
    case CC_OP_NZ:
906
    case CC_OP_FLOGR:
891 907
        c->u.s64.a = cc_dst;
892 908
        c->u.s64.b = tcg_const_i64(0);
893 909
        c->g1 = true;
......
1414 1430
#undef FP_HELPER
1415 1431
}
1416 1432

  
1417
static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
1418
                     int r2)
1419
{
1420
    TCGv_i64 tmp;
1421
    TCGv_i32 tmp32_1;
1422

  
1423
    LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
1424
    switch (op) {
1425
    case 0x83: /* FLOGR R1,R2 [RRE] */
1426
        tmp = load_reg(r2);
1427
        tmp32_1 = tcg_const_i32(r1);
1428
        gen_helper_flogr(cc_op, cpu_env, tmp32_1, tmp);
1429
        set_cc_static(s);
1430
        tcg_temp_free_i64(tmp);
1431
        tcg_temp_free_i32(tmp32_1);
1432
        break;
1433
    default:
1434
        LOG_DISAS("illegal b9 operation 0x%x\n", op);
1435
        gen_illegal_opcode(s);
1436
        break;
1437
    }
1438
}
1439

  
1440 1433
static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
1441 1434
{
1442 1435
    unsigned char opc;
......
1460 1453
        r2 = insn & 0xf;
1461 1454
        disas_b3(env, s, op, r3, r1, r2);
1462 1455
        break;
1463
    case 0xb9:
1464
        insn = ld_code4(env, s->pc);
1465
        r1 = (insn >> 4) & 0xf;
1466
        r2 = insn & 0xf;
1467
        op = (insn >> 16) & 0xff;
1468
        disas_b9(env, s, op, r1, r2);
1469
        break;
1470 1456
    default:
1471 1457
        qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
1472 1458
        gen_illegal_opcode(s);
......
2330 2316
    return NO_EXIT;
2331 2317
}
2332 2318

  
2319
static ExitStatus op_flogr(DisasContext *s, DisasOps *o)
2320
{
2321
    /* We'll use the original input for cc computation, since we get to
2322
       compare that against 0, which ought to be better than comparing
2323
       the real output against 64.  It also lets cc_dst be a convenient
2324
       temporary during our computation.  */
2325
    gen_op_update1_cc_i64(s, CC_OP_FLOGR, o->in2);
2326

  
2327
    /* R1 = IN ? CLZ(IN) : 64.  */
2328
    gen_helper_clz(o->out, o->in2);
2329

  
2330
    /* R1+1 = IN & ~(found bit).  Note that we may attempt to shift this
2331
       value by 64, which is undefined.  But since the shift is 64 iff the
2332
       input is zero, we still get the correct result after and'ing.  */
2333
    tcg_gen_movi_i64(o->out2, 0x8000000000000000ull);
2334
    tcg_gen_shr_i64(o->out2, o->out2, o->out);
2335
    tcg_gen_andc_i64(o->out2, cc_dst, o->out2);
2336
    return NO_EXIT;
2337
}
2338

  
2333 2339
static ExitStatus op_icm(DisasContext *s, DisasOps *o)
2334 2340
{
2335 2341
    int m3 = get_field(s->fields, m3);

Also available in: Unified diff