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