+2019-12-27 Jan Beulich <jbeulich@suse.com>
+
+ * config/tc-i386.c (flip_code16): New.
+ (output_branch, output_jump): Use it.
+ (i386_displacement): Restrict template set to just direct
+ branches when handling a respective operand. Don't set Disp16
+ when in Intel64 mode and there's a respective template.
+ * testsuite/gas/i386/i386.exp: Convert x86-64-branch-3 from list
+ to dump test. Drop its XFail again.
+ * testsuite/gas/i386/x86-64-branch-3.d: New.
+ * testsuite/gas/i386/x86-64-branch-3.l: Delete.
+ * testsuite/gas/i386/x86-64-branch-3.s: Add XBEGIN case.
+
2019-12-27 Jan Beulich <jbeulich@suse.com>
* config/tc-i386.c (i386_addressing_mode): Declare.
return default_seg;
}
+static unsigned int
+flip_code16 (unsigned int code16)
+{
+ gas_assert (i.tm.operands == 1);
+
+ return !(i.prefix[REX_PREFIX] & REX_W)
+ && (code16 ? i.tm.operand_types[0].bitfield.disp32
+ || i.tm.operand_types[0].bitfield.disp32s
+ : i.tm.operand_types[0].bitfield.disp16)
+ ? CODE16 : 0;
+}
+
static void
output_branch (void)
{
{
prefix = 1;
i.prefixes -= 1;
- code16 ^= CODE16;
+ code16 ^= flip_code16(code16);
}
/* Pentium4 branch hints. */
if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
{
FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
i.prefixes -= 1;
- code16 ^= CODE16;
+ code16 ^= flip_code16(code16);
}
size = 4;
}
else
{
- /* For PC-relative branches, the width of the displacement
- is dependent upon data size, not address size. */
+ /* For PC-relative branches, the width of the displacement may be
+ dependent upon data size, but is never dependent upon address size.
+ Also make sure to not unintentionally match against a non-PC-relative
+ branch template. */
+ static templates aux_templates;
+ const insn_template *t = current_templates->start;
+ bfd_boolean has_intel64 = FALSE;
+
+ aux_templates.start = t;
+ while (++t < current_templates->end)
+ {
+ if (t->opcode_modifier.jump
+ != current_templates->start->opcode_modifier.jump)
+ break;
+ if (t->opcode_modifier.intel64)
+ has_intel64 = TRUE;
+ }
+ if (t < current_templates->end)
+ {
+ aux_templates.end = t;
+ current_templates = &aux_templates;
+ }
+
override = (i.prefix[DATA_PREFIX] != 0);
if (flag_code == CODE_64BIT)
{
- if (override || i.suffix == WORD_MNEM_SUFFIX)
+ if ((override || i.suffix == WORD_MNEM_SUFFIX)
+ && (!intel64 || !has_intel64))
bigdisp.bitfield.disp16 = 1;
else
bigdisp.bitfield.disp32s = 1;
run_dump_test "x86-64-jump"
run_dump_test "x86-64-branch-2"
- setup_xfail "*-*-*"
- run_list_test "x86-64-branch-3" "-al -mintel64"
+ run_dump_test "x86-64-branch-3"
run_list_test "x86-64-branch-4" "-al -mintel64"
run_dump_test "x86-64-gotpcrel"
--- /dev/null
+#as: -J -mintel64
+#objdump: -dwr -Mintel64
+#name: x86-64 branch 3
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <bar-0x6>:
+[ ]*[a-f0-9]+: 66 e9 00 00 00 00 data16 jmpq 6 <bar> 2: R_X86_64_PLT32 foo-0x4
+
+0+6 <bar>:
+[ ]*[a-f0-9]+: 89 c3 mov %eax,%ebx
+[ ]*[a-f0-9]+: 66 e8 00 00 00 00 data16 callq e <bar\+0x8> a: R_X86_64_PLT32 foo-0x4
+[ ]*[a-f0-9]+: 66 c7 f8 00 00 xbeginw 13 <bar\+0xd> 11: R_X86_64_PC16 foo-0x2
+#pass
+++ /dev/null
-.*: Assembler messages:
-.*:2: Warning: indirect jmp without `\*'
-.*:7: Warning: indirect call without `\*'
-GAS LISTING .*
-
-
-[ ]*1[ ]+\.text
-[ ]*2[ ]+0000 66FF2C25 data16 jmp foo
-\*\*\*\* Warning: indirect jmp without `\*'
-[ ]*2[ ]+00000000
-[ ]*3[ ]+
-[ ]*4[ ]+bar:
-[ ]*5[ ]+0008 89C3 mov %eax, %ebx
-[ ]*6[ ]+
-[ ]*7[ ]+000a 66FF1C25 data16 call foo
-\*\*\*\* Warning: indirect call without `\*'
-[ ]*7[ ]+00000000
mov %eax, %ebx
data16 call foo
+
+ data16 xbegin foo
+2019-12-27 Jan Beulich <jbeulich@suse.com>
+
+ * i386-dis.c (Jdqw): Define.
+ (dqw_mode): Adjust associated comment.
+ (rm_table): Use Jdqw for XBEGIN.
+ (OP_J): Handle dqw_mode.
+
2019-12-27 Jan Beulich <jbeulich@suse.com>
* i386-gen.c (process_i386_operand_type): Don't set Disp32 for
#define I1 { OP_I, const_1_mode }
#define Jb { OP_J, b_mode }
#define Jv { OP_J, v_mode }
+#define Jdqw { OP_J, dqw_mode }
#define Cm { OP_C, m_mode }
#define Dm { OP_D, m_mode }
#define Td { OP_T, d_mode }
v_bndmk_mode,
/* operand size depends on REX prefixes. */
dq_mode,
- /* registers like dq_mode, memory like w_mode. */
+ /* registers like dq_mode, memory like w_mode, displacements like
+ v_mode without considering Intel64 ISA. */
dqw_mode,
/* bounds operand */
bnd_mode,
},
{
/* RM_C7_REG_7 */
- { "xbeginT", { Skip_MODRM, Jv }, 0 },
+ { "xbeginT", { Skip_MODRM, Jdqw }, 0 },
},
{
/* RM_0F01_REG_0 */
break;
case v_mode:
if (isa64 == amd64)
+ case dqw_mode:
USED_REX (REX_W);
if ((sizeflag & DFLAG)
|| (address_mode == mode_64bit
- && (isa64 != amd64 || (rex & REX_W))))
+ && ((isa64 != amd64 && bytemode != dqw_mode)
+ || (rex & REX_W))))
disp = get32s ();
else
{