diff options
Diffstat (limited to 'target')
| -rw-r--r-- | target/alpha/translate.c | 94 | ||||
| -rw-r--r-- | target/m68k/translate.c | 74 | ||||
| -rw-r--r-- | target/ppc/cpu-models.c | 10 | ||||
| -rw-r--r-- | target/s390x/cpu-dump.c | 3 | ||||
| -rw-r--r-- | target/s390x/gdbstub.c | 6 | ||||
| -rw-r--r-- | target/s390x/helper.c | 3 | ||||
| -rw-r--r-- | target/s390x/helper.h | 3 | ||||
| -rw-r--r-- | target/s390x/kvm/kvm.c | 6 | ||||
| -rw-r--r-- | target/s390x/tcg/excp_helper.c | 11 | ||||
| -rw-r--r-- | target/s390x/tcg/insn-data.h.inc | 5 | ||||
| -rw-r--r-- | target/s390x/tcg/int_helper.c | 97 | ||||
| -rw-r--r-- | target/s390x/tcg/misc_helper.c | 4 | ||||
| -rw-r--r-- | target/s390x/tcg/translate.c | 111 | ||||
| -rw-r--r-- | target/sparc/translate.c | 4 |
14 files changed, 250 insertions, 181 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); diff --git a/target/m68k/translate.c b/target/m68k/translate.c index f886190f88..d7d5ff4300 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -5129,46 +5129,44 @@ undef: static void gen_fcc_cond(DisasCompare *c, DisasContext *s, int cond) { TCGv fpsr; + int imm = 0; - c->v2 = tcg_constant_i32(0); /* TODO: Raise BSUN exception. */ fpsr = tcg_temp_new(); gen_load_fcr(s, fpsr, M68K_FPSR); + c->v1 = fpsr; + switch (cond) { case 0: /* False */ case 16: /* Signaling False */ - c->v1 = c->v2; c->tcond = TCG_COND_NEVER; break; case 1: /* EQual Z */ case 17: /* Signaling EQual Z */ - c->v1 = tcg_temp_new(); - tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z); - c->tcond = TCG_COND_NE; + imm = FPSR_CC_Z; + c->tcond = TCG_COND_TSTNE; break; case 2: /* Ordered Greater Than !(A || Z || N) */ case 18: /* Greater Than !(A || Z || N) */ - c->v1 = tcg_temp_new(); - tcg_gen_andi_i32(c->v1, fpsr, - FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); - c->tcond = TCG_COND_EQ; + imm = FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N; + c->tcond = TCG_COND_TSTEQ; break; case 3: /* Ordered Greater than or Equal Z || !(A || N) */ case 19: /* Greater than or Equal Z || !(A || N) */ c->v1 = tcg_temp_new(); tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A); tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_A)); - tcg_gen_andi_i32(fpsr, fpsr, FPSR_CC_Z | FPSR_CC_N); tcg_gen_or_i32(c->v1, c->v1, fpsr); tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N); - c->tcond = TCG_COND_NE; + imm = FPSR_CC_Z | FPSR_CC_N; + c->tcond = TCG_COND_TSTNE; break; case 4: /* Ordered Less Than !(!N || A || Z); */ case 20: /* Less Than !(!N || A || Z); */ c->v1 = tcg_temp_new(); tcg_gen_xori_i32(c->v1, fpsr, FPSR_CC_N); - tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_N | FPSR_CC_A | FPSR_CC_Z); - c->tcond = TCG_COND_EQ; + imm = FPSR_CC_N | FPSR_CC_A | FPSR_CC_Z; + c->tcond = TCG_COND_TSTEQ; break; case 5: /* Ordered Less than or Equal Z || (N && !A) */ case 21: /* Less than or Equal Z || (N && !A) */ @@ -5176,49 +5174,45 @@ static void gen_fcc_cond(DisasCompare *c, DisasContext *s, int cond) tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A); tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_A)); tcg_gen_andc_i32(c->v1, fpsr, c->v1); - tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_Z | FPSR_CC_N); - c->tcond = TCG_COND_NE; + imm = FPSR_CC_Z | FPSR_CC_N; + c->tcond = TCG_COND_TSTNE; break; case 6: /* Ordered Greater or Less than !(A || Z) */ case 22: /* Greater or Less than !(A || Z) */ - c->v1 = tcg_temp_new(); - tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z); - c->tcond = TCG_COND_EQ; + imm = FPSR_CC_A | FPSR_CC_Z; + c->tcond = TCG_COND_TSTEQ; break; case 7: /* Ordered !A */ case 23: /* Greater, Less or Equal !A */ - c->v1 = tcg_temp_new(); - tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A); - c->tcond = TCG_COND_EQ; + imm = FPSR_CC_A; + c->tcond = TCG_COND_TSTEQ; break; case 8: /* Unordered A */ case 24: /* Not Greater, Less or Equal A */ - c->v1 = tcg_temp_new(); - tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A); - c->tcond = TCG_COND_NE; + imm = FPSR_CC_A; + c->tcond = TCG_COND_TSTNE; break; case 9: /* Unordered or Equal A || Z */ case 25: /* Not Greater or Less then A || Z */ - c->v1 = tcg_temp_new(); - tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z); - c->tcond = TCG_COND_NE; + imm = FPSR_CC_A | FPSR_CC_Z; + c->tcond = TCG_COND_TSTNE; break; case 10: /* Unordered or Greater Than A || !(N || Z)) */ case 26: /* Not Less or Equal A || !(N || Z)) */ c->v1 = tcg_temp_new(); tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z); tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_Z)); - tcg_gen_andi_i32(fpsr, fpsr, FPSR_CC_A | FPSR_CC_N); tcg_gen_or_i32(c->v1, c->v1, fpsr); tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N); - c->tcond = TCG_COND_NE; + imm = FPSR_CC_A | FPSR_CC_N; + c->tcond = TCG_COND_TSTNE; break; case 11: /* Unordered or Greater or Equal A || Z || !N */ case 27: /* Not Less Than A || Z || !N */ c->v1 = tcg_temp_new(); - tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); - tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N); - c->tcond = TCG_COND_NE; + tcg_gen_xori_i32(c->v1, fpsr, FPSR_CC_N); + imm = FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N; + c->tcond = TCG_COND_TSTNE; break; case 12: /* Unordered or Less Than A || (N && !Z) */ case 28: /* Not Greater than or Equal A || (N && !Z) */ @@ -5226,27 +5220,25 @@ static void gen_fcc_cond(DisasCompare *c, DisasContext *s, int cond) tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z); tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_Z)); tcg_gen_andc_i32(c->v1, fpsr, c->v1); - tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_A | FPSR_CC_N); - c->tcond = TCG_COND_NE; + imm = FPSR_CC_A | FPSR_CC_N; + c->tcond = TCG_COND_TSTNE; break; case 13: /* Unordered or Less or Equal A || Z || N */ case 29: /* Not Greater Than A || Z || N */ - c->v1 = tcg_temp_new(); - tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N); - c->tcond = TCG_COND_NE; + imm = FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N; + c->tcond = TCG_COND_TSTNE; break; case 14: /* Not Equal !Z */ case 30: /* Signaling Not Equal !Z */ - c->v1 = tcg_temp_new(); - tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z); - c->tcond = TCG_COND_EQ; + imm = FPSR_CC_Z; + c->tcond = TCG_COND_TSTEQ; break; case 15: /* True */ case 31: /* Signaling True */ - c->v1 = c->v2; c->tcond = TCG_COND_ALWAYS; break; } + c->v2 = tcg_constant_i32(imm); } static void gen_fjmpcc(DisasContext *s, int cond, TCGLabel *l1) diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c index 7dbb47de64..36e465b390 100644 --- a/target/ppc/cpu-models.c +++ b/target/ppc/cpu-models.c @@ -716,11 +716,11 @@ "PowerPC 970MP v1.0") POWERPC_DEF("970mp_v1.1", CPU_POWERPC_970MP_v11, 970, "PowerPC 970MP v1.1") - POWERPC_DEF("power5+_v2.1", CPU_POWERPC_POWER5P_v21, POWER5P, + POWERPC_DEF("power5p_v2.1", CPU_POWERPC_POWER5P_v21, POWER5P, "POWER5+ v2.1") POWERPC_DEF("power7_v2.3", CPU_POWERPC_POWER7_v23, POWER7, "POWER7 v2.3") - POWERPC_DEF("power7+_v2.1", CPU_POWERPC_POWER7P_v21, POWER7, + POWERPC_DEF("power7p_v2.1", CPU_POWERPC_POWER7P_v21, POWER7, "POWER7+ v2.1") POWERPC_DEF("power8e_v2.1", CPU_POWERPC_POWER8E_v21, POWER8, "POWER8E v2.1") @@ -902,10 +902,12 @@ PowerPCCPUAlias ppc_cpu_aliases[] = { { "970", "970_v2.2" }, { "970fx", "970fx_v3.1" }, { "970mp", "970mp_v1.1" }, - { "power5+", "power5+_v2.1" }, + { "power5+", "power5p_v2.1" }, + { "power5+_v2.1", "power5p_v2.1" }, { "power5gs", "power5+_v2.1" }, { "power7", "power7_v2.3" }, - { "power7+", "power7+_v2.1" }, + { "power7+", "power7p_v2.1" }, + { "power7+_v2.1", "power7p_v2.1" }, { "power8e", "power8e_v2.1" }, { "power8", "power8_v2.0" }, { "power8nvl", "power8nvl_v1.0" }, diff --git a/target/s390x/cpu-dump.c b/target/s390x/cpu-dump.c index ffa9e94d84..69cc9f7746 100644 --- a/target/s390x/cpu-dump.c +++ b/target/s390x/cpu-dump.c @@ -27,8 +27,7 @@ void s390_cpu_dump_state(CPUState *cs, FILE *f, int flags) { - S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; + CPUS390XState *env = cpu_env(cs); int i; qemu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64, diff --git a/target/s390x/gdbstub.c b/target/s390x/gdbstub.c index 6fbfd41bc8..f02fa316e5 100644 --- a/target/s390x/gdbstub.c +++ b/target/s390x/gdbstub.c @@ -30,8 +30,7 @@ int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) { - S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; + CPUS390XState *env = cpu_env(cs); switch (n) { case S390_PSWM_REGNUM: @@ -46,8 +45,7 @@ int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { - S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; + CPUS390XState *env = cpu_env(cs); target_ulong tmpl = ldtul_p(mem_buf); switch (n) { diff --git a/target/s390x/helper.c b/target/s390x/helper.c index d76c06381b..00d5d403f3 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -139,8 +139,7 @@ void do_restart_interrupt(CPUS390XState *env) void s390_cpu_recompute_watchpoints(CPUState *cs) { const int wp_flags = BP_CPU | BP_MEM_WRITE | BP_STOP_BEFORE_ACCESS; - S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; + CPUS390XState *env = cpu_env(cs); /* We are called when the watchpoints have changed. First remove them all. */ diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 05102578fc..cc1c20e9e3 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -88,7 +88,10 @@ DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_RWG_SE, i32, env, i128, i64) DEF_HELPER_FLAGS_2(sqeb, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_2(sqdb, TCG_CALL_NO_WG, i64, env, i64) DEF_HELPER_FLAGS_2(sqxb, TCG_CALL_NO_WG, i128, env, i128) +DEF_HELPER_3(cvb, void, env, i32, i64) +DEF_HELPER_FLAGS_2(cvbg, TCG_CALL_NO_WG, i64, env, i128) DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32) +DEF_HELPER_FLAGS_1(cvdg, TCG_CALL_NO_RWG_SE, i128, s64) DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_WG, void, env, i32, i64, i64) DEF_HELPER_FLAGS_4(pka, TCG_CALL_NO_WG, void, env, i64, i64, i32) DEF_HELPER_FLAGS_4(pku, TCG_CALL_NO_WG, void, env, i64, i64, i32) diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c index 888d6c1a1c..4ce809c5d4 100644 --- a/target/s390x/kvm/kvm.c +++ b/target/s390x/kvm/kvm.c @@ -474,8 +474,7 @@ static int can_sync_regs(CPUState *cs, int regs) int kvm_arch_put_registers(CPUState *cs, int level) { - S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; + CPUS390XState *env = cpu_env(cs); struct kvm_fpu fpu = {}; int r; int i; @@ -601,8 +600,7 @@ int kvm_arch_put_registers(CPUState *cs, int level) int kvm_arch_get_registers(CPUState *cs) { - S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; + CPUS390XState *env = cpu_env(cs); struct kvm_fpu fpu; int i, r; diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c index b875bf14e5..f1c33f7967 100644 --- a/target/s390x/tcg/excp_helper.c +++ b/target/s390x/tcg/excp_helper.c @@ -90,10 +90,7 @@ void HELPER(data_exception)(CPUS390XState *env, uint32_t dxc) static G_NORETURN void do_unaligned_access(CPUState *cs, uintptr_t retaddr) { - S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; - - tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr); + tcg_s390_program_interrupt(cpu_env(cs), PGM_SPECIFICATION, retaddr); } #if defined(CONFIG_USER_ONLY) @@ -146,8 +143,7 @@ bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr) { - S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; + CPUS390XState *env = cpu_env(cs); target_ulong vaddr, raddr; uint64_t asc, tec; int prot, excp; @@ -600,8 +596,7 @@ bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request) void s390x_cpu_debug_excp_handler(CPUState *cs) { - S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; + CPUS390XState *env = cpu_env(cs); CPUWatchpoint *wp_hit = cs->watchpoint_hit; if (wp_hit && wp_hit->flags & BP_CPU) { diff --git a/target/s390x/tcg/insn-data.h.inc b/target/s390x/tcg/insn-data.h.inc index 2f07f39d9c..e7d61cdec2 100644 --- a/target/s390x/tcg/insn-data.h.inc +++ b/target/s390x/tcg/insn-data.h.inc @@ -293,9 +293,14 @@ D(0xec73, CLFIT, RIE_a, GIE, r1_32u, i2_16u, 0, 0, ct, 0, 1) D(0xec71, CLGIT, RIE_a, GIE, r1_o, i2_16u, 0, 0, ct, 0, 1) +/* CONVERT TO BINARY */ + C(0x4f00, CVB, RX_a, Z, la2, 0, 0, 0, cvb, 0) + C(0xe306, CVBY, RXY_a, LD, la2, 0, 0, 0, cvb, 0) + C(0xe30e, CVBG, RXY_a, Z, la2, 0, r1, 0, cvbg, 0) /* CONVERT TO DECIMAL */ C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0) C(0xe326, CVDY, RXY_a, LD, r1_o, a2, 0, 0, cvd, 0) + C(0xe32e, CVDG, RXY_a, Z, r1_o, a2, 0, 0, cvdg, 0) /* CONVERT TO FIXED */ F(0xb398, CFEBR, RRF_e, Z, 0, e2, new, r1_32, cfeb, 0, IF_BFP) F(0xb399, CFDBR, RRF_e, Z, 0, f2, new, r1_32, cfdb, 0, IF_BFP) diff --git a/target/s390x/tcg/int_helper.c b/target/s390x/tcg/int_helper.c index eb8e6dd1b5..2af970f2c8 100644 --- a/target/s390x/tcg/int_helper.c +++ b/target/s390x/tcg/int_helper.c @@ -25,6 +25,7 @@ #include "exec/exec-all.h" #include "qemu/host-utils.h" #include "exec/helper-proto.h" +#include "exec/cpu_ldst.h" /* #define DEBUG_HELPER */ #ifdef DEBUG_HELPER @@ -98,6 +99,81 @@ Int128 HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t b) tcg_s390_program_interrupt(env, PGM_FIXPT_DIVIDE, GETPC()); } +void HELPER(cvb)(CPUS390XState *env, uint32_t r1, uint64_t dec) +{ + int64_t pow10 = 1, bin = 0; + int digit, sign; + + sign = dec & 0xf; + if (sign < 0xa) { + tcg_s390_data_exception(env, 0, GETPC()); + } + dec >>= 4; + + while (dec) { + digit = dec & 0xf; + if (digit > 0x9) { + tcg_s390_data_exception(env, 0, GETPC()); + } + dec >>= 4; + bin += digit * pow10; + pow10 *= 10; + } + + if (sign == 0xb || sign == 0xd) { + bin = -bin; + } + + /* R1 is updated even on fixed-point-divide exception. */ + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (uint32_t)bin; + if (bin != (int32_t)bin) { + tcg_s390_program_interrupt(env, PGM_FIXPT_DIVIDE, GETPC()); + } +} + +uint64_t HELPER(cvbg)(CPUS390XState *env, Int128 dec) +{ + uint64_t dec64[] = {int128_getlo(dec), int128_gethi(dec)}; + int64_t bin = 0, pow10, tmp; + int digit, i, sign; + + sign = dec64[0] & 0xf; + if (sign < 0xa) { + tcg_s390_data_exception(env, 0, GETPC()); + } + dec64[0] >>= 4; + pow10 = (sign == 0xb || sign == 0xd) ? -1 : 1; + + for (i = 1; i < 20; i++) { + digit = dec64[i >> 4] & 0xf; + if (digit > 0x9) { + tcg_s390_data_exception(env, 0, GETPC()); + } + dec64[i >> 4] >>= 4; + /* + * Prepend the next digit and check for overflow. The multiplication + * cannot overflow, since, conveniently, the int64_t limits are + * approximately +-9.2E+18. If bin is zero, the addition cannot + * overflow. Otherwise bin is known to have the same sign as the rhs + * addend, in which case overflow happens if and only if the result + * has a different sign. + */ + tmp = bin + pow10 * digit; + if (bin && ((tmp ^ bin) < 0)) { + tcg_s390_program_interrupt(env, PGM_FIXPT_DIVIDE, GETPC()); + } + bin = tmp; + pow10 *= 10; + } + + g_assert(!dec64[0]); + if (dec64[1]) { + tcg_s390_program_interrupt(env, PGM_FIXPT_DIVIDE, GETPC()); + } + + return bin; +} + uint64_t HELPER(cvd)(int32_t reg) { /* positive 0 */ @@ -118,6 +194,27 @@ uint64_t HELPER(cvd)(int32_t reg) return dec; } +Int128 HELPER(cvdg)(int64_t reg) +{ + /* positive 0 */ + Int128 dec = int128_make64(0x0c); + Int128 bin = int128_makes64(reg); + Int128 base = int128_make64(10); + int shift; + + if (!int128_nonneg(bin)) { + bin = int128_neg(bin); + dec = int128_make64(0x0d); + } + + for (shift = 4; (shift < 128) && int128_nz(bin); shift += 4) { + dec = int128_or(dec, int128_lshift(int128_remu(bin, base), shift)); + bin = int128_divu(bin, base); + } + + return dec; +} + uint64_t HELPER(popcnt)(uint64_t val) { /* Note that we don't fold past bytes. */ diff --git a/target/s390x/tcg/misc_helper.c b/target/s390x/tcg/misc_helper.c index 89b5268fd4..8764846ce8 100644 --- a/target/s390x/tcg/misc_helper.c +++ b/target/s390x/tcg/misc_helper.c @@ -214,9 +214,7 @@ void HELPER(sckc)(CPUS390XState *env, uint64_t ckc) void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque) { - S390CPU *cpu = S390_CPU(cs); - - update_ckc_timer(&cpu->env); + update_ckc_timer(cpu_env(cs)); } /* Set Clock */ diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index a5fd9cccaa..0d0c672c95 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -754,10 +754,10 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) case CC_OP_TM_64: switch (mask) { case 8: - cond = TCG_COND_EQ; + cond = TCG_COND_TSTEQ; break; case 4 | 2 | 1: - cond = TCG_COND_NE; + cond = TCG_COND_TSTNE; break; default: goto do_dynamic; @@ -768,11 +768,11 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) case CC_OP_ICM: switch (mask) { case 8: - cond = TCG_COND_EQ; + cond = TCG_COND_TSTEQ; break; case 4 | 2 | 1: case 4 | 2: - cond = TCG_COND_NE; + cond = TCG_COND_TSTNE; break; default: goto do_dynamic; @@ -854,18 +854,14 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) c->u.s64.a = cc_dst; c->u.s64.b = tcg_constant_i64(0); break; + case CC_OP_LTGT_64: case CC_OP_LTUGTU_64: - c->u.s64.a = cc_src; - c->u.s64.b = cc_dst; - break; - case CC_OP_TM_32: case CC_OP_TM_64: case CC_OP_ICM: - c->u.s64.a = tcg_temp_new_i64(); - c->u.s64.b = tcg_constant_i64(0); - tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst); + c->u.s64.a = cc_src; + c->u.s64.b = cc_dst; break; case CC_OP_ADDU: @@ -889,67 +885,45 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) case CC_OP_STATIC: c->is_64 = false; c->u.s32.a = cc_op; - switch (mask) { - case 0x8 | 0x4 | 0x2: /* cc != 3 */ - cond = TCG_COND_NE; + + /* Fold half of the cases using bit 3 to invert. */ + switch (mask & 8 ? mask ^ 0xf : mask) { + case 0x1: /* cc == 3 */ + cond = TCG_COND_EQ; c->u.s32.b = tcg_constant_i32(3); break; - case 0x8 | 0x4 | 0x1: /* cc != 2 */ - cond = TCG_COND_NE; - c->u.s32.b = tcg_constant_i32(2); - break; - case 0x8 | 0x2 | 0x1: /* cc != 1 */ - cond = TCG_COND_NE; - c->u.s32.b = tcg_constant_i32(1); - break; - case 0x8 | 0x2: /* cc == 0 || cc == 2 => (cc & 1) == 0 */ + case 0x2: /* cc == 2 */ cond = TCG_COND_EQ; - c->u.s32.a = tcg_temp_new_i32(); - c->u.s32.b = tcg_constant_i32(0); - tcg_gen_andi_i32(c->u.s32.a, cc_op, 1); - break; - case 0x8 | 0x4: /* cc < 2 */ - cond = TCG_COND_LTU; c->u.s32.b = tcg_constant_i32(2); break; - case 0x8: /* cc == 0 */ - cond = TCG_COND_EQ; - c->u.s32.b = tcg_constant_i32(0); - break; - case 0x4 | 0x2 | 0x1: /* cc != 0 */ - cond = TCG_COND_NE; - c->u.s32.b = tcg_constant_i32(0); - break; - case 0x4 | 0x1: /* cc == 1 || cc == 3 => (cc & 1) != 0 */ - cond = TCG_COND_NE; - c->u.s32.a = tcg_temp_new_i32(); - c->u.s32.b = tcg_constant_i32(0); - tcg_gen_andi_i32(c->u.s32.a, cc_op, 1); - break; case 0x4: /* cc == 1 */ cond = TCG_COND_EQ; c->u.s32.b = tcg_constant_i32(1); break; - case 0x2 | 0x1: /* cc > 1 */ + case 0x2 | 0x1: /* cc == 2 || cc == 3 => cc > 1 */ cond = TCG_COND_GTU; c->u.s32.b = tcg_constant_i32(1); break; - case 0x2: /* cc == 2 */ - cond = TCG_COND_EQ; - c->u.s32.b = tcg_constant_i32(2); + case 0x4 | 0x1: /* cc == 1 || cc == 3 => (cc & 1) != 0 */ + cond = TCG_COND_TSTNE; + c->u.s32.b = tcg_constant_i32(1); break; - case 0x1: /* cc == 3 */ - cond = TCG_COND_EQ; - c->u.s32.b = tcg_constant_i32(3); + case 0x4 | 0x2: /* cc == 1 || cc == 2 => (cc - 1) <= 1 */ + cond = TCG_COND_LEU; + c->u.s32.a = tcg_temp_new_i32(); + c->u.s32.b = tcg_constant_i32(1); + tcg_gen_addi_i32(c->u.s32.a, cc_op, -1); break; - default: - /* CC is masked by something else: (8 >> cc) & mask. */ + case 0x4 | 0x2 | 0x1: /* cc != 0 */ cond = TCG_COND_NE; - c->u.s32.a = tcg_temp_new_i32(); c->u.s32.b = tcg_constant_i32(0); - tcg_gen_shr_i32(c->u.s32.a, tcg_constant_i32(8), cc_op); - tcg_gen_andi_i32(c->u.s32.a, c->u.s32.a, mask); break; + default: + /* case 0: never, handled above. */ + g_assert_not_reached(); + } + if (mask & 8) { + cond = tcg_invert_cond(cond); } break; @@ -2223,6 +2197,22 @@ static DisasJumpType op_csp(DisasContext *s, DisasOps *o) } #endif +static DisasJumpType op_cvb(DisasContext *s, DisasOps *o) +{ + TCGv_i64 t = tcg_temp_new_i64(); + tcg_gen_qemu_ld_i64(t, o->addr1, get_mem_index(s), MO_TEUQ); + gen_helper_cvb(tcg_env, tcg_constant_i32(get_field(s, r1)), t); + return DISAS_NEXT; +} + +static DisasJumpType op_cvbg(DisasContext *s, DisasOps *o) +{ + TCGv_i128 t = tcg_temp_new_i128(); + tcg_gen_qemu_ld_i128(t, o->addr1, get_mem_index(s), MO_TE | MO_128); + gen_helper_cvbg(o->out, tcg_env, t); + return DISAS_NEXT; +} + static DisasJumpType op_cvd(DisasContext *s, DisasOps *o) { TCGv_i64 t1 = tcg_temp_new_i64(); @@ -2233,6 +2223,14 @@ static DisasJumpType op_cvd(DisasContext *s, DisasOps *o) return DISAS_NEXT; } +static DisasJumpType op_cvdg(DisasContext *s, DisasOps *o) +{ + TCGv_i128 t = tcg_temp_new_i128(); + gen_helper_cvdg(t, o->in1); + tcg_gen_qemu_st_i128(t, o->in2, get_mem_index(s), MO_TE | MO_128); + return DISAS_NEXT; +} + static DisasJumpType op_ct(DisasContext *s, DisasOps *o) { int m3 = get_field(s, m3); @@ -6558,8 +6556,7 @@ void s390x_restore_state_to_opc(CPUState *cs, const TranslationBlock *tb, const uint64_t *data) { - S390CPU *cpu = S390_CPU(cs); - CPUS390XState *env = &cpu->env; + CPUS390XState *env = cpu_env(cs); int cc_op = data[1]; env->psw.addr = data[0]; diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 7df6f83b13..d9304a5bc4 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -488,6 +488,7 @@ static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2) static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) { TCGv zero = tcg_constant_tl(0); + TCGv one = tcg_constant_tl(1); TCGv t_src1 = tcg_temp_new(); TCGv t_src2 = tcg_temp_new(); TCGv t0 = tcg_temp_new(); @@ -499,8 +500,7 @@ static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) * if (!(env->y & 1)) * src2 = 0; */ - tcg_gen_andi_tl(t0, cpu_y, 0x1); - tcg_gen_movcond_tl(TCG_COND_EQ, t_src2, t0, zero, zero, t_src2); + tcg_gen_movcond_tl(TCG_COND_TSTEQ, t_src2, cpu_y, one, zero, t_src2); /* * b2 = src1 & 1; |