mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-25 22:16:46 +00:00
target-mips: Misaligned memory accesses for R6
Release 6 requires misaligned memory access support for all ordinary memory access instructions (for example, LW/SW, LWC1/SWC1). However misaligned support is not provided for certain special memory accesses such as atomics (for example, LL/SC). Backports commit be3a8c53b4f18bcc51a462d977cc61a0f46ebb1c from qemu
This commit is contained in:
parent
c54458b638
commit
6d0766f246
|
@ -1397,6 +1397,7 @@ typedef struct DisasContext {
|
||||||
int32_t CP0_Config1;
|
int32_t CP0_Config1;
|
||||||
/* Routine used to access memory */
|
/* Routine used to access memory */
|
||||||
int mem_idx;
|
int mem_idx;
|
||||||
|
TCGMemOp default_tcg_memop_mask;
|
||||||
uint32_t hflags, saved_hflags;
|
uint32_t hflags, saved_hflags;
|
||||||
int bstate;
|
int bstate;
|
||||||
target_ulong btarget;
|
target_ulong btarget;
|
||||||
|
@ -2094,12 +2095,14 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
|
||||||
switch (opc) {
|
switch (opc) {
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
case OPC_LWU:
|
case OPC_LWU:
|
||||||
tcg_gen_qemu_ld_tl(ctx->uc, t0, t0, ctx->mem_idx, MO_TEUL);
|
tcg_gen_qemu_ld_tl(ctx->uc, t0, t0, ctx->mem_idx, MO_TEUL |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
gen_store_gpr(tcg_ctx, t0, rt);
|
gen_store_gpr(tcg_ctx, t0, rt);
|
||||||
opn = "lwu";
|
opn = "lwu";
|
||||||
break;
|
break;
|
||||||
case OPC_LD:
|
case OPC_LD:
|
||||||
tcg_gen_qemu_ld_tl(ctx->uc, t0, t0, ctx->mem_idx, MO_TEQ);
|
tcg_gen_qemu_ld_tl(ctx->uc, t0, t0, ctx->mem_idx, MO_TEQ |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
gen_store_gpr(tcg_ctx, t0, rt);
|
gen_store_gpr(tcg_ctx, t0, rt);
|
||||||
opn = "ld";
|
opn = "ld";
|
||||||
break;
|
break;
|
||||||
|
@ -2170,17 +2173,20 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
|
||||||
opn = "lwpc";
|
opn = "lwpc";
|
||||||
break;
|
break;
|
||||||
case OPC_LW:
|
case OPC_LW:
|
||||||
tcg_gen_qemu_ld_tl(ctx->uc, t0, t0, ctx->mem_idx, MO_TESL);
|
tcg_gen_qemu_ld_tl(ctx->uc, t0, t0, ctx->mem_idx, MO_TESL |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
gen_store_gpr(tcg_ctx, t0, rt);
|
gen_store_gpr(tcg_ctx, t0, rt);
|
||||||
opn = "lw";
|
opn = "lw";
|
||||||
break;
|
break;
|
||||||
case OPC_LH:
|
case OPC_LH:
|
||||||
tcg_gen_qemu_ld_tl(ctx->uc, t0, t0, ctx->mem_idx, MO_TESW);
|
tcg_gen_qemu_ld_tl(ctx->uc, t0, t0, ctx->mem_idx, MO_TESW |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
gen_store_gpr(tcg_ctx, t0, rt);
|
gen_store_gpr(tcg_ctx, t0, rt);
|
||||||
opn = "lh";
|
opn = "lh";
|
||||||
break;
|
break;
|
||||||
case OPC_LHU:
|
case OPC_LHU:
|
||||||
tcg_gen_qemu_ld_tl(ctx->uc, t0, t0, ctx->mem_idx, MO_TEUW);
|
tcg_gen_qemu_ld_tl(ctx->uc, t0, t0, ctx->mem_idx, MO_TEUW |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
gen_store_gpr(tcg_ctx, t0, rt);
|
gen_store_gpr(tcg_ctx, t0, rt);
|
||||||
opn = "lhu";
|
opn = "lhu";
|
||||||
break;
|
break;
|
||||||
|
@ -2265,7 +2271,8 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
|
||||||
switch (opc) {
|
switch (opc) {
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
case OPC_SD:
|
case OPC_SD:
|
||||||
tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx, MO_TEQ);
|
tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx, MO_TEQ |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
opn = "sd";
|
opn = "sd";
|
||||||
break;
|
break;
|
||||||
case OPC_SDL:
|
case OPC_SDL:
|
||||||
|
@ -2280,11 +2287,13 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case OPC_SW:
|
case OPC_SW:
|
||||||
tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx, MO_TEUL);
|
tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx, MO_TEUL |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
opn = "sw";
|
opn = "sw";
|
||||||
break;
|
break;
|
||||||
case OPC_SH:
|
case OPC_SH:
|
||||||
tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx, MO_TEUW);
|
tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx, MO_TEUW |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
opn = "sh";
|
opn = "sh";
|
||||||
break;
|
break;
|
||||||
case OPC_SB:
|
case OPC_SB:
|
||||||
|
@ -2363,7 +2372,8 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
|
||||||
case OPC_LWC1:
|
case OPC_LWC1:
|
||||||
{
|
{
|
||||||
TCGv_i32 fp0 = tcg_temp_new_i32(tcg_ctx);
|
TCGv_i32 fp0 = tcg_temp_new_i32(tcg_ctx);
|
||||||
tcg_gen_qemu_ld_i32(ctx->uc, fp0, t0, ctx->mem_idx, MO_TESL);
|
tcg_gen_qemu_ld_i32(ctx->uc, fp0, t0, ctx->mem_idx, MO_TESL |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
gen_store_fpr32(ctx, fp0, ft);
|
gen_store_fpr32(ctx, fp0, ft);
|
||||||
tcg_temp_free_i32(tcg_ctx, fp0);
|
tcg_temp_free_i32(tcg_ctx, fp0);
|
||||||
}
|
}
|
||||||
|
@ -2373,7 +2383,8 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
|
||||||
{
|
{
|
||||||
TCGv_i32 fp0 = tcg_temp_new_i32(tcg_ctx);
|
TCGv_i32 fp0 = tcg_temp_new_i32(tcg_ctx);
|
||||||
gen_load_fpr32(ctx, fp0, ft);
|
gen_load_fpr32(ctx, fp0, ft);
|
||||||
tcg_gen_qemu_st_i32(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEUL);
|
tcg_gen_qemu_st_i32(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEUL |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
tcg_temp_free_i32(tcg_ctx, fp0);
|
tcg_temp_free_i32(tcg_ctx, fp0);
|
||||||
}
|
}
|
||||||
opn = "swc1";
|
opn = "swc1";
|
||||||
|
@ -2381,7 +2392,8 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
|
||||||
case OPC_LDC1:
|
case OPC_LDC1:
|
||||||
{
|
{
|
||||||
TCGv_i64 fp0 = tcg_temp_new_i64(tcg_ctx);
|
TCGv_i64 fp0 = tcg_temp_new_i64(tcg_ctx);
|
||||||
tcg_gen_qemu_ld_i64(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEQ);
|
tcg_gen_qemu_ld_i64(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEQ |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
gen_store_fpr64(ctx, fp0, ft);
|
gen_store_fpr64(ctx, fp0, ft);
|
||||||
tcg_temp_free_i64(tcg_ctx, fp0);
|
tcg_temp_free_i64(tcg_ctx, fp0);
|
||||||
}
|
}
|
||||||
|
@ -2391,7 +2403,8 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
|
||||||
{
|
{
|
||||||
TCGv_i64 fp0 = tcg_temp_new_i64(tcg_ctx);
|
TCGv_i64 fp0 = tcg_temp_new_i64(tcg_ctx);
|
||||||
gen_load_fpr64(ctx, fp0, ft);
|
gen_load_fpr64(ctx, fp0, ft);
|
||||||
tcg_gen_qemu_st_i64(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEQ);
|
tcg_gen_qemu_st_i64(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEQ |
|
||||||
|
ctx->default_tcg_memop_mask);
|
||||||
tcg_temp_free_i64(tcg_ctx, fp0);
|
tcg_temp_free_i64(tcg_ctx, fp0);
|
||||||
}
|
}
|
||||||
opn = "sdc1";
|
opn = "sdc1";
|
||||||
|
@ -19321,6 +19334,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
|
||||||
#else
|
#else
|
||||||
ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
|
ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
|
||||||
#endif
|
#endif
|
||||||
|
ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
|
||||||
|
MO_UNALN : MO_ALIGN;
|
||||||
|
|
||||||
num_insns = 0;
|
num_insns = 0;
|
||||||
max_insns = tb->cflags & CF_COUNT_MASK;
|
max_insns = tb->cflags & CF_COUNT_MASK;
|
||||||
if (max_insns == 0)
|
if (max_insns == 0)
|
||||||
|
|
Loading…
Reference in a new issue