* [PATCH 00/22] target/i386: pc-relative translation
@ 2022-08-22 23:32 Richard Henderson
2022-08-22 23:32 ` [PATCH 01/22] target/i386: Return bool from disas_insn Richard Henderson
` (21 more replies)
0 siblings, 22 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:32 UTC (permalink / raw)
To: qemu-devel
Based-on: <20220822232338.1727934-1-richard.henderson@linaro.org>
("[PATCH v3 00/17] accel/tcg + target/arm: pc-relative translation")
Improve translation with address space randomization.
Before:
gen code size 232687283/1073577984
TB count 434021
TB flush count 1
TB invalidate count 478996
After:
gen code size 281614723/1073577984
TB count 527520
TB flush count 0
TB invalidate count 125631
before after
BootLinuxX8664.test_pc_i440fx_tcg: 63.79 56.01
BootLinuxX8664.test_pc_q35_tcg: 69.11 50.00
JOB TIME 595.51 533.57
r~
Richard Henderson (22):
target/i386: Return bool from disas_insn
target/i386: Remove cur_eip argument to gen_exception
target/i386: Remove cur_eip, next_eip arguments to gen_interrupt
target/i386: Create gen_update_eip_cur
target/i386: Create gen_update_eip_next
target/i386: Introduce DISAS_EOB*
target/i386: Use DISAS_EOB* in gen_movl_seg_T0
target/i386: Use DISAS_EOB_NEXT
target/i386: USe DISAS_EOB_ONLY
target/i386: Create cur_insn_len, cur_insn_len_i32
target/i386: Remove cur_eip, next_eip arguments to gen_repz*
target/i386: Introduce DISAS_JUMP
target/i386: Truncate values for lcall_real to i32
target/i386: Create eip_next_*
target/i386: Use DISAS_TOO_MANY to exit after gen_io_start
target/i386: Create gen_jmp_rel
target/i386: Use gen_jmp_rel for loop and jecxz insns
target/i386: Use gen_jmp_rel for gen_jcc
target/i386: Use gen_jmp_rel for gen_repz*
target/i386: Use gen_jmp_rel for DISAS_TOO_MANY
target/i386: Create gen_eip_cur
target/i386: Enable TARGET_TB_PCREL
target/i386/cpu-param.h | 1 +
target/i386/helper.h | 2 +-
target/i386/tcg/seg_helper.c | 6 +-
target/i386/tcg/tcg-cpu.c | 8 +-
target/i386/tcg/translate.c | 710 ++++++++++++++++++-----------------
5 files changed, 365 insertions(+), 362 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 01/22] target/i386: Return bool from disas_insn
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
@ 2022-08-22 23:32 ` Richard Henderson
2022-08-22 23:32 ` [PATCH 02/22] target/i386: Remove cur_eip argument to gen_exception Richard Henderson
` (20 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:32 UTC (permalink / raw)
To: qemu-devel
Instead of returning the new pc, which is present in
DisasContext, return true if an insn was translated.
This is false when we detect a page crossing and must
undo the insn under translation.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 42 +++++++++++++++++++------------------
1 file changed, 22 insertions(+), 20 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index a9a9a9de6e..2bdbfc6ddf 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -4552,7 +4552,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b)
/* convert one instruction. s->base.is_jmp is set if the translation must
be stopped. Return the next pc value */
-static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
+static bool disas_insn(DisasContext *s, CPUState *cpu)
{
CPUX86State *env = cpu->env_ptr;
int b, prefixes;
@@ -4582,12 +4582,13 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
return s->pc;
case 2:
/* Restore state that may affect the next instruction. */
+ s->pc = s->base.pc_next;
s->cc_op_dirty = orig_cc_op_dirty;
s->cc_op = orig_cc_op;
s->base.num_insns--;
tcg_remove_ops_after(s->prev_insn_end);
s->base.is_jmp = DISAS_TOO_MANY;
- return s->base.pc_next;
+ return false;
default:
g_assert_not_reached();
}
@@ -8496,13 +8497,13 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
default:
goto unknown_op;
}
- return s->pc;
+ return true;
illegal_op:
gen_illegal_opcode(s);
- return s->pc;
+ return true;
unknown_op:
gen_unknown_opcode(env, s);
- return s->pc;
+ return true;
}
void tcg_x86_init(void)
@@ -8667,7 +8668,6 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
- target_ulong pc_next;
#ifdef TARGET_VSYSCALL_PAGE
/*
@@ -8680,21 +8680,23 @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
}
#endif
- pc_next = disas_insn(dc, cpu);
- dc->base.pc_next = pc_next;
+ if (disas_insn(dc, cpu)) {
+ target_ulong pc_next = dc->pc;
+ dc->base.pc_next = pc_next;
- if (dc->base.is_jmp == DISAS_NEXT) {
- if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
- /*
- * If single step mode, we generate only one instruction and
- * generate an exception.
- * If irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
- * the flag and abort the translation to give the irqs a
- * chance to happen.
- */
- dc->base.is_jmp = DISAS_TOO_MANY;
- } else if (!is_same_page(&dc->base, pc_next)) {
- dc->base.is_jmp = DISAS_TOO_MANY;
+ if (dc->base.is_jmp == DISAS_NEXT) {
+ if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
+ /*
+ * If single step mode, we generate only one instruction and
+ * generate an exception.
+ * If irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
+ * the flag and abort the translation to give the irqs a
+ * chance to happen.
+ */
+ dc->base.is_jmp = DISAS_TOO_MANY;
+ } else if (!is_same_page(&dc->base, pc_next)) {
+ dc->base.is_jmp = DISAS_TOO_MANY;
+ }
}
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 02/22] target/i386: Remove cur_eip argument to gen_exception
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
2022-08-22 23:32 ` [PATCH 01/22] target/i386: Return bool from disas_insn Richard Henderson
@ 2022-08-22 23:32 ` Richard Henderson
2022-08-22 23:32 ` [PATCH 03/22] target/i386: Remove cur_eip, next_eip arguments to gen_interrupt Richard Henderson
` (19 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:32 UTC (permalink / raw)
To: qemu-devel
All callers pass s->base.pc_next - s->cs_base, which we can just
as well compute within the function. Note the special case of
EXCP_VSYSCALL in which s->cs_base didn't have the subtraction,
but cs_base is always zero in 64-bit mode, when vsyscall is used.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 2bdbfc6ddf..f6a861e10c 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -1332,10 +1332,10 @@ static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
}
}
-static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
+static void gen_exception(DisasContext *s, int trapno)
{
gen_update_cc_op(s);
- gen_jmp_im(s, cur_eip);
+ gen_jmp_im(s, s->base.pc_next - s->cs_base);
gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
s->base.is_jmp = DISAS_NORETURN;
}
@@ -1344,13 +1344,13 @@ static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
the instruction is known, but it isn't allowed in the current cpu mode. */
static void gen_illegal_opcode(DisasContext *s)
{
- gen_exception(s, EXCP06_ILLOP, s->base.pc_next - s->cs_base);
+ gen_exception(s, EXCP06_ILLOP);
}
/* Generate #GP for the current instruction. */
static void gen_exception_gpf(DisasContext *s)
{
- gen_exception(s, EXCP0D_GPF, s->base.pc_next - s->cs_base);
+ gen_exception(s, EXCP0D_GPF);
}
/* Check for cpl == 0; if not, raise #GP and return false. */
@@ -3148,7 +3148,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b)
}
/* simple MMX/SSE operation */
if (s->flags & HF_TS_MASK) {
- gen_exception(s, EXCP07_PREX, s->base.pc_next - s->cs_base);
+ gen_exception(s, EXCP07_PREX);
return;
}
if (s->flags & HF_EM_MASK) {
@@ -5929,7 +5929,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
/* if CR0.EM or CR0.TS are set, generate an FPU exception */
/* XXX: what to do if illegal op ? */
- gen_exception(s, EXCP07_PREX, s->base.pc_next - s->cs_base);
+ gen_exception(s, EXCP07_PREX);
break;
}
modrm = x86_ldub_code(env, s);
@@ -7154,7 +7154,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
val = x86_ldub_code(env, s);
if (val == 0) {
- gen_exception(s, EXCP00_DIVZ, s->base.pc_next - s->cs_base);
+ gen_exception(s, EXCP00_DIVZ);
} else {
gen_helper_aam(cpu_env, tcg_const_i32(val));
set_cc_op(s, CC_OP_LOGICB);
@@ -7188,7 +7188,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0x9b: /* fwait */
if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
(HF_MP_MASK | HF_TS_MASK)) {
- gen_exception(s, EXCP07_PREX, s->base.pc_next - s->cs_base);
+ gen_exception(s, EXCP07_PREX);
} else {
gen_helper_fwait(cpu_env);
}
@@ -8245,7 +8245,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
- gen_exception(s, EXCP07_PREX, s->base.pc_next - s->cs_base);
+ gen_exception(s, EXCP07_PREX);
break;
}
gen_lea_modrm(env, s, modrm);
@@ -8258,7 +8258,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
- gen_exception(s, EXCP07_PREX, s->base.pc_next - s->cs_base);
+ gen_exception(s, EXCP07_PREX);
break;
}
gen_lea_modrm(env, s, modrm);
@@ -8270,7 +8270,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
if (s->flags & HF_TS_MASK) {
- gen_exception(s, EXCP07_PREX, s->base.pc_next - s->cs_base);
+ gen_exception(s, EXCP07_PREX);
break;
}
gen_lea_modrm(env, s, modrm);
@@ -8283,7 +8283,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
if (s->flags & HF_TS_MASK) {
- gen_exception(s, EXCP07_PREX, s->base.pc_next - s->cs_base);
+ gen_exception(s, EXCP07_PREX);
break;
}
gen_helper_update_mxcsr(cpu_env);
@@ -8674,7 +8674,7 @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
* Detect entry into the vsyscall page and invoke the syscall.
*/
if ((dc->base.pc_next & TARGET_PAGE_MASK) == TARGET_VSYSCALL_PAGE) {
- gen_exception(dc, EXCP_VSYSCALL, dc->base.pc_next);
+ gen_exception(dc, EXCP_VSYSCALL);
dc->base.pc_next = dc->pc + 1;
return;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 03/22] target/i386: Remove cur_eip, next_eip arguments to gen_interrupt
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
2022-08-22 23:32 ` [PATCH 01/22] target/i386: Return bool from disas_insn Richard Henderson
2022-08-22 23:32 ` [PATCH 02/22] target/i386: Remove cur_eip argument to gen_exception Richard Henderson
@ 2022-08-22 23:32 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 04/22] target/i386: Create gen_update_eip_cur Richard Henderson
` (18 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:32 UTC (permalink / raw)
To: qemu-devel
All callers pass s->base.pc_next and s->pc, which we can just
as well compute within the function.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index f6a861e10c..d3b16ea28c 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2602,13 +2602,12 @@ static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
/* an interrupt is different from an exception because of the
privilege checks */
-static void gen_interrupt(DisasContext *s, int intno,
- target_ulong cur_eip, target_ulong next_eip)
+static void gen_interrupt(DisasContext *s, int intno)
{
gen_update_cc_op(s);
- gen_jmp_im(s, cur_eip);
- gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
- tcg_const_i32(next_eip - cur_eip));
+ gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_helper_raise_interrupt(cpu_env, tcg_constant_i32(intno),
+ tcg_constant_i32(s->pc - s->base.pc_next));
s->base.is_jmp = DISAS_NORETURN;
}
@@ -7194,12 +7193,12 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
break;
case 0xcc: /* int3 */
- gen_interrupt(s, EXCP03_INT3, s->base.pc_next - s->cs_base, s->pc - s->cs_base);
+ gen_interrupt(s, EXCP03_INT3);
break;
case 0xcd: /* int N */
val = x86_ldub_code(env, s);
if (check_vm86_iopl(s)) {
- gen_interrupt(s, val, s->base.pc_next - s->cs_base, s->pc - s->cs_base);
+ gen_interrupt(s, val);
}
break;
case 0xce: /* into */
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 04/22] target/i386: Create gen_update_eip_cur
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (2 preceding siblings ...)
2022-08-22 23:32 ` [PATCH 03/22] target/i386: Remove cur_eip, next_eip arguments to gen_interrupt Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 05/22] target/i386: Create gen_update_eip_next Richard Henderson
` (17 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Like gen_update_cc_op, sync EIP before doing something
that could raise an exception. Replace all gen_jmp_im
that use s->base.pc_next.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 52 ++++++++++++++++++++-----------------
1 file changed, 28 insertions(+), 24 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index d3b16ea28c..78b7641786 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -511,10 +511,14 @@ static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
}
}
-static inline void gen_jmp_im(DisasContext *s, target_ulong pc)
+static void gen_jmp_im(DisasContext *s, target_ulong pc)
{
- tcg_gen_movi_tl(s->tmp0, pc);
- gen_op_jmp_v(s->tmp0);
+ gen_op_jmp_v(tcg_constant_tl(pc));
+}
+
+static void gen_update_eip_cur(DisasContext *s)
+{
+ gen_jmp_im(s, s->base.pc_next - s->cs_base);
}
/* Compute SEG:REG into A0. SEG is selected from the override segment
@@ -703,7 +707,7 @@ static bool gen_check_io(DisasContext *s, MemOp ot, TCGv_i32 port,
target_ulong next_eip = s->pc - s->cs_base;
gen_update_cc_op(s);
- gen_jmp_im(s, cur_eip);
+ gen_update_eip_cur(s);
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
svm_flags |= SVM_IOIO_REP_MASK;
}
@@ -1335,7 +1339,7 @@ static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
static void gen_exception(DisasContext *s, int trapno)
{
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
s->base.is_jmp = DISAS_NORETURN;
}
@@ -2605,7 +2609,7 @@ static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
static void gen_interrupt(DisasContext *s, int intno)
{
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_raise_interrupt(cpu_env, tcg_constant_i32(intno),
tcg_constant_i32(s->pc - s->base.pc_next));
s->base.is_jmp = DISAS_NORETURN;
@@ -6683,7 +6687,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
do_lret:
if (PE(s) && !VM86(s)) {
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
tcg_const_i32(val));
} else {
@@ -7179,7 +7183,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
if (prefixes & PREFIX_REPZ) {
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_pause(cpu_env, tcg_const_i32(s->pc - s->base.pc_next));
s->base.is_jmp = DISAS_NORETURN;
}
@@ -7205,7 +7209,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (CODE64(s))
goto illegal_op;
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_into(cpu_env, tcg_const_i32(s->pc - s->base.pc_next));
break;
#ifdef WANT_ICEBP
@@ -7312,7 +7316,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0x132: /* rdmsr */
if (check_cpl0(s)) {
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
if (b & 2) {
gen_helper_rdmsr(cpu_env);
} else {
@@ -7324,7 +7328,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
case 0x131: /* rdtsc */
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
@@ -7335,7 +7339,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
case 0x133: /* rdpmc */
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_rdpmc(cpu_env);
s->base.is_jmp = DISAS_NORETURN;
break;
@@ -7365,7 +7369,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0x105: /* syscall */
/* XXX: is it usable in real mode ? */
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - s->base.pc_next));
/* TF handling for the syscall insn is different. The TF bit is checked
after the syscall insn completes. This allows #DB to not be
@@ -7391,13 +7395,13 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
#endif
case 0x1a2: /* cpuid */
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_cpuid(cpu_env);
break;
case 0xf4: /* hlt */
if (check_cpl0(s)) {
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - s->base.pc_next));
s->base.is_jmp = DISAS_NORETURN;
}
@@ -7494,7 +7498,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
gen_extu(s->aflag, s->A0);
gen_add_A0_ds_seg(s);
@@ -7506,7 +7510,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - s->base.pc_next));
s->base.is_jmp = DISAS_NORETURN;
break;
@@ -7584,7 +7588,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
}
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
tcg_const_i32(s->pc - s->base.pc_next));
tcg_gen_exit_tb(NULL, 0);
@@ -7596,7 +7600,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_vmmcall(cpu_env);
break;
@@ -7608,7 +7612,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
}
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
break;
@@ -7620,7 +7624,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
}
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
break;
@@ -7646,7 +7650,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
}
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
gen_helper_clgi(cpu_env);
break;
@@ -7792,7 +7796,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
gen_update_cc_op(s);
- gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ gen_update_eip_cur(s);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
}
@@ -8705,7 +8709,7 @@ static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
DisasContext *dc = container_of(dcbase, DisasContext, base);
if (dc->base.is_jmp == DISAS_TOO_MANY) {
- gen_jmp_im(dc, dc->base.pc_next - dc->cs_base);
+ gen_update_eip_cur(dc);
gen_eob(dc);
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 05/22] target/i386: Create gen_update_eip_next
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (3 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 04/22] target/i386: Create gen_update_eip_cur Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 06/22] target/i386: Introduce DISAS_EOB* Richard Henderson
` (16 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Sync EIP before exiting a translation block.
Replace all gen_jmp_im that use s->pc.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 45 ++++++++++++++++++++-----------------
1 file changed, 25 insertions(+), 20 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 78b7641786..36883410e0 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -521,6 +521,11 @@ static void gen_update_eip_cur(DisasContext *s)
gen_jmp_im(s, s->base.pc_next - s->cs_base);
}
+static void gen_update_eip_next(DisasContext *s)
+{
+ gen_jmp_im(s, s->pc - s->cs_base);
+}
+
/* Compute SEG:REG into A0. SEG is selected from the override segment
(OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
indicate no override. */
@@ -5562,7 +5567,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_pop_update(s, ot);
/* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
if (s->base.is_jmp) {
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
if (reg == R_SS) {
s->flags &= ~HF_TF_MASK;
gen_eob_inhibit_irq(s, true);
@@ -5577,7 +5582,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_movl_seg_T0(s, (b >> 3) & 7);
gen_pop_update(s, ot);
if (s->base.is_jmp) {
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
}
break;
@@ -5628,7 +5633,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_movl_seg_T0(s, reg);
/* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
if (s->base.is_jmp) {
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
if (reg == R_SS) {
s->flags &= ~HF_TF_MASK;
gen_eob_inhibit_irq(s, true);
@@ -5835,7 +5840,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
/* then put the data */
gen_op_mov_reg_v(s, ot, reg, s->T1);
if (s->base.is_jmp) {
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
}
break;
@@ -6891,7 +6896,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_pop_update(s, ot);
set_cc_op(s, CC_OP_EFLAGS);
/* abort translation because TF/AC flag may change */
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
}
break;
@@ -7227,7 +7232,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (check_iopl(s)) {
gen_helper_sti(cpu_env);
/* interruptions are enabled only the first insn after sti */
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob_inhibit_irq(s, true);
}
break;
@@ -7303,7 +7308,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
gen_set_label(l3);
- gen_jmp_im(s, next_eip);
+ gen_update_eip_next(s);
tcg_gen_br(l2);
gen_set_label(l1);
@@ -7321,7 +7326,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_helper_rdmsr(cpu_env);
} else {
gen_helper_wrmsr(cpu_env);
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
}
}
@@ -7521,7 +7526,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
gen_helper_clac(cpu_env);
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
break;
@@ -7531,7 +7536,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
gen_helper_stac(cpu_env);
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
break;
@@ -7576,7 +7581,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
gen_helper_xsetbv(cpu_env, s->tmp2_i32, s->tmp1_i64);
/* End TB because translation flags may change. */
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
break;
@@ -7638,7 +7643,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
gen_update_cc_op(s);
gen_helper_stgi(cpu_env);
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
break;
@@ -7677,7 +7682,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
tcg_gen_ext32u_tl(s->A0, cpu_regs[R_EAX]);
}
gen_helper_flush_page(cpu_env, s->A0);
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
break;
@@ -7761,7 +7766,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
tcg_gen_andi_tl(s->T1, s->T1, ~0xe);
tcg_gen_or_tl(s->T0, s->T0, s->T1);
gen_helper_write_crN(cpu_env, tcg_constant_i32(0), s->T0);
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
break;
@@ -7772,7 +7777,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_svm_check_intercept(s, SVM_EXIT_INVLPG);
gen_lea_modrm(env, s, modrm);
gen_helper_flush_page(cpu_env, s->A0);
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
break;
@@ -8172,7 +8177,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0 + reg);
gen_op_mov_v_reg(s, ot, s->T0, rm);
gen_helper_write_crN(cpu_env, tcg_constant_i32(reg), s->T0);
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
} else {
gen_svm_check_intercept(s, SVM_EXIT_READ_CR0 + reg);
@@ -8207,7 +8212,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_op_mov_v_reg(s, ot, s->T0, rm);
tcg_gen_movi_i32(s->tmp2_i32, reg);
gen_helper_set_dr(cpu_env, s->tmp2_i32, s->T0);
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
} else {
gen_svm_check_intercept(s, SVM_EXIT_READ_DR0 + reg);
@@ -8222,7 +8227,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
gen_helper_clts(cpu_env);
/* abort block because static cpu state changed */
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
}
break;
@@ -8320,7 +8325,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
/* XRSTOR is how MPX is enabled, which changes how
we translate. Thus we need to end the TB. */
gen_update_cc_op(s);
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_eob(s);
break;
@@ -8454,7 +8459,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
g_assert_not_reached();
#else
gen_update_cc_op(s);
- gen_jmp_im(s, s->pc - s->cs_base);
+ gen_update_eip_next(s);
gen_helper_rsm(cpu_env);
#endif /* CONFIG_USER_ONLY */
gen_eob(s);
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 06/22] target/i386: Introduce DISAS_EOB*
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (4 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 05/22] target/i386: Create gen_update_eip_next Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 07/22] target/i386: Use DISAS_EOB* in gen_movl_seg_T0 Richard Henderson
` (15 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Add a few DISAS_TARGET_* aliases to reduce the number of
calls to gen_eob() and gen_eob_inhibit_irq(). So far,
only update i386_tr_translate_insn for exiting the block
because of single-step or previous inhibit irq.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 36883410e0..579ba37e76 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -132,6 +132,10 @@ typedef struct DisasContext {
TCGOp *prev_insn_end;
} DisasContext;
+#define DISAS_EOB_ONLY DISAS_TARGET_0
+#define DISAS_EOB_NEXT DISAS_TARGET_1
+#define DISAS_EOB_INHIBIT_IRQ DISAS_TARGET_2
+
/* The environment in which user-only runs is constrained. */
#ifdef CONFIG_USER_ONLY
#define PE(S) true
@@ -8701,7 +8705,7 @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
* the flag and abort the translation to give the irqs a
* chance to happen.
*/
- dc->base.is_jmp = DISAS_TOO_MANY;
+ dc->base.is_jmp = DISAS_EOB_NEXT;
} else if (!is_same_page(&dc->base, pc_next)) {
dc->base.is_jmp = DISAS_TOO_MANY;
}
@@ -8713,9 +8717,24 @@ static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
- if (dc->base.is_jmp == DISAS_TOO_MANY) {
+ switch (dc->base.is_jmp) {
+ case DISAS_NORETURN:
+ break;
+ case DISAS_TOO_MANY:
+ case DISAS_EOB_NEXT:
+ gen_update_cc_op(dc);
gen_update_eip_cur(dc);
+ /* fall through */
+ case DISAS_EOB_ONLY:
gen_eob(dc);
+ break;
+ case DISAS_EOB_INHIBIT_IRQ:
+ gen_update_cc_op(dc);
+ gen_update_eip_cur(dc);
+ gen_eob_inhibit_irq(dc, true);
+ break;
+ default:
+ g_assert_not_reached();
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 07/22] target/i386: Use DISAS_EOB* in gen_movl_seg_T0
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (5 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 06/22] target/i386: Introduce DISAS_EOB* Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 08/22] target/i386: Use DISAS_EOB_NEXT Richard Henderson
` (14 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Set is_jmp properly in gen_movl_seg_T0, so that the callers
need to nothing special.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 36 +++++-------------------------------
1 file changed, 5 insertions(+), 31 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 579ba37e76..4dc8f4c1f8 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2432,13 +2432,15 @@ static void gen_movl_seg_T0(DisasContext *s, X86Seg seg_reg)
because ss32 may change. For R_SS, translation must always
stop as a special handling must be done to disable hardware
interrupts for the next instruction */
- if (seg_reg == R_SS || (CODE32(s) && seg_reg < R_FS)) {
- s->base.is_jmp = DISAS_TOO_MANY;
+ if (seg_reg == R_SS) {
+ s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
+ } else if (CODE32(s) && seg_reg < R_FS) {
+ s->base.is_jmp = DISAS_EOB_NEXT;
}
} else {
gen_op_movl_seg_T0_vm(s, seg_reg);
if (seg_reg == R_SS) {
- s->base.is_jmp = DISAS_TOO_MANY;
+ s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
}
}
}
@@ -5569,26 +5571,12 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
ot = gen_pop_T0(s);
gen_movl_seg_T0(s, reg);
gen_pop_update(s, ot);
- /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
- if (s->base.is_jmp) {
- gen_update_eip_next(s);
- if (reg == R_SS) {
- s->flags &= ~HF_TF_MASK;
- gen_eob_inhibit_irq(s, true);
- } else {
- gen_eob(s);
- }
- }
break;
case 0x1a1: /* pop fs */
case 0x1a9: /* pop gs */
ot = gen_pop_T0(s);
gen_movl_seg_T0(s, (b >> 3) & 7);
gen_pop_update(s, ot);
- if (s->base.is_jmp) {
- gen_update_eip_next(s);
- gen_eob(s);
- }
break;
/**************************/
@@ -5635,16 +5623,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
gen_movl_seg_T0(s, reg);
- /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
- if (s->base.is_jmp) {
- gen_update_eip_next(s);
- if (reg == R_SS) {
- s->flags &= ~HF_TF_MASK;
- gen_eob_inhibit_irq(s, true);
- } else {
- gen_eob(s);
- }
- }
break;
case 0x8c: /* mov Gv, seg */
modrm = x86_ldub_code(env, s);
@@ -5843,10 +5821,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_movl_seg_T0(s, op);
/* then put the data */
gen_op_mov_reg_v(s, ot, reg, s->T1);
- if (s->base.is_jmp) {
- gen_update_eip_next(s);
- gen_eob(s);
- }
break;
/************************/
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 08/22] target/i386: Use DISAS_EOB_NEXT
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (6 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 07/22] target/i386: Use DISAS_EOB* in gen_movl_seg_T0 Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 09/22] target/i386: USe DISAS_EOB_ONLY Richard Henderson
` (13 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Replace sequences of gen_update_cc_op, gen_update_eip_next,
and gen_eob with the new is_jmp enumerator.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 40 ++++++++++++-------------------------
1 file changed, 13 insertions(+), 27 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 4dc8f4c1f8..73e4330fc0 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -6874,8 +6874,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_pop_update(s, ot);
set_cc_op(s, CC_OP_EFLAGS);
/* abort translation because TF/AC flag may change */
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
}
break;
case 0x9e: /* sahf */
@@ -7304,8 +7303,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_helper_rdmsr(cpu_env);
} else {
gen_helper_wrmsr(cpu_env);
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
}
}
break;
@@ -7504,8 +7502,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
gen_helper_clac(cpu_env);
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
break;
case 0xcb: /* stac */
@@ -7514,8 +7511,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
}
gen_helper_stac(cpu_env);
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
break;
CASE_MODRM_MEM_OP(1): /* sidt */
@@ -7559,8 +7555,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
tcg_gen_trunc_tl_i32(s->tmp2_i32, cpu_regs[R_ECX]);
gen_helper_xsetbv(cpu_env, s->tmp2_i32, s->tmp1_i64);
/* End TB because translation flags may change. */
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
break;
case 0xd8: /* VMRUN */
@@ -7621,8 +7616,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
gen_update_cc_op(s);
gen_helper_stgi(cpu_env);
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
break;
case 0xdd: /* CLGI */
@@ -7660,8 +7654,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
tcg_gen_ext32u_tl(s->A0, cpu_regs[R_EAX]);
}
gen_helper_flush_page(cpu_env, s->A0);
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
break;
CASE_MODRM_MEM_OP(2): /* lgdt */
@@ -7744,8 +7737,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
tcg_gen_andi_tl(s->T1, s->T1, ~0xe);
tcg_gen_or_tl(s->T0, s->T0, s->T1);
gen_helper_write_crN(cpu_env, tcg_constant_i32(0), s->T0);
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
break;
CASE_MODRM_MEM_OP(7): /* invlpg */
@@ -7755,8 +7747,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_svm_check_intercept(s, SVM_EXIT_INVLPG);
gen_lea_modrm(env, s, modrm);
gen_helper_flush_page(cpu_env, s->A0);
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
break;
case 0xf8: /* swapgs */
@@ -8155,8 +8146,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0 + reg);
gen_op_mov_v_reg(s, ot, s->T0, rm);
gen_helper_write_crN(cpu_env, tcg_constant_i32(reg), s->T0);
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
} else {
gen_svm_check_intercept(s, SVM_EXIT_READ_CR0 + reg);
gen_helper_read_crN(s->T0, cpu_env, tcg_constant_i32(reg));
@@ -8190,8 +8180,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_op_mov_v_reg(s, ot, s->T0, rm);
tcg_gen_movi_i32(s->tmp2_i32, reg);
gen_helper_set_dr(cpu_env, s->tmp2_i32, s->T0);
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
} else {
gen_svm_check_intercept(s, SVM_EXIT_READ_DR0 + reg);
tcg_gen_movi_i32(s->tmp2_i32, reg);
@@ -8205,8 +8194,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0);
gen_helper_clts(cpu_env);
/* abort block because static cpu state changed */
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
}
break;
/* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
@@ -8302,9 +8290,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_helper_xrstor(cpu_env, s->A0, s->tmp1_i64);
/* XRSTOR is how MPX is enabled, which changes how
we translate. Thus we need to end the TB. */
- gen_update_cc_op(s);
- gen_update_eip_next(s);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_NEXT;
break;
CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 09/22] target/i386: USe DISAS_EOB_ONLY
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (7 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 08/22] target/i386: Use DISAS_EOB_NEXT Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 10/22] target/i386: Create cur_insn_len, cur_insn_len_i32 Richard Henderson
` (12 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Replace lone calls to gen_eob() with the new enumerator.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 73e4330fc0..1dc3ff67ae 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -6687,7 +6687,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
/* add stack offset */
gen_stack_update(s, val + (2 << dflag));
}
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_ONLY;
break;
case 0xcb: /* lret */
val = 0;
@@ -6705,7 +6705,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
tcg_const_i32(s->pc - s->cs_base));
}
set_cc_op(s, CC_OP_EFLAGS);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_ONLY;
break;
case 0xe8: /* call im */
{
@@ -7291,7 +7291,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_set_label(l1);
gen_jmp_im(s, tval);
gen_set_label(l2);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_ONLY;
}
break;
case 0x130: /* wrmsr */
@@ -7332,7 +7332,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_exception_gpf(s);
} else {
gen_helper_sysenter(cpu_env);
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_ONLY;
}
break;
case 0x135: /* sysexit */
@@ -7343,7 +7343,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_exception_gpf(s);
} else {
gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_ONLY;
}
break;
#ifdef TARGET_X86_64
@@ -8426,7 +8426,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_update_eip_next(s);
gen_helper_rsm(cpu_env);
#endif /* CONFIG_USER_ONLY */
- gen_eob(s);
+ s->base.is_jmp = DISAS_EOB_ONLY;
break;
case 0x1b8: /* SSE4.2 popcnt */
if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 10/22] target/i386: Create cur_insn_len, cur_insn_len_i32
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (8 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 09/22] target/i386: USe DISAS_EOB_ONLY Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 11/22] target/i386: Remove cur_eip, next_eip arguments to gen_repz* Richard Henderson
` (11 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Create common routines for computing the length of the insn.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 1dc3ff67ae..ee8e87a617 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -530,6 +530,16 @@ static void gen_update_eip_next(DisasContext *s)
gen_jmp_im(s, s->pc - s->cs_base);
}
+static int cur_insn_len(DisasContext *s)
+{
+ return s->pc - s->base.pc_next;
+}
+
+static TCGv_i32 cur_insn_len_i32(DisasContext *s)
+{
+ return tcg_constant_i32(cur_insn_len(s));
+}
+
/* Compute SEG:REG into A0. SEG is selected from the override segment
(OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
indicate no override. */
@@ -712,9 +722,6 @@ static bool gen_check_io(DisasContext *s, MemOp ot, TCGv_i32 port,
gen_helper_check_io(cpu_env, port, tcg_constant_i32(1 << ot));
}
if (GUEST(s)) {
- target_ulong cur_eip = s->base.pc_next - s->cs_base;
- target_ulong next_eip = s->pc - s->cs_base;
-
gen_update_cc_op(s);
gen_update_eip_cur(s);
if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
@@ -723,7 +730,7 @@ static bool gen_check_io(DisasContext *s, MemOp ot, TCGv_i32 port,
svm_flags |= 1 << (SVM_IOIO_SIZE_SHIFT + ot);
gen_helper_svm_check_io(cpu_env, port,
tcg_constant_i32(svm_flags),
- tcg_constant_i32(next_eip - cur_eip));
+ cur_insn_len_i32(s));
}
return true;
#endif
@@ -2028,7 +2035,7 @@ static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
}
s->pc += num_bytes;
- if (unlikely(s->pc - s->base.pc_next > X86_MAX_INSN_LENGTH)) {
+ if (unlikely(cur_insn_len(s) > X86_MAX_INSN_LENGTH)) {
/* If the instruction's 16th byte is on a different page than the 1st, a
* page fault on the second page wins over the general protection fault
* caused by the instruction being too long.
@@ -2622,7 +2629,7 @@ static void gen_interrupt(DisasContext *s, int intno)
gen_update_cc_op(s);
gen_update_eip_cur(s);
gen_helper_raise_interrupt(cpu_env, tcg_constant_i32(intno),
- tcg_constant_i32(s->pc - s->base.pc_next));
+ cur_insn_len_i32(s));
s->base.is_jmp = DISAS_NORETURN;
}
@@ -7166,7 +7173,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (prefixes & PREFIX_REPZ) {
gen_update_cc_op(s);
gen_update_eip_cur(s);
- gen_helper_pause(cpu_env, tcg_const_i32(s->pc - s->base.pc_next));
+ gen_helper_pause(cpu_env, cur_insn_len_i32(s));
s->base.is_jmp = DISAS_NORETURN;
}
break;
@@ -7192,7 +7199,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
goto illegal_op;
gen_update_cc_op(s);
gen_update_eip_cur(s);
- gen_helper_into(cpu_env, tcg_const_i32(s->pc - s->base.pc_next));
+ gen_helper_into(cpu_env, cur_insn_len_i32(s));
break;
#ifdef WANT_ICEBP
case 0xf1: /* icebp (undocumented, exits to external debugger) */
@@ -7351,7 +7358,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
/* XXX: is it usable in real mode ? */
gen_update_cc_op(s);
gen_update_eip_cur(s);
- gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - s->base.pc_next));
+ gen_helper_syscall(cpu_env, cur_insn_len_i32(s));
/* TF handling for the syscall insn is different. The TF bit is checked
after the syscall insn completes. This allows #DB to not be
generated after one has entered CPL0 if TF is set in FMASK. */
@@ -7383,7 +7390,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (check_cpl0(s)) {
gen_update_cc_op(s);
gen_update_eip_cur(s);
- gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - s->base.pc_next));
+ gen_helper_hlt(cpu_env, cur_insn_len_i32(s));
s->base.is_jmp = DISAS_NORETURN;
}
break;
@@ -7492,7 +7499,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
gen_update_cc_op(s);
gen_update_eip_cur(s);
- gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - s->base.pc_next));
+ gen_helper_mwait(cpu_env, cur_insn_len_i32(s));
s->base.is_jmp = DISAS_NORETURN;
break;
@@ -7568,7 +7575,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_update_cc_op(s);
gen_update_eip_cur(s);
gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
- tcg_const_i32(s->pc - s->base.pc_next));
+ cur_insn_len_i32(s));
tcg_gen_exit_tb(NULL, 0);
s->base.is_jmp = DISAS_NORETURN;
break;
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 11/22] target/i386: Remove cur_eip, next_eip arguments to gen_repz*
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (9 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 10/22] target/i386: Create cur_insn_len, cur_insn_len_i32 Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 12/22] target/i386: Introduce DISAS_JUMP Richard Henderson
` (10 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
All callers pass s->base.pc_next and s->pc, which we can just
as well compute within the functions. Pull out common helpers
and reduce the amount of code under macros.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 116 ++++++++++++++++++------------------
1 file changed, 57 insertions(+), 59 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index ee8e87a617..38f4589fd2 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -736,7 +736,7 @@ static bool gen_check_io(DisasContext *s, MemOp ot, TCGv_i32 port,
#endif
}
-static inline void gen_movs(DisasContext *s, MemOp ot)
+static void gen_movs(DisasContext *s, MemOp ot)
{
gen_string_movl_A0_ESI(s);
gen_op_ld_v(s, ot, s->T0, s->A0);
@@ -1156,18 +1156,18 @@ static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
/* XXX: does not work with gdbstub "ice" single step - not a
serious problem */
-static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
+static TCGLabel *gen_jz_ecx_string(DisasContext *s)
{
TCGLabel *l1 = gen_new_label();
TCGLabel *l2 = gen_new_label();
gen_op_jnz_ecx(s, s->aflag, l1);
gen_set_label(l2);
- gen_jmp_tb(s, next_eip, 1);
+ gen_jmp_tb(s, s->pc - s->cs_base, 1);
gen_set_label(l1);
return l2;
}
-static inline void gen_stos(DisasContext *s, MemOp ot)
+static void gen_stos(DisasContext *s, MemOp ot)
{
gen_op_mov_v_reg(s, MO_32, s->T0, R_EAX);
gen_string_movl_A0_EDI(s);
@@ -1176,7 +1176,7 @@ static inline void gen_stos(DisasContext *s, MemOp ot)
gen_op_add_reg_T0(s, s->aflag, R_EDI);
}
-static inline void gen_lods(DisasContext *s, MemOp ot)
+static void gen_lods(DisasContext *s, MemOp ot)
{
gen_string_movl_A0_ESI(s);
gen_op_ld_v(s, ot, s->T0, s->A0);
@@ -1185,7 +1185,7 @@ static inline void gen_lods(DisasContext *s, MemOp ot)
gen_op_add_reg_T0(s, s->aflag, R_ESI);
}
-static inline void gen_scas(DisasContext *s, MemOp ot)
+static void gen_scas(DisasContext *s, MemOp ot)
{
gen_string_movl_A0_EDI(s);
gen_op_ld_v(s, ot, s->T1, s->A0);
@@ -1194,7 +1194,7 @@ static inline void gen_scas(DisasContext *s, MemOp ot)
gen_op_add_reg_T0(s, s->aflag, R_EDI);
}
-static inline void gen_cmps(DisasContext *s, MemOp ot)
+static void gen_cmps(DisasContext *s, MemOp ot)
{
gen_string_movl_A0_EDI(s);
gen_op_ld_v(s, ot, s->T1, s->A0);
@@ -1222,7 +1222,7 @@ static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
}
}
-static inline void gen_ins(DisasContext *s, MemOp ot)
+static void gen_ins(DisasContext *s, MemOp ot)
{
gen_string_movl_A0_EDI(s);
/* Note: we must do this dummy write first to be restartable in
@@ -1238,7 +1238,7 @@ static inline void gen_ins(DisasContext *s, MemOp ot)
gen_bpt_io(s, s->tmp2_i32, ot);
}
-static inline void gen_outs(DisasContext *s, MemOp ot)
+static void gen_outs(DisasContext *s, MemOp ot)
{
gen_string_movl_A0_ESI(s);
gen_op_ld_v(s, ot, s->T0, s->A0);
@@ -1252,42 +1252,49 @@ static inline void gen_outs(DisasContext *s, MemOp ot)
gen_bpt_io(s, s->tmp2_i32, ot);
}
-/* same method as Valgrind : we generate jumps to current or next
- instruction */
-#define GEN_REPZ(op) \
-static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
- target_ulong cur_eip, target_ulong next_eip) \
-{ \
- TCGLabel *l2; \
- gen_update_cc_op(s); \
- l2 = gen_jz_ecx_string(s, next_eip); \
- gen_ ## op(s, ot); \
- gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
- /* a loop would cause two single step exceptions if ECX = 1 \
- before rep string_insn */ \
- if (s->repz_opt) \
- gen_op_jz_ecx(s, s->aflag, l2); \
- gen_jmp(s, cur_eip); \
+/* Generate jumps to current or next instruction */
+static void gen_repz(DisasContext *s, MemOp ot,
+ void (*fn)(DisasContext *s, MemOp ot))
+{
+ TCGLabel *l2;
+ gen_update_cc_op(s);
+ l2 = gen_jz_ecx_string(s);
+ fn(s, ot);
+ gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
+ /*
+ * A loop would cause two single step exceptions if ECX = 1
+ * before rep string_insn
+ */
+ if (s->repz_opt) {
+ gen_op_jz_ecx(s, s->aflag, l2);
+ }
+ gen_jmp(s, s->base.pc_next - s->cs_base);
}
-#define GEN_REPZ2(op) \
-static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, \
- target_ulong cur_eip, \
- target_ulong next_eip, \
- int nz) \
-{ \
- TCGLabel *l2; \
- gen_update_cc_op(s); \
- l2 = gen_jz_ecx_string(s, next_eip); \
- gen_ ## op(s, ot); \
- gen_op_add_reg_im(s, s->aflag, R_ECX, -1); \
- gen_update_cc_op(s); \
- gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
- if (s->repz_opt) \
- gen_op_jz_ecx(s, s->aflag, l2); \
- gen_jmp(s, cur_eip); \
+#define GEN_REPZ(op) \
+ static inline void gen_repz_ ## op(DisasContext *s, MemOp ot) \
+ { gen_repz(s, ot, gen_##op); }
+
+static void gen_repz2(DisasContext *s, MemOp ot, int nz,
+ void (*fn)(DisasContext *s, MemOp ot))
+{
+ TCGLabel *l2;
+ gen_update_cc_op(s);
+ l2 = gen_jz_ecx_string(s);
+ fn(s, ot);
+ gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
+ gen_update_cc_op(s);
+ gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2);
+ if (s->repz_opt) {
+ gen_op_jz_ecx(s, s->aflag, l2);
+ }
+ gen_jmp(s, s->base.pc_next - s->cs_base);
}
+#define GEN_REPZ2(op) \
+ static inline void gen_repz_ ## op(DisasContext *s, MemOp ot, int nz) \
+ { gen_repz2(s, ot, nz, gen_##op); }
+
GEN_REPZ(movs)
GEN_REPZ(stos)
GEN_REPZ(lods)
@@ -6475,8 +6482,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0xa5:
ot = mo_b_d(b, dflag);
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
- gen_repz_movs(s, ot, s->base.pc_next - s->cs_base,
- s->pc - s->cs_base);
+ gen_repz_movs(s, ot);
} else {
gen_movs(s, ot);
}
@@ -6486,8 +6492,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0xab:
ot = mo_b_d(b, dflag);
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
- gen_repz_stos(s, ot, s->base.pc_next - s->cs_base,
- s->pc - s->cs_base);
+ gen_repz_stos(s, ot);
} else {
gen_stos(s, ot);
}
@@ -6496,8 +6501,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0xad:
ot = mo_b_d(b, dflag);
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
- gen_repz_lods(s, ot, s->base.pc_next - s->cs_base,
- s->pc - s->cs_base);
+ gen_repz_lods(s, ot);
} else {
gen_lods(s, ot);
}
@@ -6506,11 +6510,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0xaf:
ot = mo_b_d(b, dflag);
if (prefixes & PREFIX_REPNZ) {
- gen_repz_scas(s, ot, s->base.pc_next - s->cs_base,
- s->pc - s->cs_base, 1);
+ gen_repz_scas(s, ot, 1);
} else if (prefixes & PREFIX_REPZ) {
- gen_repz_scas(s, ot, s->base.pc_next - s->cs_base,
- s->pc - s->cs_base, 0);
+ gen_repz_scas(s, ot, 0);
} else {
gen_scas(s, ot);
}
@@ -6520,11 +6522,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0xa7:
ot = mo_b_d(b, dflag);
if (prefixes & PREFIX_REPNZ) {
- gen_repz_cmps(s, ot, s->base.pc_next - s->cs_base,
- s->pc - s->cs_base, 1);
+ gen_repz_cmps(s, ot, 1);
} else if (prefixes & PREFIX_REPZ) {
- gen_repz_cmps(s, ot, s->base.pc_next - s->cs_base,
- s->pc - s->cs_base, 0);
+ gen_repz_cmps(s, ot, 0);
} else {
gen_cmps(s, ot);
}
@@ -6542,8 +6542,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_io_start();
}
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
- gen_repz_ins(s, ot, s->base.pc_next - s->cs_base,
- s->pc - s->cs_base);
+ gen_repz_ins(s, ot);
/* jump generated by gen_repz_ins */
} else {
gen_ins(s, ot);
@@ -6564,8 +6563,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_io_start();
}
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
- gen_repz_outs(s, ot, s->base.pc_next - s->cs_base,
- s->pc - s->cs_base);
+ gen_repz_outs(s, ot);
/* jump generated by gen_repz_outs */
} else {
gen_outs(s, ot);
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 12/22] target/i386: Introduce DISAS_JUMP
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (10 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 11/22] target/i386: Remove cur_eip, next_eip arguments to gen_repz* Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 13/22] target/i386: Truncate values for lcall_real to i32 Richard Henderson
` (9 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Drop the unused dest argument to gen_jr().
Remove most of the calls to gen_jr, and use DISAS_JUMP.
Remove some unused loads of eip for lcall and ljmp.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 38f4589fd2..367a7a335a 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -135,6 +135,7 @@ typedef struct DisasContext {
#define DISAS_EOB_ONLY DISAS_TARGET_0
#define DISAS_EOB_NEXT DISAS_TARGET_1
#define DISAS_EOB_INHIBIT_IRQ DISAS_TARGET_2
+#define DISAS_JUMP DISAS_TARGET_3
/* The environment in which user-only runs is constrained. */
#ifdef CONFIG_USER_ONLY
@@ -222,7 +223,7 @@ STUB_HELPER(wrmsr, TCGv_env env)
#endif
static void gen_eob(DisasContext *s);
-static void gen_jr(DisasContext *s, TCGv dest);
+static void gen_jr(DisasContext *s);
static void gen_jmp(DisasContext *s, target_ulong eip);
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
@@ -2360,7 +2361,7 @@ static void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
} else {
/* jump to another page */
gen_jmp_im(s, eip);
- gen_jr(s, s->tmp0);
+ gen_jr(s);
}
}
@@ -2729,7 +2730,7 @@ static void gen_eob(DisasContext *s)
}
/* Jump to register */
-static void gen_jr(DisasContext *s, TCGv dest)
+static void gen_jr(DisasContext *s)
{
do_gen_eob_worker(s, false, false, true);
}
@@ -5171,7 +5172,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_push_v(s, s->T1);
gen_op_jmp_v(s->T0);
gen_bnd_jmp(s);
- gen_jr(s, s->T0);
+ s->base.is_jmp = DISAS_JUMP;
break;
case 3: /* lcall Ev */
if (mod == 3) {
@@ -5192,8 +5193,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
tcg_const_i32(dflag - 1),
tcg_const_i32(s->pc - s->cs_base));
}
- tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
- gen_jr(s, s->tmp4);
+ s->base.is_jmp = DISAS_JUMP;
break;
case 4: /* jmp Ev */
if (dflag == MO_16) {
@@ -5201,7 +5201,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
gen_op_jmp_v(s->T0);
gen_bnd_jmp(s);
- gen_jr(s, s->T0);
+ s->base.is_jmp = DISAS_JUMP;
break;
case 5: /* ljmp Ev */
if (mod == 3) {
@@ -5219,8 +5219,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_op_movl_seg_T0_vm(s, R_CS);
gen_op_jmp_v(s->T1);
}
- tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
- gen_jr(s, s->tmp4);
+ s->base.is_jmp = DISAS_JUMP;
break;
case 6: /* push Ev */
gen_push_v(s, s->T0);
@@ -6660,7 +6659,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
/* Note that gen_pop_T0 uses a zero-extending load. */
gen_op_jmp_v(s->T0);
gen_bnd_jmp(s);
- gen_jr(s, s->T0);
+ s->base.is_jmp = DISAS_JUMP;
break;
case 0xc3: /* ret */
ot = gen_pop_T0(s);
@@ -6668,7 +6667,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
/* Note that gen_pop_T0 uses a zero-extending load. */
gen_op_jmp_v(s->T0);
gen_bnd_jmp(s);
- gen_jr(s, s->T0);
+ s->base.is_jmp = DISAS_JUMP;
break;
case 0xca: /* lret im */
val = x86_ldsw_code(env, s);
@@ -8698,6 +8697,9 @@ static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
gen_update_eip_cur(dc);
gen_eob_inhibit_irq(dc, true);
break;
+ case DISAS_JUMP:
+ gen_jr(dc);
+ break;
default:
g_assert_not_reached();
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 13/22] target/i386: Truncate values for lcall_real to i32
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (11 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 12/22] target/i386: Introduce DISAS_JUMP Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 14/22] target/i386: Create eip_next_* Richard Henderson
` (8 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Use i32 not int or tl for eip and cs arguments.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/helper.h | 2 +-
target/i386/tcg/seg_helper.c | 6 ++----
target/i386/tcg/translate.c | 3 ++-
3 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/target/i386/helper.h b/target/i386/helper.h
index ac3b4d1ee3..39a3c24182 100644
--- a/target/i386/helper.h
+++ b/target/i386/helper.h
@@ -37,7 +37,7 @@ DEF_HELPER_2(lldt, void, env, int)
DEF_HELPER_2(ltr, void, env, int)
DEF_HELPER_3(load_seg, void, env, int, int)
DEF_HELPER_4(ljmp_protected, void, env, int, tl, tl)
-DEF_HELPER_5(lcall_real, void, env, int, tl, int, int)
+DEF_HELPER_5(lcall_real, void, env, i32, i32, int, i32)
DEF_HELPER_5(lcall_protected, void, env, int, tl, int, tl)
DEF_HELPER_2(iret_real, void, env, int)
DEF_HELPER_3(iret_protected, void, env, int, int)
diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index bffd82923f..539189b4d1 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -1504,14 +1504,12 @@ void helper_ljmp_protected(CPUX86State *env, int new_cs, target_ulong new_eip,
}
/* real mode call */
-void helper_lcall_real(CPUX86State *env, int new_cs, target_ulong new_eip1,
- int shift, int next_eip)
+void helper_lcall_real(CPUX86State *env, uint32_t new_cs, uint32_t new_eip,
+ int shift, uint32_t next_eip)
{
- int new_eip;
uint32_t esp, esp_mask;
target_ulong ssp;
- new_eip = new_eip1;
esp = env->regs[R_ESP];
esp_mask = get_sp_mask(env->segs[R_SS].flags);
ssp = env->segs[R_SS].base;
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 367a7a335a..13577f5d7b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -5189,7 +5189,8 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
tcg_const_tl(s->pc - s->cs_base));
} else {
tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
- gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->T1,
+ tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
+ gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->tmp3_i32,
tcg_const_i32(dflag - 1),
tcg_const_i32(s->pc - s->cs_base));
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 14/22] target/i386: Create eip_next_*
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (12 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 13/22] target/i386: Truncate values for lcall_real to i32 Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 15/22] target/i386: Use DISAS_TOO_MANY to exit after gen_io_start Richard Henderson
` (7 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Create helpers for loading the address of the next insn.
Use tcg_constant_* in adjacent code where convenient.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 44 +++++++++++++++++++------------------
1 file changed, 23 insertions(+), 21 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 13577f5d7b..47d6cd2fce 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -541,6 +541,16 @@ static TCGv_i32 cur_insn_len_i32(DisasContext *s)
return tcg_constant_i32(cur_insn_len(s));
}
+static TCGv_i32 eip_next_i32(DisasContext *s)
+{
+ return tcg_constant_i32(s->pc - s->cs_base);
+}
+
+static TCGv eip_next_tl(DisasContext *s)
+{
+ return tcg_constant_tl(s->pc - s->cs_base);
+}
+
/* Compute SEG:REG into A0. SEG is selected from the override segment
(OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
indicate no override. */
@@ -1213,12 +1223,9 @@ static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
/* user-mode cpu should not be in IOBPT mode */
g_assert_not_reached();
#else
- TCGv_i32 t_size = tcg_const_i32(1 << ot);
- TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
-
+ TCGv_i32 t_size = tcg_constant_i32(1 << ot);
+ TCGv t_next = eip_next_tl(s);
gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
- tcg_temp_free_i32(t_size);
- tcg_temp_free(t_next);
#endif /* CONFIG_USER_ONLY */
}
}
@@ -5167,9 +5174,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (dflag == MO_16) {
tcg_gen_ext16u_tl(s->T0, s->T0);
}
- next_eip = s->pc - s->cs_base;
- tcg_gen_movi_tl(s->T1, next_eip);
- gen_push_v(s, s->T1);
+ gen_push_v(s, eip_next_tl(s));
gen_op_jmp_v(s->T0);
gen_bnd_jmp(s);
s->base.is_jmp = DISAS_JUMP;
@@ -5185,14 +5190,14 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (PE(s) && !VM86(s)) {
tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
gen_helper_lcall_protected(cpu_env, s->tmp2_i32, s->T1,
- tcg_const_i32(dflag - 1),
- tcg_const_tl(s->pc - s->cs_base));
+ tcg_constant_i32(dflag - 1),
+ eip_next_tl(s));
} else {
tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->tmp3_i32,
- tcg_const_i32(dflag - 1),
- tcg_const_i32(s->pc - s->cs_base));
+ tcg_constant_i32(dflag - 1),
+ eip_next_i32(s));
}
s->base.is_jmp = DISAS_JUMP;
break;
@@ -5215,7 +5220,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (PE(s) && !VM86(s)) {
tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
gen_helper_ljmp_protected(cpu_env, s->tmp2_i32, s->T1,
- tcg_const_tl(s->pc - s->cs_base));
+ eip_next_tl(s));
} else {
gen_op_movl_seg_T0_vm(s, R_CS);
gen_op_jmp_v(s->T1);
@@ -6706,8 +6711,8 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
} else {
- gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
- tcg_const_i32(s->pc - s->cs_base));
+ gen_helper_iret_protected(cpu_env, tcg_constant_i32(dflag - 1),
+ eip_next_i32(s));
}
set_cc_op(s, CC_OP_EFLAGS);
s->base.is_jmp = DISAS_EOB_ONLY;
@@ -6719,15 +6724,13 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
} else {
tval = (int16_t)insn_get(env, s, MO_16);
}
- next_eip = s->pc - s->cs_base;
- tval += next_eip;
+ tval += s->pc - s->cs_base;
if (dflag == MO_16) {
tval &= 0xffff;
} else if (!CODE64(s)) {
tval &= 0xffffffff;
}
- tcg_gen_movi_tl(s->T0, next_eip);
- gen_push_v(s, s->T0);
+ gen_push_v(s, eip_next_tl(s));
gen_bnd_jmp(s);
gen_jmp(s, tval);
}
@@ -7261,8 +7264,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
TCGLabel *l1, *l2, *l3;
tval = (int8_t)insn_get(env, s, MO_8);
- next_eip = s->pc - s->cs_base;
- tval += next_eip;
+ tval += s->pc - s->cs_base;
if (dflag == MO_16) {
tval &= 0xffff;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 15/22] target/i386: Use DISAS_TOO_MANY to exit after gen_io_start
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (13 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 14/22] target/i386: Create eip_next_* Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 16/22] target/i386: Create gen_jmp_rel Richard Henderson
` (6 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
We can set is_jmp early, using only one if, and let that
be overwritten by gen_repz_* etc.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 42 +++++++++----------------------------
1 file changed, 10 insertions(+), 32 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 47d6cd2fce..cacd52c50f 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -5492,14 +5492,12 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
+ s->base.is_jmp = DISAS_TOO_MANY;
}
gen_helper_rdrand(s->T0, cpu_env);
rm = (modrm & 7) | REX_B(s);
gen_op_mov_reg_v(s, dflag, rm, s->T0);
set_cc_op(s, CC_OP_EFLAGS);
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
- gen_jmp(s, s->pc - s->cs_base);
- }
break;
default:
@@ -6545,15 +6543,12 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
+ s->base.is_jmp = DISAS_TOO_MANY;
}
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz_ins(s, ot);
- /* jump generated by gen_repz_ins */
} else {
gen_ins(s, ot);
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
- gen_jmp(s, s->pc - s->cs_base);
- }
}
break;
case 0x6e: /* outsS */
@@ -6566,15 +6561,12 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
+ s->base.is_jmp = DISAS_TOO_MANY;
}
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
gen_repz_outs(s, ot);
- /* jump generated by gen_repz_outs */
} else {
gen_outs(s, ot);
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
- gen_jmp(s, s->pc - s->cs_base);
- }
}
break;
@@ -6591,13 +6583,11 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
+ s->base.is_jmp = DISAS_TOO_MANY;
}
gen_helper_in_func(ot, s->T1, s->tmp2_i32);
gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
gen_bpt_io(s, s->tmp2_i32, ot);
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
- gen_jmp(s, s->pc - s->cs_base);
- }
break;
case 0xe6:
case 0xe7:
@@ -6609,14 +6599,12 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
+ s->base.is_jmp = DISAS_TOO_MANY;
}
gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
gen_bpt_io(s, s->tmp2_i32, ot);
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
- gen_jmp(s, s->pc - s->cs_base);
- }
break;
case 0xec:
case 0xed:
@@ -6628,13 +6616,11 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
+ s->base.is_jmp = DISAS_TOO_MANY;
}
gen_helper_in_func(ot, s->T1, s->tmp2_i32);
gen_op_mov_reg_v(s, ot, R_EAX, s->T1);
gen_bpt_io(s, s->tmp2_i32, ot);
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
- gen_jmp(s, s->pc - s->cs_base);
- }
break;
case 0xee:
case 0xef:
@@ -6646,14 +6632,12 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
+ s->base.is_jmp = DISAS_TOO_MANY;
}
gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
tcg_gen_trunc_tl_i32(s->tmp3_i32, s->T1);
gen_helper_out_func(ot, s->tmp2_i32, s->tmp3_i32);
gen_bpt_io(s, s->tmp2_i32, ot);
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
- gen_jmp(s, s->pc - s->cs_base);
- }
break;
/************************/
@@ -7319,11 +7303,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_update_eip_cur(s);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
+ s->base.is_jmp = DISAS_TOO_MANY;
}
gen_helper_rdtsc(cpu_env);
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
- gen_jmp(s, s->pc - s->cs_base);
- }
break;
case 0x133: /* rdpmc */
gen_update_cc_op(s);
@@ -7780,11 +7762,9 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_update_eip_cur(s);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
+ s->base.is_jmp = DISAS_TOO_MANY;
}
gen_helper_rdtscp(cpu_env);
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
- gen_jmp(s, s->pc - s->cs_base);
- }
break;
default:
@@ -8148,6 +8128,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
+ s->base.is_jmp = DISAS_TOO_MANY;
}
if (b & 2) {
gen_svm_check_intercept(s, SVM_EXIT_WRITE_CR0 + reg);
@@ -8158,9 +8139,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
gen_svm_check_intercept(s, SVM_EXIT_READ_CR0 + reg);
gen_helper_read_crN(s->T0, cpu_env, tcg_constant_i32(reg));
gen_op_mov_reg_v(s, ot, rm, s->T0);
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
- gen_jmp(s, s->pc - s->cs_base);
- }
}
break;
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 16/22] target/i386: Create gen_jmp_rel
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (14 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 15/22] target/i386: Use DISAS_TOO_MANY to exit after gen_io_start Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 17/22] target/i386: Use gen_jmp_rel for loop and jecxz insns Richard Henderson
` (5 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Create a common helper for pc-relative branches.
The jmp jb insn was missing a mask for CODE32.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 57 ++++++++++++++++++-------------------
1 file changed, 27 insertions(+), 30 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index cacd52c50f..0a2ec85972 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -226,6 +226,7 @@ static void gen_eob(DisasContext *s);
static void gen_jr(DisasContext *s);
static void gen_jmp(DisasContext *s, target_ulong eip);
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
+static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num);
static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
static void gen_exception_gpf(DisasContext *s);
@@ -1173,7 +1174,7 @@ static TCGLabel *gen_jz_ecx_string(DisasContext *s)
TCGLabel *l2 = gen_new_label();
gen_op_jnz_ecx(s, s->aflag, l1);
gen_set_label(l2);
- gen_jmp_tb(s, s->pc - s->cs_base, 1);
+ gen_jmp_rel(s, MO_32, 0, 1);
gen_set_label(l1);
return l2;
}
@@ -2756,6 +2757,18 @@ static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
}
}
+static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num)
+{
+ target_ulong dest = s->pc - s->cs_base + diff;
+
+ if (ot == MO_16) {
+ dest &= 0xffff;
+ } else if (!CODE64(s)) {
+ dest &= 0xffffffff;
+ }
+ gen_jmp_tb(s, dest, tb_num);
+}
+
static void gen_jmp(DisasContext *s, target_ulong eip)
{
gen_jmp_tb(s, eip, 0);
@@ -6703,20 +6716,12 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
case 0xe8: /* call im */
{
- if (dflag != MO_16) {
- tval = (int32_t)insn_get(env, s, MO_32);
- } else {
- tval = (int16_t)insn_get(env, s, MO_16);
- }
- tval += s->pc - s->cs_base;
- if (dflag == MO_16) {
- tval &= 0xffff;
- } else if (!CODE64(s)) {
- tval &= 0xffffffff;
- }
+ int diff = (dflag != MO_16
+ ? (int32_t)insn_get(env, s, MO_32)
+ : (int16_t)insn_get(env, s, MO_16));
gen_push_v(s, eip_next_tl(s));
gen_bnd_jmp(s);
- gen_jmp(s, tval);
+ gen_jmp_rel(s, dflag, diff, 0);
}
break;
case 0x9a: /* lcall im */
@@ -6734,19 +6739,13 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
goto do_lcall;
case 0xe9: /* jmp im */
- if (dflag != MO_16) {
- tval = (int32_t)insn_get(env, s, MO_32);
- } else {
- tval = (int16_t)insn_get(env, s, MO_16);
+ {
+ int diff = (dflag != MO_16
+ ? (int32_t)insn_get(env, s, MO_32)
+ : (int16_t)insn_get(env, s, MO_16));
+ gen_bnd_jmp(s);
+ gen_jmp_rel(s, dflag, diff, 0);
}
- tval += s->pc - s->cs_base;
- if (dflag == MO_16) {
- tval &= 0xffff;
- } else if (!CODE64(s)) {
- tval &= 0xffffffff;
- }
- gen_bnd_jmp(s);
- gen_jmp(s, tval);
break;
case 0xea: /* ljmp im */
{
@@ -6763,12 +6762,10 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
goto do_ljmp;
case 0xeb: /* jmp Jb */
- tval = (int8_t)insn_get(env, s, MO_8);
- tval += s->pc - s->cs_base;
- if (dflag == MO_16) {
- tval &= 0xffff;
+ {
+ int diff = (int8_t)insn_get(env, s, MO_8);
+ gen_jmp_rel(s, dflag, diff, 0);
}
- gen_jmp(s, tval);
break;
case 0x70 ... 0x7f: /* jcc Jb */
tval = (int8_t)insn_get(env, s, MO_8);
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 17/22] target/i386: Use gen_jmp_rel for loop and jecxz insns
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (15 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 16/22] target/i386: Create gen_jmp_rel Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 18/22] target/i386: Use gen_jmp_rel for gen_jcc Richard Henderson
` (4 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
With gen_jmp_rel, we may chain to the next tb
instead of merely writing to eip and exiting.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 21 ++++++---------------
1 file changed, 6 insertions(+), 15 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 0a2ec85972..59e7596629 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -7242,24 +7242,18 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0xe2: /* loop */
case 0xe3: /* jecxz */
{
- TCGLabel *l1, *l2, *l3;
-
- tval = (int8_t)insn_get(env, s, MO_8);
- tval += s->pc - s->cs_base;
- if (dflag == MO_16) {
- tval &= 0xffff;
- }
+ TCGLabel *l1, *l2;
+ int diff = (int8_t)insn_get(env, s, MO_8);
l1 = gen_new_label();
l2 = gen_new_label();
- l3 = gen_new_label();
gen_update_cc_op(s);
b &= 3;
switch(b) {
case 0: /* loopnz */
case 1: /* loopz */
gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
- gen_op_jz_ecx(s, s->aflag, l3);
+ gen_op_jz_ecx(s, s->aflag, l2);
gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
break;
case 2: /* loop */
@@ -7272,14 +7266,11 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
break;
}
- gen_set_label(l3);
- gen_update_eip_next(s);
- tcg_gen_br(l2);
+ gen_set_label(l2);
+ gen_jmp_rel(s, MO_32, 0, 1);
gen_set_label(l1);
- gen_jmp_im(s, tval);
- gen_set_label(l2);
- s->base.is_jmp = DISAS_EOB_ONLY;
+ gen_jmp_rel(s, dflag, diff, 0);
}
break;
case 0x130: /* wrmsr */
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 18/22] target/i386: Use gen_jmp_rel for gen_jcc
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (16 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 17/22] target/i386: Use gen_jmp_rel for loop and jecxz insns Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 19/22] target/i386: Use gen_jmp_rel for gen_repz* Richard Henderson
` (3 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 57 ++++++++++++-------------------------
1 file changed, 18 insertions(+), 39 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 59e7596629..6d6c751c10 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2373,32 +2373,14 @@ static void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
}
}
-static inline void gen_jcc(DisasContext *s, int b,
- target_ulong val, target_ulong next_eip)
+static void gen_jcc(DisasContext *s, MemOp ot, int b, int diff)
{
- TCGLabel *l1, *l2;
+ TCGLabel *l1 = gen_new_label();
- if (s->jmp_opt) {
- l1 = gen_new_label();
- gen_jcc1(s, b, l1);
-
- gen_goto_tb(s, 0, next_eip);
-
- gen_set_label(l1);
- gen_goto_tb(s, 1, val);
- } else {
- l1 = gen_new_label();
- l2 = gen_new_label();
- gen_jcc1(s, b, l1);
-
- gen_jmp_im(s, next_eip);
- tcg_gen_br(l2);
-
- gen_set_label(l1);
- gen_jmp_im(s, val);
- gen_set_label(l2);
- gen_eob(s);
- }
+ gen_jcc1(s, b, l1);
+ gen_jmp_rel(s, ot, 0, 1);
+ gen_set_label(l1);
+ gen_jmp_rel(s, ot, diff, 0);
}
static void gen_cmovcc1(CPUX86State *env, DisasContext *s, MemOp ot, int b,
@@ -4608,7 +4590,6 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
int shift;
MemOp ot, aflag, dflag;
int modrm, reg, rm, mod, op, opreg, val;
- target_ulong next_eip, tval;
bool orig_cc_op_dirty = s->cc_op_dirty;
CCOp orig_cc_op = s->cc_op;
@@ -6768,22 +6749,20 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
}
break;
case 0x70 ... 0x7f: /* jcc Jb */
- tval = (int8_t)insn_get(env, s, MO_8);
- goto do_jcc;
+ {
+ int diff = (int8_t)insn_get(env, s, MO_8);
+ gen_bnd_jmp(s);
+ gen_jcc(s, dflag, b, diff);
+ }
+ break;
case 0x180 ... 0x18f: /* jcc Jv */
- if (dflag != MO_16) {
- tval = (int32_t)insn_get(env, s, MO_32);
- } else {
- tval = (int16_t)insn_get(env, s, MO_16);
+ {
+ int diff = (dflag != MO_16
+ ? (int32_t)insn_get(env, s, MO_32)
+ : (int16_t)insn_get(env, s, MO_16));
+ gen_bnd_jmp(s);
+ gen_jcc(s, dflag, b, diff);
}
- do_jcc:
- next_eip = s->pc - s->cs_base;
- tval += next_eip;
- if (dflag == MO_16) {
- tval &= 0xffff;
- }
- gen_bnd_jmp(s);
- gen_jcc(s, b, tval, next_eip);
break;
case 0x190 ... 0x19f: /* setcc Gv */
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 19/22] target/i386: Use gen_jmp_rel for gen_repz*
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (17 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 18/22] target/i386: Use gen_jmp_rel for gen_jcc Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 20/22] target/i386: Use gen_jmp_rel for DISAS_TOO_MANY Richard Henderson
` (2 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Subtract cur_insn_len to restart the current insn.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 6d6c751c10..67c803263b 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -224,7 +224,6 @@ STUB_HELPER(wrmsr, TCGv_env env)
static void gen_eob(DisasContext *s);
static void gen_jr(DisasContext *s);
-static void gen_jmp(DisasContext *s, target_ulong eip);
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num);
static void gen_op(DisasContext *s1, int op, MemOp ot, int d);
@@ -1277,7 +1276,7 @@ static void gen_repz(DisasContext *s, MemOp ot,
if (s->repz_opt) {
gen_op_jz_ecx(s, s->aflag, l2);
}
- gen_jmp(s, s->base.pc_next - s->cs_base);
+ gen_jmp_rel(s, MO_32, -cur_insn_len(s), 0);
}
#define GEN_REPZ(op) \
@@ -1297,7 +1296,7 @@ static void gen_repz2(DisasContext *s, MemOp ot, int nz,
if (s->repz_opt) {
gen_op_jz_ecx(s, s->aflag, l2);
}
- gen_jmp(s, s->base.pc_next - s->cs_base);
+ gen_jmp_rel(s, MO_32, -cur_insn_len(s), 0);
}
#define GEN_REPZ2(op) \
@@ -2751,11 +2750,6 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num)
gen_jmp_tb(s, dest, tb_num);
}
-static void gen_jmp(DisasContext *s, target_ulong eip)
-{
- gen_jmp_tb(s, eip, 0);
-}
-
static inline void gen_ldq_env_A0(DisasContext *s, int offset)
{
tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ);
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 20/22] target/i386: Use gen_jmp_rel for DISAS_TOO_MANY
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (18 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 19/22] target/i386: Use gen_jmp_rel for gen_repz* Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 21/22] target/i386: Create gen_eip_cur Richard Henderson
2022-08-22 23:33 ` [PATCH 22/22] target/i386: Enable TARGET_TB_PCREL Richard Henderson
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
With gen_jmp_rel, we may chain between two translation blocks
which may only be separated because of TB size limits.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 67c803263b..846040c1ab 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -8627,6 +8627,9 @@ static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
case DISAS_NORETURN:
break;
case DISAS_TOO_MANY:
+ gen_update_cc_op(dc);
+ gen_jmp_rel(dc, MO_32, 0, 0);
+ break;
case DISAS_EOB_NEXT:
gen_update_cc_op(dc);
gen_update_eip_cur(dc);
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 21/22] target/i386: Create gen_eip_cur
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (19 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 20/22] target/i386: Use gen_jmp_rel for DISAS_TOO_MANY Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
2022-08-22 23:33 ` [PATCH 22/22] target/i386: Enable TARGET_TB_PCREL Richard Henderson
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/tcg/translate.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 846040c1ab..6192a3e30e 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -516,6 +516,11 @@ static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
}
}
+static TCGv gen_eip_cur(DisasContext *s)
+{
+ return tcg_constant_tl(s->base.pc_next - s->cs_base);
+}
+
static void gen_jmp_im(DisasContext *s, target_ulong pc)
{
gen_op_jmp_v(tcg_constant_tl(pc));
@@ -6461,7 +6466,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
offsetof(CPUX86State, segs[R_CS].selector));
tcg_gen_st16_i32(s->tmp2_i32, cpu_env,
offsetof(CPUX86State, fpcs));
- tcg_gen_st_tl(tcg_constant_tl(s->base.pc_next - s->cs_base),
+ tcg_gen_st_tl(gen_eip_cur(s),
cpu_env, offsetof(CPUX86State, fpip));
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 22/22] target/i386: Enable TARGET_TB_PCREL
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
` (20 preceding siblings ...)
2022-08-22 23:33 ` [PATCH 21/22] target/i386: Create gen_eip_cur Richard Henderson
@ 2022-08-22 23:33 ` Richard Henderson
21 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2022-08-22 23:33 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/cpu-param.h | 1 +
target/i386/tcg/tcg-cpu.c | 8 ++--
target/i386/tcg/translate.c | 86 ++++++++++++++++++++++++++++++-------
3 files changed, 77 insertions(+), 18 deletions(-)
diff --git a/target/i386/cpu-param.h b/target/i386/cpu-param.h
index 9740bd7abd..51a3f153bf 100644
--- a/target/i386/cpu-param.h
+++ b/target/i386/cpu-param.h
@@ -24,5 +24,6 @@
#endif
#define TARGET_PAGE_BITS 12
#define NB_MMU_MODES 3
+#define TARGET_TB_PCREL 1
#endif
diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
index 76989a5a9d..74333247c5 100644
--- a/target/i386/tcg/tcg-cpu.c
+++ b/target/i386/tcg/tcg-cpu.c
@@ -49,9 +49,11 @@ static void x86_cpu_exec_exit(CPUState *cs)
static void x86_cpu_synchronize_from_tb(CPUState *cs,
const TranslationBlock *tb)
{
- X86CPU *cpu = X86_CPU(cs);
-
- cpu->env.eip = tb_pc(tb) - tb->cs_base;
+ /* The instruction pointer is always up to date with TARGET_TB_PCREL. */
+ if (!TARGET_TB_PCREL) {
+ CPUX86State *env = cs->env_ptr;
+ env->eip = tb_pc(tb) - tb->cs_base;
+ }
}
#ifndef CONFIG_USER_ONLY
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 6192a3e30e..5e252f26b2 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -64,6 +64,7 @@
/* global register indexes */
static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2;
+static TCGv cpu_eip;
static TCGv_i32 cpu_cc_op;
static TCGv cpu_regs[CPU_NB_REGS];
static TCGv cpu_seg_base[6];
@@ -77,6 +78,7 @@ typedef struct DisasContext {
target_ulong pc; /* pc = eip + cs_base */
target_ulong cs_base; /* base of CS segment */
+ target_ulong pc_save;
MemOp aflag;
MemOp dflag;
@@ -481,7 +483,7 @@ static void gen_add_A0_im(DisasContext *s, int val)
static inline void gen_op_jmp_v(TCGv dest)
{
- tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
+ tcg_gen_mov_tl(cpu_eip, dest);
}
static inline
@@ -516,24 +518,36 @@ static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
}
}
-static TCGv gen_eip_cur(DisasContext *s)
+static void gen_jmp_im(DisasContext *s, target_ulong eip)
{
- return tcg_constant_tl(s->base.pc_next - s->cs_base);
-}
-
-static void gen_jmp_im(DisasContext *s, target_ulong pc)
-{
- gen_op_jmp_v(tcg_constant_tl(pc));
+ if (TARGET_TB_PCREL) {
+ target_ulong eip_save = s->pc_save - s->cs_base;
+ tcg_gen_addi_tl(cpu_eip, cpu_eip, eip - eip_save);
+ } else {
+ tcg_gen_movi_tl(cpu_eip, eip);
+ }
}
static void gen_update_eip_cur(DisasContext *s)
{
gen_jmp_im(s, s->base.pc_next - s->cs_base);
+ s->pc_save = s->base.pc_next;
}
static void gen_update_eip_next(DisasContext *s)
{
gen_jmp_im(s, s->pc - s->cs_base);
+ s->pc_save = s->pc;
+}
+
+static TCGv gen_eip_cur(DisasContext *s)
+{
+ if (TARGET_TB_PCREL) {
+ gen_update_eip_cur(s);
+ return cpu_eip;
+ } else {
+ return tcg_constant_tl(s->base.pc_next - s->cs_base);
+ }
}
static int cur_insn_len(DisasContext *s)
@@ -548,12 +562,25 @@ static TCGv_i32 cur_insn_len_i32(DisasContext *s)
static TCGv_i32 eip_next_i32(DisasContext *s)
{
- return tcg_constant_i32(s->pc - s->cs_base);
+ if (TARGET_TB_PCREL) {
+ TCGv_i32 ret = tcg_temp_new_i32();
+ tcg_gen_trunc_tl_i32(ret, cpu_eip);
+ tcg_gen_addi_i32(ret, ret, s->pc - s->pc_save);
+ return ret;
+ } else {
+ return tcg_constant_i32(s->pc - s->cs_base);
+ }
}
static TCGv eip_next_tl(DisasContext *s)
{
- return tcg_constant_tl(s->pc - s->cs_base);
+ if (TARGET_TB_PCREL) {
+ TCGv ret = tcg_temp_new();
+ tcg_gen_addi_tl(ret, cpu_eip, s->pc - s->pc_save);
+ return ret;
+ } else {
+ return tcg_constant_tl(s->pc - s->cs_base);
+ }
}
/* Compute SEG:REG into A0. SEG is selected from the override segment
@@ -2252,7 +2279,12 @@ static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a)
ea = cpu_regs[a.base];
}
if (!ea) {
- tcg_gen_movi_tl(s->A0, a.disp);
+ if (TARGET_TB_PCREL && a.base == -2) {
+ /* With cpu_eip ~= pc_save, the expression is pc-relative. */
+ tcg_gen_addi_tl(s->A0, cpu_eip, a.disp - s->pc_save);
+ } else {
+ tcg_gen_movi_tl(s->A0, a.disp);
+ }
ea = s->A0;
} else if (a.disp != 0) {
tcg_gen_addi_tl(s->A0, ea, a.disp);
@@ -2366,8 +2398,13 @@ static void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
if (translator_use_goto_tb(&s->base, pc)) {
/* jump to same page: we can use a direct jump */
- tcg_gen_goto_tb(tb_num);
- gen_jmp_im(s, eip);
+ if (TARGET_TB_PCREL) {
+ gen_jmp_im(s, eip);
+ tcg_gen_goto_tb(tb_num);
+ } else {
+ tcg_gen_goto_tb(tb_num);
+ gen_jmp_im(s, eip);
+ }
tcg_gen_exit_tb(s->base.tb, tb_num);
s->base.is_jmp = DISAS_NORETURN;
} else {
@@ -8458,6 +8495,13 @@ void tcg_x86_init(void)
[R_EDI] = "edi",
[R_EBP] = "ebp",
[R_ESP] = "esp",
+#endif
+ };
+ static const char eip_name[] = {
+#ifdef TARGET_X86_64
+ "rip"
+#else
+ "eip"
#endif
};
static const char seg_base_names[6][8] = {
@@ -8484,6 +8528,7 @@ void tcg_x86_init(void)
"cc_src");
cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
"cc_src2");
+ cpu_eip = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, eip), eip_name);
for (i = 0; i < CPU_NB_REGS; ++i) {
cpu_regs[i] = tcg_global_mem_new(cpu_env,
@@ -8520,6 +8565,7 @@ static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
int iopl = (flags >> IOPL_SHIFT) & 3;
dc->cs_base = dc->base.tb->cs_base;
+ dc->pc_save = dc->base.pc_next;
dc->flags = flags;
#ifndef CONFIG_USER_ONLY
dc->cpl = cpl;
@@ -8583,9 +8629,14 @@ static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
+ target_ulong pc_arg = dc->base.pc_next;
dc->prev_insn_end = tcg_last_op();
- tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
+ if (TARGET_TB_PCREL) {
+ pc_arg -= dc->cs_base;
+ pc_arg &= ~TARGET_PAGE_MASK;
+ }
+ tcg_gen_insn_start(pc_arg, dc->cc_op);
}
static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
@@ -8686,7 +8737,12 @@ void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
target_ulong *data)
{
int cc_op = data[1];
- env->eip = data[0] - tb->cs_base;
+
+ if (TARGET_TB_PCREL) {
+ env->eip = (env->eip & TARGET_PAGE_MASK) | data[0];
+ } else {
+ env->eip = data[0] - tb->cs_base;
+ }
if (cc_op != CC_OP_DYNAMIC) {
env->cc_op = cc_op;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
end of thread, other threads:[~2022-08-23 0:10 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-08-22 23:32 [PATCH 00/22] target/i386: pc-relative translation Richard Henderson
2022-08-22 23:32 ` [PATCH 01/22] target/i386: Return bool from disas_insn Richard Henderson
2022-08-22 23:32 ` [PATCH 02/22] target/i386: Remove cur_eip argument to gen_exception Richard Henderson
2022-08-22 23:32 ` [PATCH 03/22] target/i386: Remove cur_eip, next_eip arguments to gen_interrupt Richard Henderson
2022-08-22 23:33 ` [PATCH 04/22] target/i386: Create gen_update_eip_cur Richard Henderson
2022-08-22 23:33 ` [PATCH 05/22] target/i386: Create gen_update_eip_next Richard Henderson
2022-08-22 23:33 ` [PATCH 06/22] target/i386: Introduce DISAS_EOB* Richard Henderson
2022-08-22 23:33 ` [PATCH 07/22] target/i386: Use DISAS_EOB* in gen_movl_seg_T0 Richard Henderson
2022-08-22 23:33 ` [PATCH 08/22] target/i386: Use DISAS_EOB_NEXT Richard Henderson
2022-08-22 23:33 ` [PATCH 09/22] target/i386: USe DISAS_EOB_ONLY Richard Henderson
2022-08-22 23:33 ` [PATCH 10/22] target/i386: Create cur_insn_len, cur_insn_len_i32 Richard Henderson
2022-08-22 23:33 ` [PATCH 11/22] target/i386: Remove cur_eip, next_eip arguments to gen_repz* Richard Henderson
2022-08-22 23:33 ` [PATCH 12/22] target/i386: Introduce DISAS_JUMP Richard Henderson
2022-08-22 23:33 ` [PATCH 13/22] target/i386: Truncate values for lcall_real to i32 Richard Henderson
2022-08-22 23:33 ` [PATCH 14/22] target/i386: Create eip_next_* Richard Henderson
2022-08-22 23:33 ` [PATCH 15/22] target/i386: Use DISAS_TOO_MANY to exit after gen_io_start Richard Henderson
2022-08-22 23:33 ` [PATCH 16/22] target/i386: Create gen_jmp_rel Richard Henderson
2022-08-22 23:33 ` [PATCH 17/22] target/i386: Use gen_jmp_rel for loop and jecxz insns Richard Henderson
2022-08-22 23:33 ` [PATCH 18/22] target/i386: Use gen_jmp_rel for gen_jcc Richard Henderson
2022-08-22 23:33 ` [PATCH 19/22] target/i386: Use gen_jmp_rel for gen_repz* Richard Henderson
2022-08-22 23:33 ` [PATCH 20/22] target/i386: Use gen_jmp_rel for DISAS_TOO_MANY Richard Henderson
2022-08-22 23:33 ` [PATCH 21/22] target/i386: Create gen_eip_cur Richard Henderson
2022-08-22 23:33 ` [PATCH 22/22] target/i386: Enable TARGET_TB_PCREL Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).