[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] i386: fix 0x66 prefix in disassembler and translato
From: |
Jürgen Buchmüller |
Subject: |
[Qemu-devel] [PATCH] i386: fix 0x66 prefix in disassembler and translator |
Date: |
Sun, 27 Aug 2017 18:40:52 +0200 |
The opcodes 0xe8 (call) and 0xe9 (jump), when prefixed by 0x66, do not
use a 16 bit offset, but still 32 bits, just like conditional relative
jumps. To distinguish between conditional jumps and the unconditional
call/jump add a new call_jump_mode and a call_jump_flag. This
prerevents data size changes for both, call_jump_mode and
cond_jump_mode when using the Intel syntax.
In the translator respect data size changes only, if the CPU is not
and Intel type. Otherwise the size of the call/jmp is always 32 bits.
See https://github.com/xoreaxeaxeax/sandsifter/blob/master/references/d
omas_breaking_the_x86_isa_wp.pdf
for the details and reasoning.
Signed-off-by: Jürgen Buchmüller <address@hidden>
---
disas/i386.c | 31 ++++++++++++++-------------
target/i386/translate.c | 56 ++++++++++++++++++++++++++++++++---------
--------
2 files changed, 54 insertions(+), 33 deletions(-)
diff --git a/disas/i386.c b/disas/i386.c
index f1e376ca4a..2b18285fb8 100644
--- a/disas/i386.c
+++ b/disas/i386.c
@@ -464,6 +464,7 @@ fetch_data(struct disassemble_info *info, bfd_byte
*addr)
#define ALr { REP_Fixup, al_reg }
#define eAXr { REP_Fixup, eAX_reg }
+#define call_jump_flag { NULL, call_jump_mode }
#define cond_jump_flag { NULL, cond_jump_mode }
#define loop_jcxz_flag { NULL, loop_jcxz_mode }
@@ -480,17 +481,18 @@ fetch_data(struct disassemble_info *info,
bfd_byte *addr)
#define t_mode 6 /* ten-byte operand */
#define x_mode 7 /* 16-byte XMM operand */
#define m_mode 8 /* d_mode in 32bit, q_mode in 64bit mode. */
-#define cond_jump_mode 9
-#define loop_jcxz_mode 10
-#define dq_mode 11 /* operand size depends on REX prefixes. */
-#define dqw_mode 12 /* registers like dq_mode, memory like w_mode. */
-#define f_mode 13 /* 4- or 6-byte pointer operand */
-#define const_1_mode 14
-#define stack_v_mode 15 /* v_mode for stack-related opcodes. */
-#define z_mode 16 /* non-quad operand size depends on prefixes */
-#define o_mode 17 /* 16-byte operand */
-#define dqb_mode 18 /* registers like dq_mode, memory like b_mode. */
-#define dqd_mode 19 /* registers like dq_mode, memory like d_mode. */
+#define call_jump_mode 9
+#define cond_jump_mode 10
+#define loop_jcxz_mode 11
+#define dq_mode 12 /* operand size depends on REX prefixes. */
+#define dqw_mode 13 /* registers like dq_mode, memory like w_mode. */
+#define f_mode 14 /* 4- or 6-byte pointer operand */
+#define const_1_mode 15
+#define stack_v_mode 16 /* v_mode for stack-related opcodes. */
+#define z_mode 17 /* non-quad operand size depends on prefixes */
+#define o_mode 18 /* 16-byte operand */
+#define dqb_mode 19 /* registers like dq_mode, memory like b_mode. */
+#define dqd_mode 20 /* registers like dq_mode, memory like d_mode. */
#define es_reg 100
#define cs_reg 101
@@ -1007,8 +1009,8 @@ static const struct dis386 dis386[] = {
{ "outB", { Ib, AL } },
{ "outG", { Ib, zAX } },
/* e8 */
- { "callT", { Jv } },
- { "jmpT", { Jv } },
+ { "callT", { Jv, XX, call_jump_flag } },
+ { "jmpT", { Jv, XX, call_jump_flag } },
{ "Jjmp{T|}", { Ap } },
{ "jmp", { Jb } },
{ "inB", { AL, indirDX } },
@@ -3968,7 +3970,8 @@ print_insn (bfd_vma pc, disassemble_info *info)
if (!uses_DATA_prefix && (prefixes & PREFIX_DATA))
{
sizeflag ^= DFLAG;
- if (dp->op[2].bytemode == cond_jump_mode
+ if ((dp->op[2].bytemode == call_jump_mode
+ || dp->op[2].bytemode == cond_jump_mode)
&& dp->op[0].bytemode == v_mode
&& !intel_syntax)
{
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 5fdadf98cf..a97cc9496f 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -6480,17 +6480,26 @@ static target_ulong disas_insn(CPUX86State
*env, DisasContext *s,
break;
case 0xe8: /* call im */
{
- if (dflag != MO_16) {
- tval = (int32_t)insn_get(env, s, MO_32);
+ if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
+ if (dflag != MO_16) {
+ tval = (int32_t)insn_get(env, s, MO_32);
+ } else {
+ tval = (int16_t)insn_get(env, s, MO_16);
+ }
+ next_eip = s->pc - s->cs_base;
+ tval += next_eip;
+ if (dflag == MO_16) {
+ tval &= 0xffff;
+ } else if (!CODE64(s)) {
+ tval &= 0xffffffff;
+ }
} else {
- tval = (int16_t)insn_get(env, s, MO_16);
- }
- next_eip = s->pc - s->cs_base;
- tval += next_eip;
- if (dflag == MO_16) {
- tval &= 0xffff;
- } else if (!CODE64(s)) {
- tval &= 0xffffffff;
+ tval = (int32_t)insn_get(env, s, MO_32);
+ next_eip = s->pc - s->cs_base;
+ tval += next_eip;
+ if (!CODE64(s)) {
+ tval &= 0xffffffff;
+ }
}
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
@@ -6513,16 +6522,25 @@ static target_ulong disas_insn(CPUX86State
*env, DisasContext *s,
}
goto do_lcall;
case 0xe9: /* jmp im */
- if (dflag != MO_16) {
- tval = (int32_t)insn_get(env, s, MO_32);
+ if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1) {
+ if (dflag != MO_16) {
+ tval = (int32_t)insn_get(env, s, MO_32);
+ } else {
+ tval = (int16_t)insn_get(env, s, MO_16);
+ }
+ next_eip = s->pc - s->cs_base;
+ tval += next_eip;
+ if (dflag == MO_16) {
+ tval &= 0xffff;
+ } else if (!CODE64(s)) {
+ tval &= 0xffffffff;
+ }
} 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;
+ tval = (int32_t)insn_get(env, s, MO_32);
+ tval += s->pc - s->cs_base;
+ if (!CODE64(s)) {
+ tval &= 0xffffffff;
+ }
}
gen_bnd_jmp(s);
gen_jmp(s, tval);
--
2.14.1
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] i386: fix 0x66 prefix in disassembler and translator,
Jürgen Buchmüller <=