Cleanup alpha, hppa, or1k wrt tcg_constant_tl.

Implement x86 fcs:fip, fds:fdp.
 Trivial x86 watchpoint cleanup.
 -----BEGIN PGP SIGNATURE-----
 
 iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmDtwQ0dHHJpY2hhcmQu
 aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV/GnAf/SYNhdmIuKCWk/uk8
 IC0v2sm5KHVFfkfkobQ+04pFB26tX557i2zTtEfj/A5QVlJSvliZowCVIO6JV63N
 9oedLSzdqrxRqDb+Mpmkwnam/k5XfrC20V7os17FuZE98u3Jgky8QNs7Uxq0bCBZ
 01AKB9HNRFKeY2o55IxPwC7CLtyz3SStJJP28aa5ROYK7MIP303qsI5pezgkHgGo
 /qo5GXwHs/Pu4pnFuAJyOfG38wT6uTt7NrAGjTH0VhbAKNMSP/QND+VvxbuCugZR
 6MEVeb+rLy+MN4b3dH6kI89JQvQGBCaWZD/eTF5+8UDPj3I8vpRqufRh8l5WukT1
 Q2g1zA==
 =eqkT
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-misc-20210713' into staging

Cleanup alpha, hppa, or1k wrt tcg_constant_tl.
Implement x86 fcs:fip, fds:fdp.
Trivial x86 watchpoint cleanup.

# gpg: Signature made Tue 13 Jul 2021 17:36:29 BST
# gpg:                using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg:                issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full]
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A  05C0 64DF 38E8 AF7E 215F

* remotes/rth-gitlab/tags/pull-misc-20210713:
  target/hppa: Clean up DisasCond
  target/hppa: Use tcg_constant_*
  target/openrisc: Use dc->zero in gen_add, gen_addc
  target/openrisc: Cache constant 0 in DisasContext
  target/openrisc: Use tcg_constant_tl for dc->R0
  target/openrisc: Use tcg_constant_*
  target/alpha: Use tcg_constant_* elsewhere
  target/alpha: Use tcg_constant_i64 for zero and lit
  target/alpha: Use dest_sink for HW_RET temporary
  target/alpha: Store set into rx flag
  target/i386: Correct implementation for FCS, FIP, FDS and FDP
  target/i386: Split out do_fninit
  target/i386: Trivial code motion and code style fix
  target/i386: Tidy hw_breakpoint_remove

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-07-14 14:12:08 +01:00
commit 20a9676179
7 changed files with 599 additions and 656 deletions

View file

@ -66,8 +66,6 @@ struct DisasContext {
/* Temporaries for $31 and $f31 as source and destination. */
TCGv zero;
TCGv sink;
/* Temporary for immediate constants. */
TCGv lit;
};
/* Target-specific return values from translate_one, indicating the
@ -157,7 +155,7 @@ void alpha_translate_init(void)
static TCGv load_zero(DisasContext *ctx)
{
if (!ctx->zero) {
ctx->zero = tcg_const_i64(0);
ctx->zero = tcg_constant_i64(0);
}
return ctx->zero;
}
@ -177,14 +175,6 @@ static void free_context_temps(DisasContext *ctx)
tcg_temp_free(ctx->sink);
ctx->sink = NULL;
}
if (ctx->zero) {
tcg_temp_free(ctx->zero);
ctx->zero = NULL;
}
if (ctx->lit) {
tcg_temp_free(ctx->lit);
ctx->lit = NULL;
}
}
static TCGv load_gpr(DisasContext *ctx, unsigned reg)
@ -200,8 +190,7 @@ static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
uint8_t lit, bool islit)
{
if (islit) {
ctx->lit = tcg_const_i64(lit);
return ctx->lit;
return tcg_constant_i64(lit);
} else if (likely(reg < 31)) {
return ctx->ir[reg];
} else {
@ -261,11 +250,9 @@ static void gen_excp_1(int exception, int error_code)
{
TCGv_i32 tmp1, tmp2;
tmp1 = tcg_const_i32(exception);
tmp2 = tcg_const_i32(error_code);
tmp1 = tcg_constant_i32(exception);
tmp2 = tcg_constant_i32(error_code);
gen_helper_excp(cpu_env, tmp1, tmp2);
tcg_temp_free_i32(tmp2);
tcg_temp_free_i32(tmp1);
}
static DisasJumpType gen_excp(DisasContext *ctx, int exception, int error_code)
@ -485,15 +472,11 @@ static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond,
return DISAS_NORETURN;
} else {
TCGv_i64 z = tcg_const_i64(0);
TCGv_i64 d = tcg_const_i64(dest);
TCGv_i64 p = tcg_const_i64(ctx->base.pc_next);
TCGv_i64 z = load_zero(ctx);
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_temp_free_i64(z);
tcg_temp_free_i64(d);
tcg_temp_free_i64(p);
return DISAS_PC_UPDATED;
}
}
@ -695,22 +678,19 @@ static void gen_fp_exc_raise(int rc, int fn11)
if (!(fn11 & QUAL_I)) {
ignore |= FPCR_INE;
}
ign = tcg_const_i32(ignore);
ign = tcg_constant_i32(ignore);
/* ??? Pass in the regno of the destination so that the helper can
set EXC_MASK, which contains a bitmask of destination registers
that have caused arithmetic traps. A simple userspace emulation
does not require this. We do need it for a guest kernel's entArith,
or if we were to do something clever with imprecise exceptions. */
reg = tcg_const_i32(rc + 32);
reg = tcg_constant_i32(rc + 32);
if (fn11 & QUAL_S) {
gen_helper_fp_exc_raise_s(cpu_env, ign, reg);
} else {
gen_helper_fp_exc_raise(cpu_env, ign, reg);
}
tcg_temp_free_i32(reg);
tcg_temp_free_i32(ign);
}
static void gen_cvtlq(TCGv vc, TCGv vb)
@ -803,7 +783,7 @@ IEEE_INTCVT(cvtqt)
static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask)
{
TCGv vmask = tcg_const_i64(mask);
TCGv vmask = tcg_constant_i64(mask);
TCGv tmp = tcg_temp_new_i64();
if (inv_a) {
@ -815,7 +795,6 @@ static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask)
tcg_gen_andc_i64(vc, vb, vmask);
tcg_gen_or_i64(vc, vc, tmp);
tcg_temp_free(vmask);
tcg_temp_free(tmp);
}
@ -1084,15 +1063,11 @@ static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
static void gen_rx(DisasContext *ctx, int ra, int set)
{
TCGv tmp;
if (ra != 31) {
ld_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
}
tmp = tcg_const_i64(set);
st_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
tcg_temp_free(tmp);
st_flag_byte(tcg_constant_i64(set), ENV_FLAG_RX_SHIFT);
}
static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode)
@ -1193,12 +1168,9 @@ static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode)
case 0x3E:
/* WTINT */
{
TCGv_i32 tmp = tcg_const_i32(1);
tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) +
offsetof(CPUState, halted));
tcg_temp_free_i32(tmp);
}
tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
-offsetof(AlphaCPU, env) +
offsetof(CPUState, halted));
tcg_gen_movi_i64(ctx->ir[IR_V0], 0);
return gen_excp(ctx, EXCP_HALTED, 0);
@ -1349,12 +1321,8 @@ static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
case 253:
/* WAIT */
{
TCGv_i32 tmp = tcg_const_i32(1);
tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) +
offsetof(CPUState, halted));
tcg_temp_free_i32(tmp);
}
tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
-offsetof(AlphaCPU, env) + offsetof(CPUState, halted));
return gen_excp(ctx, EXCP_HALTED, 0);
case 252:
@ -2721,15 +2689,14 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
/* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
address from EXC_ADDR. This turns out to be useful for our
emulation PALcode, so continue to accept it. */
ctx->lit = vb = tcg_temp_new();
vb = dest_sink(ctx);
tcg_gen_ld_i64(vb, cpu_env, offsetof(CPUAlphaState, exc_addr));
} else {
vb = load_gpr(ctx, rb);
}
tcg_gen_movi_i64(cpu_lock_addr, -1);
st_flag_byte(load_zero(ctx), ENV_FLAG_RX_SHIFT);
tmp = tcg_temp_new();
tcg_gen_movi_i64(tmp, 0);
st_flag_byte(tmp, ENV_FLAG_RX_SHIFT);
tcg_gen_andi_i64(tmp, vb, 1);
st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
tcg_temp_free(tmp);
@ -2996,7 +2963,6 @@ static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
ctx->zero = NULL;
ctx->sink = NULL;
ctx->lit = NULL;
/* Bound the number of insns to execute to those left on the page. */
bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;

View file

@ -144,6 +144,7 @@
#define tcg_gen_sextract_reg tcg_gen_sextract_i64
#define tcg_const_reg tcg_const_i64
#define tcg_const_local_reg tcg_const_local_i64
#define tcg_constant_reg tcg_constant_i64
#define tcg_gen_movcond_reg tcg_gen_movcond_i64
#define tcg_gen_add2_reg tcg_gen_add2_i64
#define tcg_gen_sub2_reg tcg_gen_sub2_i64
@ -238,6 +239,7 @@
#define tcg_gen_sextract_reg tcg_gen_sextract_i32
#define tcg_const_reg tcg_const_i32
#define tcg_const_local_reg tcg_const_local_i32
#define tcg_constant_reg tcg_constant_i32
#define tcg_gen_movcond_reg tcg_gen_movcond_i32
#define tcg_gen_add2_reg tcg_gen_add2_i32
#define tcg_gen_sub2_reg tcg_gen_sub2_i32
@ -250,8 +252,6 @@
typedef struct DisasCond {
TCGCond c;
TCGv_reg a0, a1;
bool a0_is_n;
bool a1_is_0;
} DisasCond;
typedef struct DisasContext {
@ -446,9 +446,7 @@ static DisasCond cond_make_n(void)
return (DisasCond){
.c = TCG_COND_NE,
.a0 = cpu_psw_n,
.a0_is_n = true,
.a1 = NULL,
.a1_is_0 = true
.a1 = tcg_constant_reg(0)
};
}
@ -456,7 +454,7 @@ static DisasCond cond_make_0_tmp(TCGCond c, TCGv_reg a0)
{
assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
return (DisasCond){
.c = c, .a0 = a0, .a1_is_0 = true
.c = c, .a0 = a0, .a1 = tcg_constant_reg(0)
};
}
@ -480,26 +478,14 @@ static DisasCond cond_make(TCGCond c, TCGv_reg a0, TCGv_reg a1)
return r;
}
static void cond_prep(DisasCond *cond)
{
if (cond->a1_is_0) {
cond->a1_is_0 = false;
cond->a1 = tcg_const_reg(0);
}
}
static void cond_free(DisasCond *cond)
{
switch (cond->c) {
default:
if (!cond->a0_is_n) {
if (cond->a0 != cpu_psw_n) {
tcg_temp_free(cond->a0);
}
if (!cond->a1_is_0) {
tcg_temp_free(cond->a1);
}
cond->a0_is_n = false;
cond->a1_is_0 = false;
tcg_temp_free(cond->a1);
cond->a0 = NULL;
cond->a1 = NULL;
/* fallthru */
@ -557,9 +543,8 @@ static TCGv_reg dest_gpr(DisasContext *ctx, unsigned reg)
static void save_or_nullify(DisasContext *ctx, TCGv_reg dest, TCGv_reg t)
{
if (ctx->null_cond.c != TCG_COND_NEVER) {
cond_prep(&ctx->null_cond);
tcg_gen_movcond_reg(ctx->null_cond.c, dest, ctx->null_cond.a0,
ctx->null_cond.a1, dest, t);
ctx->null_cond.a1, dest, t);
} else {
tcg_gen_mov_reg(dest, t);
}
@ -666,11 +651,9 @@ static void nullify_over(DisasContext *ctx)
assert(ctx->null_cond.c != TCG_COND_ALWAYS);
ctx->null_lab = gen_new_label();
cond_prep(&ctx->null_cond);
/* If we're using PSW[N], copy it to a temp because... */
if (ctx->null_cond.a0_is_n) {
ctx->null_cond.a0_is_n = false;
if (ctx->null_cond.a0 == cpu_psw_n) {
ctx->null_cond.a0 = tcg_temp_new();
tcg_gen_mov_reg(ctx->null_cond.a0, cpu_psw_n);
}
@ -683,7 +666,7 @@ static void nullify_over(DisasContext *ctx)
}
tcg_gen_brcond_reg(ctx->null_cond.c, ctx->null_cond.a0,
ctx->null_cond.a1, ctx->null_lab);
ctx->null_cond.a1, ctx->null_lab);
cond_free(&ctx->null_cond);
}
}
@ -697,10 +680,9 @@ static void nullify_save(DisasContext *ctx)
}
return;
}
if (!ctx->null_cond.a0_is_n) {
cond_prep(&ctx->null_cond);
if (ctx->null_cond.a0 != cpu_psw_n) {
tcg_gen_setcond_reg(ctx->null_cond.c, cpu_psw_n,
ctx->null_cond.a0, ctx->null_cond.a1);
ctx->null_cond.a0, ctx->null_cond.a1);
ctx->psw_n_nonzero = true;
}
cond_free(&ctx->null_cond);
@ -771,9 +753,7 @@ static inline target_ureg iaoq_dest(DisasContext *ctx, target_sreg disp)
static void gen_excp_1(int exception)
{
TCGv_i32 t = tcg_const_i32(exception);
gen_helper_excp(cpu_env, t);
tcg_temp_free_i32(t);
gen_helper_excp(cpu_env, tcg_constant_i32(exception));
}
static void gen_excp(DisasContext *ctx, int exception)
@ -787,12 +767,9 @@ static void gen_excp(DisasContext *ctx, int exception)
static bool gen_excp_iir(DisasContext *ctx, int exc)
{
TCGv_reg tmp;
nullify_over(ctx);
tmp = tcg_const_reg(ctx->insn);
tcg_gen_st_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[CR_IIR]));
tcg_temp_free(tmp);
tcg_gen_st_reg(tcg_constant_reg(ctx->insn),
cpu_env, offsetof(CPUHPPAState, cr[CR_IIR]));
gen_excp(ctx, exc);
return nullify_end(ctx);
}
@ -1150,13 +1127,12 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1,
}
if (!is_l || cond_need_cb(c)) {
TCGv_reg zero = tcg_const_reg(0);
TCGv_reg zero = tcg_constant_reg(0);
cb_msb = get_temp(ctx);
tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero);
if (is_c) {
tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero);
}
tcg_temp_free(zero);
if (!is_l) {
cb = get_temp(ctx);
tcg_gen_xor_reg(cb, in1, in2);
@ -1182,7 +1158,6 @@ static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1,
/* Emit any conditional trap before any writeback. */
cond = do_cond(cf, dest, cb_msb, sv);
if (is_tc) {
cond_prep(&cond);
tmp = tcg_temp_new();
tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
gen_helper_tcond(cpu_env, tmp);
@ -1242,7 +1217,7 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
cb = tcg_temp_new();
cb_msb = tcg_temp_new();
zero = tcg_const_reg(0);
zero = tcg_constant_reg(0);
if (is_b) {
/* DEST,C = IN1 + ~IN2 + C. */
tcg_gen_not_reg(cb, in2);
@ -1258,7 +1233,6 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
tcg_gen_eqv_reg(cb, in1, in2);
tcg_gen_xor_reg(cb, cb, dest);
}
tcg_temp_free(zero);
/* Compute signed overflow if required. */
sv = NULL;
@ -1278,7 +1252,6 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
/* Emit any conditional trap before any writeback. */
if (is_tc) {
cond_prep(&cond);
tmp = tcg_temp_new();
tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
gen_helper_tcond(cpu_env, tmp);
@ -1404,7 +1377,6 @@ static void do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1,
if (is_tc) {
TCGv_reg tmp = tcg_temp_new();
cond_prep(&cond);
tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
gen_helper_tcond(cpu_env, tmp);
tcg_temp_free(tmp);
@ -1860,7 +1832,6 @@ static bool do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n,
}
taken = gen_new_label();
cond_prep(cond);
tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken);
cond_free(cond);
@ -1957,7 +1928,6 @@ static bool do_ibranch(DisasContext *ctx, TCGv_reg dest,
tcg_gen_lookup_and_goto_ptr();
return nullify_end(ctx);
} else {
cond_prep(&ctx->null_cond);
c = ctx->null_cond.c;
a0 = ctx->null_cond.a0;
a1 = ctx->null_cond.a1;
@ -2449,17 +2419,16 @@ static bool trans_probe(DisasContext *ctx, arg_probe *a)
form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
if (a->imm) {
level = tcg_const_i32(a->ri);
level = tcg_constant_i32(a->ri);
} else {
level = tcg_temp_new_i32();
tcg_gen_trunc_reg_i32(level, load_gpr(ctx, a->ri));
tcg_gen_andi_i32(level, level, 3);
}
want = tcg_const_i32(a->write ? PAGE_WRITE : PAGE_READ);
want = tcg_constant_i32(a->write ? PAGE_WRITE : PAGE_READ);
gen_helper_probe(dest, cpu_env, addr, level, want);
tcg_temp_free_i32(want);
tcg_temp_free_i32(level);
save_gpr(ctx, a->t, dest);
@ -2599,17 +2568,13 @@ static bool trans_lpa(DisasContext *ctx, arg_ldst *a)
static bool trans_lci(DisasContext *ctx, arg_lci *a)
{
TCGv_reg ci;
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
/* The Coherence Index is an implementation-defined function of the
physical address. Two addresses with the same CI have a coherent
view of the cache. Our implementation is to return 0 for all,
since the entire address space is coherent. */
ci = tcg_const_reg(0);
save_gpr(ctx, a->t, ci);
tcg_temp_free(ci);
save_gpr(ctx, a->t, tcg_constant_reg(0));
cond_free(&ctx->null_cond);
return true;
@ -2710,8 +2675,6 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf *a)
* currently implemented as idle.
*/
if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */
TCGv_i32 tmp;
/* No need to check for supervisor, as userland can only pause
until the next timer interrupt. */
nullify_over(ctx);
@ -2722,10 +2685,8 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf *a)
nullify_set(ctx, 0);
/* Tell the qemu main loop to halt until this cpu has work. */
tmp = tcg_const_i32(1);
tcg_gen_st_i32(tmp, cpu_env, -offsetof(HPPACPU, env) +
offsetof(CPUState, halted));
tcg_temp_free_i32(tmp);
tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
offsetof(CPUState, halted) - offsetof(HPPACPU, env));
gen_excp_1(EXCP_HALTED);
ctx->base.is_jmp = DISAS_NORETURN;
@ -2833,7 +2794,7 @@ static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
add2 = tcg_temp_new();
addc = tcg_temp_new();
dest = tcg_temp_new();
zero = tcg_const_reg(0);
zero = tcg_constant_reg(0);
/* Form R1 << 1 | PSW[CB]{8}. */
tcg_gen_add_reg(add1, in1, in1);
@ -2851,7 +2812,6 @@ static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
tcg_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero);
tcg_temp_free(addc);
tcg_temp_free(zero);
/* Write back the result register. */
save_gpr(ctx, a->t, dest);
@ -2967,9 +2927,8 @@ static bool trans_ldc(DisasContext *ctx, arg_ldst *a)
*/
gen_helper_ldc_check(addr);
zero = tcg_const_reg(0);
zero = tcg_constant_reg(0);
tcg_gen_atomic_xchg_reg(dest, addr, zero, ctx->mmu_idx, mop);
tcg_temp_free(zero);
if (a->m) {
save_gpr(ctx, a->b, ofs);
@ -3882,15 +3841,13 @@ static bool trans_fcmp_f(DisasContext *ctx, arg_fclass2 *a)
ta = load_frw0_i32(a->r1);
tb = load_frw0_i32(a->r2);
ty = tcg_const_i32(a->y);
tc = tcg_const_i32(a->c);
ty = tcg_constant_i32(a->y);
tc = tcg_constant_i32(a->c);
gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc);
tcg_temp_free_i32(ta);
tcg_temp_free_i32(tb);
tcg_temp_free_i32(ty);
tcg_temp_free_i32(tc);
return nullify_end(ctx);
}
@ -3904,15 +3861,13 @@ static bool trans_fcmp_d(DisasContext *ctx, arg_fclass2 *a)
ta = load_frd0(a->r1);
tb = load_frd0(a->r2);
ty = tcg_const_i32(a->y);
tc = tcg_const_i32(a->c);
ty = tcg_constant_i32(a->y);
tc = tcg_constant_i32(a->c);
gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc);
tcg_temp_free_i64(ta);
tcg_temp_free_i64(tb);
tcg_temp_free_i32(ty);
tcg_temp_free_i32(tc);
return nullify_end(ctx);
}

View file

@ -1437,6 +1437,8 @@ typedef struct CPUX86State {
FPReg fpregs[8];
/* KVM-only so far */
uint16_t fpop;
uint16_t fpcs;
uint16_t fpds;
uint64_t fpip;
uint64_t fpdp;

View file

@ -727,10 +727,14 @@ void helper_fwait(CPUX86State *env)
}
}
void helper_fninit(CPUX86State *env)
static void do_fninit(CPUX86State *env)
{
env->fpus = 0;
env->fpstt = 0;
env->fpcs = 0;
env->fpds = 0;
env->fpip = 0;
env->fpdp = 0;
cpu_set_fpuc(env, 0x37f);
env->fptags[0] = 1;
env->fptags[1] = 1;
@ -742,6 +746,11 @@ void helper_fninit(CPUX86State *env)
env->fptags[7] = 1;
}
void helper_fninit(CPUX86State *env)
{
do_fninit(env);
}
/* BCD ops */
void helper_fbld_ST0(CPUX86State *env, target_ulong ptr)
@ -2373,19 +2382,19 @@ static void do_fstenv(CPUX86State *env, target_ulong ptr, int data32,
cpu_stl_data_ra(env, ptr, env->fpuc, retaddr);
cpu_stl_data_ra(env, ptr + 4, fpus, retaddr);
cpu_stl_data_ra(env, ptr + 8, fptag, retaddr);
cpu_stl_data_ra(env, ptr + 12, 0, retaddr); /* fpip */
cpu_stl_data_ra(env, ptr + 16, 0, retaddr); /* fpcs */
cpu_stl_data_ra(env, ptr + 20, 0, retaddr); /* fpoo */
cpu_stl_data_ra(env, ptr + 24, 0, retaddr); /* fpos */
cpu_stl_data_ra(env, ptr + 12, env->fpip, retaddr); /* fpip */
cpu_stl_data_ra(env, ptr + 16, env->fpcs, retaddr); /* fpcs */
cpu_stl_data_ra(env, ptr + 20, env->fpdp, retaddr); /* fpoo */
cpu_stl_data_ra(env, ptr + 24, env->fpds, retaddr); /* fpos */
} else {
/* 16 bit */
cpu_stw_data_ra(env, ptr, env->fpuc, retaddr);
cpu_stw_data_ra(env, ptr + 2, fpus, retaddr);
cpu_stw_data_ra(env, ptr + 4, fptag, retaddr);
cpu_stw_data_ra(env, ptr + 6, 0, retaddr);
cpu_stw_data_ra(env, ptr + 8, 0, retaddr);
cpu_stw_data_ra(env, ptr + 10, 0, retaddr);
cpu_stw_data_ra(env, ptr + 12, 0, retaddr);
cpu_stw_data_ra(env, ptr + 6, env->fpip, retaddr);
cpu_stw_data_ra(env, ptr + 8, env->fpcs, retaddr);
cpu_stw_data_ra(env, ptr + 10, env->fpdp, retaddr);
cpu_stw_data_ra(env, ptr + 12, env->fpds, retaddr);
}
}
@ -2451,18 +2460,7 @@ static void do_fsave(CPUX86State *env, target_ulong ptr, int data32,
ptr += 10;
}
/* fninit */
env->fpus = 0;
env->fpstt = 0;
cpu_set_fpuc(env, 0x37f);
env->fptags[0] = 1;
env->fptags[1] = 1;
env->fptags[2] = 1;
env->fptags[3] = 1;
env->fptags[4] = 1;
env->fptags[5] = 1;
env->fptags[6] = 1;
env->fptags[7] = 1;
do_fninit(env);
}
void helper_fsave(CPUX86State *env, target_ulong ptr, int data32)
@ -2834,7 +2832,7 @@ void helper_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
if (xstate_bv & XSTATE_FP_MASK) {
do_xrstor_fpu(env, ptr, ra);
} else {
helper_fninit(env);
do_fninit(env);
memset(env->fpregs, 0, sizeof(env->fpregs));
}
}

View file

@ -109,9 +109,9 @@ static void hw_breakpoint_remove(CPUX86State *env, int index)
case DR7_TYPE_DATA_WR:
case DR7_TYPE_DATA_RW:
if (env->cpu_breakpoint[index]) {
if (env->cpu_watchpoint[index]) {
cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
env->cpu_breakpoint[index] = NULL;
env->cpu_watchpoint[index] = NULL;
}
break;

File diff suppressed because it is too large Load diff

View file

@ -52,6 +52,8 @@ typedef struct DisasContext {
/* The temporary corresponding to register 0 for this compilation. */
TCGv R0;
/* The constant zero. */
TCGv zero;
} DisasContext;
static inline bool is_user(DisasContext *dc)
@ -129,9 +131,7 @@ void openrisc_translate_init(void)
static void gen_exception(DisasContext *dc, unsigned int excp)
{
TCGv_i32 tmp = tcg_const_i32(excp);
gen_helper_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
gen_helper_exception(cpu_env, tcg_constant_i32(excp));
}
static void gen_illegal_exception(DisasContext *dc)
@ -199,10 +199,10 @@ static void gen_ove_cyov(DisasContext *dc)
static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
{
TCGv t0 = tcg_const_tl(0);
TCGv t0 = tcg_temp_new();
TCGv res = tcg_temp_new();
tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0);
tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, srcb, dc->zero);
tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
tcg_gen_xor_tl(t0, res, srcb);
tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
@ -216,11 +216,11 @@ static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
{
TCGv t0 = tcg_const_tl(0);
TCGv t0 = tcg_temp_new();
TCGv res = tcg_temp_new();
tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0);
tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, cpu_sr_cy, dc->zero);
tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, dc->zero);
tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
tcg_gen_xor_tl(t0, res, srcb);
tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
@ -538,13 +538,9 @@ static bool trans_l_extbz(DisasContext *dc, arg_da *a)
static bool trans_l_cmov(DisasContext *dc, arg_dab *a)
{
TCGv zero;
check_r0_write(dc, a->d);
zero = tcg_const_tl(0);
tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, zero,
tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, dc->zero,
cpu_R(dc, a->a), cpu_R(dc, a->b));
tcg_temp_free(zero);
return true;
}
@ -632,15 +628,10 @@ static bool trans_l_jal(DisasContext *dc, arg_l_jal *a)
static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond)
{
target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
TCGv t_next = tcg_const_tl(dc->base.pc_next + 8);
TCGv t_true = tcg_const_tl(tmp_pc);
TCGv t_zero = tcg_const_tl(0);
TCGv t_next = tcg_constant_tl(dc->base.pc_next + 8);
TCGv t_true = tcg_constant_tl(tmp_pc);
tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
tcg_temp_free(t_next);
tcg_temp_free(t_true);
tcg_temp_free(t_zero);
tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, dc->zero, t_true, t_next);
dc->delayed_branch = 2;
}
@ -740,12 +731,6 @@ static bool trans_l_swa(DisasContext *dc, arg_store *a)
ea = tcg_temp_new();
tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
/* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
to cpu_regs[0]. Since l.swa is quite often immediately followed by a
branch, don't bother reallocating; finish the TB using the "real" R0.
This also takes care of RB input across the branch. */
dc->R0 = cpu_regs[0];
lab_fail = gen_new_label();
lab_done = gen_new_label();
tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
@ -753,7 +738,7 @@ static bool trans_l_swa(DisasContext *dc, arg_store *a)
val = tcg_temp_new();
tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
cpu_regs[a->b], dc->mem_idx, MO_TEUL);
cpu_R(dc, a->b), dc->mem_idx, MO_TEUL);
tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
tcg_temp_free(val);
@ -813,44 +798,28 @@ static bool trans_l_adrp(DisasContext *dc, arg_l_adrp *a)
static bool trans_l_addi(DisasContext *dc, arg_rri *a)
{
TCGv t0;
check_r0_write(dc, a->d);
t0 = tcg_const_tl(a->i);
gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
tcg_temp_free(t0);
gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
return true;
}
static bool trans_l_addic(DisasContext *dc, arg_rri *a)
{
TCGv t0;
check_r0_write(dc, a->d);
t0 = tcg_const_tl(a->i);
gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
tcg_temp_free(t0);
gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
return true;
}
static bool trans_l_muli(DisasContext *dc, arg_rri *a)
{
TCGv t0;
check_r0_write(dc, a->d);
t0 = tcg_const_tl(a->i);
gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
tcg_temp_free(t0);
gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
return true;
}
static bool trans_l_maci(DisasContext *dc, arg_l_maci *a)
{
TCGv t0;
t0 = tcg_const_tl(a->i);
gen_mac(dc, cpu_R(dc, a->a), t0);
tcg_temp_free(t0);
gen_mac(dc, cpu_R(dc, a->a), tcg_constant_tl(a->i));
return true;
}
@ -1624,8 +1593,9 @@ static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
/* Allow the TCG optimizer to see that R0 == 0,
when it's true, which is the common case. */
dc->zero = tcg_constant_tl(0);
if (dc->tb_flags & TB_FLAGS_R0_0) {
dc->R0 = tcg_const_tl(0);
dc->R0 = dc->zero;
} else {
dc->R0 = cpu_regs[0];
}