diff options
Diffstat (limited to 'target/alpha/translate.c')
| -rw-r--r-- | target/alpha/translate.c | 94 |
1 files changed, 40 insertions, 54 deletions
diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 4b464f8651..882cf6cea0 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -453,13 +453,13 @@ static DisasJumpType gen_bdirect(DisasContext *ctx, int ra, int32_t disp) } static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond, - TCGv cmp, int32_t disp) + TCGv cmp, uint64_t imm, int32_t disp) { uint64_t dest = ctx->base.pc_next + (disp << 2); TCGLabel *lab_true = gen_new_label(); if (use_goto_tb(ctx, dest)) { - tcg_gen_brcondi_i64(cond, cmp, 0, lab_true); + tcg_gen_brcondi_i64(cond, cmp, imm, lab_true); tcg_gen_goto_tb(0); tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next); @@ -472,81 +472,71 @@ static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond, return DISAS_NORETURN; } else { - TCGv_i64 z = load_zero(ctx); + TCGv_i64 i = tcg_constant_i64(imm); TCGv_i64 d = tcg_constant_i64(dest); TCGv_i64 p = tcg_constant_i64(ctx->base.pc_next); - tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p); + tcg_gen_movcond_i64(cond, cpu_pc, cmp, i, d, p); return DISAS_PC_UPDATED; } } static DisasJumpType gen_bcond(DisasContext *ctx, TCGCond cond, int ra, - int32_t disp, int mask) + int32_t disp) { - if (mask) { - TCGv tmp = tcg_temp_new(); - DisasJumpType ret; - - tcg_gen_andi_i64(tmp, load_gpr(ctx, ra), 1); - ret = gen_bcond_internal(ctx, cond, tmp, disp); - return ret; - } - return gen_bcond_internal(ctx, cond, load_gpr(ctx, ra), disp); + return gen_bcond_internal(ctx, cond, load_gpr(ctx, ra), + is_tst_cond(cond), disp); } /* Fold -0.0 for comparison with COND. */ -static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src) +static TCGv_i64 gen_fold_mzero(TCGCond *pcond, uint64_t *pimm, TCGv_i64 src) { - uint64_t mzero = 1ull << 63; + TCGv_i64 tmp; - switch (cond) { + *pimm = 0; + switch (*pcond) { case TCG_COND_LE: case TCG_COND_GT: /* For <= or >, the -0.0 value directly compares the way we want. */ - tcg_gen_mov_i64(dest, src); - break; + return src; case TCG_COND_EQ: case TCG_COND_NE: - /* For == or !=, we can simply mask off the sign bit and compare. */ - tcg_gen_andi_i64(dest, src, mzero - 1); - break; + /* For == or !=, we can compare without the sign bit. */ + *pcond = *pcond == TCG_COND_EQ ? TCG_COND_TSTEQ : TCG_COND_TSTNE; + *pimm = INT64_MAX; + return src; case TCG_COND_GE: case TCG_COND_LT: /* For >= or <, map -0.0 to +0.0. */ - tcg_gen_movcond_i64(TCG_COND_NE, dest, src, tcg_constant_i64(mzero), - src, tcg_constant_i64(0)); - break; + tmp = tcg_temp_new_i64(); + tcg_gen_movcond_i64(TCG_COND_EQ, tmp, + src, tcg_constant_i64(INT64_MIN), + tcg_constant_i64(0), src); + return tmp; default: - abort(); + g_assert_not_reached(); } } static DisasJumpType gen_fbcond(DisasContext *ctx, TCGCond cond, int ra, int32_t disp) { - TCGv cmp_tmp = tcg_temp_new(); - DisasJumpType ret; - - gen_fold_mzero(cond, cmp_tmp, load_fpr(ctx, ra)); - ret = gen_bcond_internal(ctx, cond, cmp_tmp, disp); - return ret; + uint64_t imm; + TCGv_i64 tmp = gen_fold_mzero(&cond, &imm, load_fpr(ctx, ra)); + return gen_bcond_internal(ctx, cond, tmp, imm, disp); } static void gen_fcmov(DisasContext *ctx, TCGCond cond, int ra, int rb, int rc) { - TCGv_i64 va, vb, z; - - z = load_zero(ctx); - vb = load_fpr(ctx, rb); - va = tcg_temp_new(); - gen_fold_mzero(cond, va, load_fpr(ctx, ra)); - - tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc), va, z, vb, load_fpr(ctx, rc)); + uint64_t imm; + TCGv_i64 tmp = gen_fold_mzero(&cond, &imm, load_fpr(ctx, ra)); + tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc), + tmp, tcg_constant_i64(imm), + load_fpr(ctx, rb), load_fpr(ctx, rc)); } #define QUAL_RM_N 0x080 /* Round mode nearest even */ @@ -1683,16 +1673,12 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) break; case 0x14: /* CMOVLBS */ - tmp = tcg_temp_new(); - tcg_gen_andi_i64(tmp, va, 1); - tcg_gen_movcond_i64(TCG_COND_NE, vc, tmp, load_zero(ctx), + tcg_gen_movcond_i64(TCG_COND_TSTNE, vc, va, tcg_constant_i64(1), vb, load_gpr(ctx, rc)); break; case 0x16: /* CMOVLBC */ - tmp = tcg_temp_new(); - tcg_gen_andi_i64(tmp, va, 1); - tcg_gen_movcond_i64(TCG_COND_EQ, vc, tmp, load_zero(ctx), + tcg_gen_movcond_i64(TCG_COND_TSTEQ, vc, va, tcg_constant_i64(1), vb, load_gpr(ctx, rc)); break; case 0x20: @@ -2827,35 +2813,35 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) break; case 0x38: /* BLBC */ - ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1); + ret = gen_bcond(ctx, TCG_COND_TSTEQ, ra, disp21); break; case 0x39: /* BEQ */ - ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0); + ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21); break; case 0x3A: /* BLT */ - ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0); + ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21); break; case 0x3B: /* BLE */ - ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0); + ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21); break; case 0x3C: /* BLBS */ - ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1); + ret = gen_bcond(ctx, TCG_COND_TSTNE, ra, disp21); break; case 0x3D: /* BNE */ - ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0); + ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21); break; case 0x3E: /* BGE */ - ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0); + ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21); break; case 0x3F: /* BGT */ - ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0); + ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21); break; invalid_opc: ret = gen_invalid(ctx); |