mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-08 10:09:43 +00:00
target-i386: Access segs via TCG registers
Having segs[].base as a register significantly improves code generation for real and protected modes, particularly for TBs that have multiple memory references where the segment base can be held in a hard register through the TB. Backports commit 3558f8055f37a34762b7a2a0f02687e6eeab893d from qemu
This commit is contained in:
parent
969f8ab407
commit
092c7bea97
|
@ -507,14 +507,13 @@ static inline void gen_op_addl_A0_seg(DisasContext *s, int reg)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
TCGv cpu_A0 = *(TCGv *)tcg_ctx->cpu_A0;
|
TCGv cpu_A0 = *(TCGv *)tcg_ctx->cpu_A0;
|
||||||
TCGv cpu_tmp0 = *(TCGv *)tcg_ctx->cpu_tmp0;
|
TCGv **cpu_seg_base = (TCGv **)tcg_ctx->cpu_seg_base;
|
||||||
|
|
||||||
tcg_gen_ld_tl(tcg_ctx, cpu_tmp0, tcg_ctx->cpu_env, offsetof(CPUX86State, segs[reg].base));
|
|
||||||
if (CODE64(s)) {
|
if (CODE64(s)) {
|
||||||
tcg_gen_ext32u_tl(tcg_ctx, cpu_A0, cpu_A0);
|
tcg_gen_ext32u_tl(tcg_ctx, cpu_A0, cpu_A0);
|
||||||
tcg_gen_add_tl(tcg_ctx, cpu_A0, cpu_A0, cpu_tmp0);
|
tcg_gen_add_tl(tcg_ctx, cpu_A0, cpu_A0, *cpu_seg_base[reg]);
|
||||||
} else {
|
} else {
|
||||||
tcg_gen_add_tl(tcg_ctx, cpu_A0, cpu_A0, cpu_tmp0);
|
tcg_gen_add_tl(tcg_ctx, cpu_A0, cpu_A0, *cpu_seg_base[reg]);
|
||||||
tcg_gen_ext32u_tl(tcg_ctx, cpu_A0, cpu_A0);
|
tcg_gen_ext32u_tl(tcg_ctx, cpu_A0, cpu_A0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -601,9 +600,8 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ovr_seg >= 0) {
|
if (ovr_seg >= 0) {
|
||||||
TCGv seg = tcg_temp_new(tcg_ctx);
|
TCGv **cpu_seg_base = (TCGv **)tcg_ctx->cpu_seg_base;
|
||||||
|
TCGv seg = *cpu_seg_base[ovr_seg];
|
||||||
tcg_gen_ld_tl(tcg_ctx, seg, tcg_ctx->cpu_env, offsetof(CPUX86State, segs[ovr_seg].base));
|
|
||||||
|
|
||||||
if (aflag == MO_64) {
|
if (aflag == MO_64) {
|
||||||
tcg_gen_add_tl(tcg_ctx, cpu_A0, a0, seg);
|
tcg_gen_add_tl(tcg_ctx, cpu_A0, a0, seg);
|
||||||
|
@ -614,8 +612,6 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
|
||||||
tcg_gen_add_tl(tcg_ctx, cpu_A0, a0, seg);
|
tcg_gen_add_tl(tcg_ctx, cpu_A0, a0, seg);
|
||||||
tcg_gen_ext32u_tl(tcg_ctx, cpu_A0, cpu_A0);
|
tcg_gen_ext32u_tl(tcg_ctx, cpu_A0, cpu_A0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_temp_free(tcg_ctx, seg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2483,13 +2479,12 @@ static inline void gen_op_movl_T0_seg(TCGContext *s, int seg_reg)
|
||||||
static inline void gen_op_movl_seg_T0_vm(TCGContext *s, int seg_reg)
|
static inline void gen_op_movl_seg_T0_vm(TCGContext *s, int seg_reg)
|
||||||
{
|
{
|
||||||
TCGv **cpu_T = (TCGv **)s->cpu_T;
|
TCGv **cpu_T = (TCGv **)s->cpu_T;
|
||||||
|
TCGv **cpu_seg_base = (TCGv **)s->cpu_seg_base;
|
||||||
|
|
||||||
tcg_gen_andi_tl(s, *cpu_T[0], *cpu_T[0], 0xffff);
|
tcg_gen_ext16u_tl(s, *cpu_T[0], *cpu_T[0]);
|
||||||
tcg_gen_st32_tl(s, *cpu_T[0], s->cpu_env,
|
tcg_gen_st32_tl(s, *cpu_T[0], s->cpu_env,
|
||||||
offsetof(CPUX86State,segs[seg_reg].selector));
|
offsetof(CPUX86State,segs[seg_reg].selector));
|
||||||
tcg_gen_shli_tl(s, *cpu_T[0], *cpu_T[0], 4);
|
tcg_gen_shli_tl(s, *cpu_seg_base[seg_reg], *cpu_T[0], 4);
|
||||||
tcg_gen_st_tl(s, *cpu_T[0], s->cpu_env,
|
|
||||||
offsetof(CPUX86State,segs[seg_reg].base));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* move T0 to seg_reg and compute if the CPU state may change. Never
|
/* move T0 to seg_reg and compute if the CPU state may change. Never
|
||||||
|
@ -7921,21 +7916,18 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
|
||||||
if (s->cpl != 0) {
|
if (s->cpl != 0) {
|
||||||
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
|
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
|
||||||
} else {
|
} else {
|
||||||
tcg_gen_ld_tl(tcg_ctx, *cpu_T[0], cpu_env,
|
TCGv **cpu_seg_base = (TCGv **)tcg_ctx->cpu_seg_base;
|
||||||
offsetof(CPUX86State,segs[R_GS].base));
|
|
||||||
tcg_gen_ld_tl(tcg_ctx, *cpu_T[1], cpu_env,
|
tcg_gen_mov_tl(tcg_ctx, *cpu_T[0], *cpu_seg_base[R_GS]);
|
||||||
offsetof(CPUX86State,kernelgsbase));
|
tcg_gen_ld_tl(tcg_ctx, *cpu_seg_base[R_GS], cpu_env,
|
||||||
tcg_gen_st_tl(tcg_ctx, *cpu_T[1], cpu_env,
|
offsetof(CPUX86State, kernelgsbase));
|
||||||
offsetof(CPUX86State,segs[R_GS].base));
|
|
||||||
tcg_gen_st_tl(tcg_ctx, *cpu_T[0], cpu_env,
|
tcg_gen_st_tl(tcg_ctx, *cpu_T[0], cpu_env,
|
||||||
offsetof(CPUX86State,kernelgsbase));
|
offsetof(CPUX86State, kernelgsbase));
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
goto illegal_op;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
goto illegal_op;
|
||||||
case 1: /* rdtscp */
|
case 1: /* rdtscp */
|
||||||
if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
|
if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
|
@ -8418,6 +8410,14 @@ void tcg_x86_init(struct uc_struct *uc)
|
||||||
"edi",
|
"edi",
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
static const char seg_base_names[6][8] = {
|
||||||
|
"es_base",
|
||||||
|
"cs_base",
|
||||||
|
"ss_base",
|
||||||
|
"ds_base",
|
||||||
|
"fs_base",
|
||||||
|
"gs_base",
|
||||||
|
};
|
||||||
int i;
|
int i;
|
||||||
TCGContext *tcg_ctx = uc->tcg_ctx;
|
TCGContext *tcg_ctx = uc->tcg_ctx;
|
||||||
|
|
||||||
|
@ -8442,6 +8442,14 @@ void tcg_x86_init(struct uc_struct *uc)
|
||||||
offsetof(CPUX86State, regs[i]),
|
offsetof(CPUX86State, regs[i]),
|
||||||
reg_names[i]);
|
reg_names[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 6; ++i) {
|
||||||
|
tcg_ctx->cpu_seg_base[i] = g_malloc0(sizeof(TCGv));
|
||||||
|
*((TCGv *)tcg_ctx->cpu_seg_base[i])
|
||||||
|
= tcg_global_mem_new(tcg_ctx, tcg_ctx->cpu_env,
|
||||||
|
offsetof(CPUX86State, segs[i].base),
|
||||||
|
seg_base_names[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate intermediate code for basic block 'tb'. */
|
/* generate intermediate code for basic block 'tb'. */
|
||||||
|
|
|
@ -52,6 +52,10 @@ void x86_release(void *ctx)
|
||||||
g_free(s->cpu_regs[i]);
|
g_free(s->cpu_regs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 6; ++i) {
|
||||||
|
g_free(s->cpu_seg_base[i]);
|
||||||
|
}
|
||||||
|
|
||||||
g_free(s->tb_ctx.tbs);
|
g_free(s->tb_ctx.tbs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -720,6 +720,7 @@ struct TCGContext {
|
||||||
TCGv_ptr cpu_env;
|
TCGv_ptr cpu_env;
|
||||||
TCGv_i32 cpu_cc_op;
|
TCGv_i32 cpu_cc_op;
|
||||||
void *cpu_regs[16]; // 16 GRP for X86-64
|
void *cpu_regs[16]; // 16 GRP for X86-64
|
||||||
|
void *cpu_seg_base[6]; // Actually an array of TCGv
|
||||||
int x86_64_hregs; // qemu/target-i386/translate.c
|
int x86_64_hregs; // qemu/target-i386/translate.c
|
||||||
|
|
||||||
/* qemu/target-i386/translate.c: global TCGv vars */
|
/* qemu/target-i386/translate.c: global TCGv vars */
|
||||||
|
|
Loading…
Reference in a new issue