mirror of https://github.com/xemu-project/xemu.git
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:
commit
20a9676179
|
@ -66,8 +66,6 @@ struct DisasContext {
|
||||||
/* Temporaries for $31 and $f31 as source and destination. */
|
/* Temporaries for $31 and $f31 as source and destination. */
|
||||||
TCGv zero;
|
TCGv zero;
|
||||||
TCGv sink;
|
TCGv sink;
|
||||||
/* Temporary for immediate constants. */
|
|
||||||
TCGv lit;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Target-specific return values from translate_one, indicating the
|
/* Target-specific return values from translate_one, indicating the
|
||||||
|
@ -157,7 +155,7 @@ void alpha_translate_init(void)
|
||||||
static TCGv load_zero(DisasContext *ctx)
|
static TCGv load_zero(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
if (!ctx->zero) {
|
if (!ctx->zero) {
|
||||||
ctx->zero = tcg_const_i64(0);
|
ctx->zero = tcg_constant_i64(0);
|
||||||
}
|
}
|
||||||
return ctx->zero;
|
return ctx->zero;
|
||||||
}
|
}
|
||||||
|
@ -177,14 +175,6 @@ static void free_context_temps(DisasContext *ctx)
|
||||||
tcg_temp_free(ctx->sink);
|
tcg_temp_free(ctx->sink);
|
||||||
ctx->sink = NULL;
|
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)
|
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)
|
uint8_t lit, bool islit)
|
||||||
{
|
{
|
||||||
if (islit) {
|
if (islit) {
|
||||||
ctx->lit = tcg_const_i64(lit);
|
return tcg_constant_i64(lit);
|
||||||
return ctx->lit;
|
|
||||||
} else if (likely(reg < 31)) {
|
} else if (likely(reg < 31)) {
|
||||||
return ctx->ir[reg];
|
return ctx->ir[reg];
|
||||||
} else {
|
} else {
|
||||||
|
@ -261,11 +250,9 @@ static void gen_excp_1(int exception, int error_code)
|
||||||
{
|
{
|
||||||
TCGv_i32 tmp1, tmp2;
|
TCGv_i32 tmp1, tmp2;
|
||||||
|
|
||||||
tmp1 = tcg_const_i32(exception);
|
tmp1 = tcg_constant_i32(exception);
|
||||||
tmp2 = tcg_const_i32(error_code);
|
tmp2 = tcg_constant_i32(error_code);
|
||||||
gen_helper_excp(cpu_env, tmp1, tmp2);
|
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)
|
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;
|
return DISAS_NORETURN;
|
||||||
} else {
|
} else {
|
||||||
TCGv_i64 z = tcg_const_i64(0);
|
TCGv_i64 z = load_zero(ctx);
|
||||||
TCGv_i64 d = tcg_const_i64(dest);
|
TCGv_i64 d = tcg_constant_i64(dest);
|
||||||
TCGv_i64 p = tcg_const_i64(ctx->base.pc_next);
|
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, z, d, p);
|
||||||
|
|
||||||
tcg_temp_free_i64(z);
|
|
||||||
tcg_temp_free_i64(d);
|
|
||||||
tcg_temp_free_i64(p);
|
|
||||||
return DISAS_PC_UPDATED;
|
return DISAS_PC_UPDATED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -695,22 +678,19 @@ static void gen_fp_exc_raise(int rc, int fn11)
|
||||||
if (!(fn11 & QUAL_I)) {
|
if (!(fn11 & QUAL_I)) {
|
||||||
ignore |= FPCR_INE;
|
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
|
/* ??? Pass in the regno of the destination so that the helper can
|
||||||
set EXC_MASK, which contains a bitmask of destination registers
|
set EXC_MASK, which contains a bitmask of destination registers
|
||||||
that have caused arithmetic traps. A simple userspace emulation
|
that have caused arithmetic traps. A simple userspace emulation
|
||||||
does not require this. We do need it for a guest kernel's entArith,
|
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. */
|
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) {
|
if (fn11 & QUAL_S) {
|
||||||
gen_helper_fp_exc_raise_s(cpu_env, ign, reg);
|
gen_helper_fp_exc_raise_s(cpu_env, ign, reg);
|
||||||
} else {
|
} else {
|
||||||
gen_helper_fp_exc_raise(cpu_env, ign, reg);
|
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)
|
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)
|
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();
|
TCGv tmp = tcg_temp_new_i64();
|
||||||
|
|
||||||
if (inv_a) {
|
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_andc_i64(vc, vb, vmask);
|
||||||
tcg_gen_or_i64(vc, vc, tmp);
|
tcg_gen_or_i64(vc, vc, tmp);
|
||||||
|
|
||||||
tcg_temp_free(vmask);
|
|
||||||
tcg_temp_free(tmp);
|
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)
|
static void gen_rx(DisasContext *ctx, int ra, int set)
|
||||||
{
|
{
|
||||||
TCGv tmp;
|
|
||||||
|
|
||||||
if (ra != 31) {
|
if (ra != 31) {
|
||||||
ld_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
|
ld_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = tcg_const_i64(set);
|
st_flag_byte(tcg_constant_i64(set), ENV_FLAG_RX_SHIFT);
|
||||||
st_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
|
|
||||||
tcg_temp_free(tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode)
|
static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode)
|
||||||
|
@ -1193,12 +1168,9 @@ static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode)
|
||||||
|
|
||||||
case 0x3E:
|
case 0x3E:
|
||||||
/* WTINT */
|
/* WTINT */
|
||||||
{
|
tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
|
||||||
TCGv_i32 tmp = tcg_const_i32(1);
|
-offsetof(AlphaCPU, env) +
|
||||||
tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) +
|
offsetof(CPUState, halted));
|
||||||
offsetof(CPUState, halted));
|
|
||||||
tcg_temp_free_i32(tmp);
|
|
||||||
}
|
|
||||||
tcg_gen_movi_i64(ctx->ir[IR_V0], 0);
|
tcg_gen_movi_i64(ctx->ir[IR_V0], 0);
|
||||||
return gen_excp(ctx, EXCP_HALTED, 0);
|
return gen_excp(ctx, EXCP_HALTED, 0);
|
||||||
|
|
||||||
|
@ -1349,12 +1321,8 @@ static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
|
||||||
|
|
||||||
case 253:
|
case 253:
|
||||||
/* WAIT */
|
/* WAIT */
|
||||||
{
|
tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
|
||||||
TCGv_i32 tmp = tcg_const_i32(1);
|
-offsetof(AlphaCPU, env) + offsetof(CPUState, halted));
|
||||||
tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) +
|
|
||||||
offsetof(CPUState, halted));
|
|
||||||
tcg_temp_free_i32(tmp);
|
|
||||||
}
|
|
||||||
return gen_excp(ctx, EXCP_HALTED, 0);
|
return gen_excp(ctx, EXCP_HALTED, 0);
|
||||||
|
|
||||||
case 252:
|
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
|
/* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
|
||||||
address from EXC_ADDR. This turns out to be useful for our
|
address from EXC_ADDR. This turns out to be useful for our
|
||||||
emulation PALcode, so continue to accept it. */
|
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));
|
tcg_gen_ld_i64(vb, cpu_env, offsetof(CPUAlphaState, exc_addr));
|
||||||
} else {
|
} else {
|
||||||
vb = load_gpr(ctx, rb);
|
vb = load_gpr(ctx, rb);
|
||||||
}
|
}
|
||||||
tcg_gen_movi_i64(cpu_lock_addr, -1);
|
tcg_gen_movi_i64(cpu_lock_addr, -1);
|
||||||
|
st_flag_byte(load_zero(ctx), ENV_FLAG_RX_SHIFT);
|
||||||
tmp = tcg_temp_new();
|
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);
|
tcg_gen_andi_i64(tmp, vb, 1);
|
||||||
st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
|
st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
|
||||||
tcg_temp_free(tmp);
|
tcg_temp_free(tmp);
|
||||||
|
@ -2996,7 +2963,6 @@ static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
|
|
||||||
ctx->zero = NULL;
|
ctx->zero = NULL;
|
||||||
ctx->sink = NULL;
|
ctx->sink = NULL;
|
||||||
ctx->lit = NULL;
|
|
||||||
|
|
||||||
/* Bound the number of insns to execute to those left on the page. */
|
/* Bound the number of insns to execute to those left on the page. */
|
||||||
bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
|
bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
|
||||||
|
|
|
@ -144,6 +144,7 @@
|
||||||
#define tcg_gen_sextract_reg tcg_gen_sextract_i64
|
#define tcg_gen_sextract_reg tcg_gen_sextract_i64
|
||||||
#define tcg_const_reg tcg_const_i64
|
#define tcg_const_reg tcg_const_i64
|
||||||
#define tcg_const_local_reg tcg_const_local_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_movcond_reg tcg_gen_movcond_i64
|
||||||
#define tcg_gen_add2_reg tcg_gen_add2_i64
|
#define tcg_gen_add2_reg tcg_gen_add2_i64
|
||||||
#define tcg_gen_sub2_reg tcg_gen_sub2_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_gen_sextract_reg tcg_gen_sextract_i32
|
||||||
#define tcg_const_reg tcg_const_i32
|
#define tcg_const_reg tcg_const_i32
|
||||||
#define tcg_const_local_reg tcg_const_local_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_movcond_reg tcg_gen_movcond_i32
|
||||||
#define tcg_gen_add2_reg tcg_gen_add2_i32
|
#define tcg_gen_add2_reg tcg_gen_add2_i32
|
||||||
#define tcg_gen_sub2_reg tcg_gen_sub2_i32
|
#define tcg_gen_sub2_reg tcg_gen_sub2_i32
|
||||||
|
@ -250,8 +252,6 @@
|
||||||
typedef struct DisasCond {
|
typedef struct DisasCond {
|
||||||
TCGCond c;
|
TCGCond c;
|
||||||
TCGv_reg a0, a1;
|
TCGv_reg a0, a1;
|
||||||
bool a0_is_n;
|
|
||||||
bool a1_is_0;
|
|
||||||
} DisasCond;
|
} DisasCond;
|
||||||
|
|
||||||
typedef struct DisasContext {
|
typedef struct DisasContext {
|
||||||
|
@ -446,9 +446,7 @@ static DisasCond cond_make_n(void)
|
||||||
return (DisasCond){
|
return (DisasCond){
|
||||||
.c = TCG_COND_NE,
|
.c = TCG_COND_NE,
|
||||||
.a0 = cpu_psw_n,
|
.a0 = cpu_psw_n,
|
||||||
.a0_is_n = true,
|
.a1 = tcg_constant_reg(0)
|
||||||
.a1 = NULL,
|
|
||||||
.a1_is_0 = true
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,7 +454,7 @@ static DisasCond cond_make_0_tmp(TCGCond c, TCGv_reg a0)
|
||||||
{
|
{
|
||||||
assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
|
assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
|
||||||
return (DisasCond){
|
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;
|
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)
|
static void cond_free(DisasCond *cond)
|
||||||
{
|
{
|
||||||
switch (cond->c) {
|
switch (cond->c) {
|
||||||
default:
|
default:
|
||||||
if (!cond->a0_is_n) {
|
if (cond->a0 != cpu_psw_n) {
|
||||||
tcg_temp_free(cond->a0);
|
tcg_temp_free(cond->a0);
|
||||||
}
|
}
|
||||||
if (!cond->a1_is_0) {
|
tcg_temp_free(cond->a1);
|
||||||
tcg_temp_free(cond->a1);
|
|
||||||
}
|
|
||||||
cond->a0_is_n = false;
|
|
||||||
cond->a1_is_0 = false;
|
|
||||||
cond->a0 = NULL;
|
cond->a0 = NULL;
|
||||||
cond->a1 = NULL;
|
cond->a1 = NULL;
|
||||||
/* fallthru */
|
/* 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)
|
static void save_or_nullify(DisasContext *ctx, TCGv_reg dest, TCGv_reg t)
|
||||||
{
|
{
|
||||||
if (ctx->null_cond.c != TCG_COND_NEVER) {
|
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,
|
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 {
|
} else {
|
||||||
tcg_gen_mov_reg(dest, t);
|
tcg_gen_mov_reg(dest, t);
|
||||||
}
|
}
|
||||||
|
@ -666,11 +651,9 @@ static void nullify_over(DisasContext *ctx)
|
||||||
assert(ctx->null_cond.c != TCG_COND_ALWAYS);
|
assert(ctx->null_cond.c != TCG_COND_ALWAYS);
|
||||||
|
|
||||||
ctx->null_lab = gen_new_label();
|
ctx->null_lab = gen_new_label();
|
||||||
cond_prep(&ctx->null_cond);
|
|
||||||
|
|
||||||
/* If we're using PSW[N], copy it to a temp because... */
|
/* If we're using PSW[N], copy it to a temp because... */
|
||||||
if (ctx->null_cond.a0_is_n) {
|
if (ctx->null_cond.a0 == cpu_psw_n) {
|
||||||
ctx->null_cond.a0_is_n = false;
|
|
||||||
ctx->null_cond.a0 = tcg_temp_new();
|
ctx->null_cond.a0 = tcg_temp_new();
|
||||||
tcg_gen_mov_reg(ctx->null_cond.a0, cpu_psw_n);
|
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,
|
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);
|
cond_free(&ctx->null_cond);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -697,10 +680,9 @@ static void nullify_save(DisasContext *ctx)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!ctx->null_cond.a0_is_n) {
|
if (ctx->null_cond.a0 != cpu_psw_n) {
|
||||||
cond_prep(&ctx->null_cond);
|
|
||||||
tcg_gen_setcond_reg(ctx->null_cond.c, 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;
|
ctx->psw_n_nonzero = true;
|
||||||
}
|
}
|
||||||
cond_free(&ctx->null_cond);
|
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)
|
static void gen_excp_1(int exception)
|
||||||
{
|
{
|
||||||
TCGv_i32 t = tcg_const_i32(exception);
|
gen_helper_excp(cpu_env, tcg_constant_i32(exception));
|
||||||
gen_helper_excp(cpu_env, t);
|
|
||||||
tcg_temp_free_i32(t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_excp(DisasContext *ctx, int 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)
|
static bool gen_excp_iir(DisasContext *ctx, int exc)
|
||||||
{
|
{
|
||||||
TCGv_reg tmp;
|
|
||||||
|
|
||||||
nullify_over(ctx);
|
nullify_over(ctx);
|
||||||
tmp = tcg_const_reg(ctx->insn);
|
tcg_gen_st_reg(tcg_constant_reg(ctx->insn),
|
||||||
tcg_gen_st_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[CR_IIR]));
|
cpu_env, offsetof(CPUHPPAState, cr[CR_IIR]));
|
||||||
tcg_temp_free(tmp);
|
|
||||||
gen_excp(ctx, exc);
|
gen_excp(ctx, exc);
|
||||||
return nullify_end(ctx);
|
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)) {
|
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);
|
cb_msb = get_temp(ctx);
|
||||||
tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero);
|
tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero);
|
||||||
if (is_c) {
|
if (is_c) {
|
||||||
tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero);
|
tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero);
|
||||||
}
|
}
|
||||||
tcg_temp_free(zero);
|
|
||||||
if (!is_l) {
|
if (!is_l) {
|
||||||
cb = get_temp(ctx);
|
cb = get_temp(ctx);
|
||||||
tcg_gen_xor_reg(cb, in1, in2);
|
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. */
|
/* Emit any conditional trap before any writeback. */
|
||||||
cond = do_cond(cf, dest, cb_msb, sv);
|
cond = do_cond(cf, dest, cb_msb, sv);
|
||||||
if (is_tc) {
|
if (is_tc) {
|
||||||
cond_prep(&cond);
|
|
||||||
tmp = tcg_temp_new();
|
tmp = tcg_temp_new();
|
||||||
tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
|
tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
|
||||||
gen_helper_tcond(cpu_env, tmp);
|
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 = tcg_temp_new();
|
||||||
cb_msb = tcg_temp_new();
|
cb_msb = tcg_temp_new();
|
||||||
|
|
||||||
zero = tcg_const_reg(0);
|
zero = tcg_constant_reg(0);
|
||||||
if (is_b) {
|
if (is_b) {
|
||||||
/* DEST,C = IN1 + ~IN2 + C. */
|
/* DEST,C = IN1 + ~IN2 + C. */
|
||||||
tcg_gen_not_reg(cb, in2);
|
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_eqv_reg(cb, in1, in2);
|
||||||
tcg_gen_xor_reg(cb, cb, dest);
|
tcg_gen_xor_reg(cb, cb, dest);
|
||||||
}
|
}
|
||||||
tcg_temp_free(zero);
|
|
||||||
|
|
||||||
/* Compute signed overflow if required. */
|
/* Compute signed overflow if required. */
|
||||||
sv = NULL;
|
sv = NULL;
|
||||||
|
@ -1278,7 +1252,6 @@ static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
|
||||||
|
|
||||||
/* Emit any conditional trap before any writeback. */
|
/* Emit any conditional trap before any writeback. */
|
||||||
if (is_tc) {
|
if (is_tc) {
|
||||||
cond_prep(&cond);
|
|
||||||
tmp = tcg_temp_new();
|
tmp = tcg_temp_new();
|
||||||
tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
|
tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
|
||||||
gen_helper_tcond(cpu_env, tmp);
|
gen_helper_tcond(cpu_env, tmp);
|
||||||
|
@ -1404,7 +1377,6 @@ static void do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1,
|
||||||
|
|
||||||
if (is_tc) {
|
if (is_tc) {
|
||||||
TCGv_reg tmp = tcg_temp_new();
|
TCGv_reg tmp = tcg_temp_new();
|
||||||
cond_prep(&cond);
|
|
||||||
tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
|
tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
|
||||||
gen_helper_tcond(cpu_env, tmp);
|
gen_helper_tcond(cpu_env, tmp);
|
||||||
tcg_temp_free(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();
|
taken = gen_new_label();
|
||||||
cond_prep(cond);
|
|
||||||
tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken);
|
tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken);
|
||||||
cond_free(cond);
|
cond_free(cond);
|
||||||
|
|
||||||
|
@ -1957,7 +1928,6 @@ static bool do_ibranch(DisasContext *ctx, TCGv_reg dest,
|
||||||
tcg_gen_lookup_and_goto_ptr();
|
tcg_gen_lookup_and_goto_ptr();
|
||||||
return nullify_end(ctx);
|
return nullify_end(ctx);
|
||||||
} else {
|
} else {
|
||||||
cond_prep(&ctx->null_cond);
|
|
||||||
c = ctx->null_cond.c;
|
c = ctx->null_cond.c;
|
||||||
a0 = ctx->null_cond.a0;
|
a0 = ctx->null_cond.a0;
|
||||||
a1 = ctx->null_cond.a1;
|
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);
|
form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
|
||||||
|
|
||||||
if (a->imm) {
|
if (a->imm) {
|
||||||
level = tcg_const_i32(a->ri);
|
level = tcg_constant_i32(a->ri);
|
||||||
} else {
|
} else {
|
||||||
level = tcg_temp_new_i32();
|
level = tcg_temp_new_i32();
|
||||||
tcg_gen_trunc_reg_i32(level, load_gpr(ctx, a->ri));
|
tcg_gen_trunc_reg_i32(level, load_gpr(ctx, a->ri));
|
||||||
tcg_gen_andi_i32(level, level, 3);
|
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);
|
gen_helper_probe(dest, cpu_env, addr, level, want);
|
||||||
|
|
||||||
tcg_temp_free_i32(want);
|
|
||||||
tcg_temp_free_i32(level);
|
tcg_temp_free_i32(level);
|
||||||
|
|
||||||
save_gpr(ctx, a->t, dest);
|
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)
|
static bool trans_lci(DisasContext *ctx, arg_lci *a)
|
||||||
{
|
{
|
||||||
TCGv_reg ci;
|
|
||||||
|
|
||||||
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
||||||
|
|
||||||
/* The Coherence Index is an implementation-defined function of the
|
/* The Coherence Index is an implementation-defined function of the
|
||||||
physical address. Two addresses with the same CI have a coherent
|
physical address. Two addresses with the same CI have a coherent
|
||||||
view of the cache. Our implementation is to return 0 for all,
|
view of the cache. Our implementation is to return 0 for all,
|
||||||
since the entire address space is coherent. */
|
since the entire address space is coherent. */
|
||||||
ci = tcg_const_reg(0);
|
save_gpr(ctx, a->t, tcg_constant_reg(0));
|
||||||
save_gpr(ctx, a->t, ci);
|
|
||||||
tcg_temp_free(ci);
|
|
||||||
|
|
||||||
cond_free(&ctx->null_cond);
|
cond_free(&ctx->null_cond);
|
||||||
return true;
|
return true;
|
||||||
|
@ -2710,8 +2675,6 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf *a)
|
||||||
* currently implemented as idle.
|
* currently implemented as idle.
|
||||||
*/
|
*/
|
||||||
if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */
|
if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */
|
||||||
TCGv_i32 tmp;
|
|
||||||
|
|
||||||
/* No need to check for supervisor, as userland can only pause
|
/* No need to check for supervisor, as userland can only pause
|
||||||
until the next timer interrupt. */
|
until the next timer interrupt. */
|
||||||
nullify_over(ctx);
|
nullify_over(ctx);
|
||||||
|
@ -2722,10 +2685,8 @@ static bool trans_or(DisasContext *ctx, arg_rrr_cf *a)
|
||||||
nullify_set(ctx, 0);
|
nullify_set(ctx, 0);
|
||||||
|
|
||||||
/* Tell the qemu main loop to halt until this cpu has work. */
|
/* Tell the qemu main loop to halt until this cpu has work. */
|
||||||
tmp = tcg_const_i32(1);
|
tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
|
||||||
tcg_gen_st_i32(tmp, cpu_env, -offsetof(HPPACPU, env) +
|
offsetof(CPUState, halted) - offsetof(HPPACPU, env));
|
||||||
offsetof(CPUState, halted));
|
|
||||||
tcg_temp_free_i32(tmp);
|
|
||||||
gen_excp_1(EXCP_HALTED);
|
gen_excp_1(EXCP_HALTED);
|
||||||
ctx->base.is_jmp = DISAS_NORETURN;
|
ctx->base.is_jmp = DISAS_NORETURN;
|
||||||
|
|
||||||
|
@ -2833,7 +2794,7 @@ static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
|
||||||
add2 = tcg_temp_new();
|
add2 = tcg_temp_new();
|
||||||
addc = tcg_temp_new();
|
addc = tcg_temp_new();
|
||||||
dest = tcg_temp_new();
|
dest = tcg_temp_new();
|
||||||
zero = tcg_const_reg(0);
|
zero = tcg_constant_reg(0);
|
||||||
|
|
||||||
/* Form R1 << 1 | PSW[CB]{8}. */
|
/* Form R1 << 1 | PSW[CB]{8}. */
|
||||||
tcg_gen_add_reg(add1, in1, in1);
|
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_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero);
|
||||||
|
|
||||||
tcg_temp_free(addc);
|
tcg_temp_free(addc);
|
||||||
tcg_temp_free(zero);
|
|
||||||
|
|
||||||
/* Write back the result register. */
|
/* Write back the result register. */
|
||||||
save_gpr(ctx, a->t, dest);
|
save_gpr(ctx, a->t, dest);
|
||||||
|
@ -2967,9 +2927,8 @@ static bool trans_ldc(DisasContext *ctx, arg_ldst *a)
|
||||||
*/
|
*/
|
||||||
gen_helper_ldc_check(addr);
|
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_gen_atomic_xchg_reg(dest, addr, zero, ctx->mmu_idx, mop);
|
||||||
tcg_temp_free(zero);
|
|
||||||
|
|
||||||
if (a->m) {
|
if (a->m) {
|
||||||
save_gpr(ctx, a->b, ofs);
|
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);
|
ta = load_frw0_i32(a->r1);
|
||||||
tb = load_frw0_i32(a->r2);
|
tb = load_frw0_i32(a->r2);
|
||||||
ty = tcg_const_i32(a->y);
|
ty = tcg_constant_i32(a->y);
|
||||||
tc = tcg_const_i32(a->c);
|
tc = tcg_constant_i32(a->c);
|
||||||
|
|
||||||
gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc);
|
gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc);
|
||||||
|
|
||||||
tcg_temp_free_i32(ta);
|
tcg_temp_free_i32(ta);
|
||||||
tcg_temp_free_i32(tb);
|
tcg_temp_free_i32(tb);
|
||||||
tcg_temp_free_i32(ty);
|
|
||||||
tcg_temp_free_i32(tc);
|
|
||||||
|
|
||||||
return nullify_end(ctx);
|
return nullify_end(ctx);
|
||||||
}
|
}
|
||||||
|
@ -3904,15 +3861,13 @@ static bool trans_fcmp_d(DisasContext *ctx, arg_fclass2 *a)
|
||||||
|
|
||||||
ta = load_frd0(a->r1);
|
ta = load_frd0(a->r1);
|
||||||
tb = load_frd0(a->r2);
|
tb = load_frd0(a->r2);
|
||||||
ty = tcg_const_i32(a->y);
|
ty = tcg_constant_i32(a->y);
|
||||||
tc = tcg_const_i32(a->c);
|
tc = tcg_constant_i32(a->c);
|
||||||
|
|
||||||
gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc);
|
gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc);
|
||||||
|
|
||||||
tcg_temp_free_i64(ta);
|
tcg_temp_free_i64(ta);
|
||||||
tcg_temp_free_i64(tb);
|
tcg_temp_free_i64(tb);
|
||||||
tcg_temp_free_i32(ty);
|
|
||||||
tcg_temp_free_i32(tc);
|
|
||||||
|
|
||||||
return nullify_end(ctx);
|
return nullify_end(ctx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1437,6 +1437,8 @@ typedef struct CPUX86State {
|
||||||
FPReg fpregs[8];
|
FPReg fpregs[8];
|
||||||
/* KVM-only so far */
|
/* KVM-only so far */
|
||||||
uint16_t fpop;
|
uint16_t fpop;
|
||||||
|
uint16_t fpcs;
|
||||||
|
uint16_t fpds;
|
||||||
uint64_t fpip;
|
uint64_t fpip;
|
||||||
uint64_t fpdp;
|
uint64_t fpdp;
|
||||||
|
|
||||||
|
|
|
@ -727,10 +727,14 @@ void helper_fwait(CPUX86State *env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_fninit(CPUX86State *env)
|
static void do_fninit(CPUX86State *env)
|
||||||
{
|
{
|
||||||
env->fpus = 0;
|
env->fpus = 0;
|
||||||
env->fpstt = 0;
|
env->fpstt = 0;
|
||||||
|
env->fpcs = 0;
|
||||||
|
env->fpds = 0;
|
||||||
|
env->fpip = 0;
|
||||||
|
env->fpdp = 0;
|
||||||
cpu_set_fpuc(env, 0x37f);
|
cpu_set_fpuc(env, 0x37f);
|
||||||
env->fptags[0] = 1;
|
env->fptags[0] = 1;
|
||||||
env->fptags[1] = 1;
|
env->fptags[1] = 1;
|
||||||
|
@ -742,6 +746,11 @@ void helper_fninit(CPUX86State *env)
|
||||||
env->fptags[7] = 1;
|
env->fptags[7] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void helper_fninit(CPUX86State *env)
|
||||||
|
{
|
||||||
|
do_fninit(env);
|
||||||
|
}
|
||||||
|
|
||||||
/* BCD ops */
|
/* BCD ops */
|
||||||
|
|
||||||
void helper_fbld_ST0(CPUX86State *env, target_ulong ptr)
|
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, env->fpuc, retaddr);
|
||||||
cpu_stl_data_ra(env, ptr + 4, fpus, 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 + 8, fptag, retaddr);
|
||||||
cpu_stl_data_ra(env, ptr + 12, 0, retaddr); /* fpip */
|
cpu_stl_data_ra(env, ptr + 12, env->fpip, retaddr); /* fpip */
|
||||||
cpu_stl_data_ra(env, ptr + 16, 0, retaddr); /* fpcs */
|
cpu_stl_data_ra(env, ptr + 16, env->fpcs, retaddr); /* fpcs */
|
||||||
cpu_stl_data_ra(env, ptr + 20, 0, retaddr); /* fpoo */
|
cpu_stl_data_ra(env, ptr + 20, env->fpdp, retaddr); /* fpoo */
|
||||||
cpu_stl_data_ra(env, ptr + 24, 0, retaddr); /* fpos */
|
cpu_stl_data_ra(env, ptr + 24, env->fpds, retaddr); /* fpos */
|
||||||
} else {
|
} else {
|
||||||
/* 16 bit */
|
/* 16 bit */
|
||||||
cpu_stw_data_ra(env, ptr, env->fpuc, retaddr);
|
cpu_stw_data_ra(env, ptr, env->fpuc, retaddr);
|
||||||
cpu_stw_data_ra(env, ptr + 2, fpus, 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 + 4, fptag, retaddr);
|
||||||
cpu_stw_data_ra(env, ptr + 6, 0, retaddr);
|
cpu_stw_data_ra(env, ptr + 6, env->fpip, retaddr);
|
||||||
cpu_stw_data_ra(env, ptr + 8, 0, retaddr);
|
cpu_stw_data_ra(env, ptr + 8, env->fpcs, retaddr);
|
||||||
cpu_stw_data_ra(env, ptr + 10, 0, retaddr);
|
cpu_stw_data_ra(env, ptr + 10, env->fpdp, retaddr);
|
||||||
cpu_stw_data_ra(env, ptr + 12, 0, 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;
|
ptr += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fninit */
|
do_fninit(env);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_fsave(CPUX86State *env, target_ulong ptr, int data32)
|
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) {
|
if (xstate_bv & XSTATE_FP_MASK) {
|
||||||
do_xrstor_fpu(env, ptr, ra);
|
do_xrstor_fpu(env, ptr, ra);
|
||||||
} else {
|
} else {
|
||||||
helper_fninit(env);
|
do_fninit(env);
|
||||||
memset(env->fpregs, 0, sizeof(env->fpregs));
|
memset(env->fpregs, 0, sizeof(env->fpregs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,9 +109,9 @@ static void hw_breakpoint_remove(CPUX86State *env, int index)
|
||||||
|
|
||||||
case DR7_TYPE_DATA_WR:
|
case DR7_TYPE_DATA_WR:
|
||||||
case DR7_TYPE_DATA_RW:
|
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]);
|
cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
|
||||||
env->cpu_breakpoint[index] = NULL;
|
env->cpu_watchpoint[index] = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -52,6 +52,8 @@ typedef struct DisasContext {
|
||||||
|
|
||||||
/* The temporary corresponding to register 0 for this compilation. */
|
/* The temporary corresponding to register 0 for this compilation. */
|
||||||
TCGv R0;
|
TCGv R0;
|
||||||
|
/* The constant zero. */
|
||||||
|
TCGv zero;
|
||||||
} DisasContext;
|
} DisasContext;
|
||||||
|
|
||||||
static inline bool is_user(DisasContext *dc)
|
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)
|
static void gen_exception(DisasContext *dc, unsigned int excp)
|
||||||
{
|
{
|
||||||
TCGv_i32 tmp = tcg_const_i32(excp);
|
gen_helper_exception(cpu_env, tcg_constant_i32(excp));
|
||||||
gen_helper_exception(cpu_env, tmp);
|
|
||||||
tcg_temp_free_i32(tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_illegal_exception(DisasContext *dc)
|
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)
|
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();
|
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(cpu_sr_ov, srca, srcb);
|
||||||
tcg_gen_xor_tl(t0, res, srcb);
|
tcg_gen_xor_tl(t0, res, srcb);
|
||||||
tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
|
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)
|
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();
|
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, srca, dc->zero, cpu_sr_cy, dc->zero);
|
||||||
tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
|
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(cpu_sr_ov, srca, srcb);
|
||||||
tcg_gen_xor_tl(t0, res, srcb);
|
tcg_gen_xor_tl(t0, res, srcb);
|
||||||
tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
|
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)
|
static bool trans_l_cmov(DisasContext *dc, arg_dab *a)
|
||||||
{
|
{
|
||||||
TCGv zero;
|
|
||||||
|
|
||||||
check_r0_write(dc, a->d);
|
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, dc->zero,
|
||||||
tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, zero,
|
|
||||||
cpu_R(dc, a->a), cpu_R(dc, a->b));
|
cpu_R(dc, a->a), cpu_R(dc, a->b));
|
||||||
tcg_temp_free(zero);
|
|
||||||
return true;
|
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)
|
static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond)
|
||||||
{
|
{
|
||||||
target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
|
target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
|
||||||
TCGv t_next = tcg_const_tl(dc->base.pc_next + 8);
|
TCGv t_next = tcg_constant_tl(dc->base.pc_next + 8);
|
||||||
TCGv t_true = tcg_const_tl(tmp_pc);
|
TCGv t_true = tcg_constant_tl(tmp_pc);
|
||||||
TCGv t_zero = tcg_const_tl(0);
|
|
||||||
|
|
||||||
tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
|
tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, dc->zero, t_true, t_next);
|
||||||
|
|
||||||
tcg_temp_free(t_next);
|
|
||||||
tcg_temp_free(t_true);
|
|
||||||
tcg_temp_free(t_zero);
|
|
||||||
dc->delayed_branch = 2;
|
dc->delayed_branch = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,12 +731,6 @@ static bool trans_l_swa(DisasContext *dc, arg_store *a)
|
||||||
ea = tcg_temp_new();
|
ea = tcg_temp_new();
|
||||||
tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
|
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_fail = gen_new_label();
|
||||||
lab_done = gen_new_label();
|
lab_done = gen_new_label();
|
||||||
tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
|
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();
|
val = tcg_temp_new();
|
||||||
tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
|
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_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
|
||||||
tcg_temp_free(val);
|
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)
|
static bool trans_l_addi(DisasContext *dc, arg_rri *a)
|
||||||
{
|
{
|
||||||
TCGv t0;
|
|
||||||
|
|
||||||
check_r0_write(dc, a->d);
|
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), tcg_constant_tl(a->i));
|
||||||
gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
|
|
||||||
tcg_temp_free(t0);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_l_addic(DisasContext *dc, arg_rri *a)
|
static bool trans_l_addic(DisasContext *dc, arg_rri *a)
|
||||||
{
|
{
|
||||||
TCGv t0;
|
|
||||||
|
|
||||||
check_r0_write(dc, a->d);
|
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), tcg_constant_tl(a->i));
|
||||||
gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
|
|
||||||
tcg_temp_free(t0);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_l_muli(DisasContext *dc, arg_rri *a)
|
static bool trans_l_muli(DisasContext *dc, arg_rri *a)
|
||||||
{
|
{
|
||||||
TCGv t0;
|
|
||||||
|
|
||||||
check_r0_write(dc, a->d);
|
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), tcg_constant_tl(a->i));
|
||||||
gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
|
|
||||||
tcg_temp_free(t0);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool trans_l_maci(DisasContext *dc, arg_l_maci *a)
|
static bool trans_l_maci(DisasContext *dc, arg_l_maci *a)
|
||||||
{
|
{
|
||||||
TCGv t0;
|
gen_mac(dc, cpu_R(dc, a->a), tcg_constant_tl(a->i));
|
||||||
|
|
||||||
t0 = tcg_const_tl(a->i);
|
|
||||||
gen_mac(dc, cpu_R(dc, a->a), t0);
|
|
||||||
tcg_temp_free(t0);
|
|
||||||
return true;
|
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,
|
/* Allow the TCG optimizer to see that R0 == 0,
|
||||||
when it's true, which is the common case. */
|
when it's true, which is the common case. */
|
||||||
|
dc->zero = tcg_constant_tl(0);
|
||||||
if (dc->tb_flags & TB_FLAGS_R0_0) {
|
if (dc->tb_flags & TB_FLAGS_R0_0) {
|
||||||
dc->R0 = tcg_const_tl(0);
|
dc->R0 = dc->zero;
|
||||||
} else {
|
} else {
|
||||||
dc->R0 = cpu_regs[0];
|
dc->R0 = cpu_regs[0];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue