mirror of
https://github.com/qemu/qemu.git
synced 2024-12-12 13:13:51 +08:00
target/mips: Split out gen_lxr
Common subroutine for LDR and LWR. Use tcg_constant_tl of ~1 instead of tcg_const_tl of 0x..fe. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
990c162e67
commit
0694cd597d
@ -2021,11 +2021,39 @@ static void gen_lxl(DisasContext *ctx, TCGv reg, TCGv addr,
|
|||||||
tcg_gen_or_tl(reg, t0, t1);
|
tcg_gen_or_tl(reg, t0, t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* LWR or LDR, depending on MemOp. */
|
||||||
|
static void gen_lxr(DisasContext *ctx, TCGv reg, TCGv addr,
|
||||||
|
int mem_idx, MemOp mop)
|
||||||
|
{
|
||||||
|
int size = memop_size(mop);
|
||||||
|
int sizem1 = size - 1;
|
||||||
|
TCGv t0 = tcg_temp_new();
|
||||||
|
TCGv t1 = tcg_temp_new();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do a byte access to possibly trigger a page
|
||||||
|
* fault with the unaligned address.
|
||||||
|
*/
|
||||||
|
tcg_gen_qemu_ld_tl(t1, addr, mem_idx, MO_UB);
|
||||||
|
tcg_gen_andi_tl(t1, addr, sizem1);
|
||||||
|
if (cpu_is_bigendian(ctx)) {
|
||||||
|
tcg_gen_xori_tl(t1, t1, sizem1);
|
||||||
|
}
|
||||||
|
tcg_gen_shli_tl(t1, t1, 3);
|
||||||
|
tcg_gen_andi_tl(t0, addr, ~sizem1);
|
||||||
|
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mop);
|
||||||
|
tcg_gen_shr_tl(t0, t0, t1);
|
||||||
|
tcg_gen_xori_tl(t1, t1, size * 8 - 1);
|
||||||
|
tcg_gen_shl_tl(t1, tcg_constant_tl(~1), t1);
|
||||||
|
tcg_gen_and_tl(t1, reg, t1);
|
||||||
|
tcg_gen_or_tl(reg, t0, t1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Load */
|
/* Load */
|
||||||
static void gen_ld(DisasContext *ctx, uint32_t opc,
|
static void gen_ld(DisasContext *ctx, uint32_t opc,
|
||||||
int rt, int base, int offset)
|
int rt, int base, int offset)
|
||||||
{
|
{
|
||||||
TCGv t0, t1, t2;
|
TCGv t0, t1;
|
||||||
int mem_idx = ctx->mem_idx;
|
int mem_idx = ctx->mem_idx;
|
||||||
|
|
||||||
if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
|
if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
|
||||||
@ -2066,26 +2094,9 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
|
|||||||
break;
|
break;
|
||||||
case OPC_LDR:
|
case OPC_LDR:
|
||||||
t1 = tcg_temp_new();
|
t1 = tcg_temp_new();
|
||||||
/*
|
|
||||||
* Do a byte access to possibly trigger a page
|
|
||||||
* fault with the unaligned address.
|
|
||||||
*/
|
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
|
|
||||||
tcg_gen_andi_tl(t1, t0, 7);
|
|
||||||
if (cpu_is_bigendian(ctx)) {
|
|
||||||
tcg_gen_xori_tl(t1, t1, 7);
|
|
||||||
}
|
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
|
||||||
tcg_gen_andi_tl(t0, t0, ~7);
|
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ);
|
|
||||||
tcg_gen_shr_tl(t0, t0, t1);
|
|
||||||
tcg_gen_xori_tl(t1, t1, 63);
|
|
||||||
t2 = tcg_const_tl(0xfffffffffffffffeull);
|
|
||||||
tcg_gen_shl_tl(t2, t2, t1);
|
|
||||||
gen_load_gpr(t1, rt);
|
gen_load_gpr(t1, rt);
|
||||||
tcg_gen_and_tl(t1, t1, t2);
|
gen_lxr(ctx, t1, t0, mem_idx, MO_TEUQ);
|
||||||
tcg_gen_or_tl(t0, t0, t1);
|
gen_store_gpr(t1, rt);
|
||||||
gen_store_gpr(t0, rt);
|
|
||||||
break;
|
break;
|
||||||
case OPC_LDPC:
|
case OPC_LDPC:
|
||||||
t1 = tcg_const_tl(pc_relative_pc(ctx));
|
t1 = tcg_const_tl(pc_relative_pc(ctx));
|
||||||
@ -2153,27 +2164,10 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
|
|||||||
/* fall through */
|
/* fall through */
|
||||||
case OPC_LWR:
|
case OPC_LWR:
|
||||||
t1 = tcg_temp_new();
|
t1 = tcg_temp_new();
|
||||||
/*
|
|
||||||
* Do a byte access to possibly trigger a page
|
|
||||||
* fault with the unaligned address.
|
|
||||||
*/
|
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
|
|
||||||
tcg_gen_andi_tl(t1, t0, 3);
|
|
||||||
if (cpu_is_bigendian(ctx)) {
|
|
||||||
tcg_gen_xori_tl(t1, t1, 3);
|
|
||||||
}
|
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
|
||||||
tcg_gen_andi_tl(t0, t0, ~3);
|
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
|
|
||||||
tcg_gen_shr_tl(t0, t0, t1);
|
|
||||||
tcg_gen_xori_tl(t1, t1, 31);
|
|
||||||
t2 = tcg_const_tl(0xfffffffeull);
|
|
||||||
tcg_gen_shl_tl(t2, t2, t1);
|
|
||||||
gen_load_gpr(t1, rt);
|
gen_load_gpr(t1, rt);
|
||||||
tcg_gen_and_tl(t1, t1, t2);
|
gen_lxr(ctx, t1, t0, mem_idx, MO_TEUL);
|
||||||
tcg_gen_or_tl(t0, t0, t1);
|
tcg_gen_ext32s_tl(t1, t1);
|
||||||
tcg_gen_ext32s_tl(t0, t0);
|
gen_store_gpr(t1, rt);
|
||||||
gen_store_gpr(t0, rt);
|
|
||||||
break;
|
break;
|
||||||
case OPC_LLE:
|
case OPC_LLE:
|
||||||
mem_idx = MIPS_HFLAG_UM;
|
mem_idx = MIPS_HFLAG_UM;
|
||||||
@ -4150,7 +4144,7 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
|
|||||||
static void gen_loongson_lswc2(DisasContext *ctx, int rt,
|
static void gen_loongson_lswc2(DisasContext *ctx, int rt,
|
||||||
int rs, int rd)
|
int rs, int rd)
|
||||||
{
|
{
|
||||||
TCGv t0, t1, t2;
|
TCGv t0, t1;
|
||||||
TCGv_i32 fp0;
|
TCGv_i32 fp0;
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
int lsq_rt1 = ctx->opcode & 0x1f;
|
int lsq_rt1 = ctx->opcode & 0x1f;
|
||||||
@ -4225,29 +4219,12 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
|
|||||||
case OPC_GSLWRC1:
|
case OPC_GSLWRC1:
|
||||||
check_cp1_enabled(ctx);
|
check_cp1_enabled(ctx);
|
||||||
gen_base_offset_addr(ctx, t0, rs, shf_offset);
|
gen_base_offset_addr(ctx, t0, rs, shf_offset);
|
||||||
t1 = tcg_temp_new();
|
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
|
|
||||||
tcg_gen_andi_tl(t1, t0, 3);
|
|
||||||
if (cpu_is_bigendian(ctx)) {
|
|
||||||
tcg_gen_xori_tl(t1, t1, 3);
|
|
||||||
}
|
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
|
||||||
tcg_gen_andi_tl(t0, t0, ~3);
|
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
|
|
||||||
tcg_gen_shr_tl(t0, t0, t1);
|
|
||||||
tcg_gen_xori_tl(t1, t1, 31);
|
|
||||||
t2 = tcg_const_tl(0xfffffffeull);
|
|
||||||
tcg_gen_shl_tl(t2, t2, t1);
|
|
||||||
fp0 = tcg_temp_new_i32();
|
fp0 = tcg_temp_new_i32();
|
||||||
gen_load_fpr32(ctx, fp0, rt);
|
gen_load_fpr32(ctx, fp0, rt);
|
||||||
|
t1 = tcg_temp_new();
|
||||||
tcg_gen_ext_i32_tl(t1, fp0);
|
tcg_gen_ext_i32_tl(t1, fp0);
|
||||||
tcg_gen_and_tl(t1, t1, t2);
|
gen_lxr(ctx, t1, t0, ctx->mem_idx, MO_TEUL);
|
||||||
tcg_gen_or_tl(t0, t0, t1);
|
tcg_gen_trunc_tl_i32(fp0, t1);
|
||||||
#if defined(TARGET_MIPS64)
|
|
||||||
tcg_gen_extrl_i64_i32(fp0, t0);
|
|
||||||
#else
|
|
||||||
tcg_gen_ext32s_tl(fp0, t0);
|
|
||||||
#endif
|
|
||||||
gen_store_fpr32(ctx, fp0, rt);
|
gen_store_fpr32(ctx, fp0, rt);
|
||||||
break;
|
break;
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
@ -4263,22 +4240,9 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt,
|
|||||||
check_cp1_enabled(ctx);
|
check_cp1_enabled(ctx);
|
||||||
gen_base_offset_addr(ctx, t0, rs, shf_offset);
|
gen_base_offset_addr(ctx, t0, rs, shf_offset);
|
||||||
t1 = tcg_temp_new();
|
t1 = tcg_temp_new();
|
||||||
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
|
|
||||||
tcg_gen_andi_tl(t1, t0, 7);
|
|
||||||
if (cpu_is_bigendian(ctx)) {
|
|
||||||
tcg_gen_xori_tl(t1, t1, 7);
|
|
||||||
}
|
|
||||||
tcg_gen_shli_tl(t1, t1, 3);
|
|
||||||
tcg_gen_andi_tl(t0, t0, ~7);
|
|
||||||
tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ);
|
|
||||||
tcg_gen_shr_tl(t0, t0, t1);
|
|
||||||
tcg_gen_xori_tl(t1, t1, 63);
|
|
||||||
t2 = tcg_const_tl(0xfffffffffffffffeull);
|
|
||||||
tcg_gen_shl_tl(t2, t2, t1);
|
|
||||||
gen_load_fpr64(ctx, t1, rt);
|
gen_load_fpr64(ctx, t1, rt);
|
||||||
tcg_gen_and_tl(t1, t1, t2);
|
gen_lxr(ctx, t1, t0, ctx->mem_idx, MO_TEUQ);
|
||||||
tcg_gen_or_tl(t0, t0, t1);
|
gen_store_fpr64(ctx, t1, rt);
|
||||||
gen_store_fpr64(ctx, t0, rt);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user