This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 2/6] x86-64: Intel64 adjustments for conditional jumps
- From: Jan Beulich <jbeulich at suse dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Cc: "H.J. Lu" <hjl dot tools at gmail dot com>
- Date: Fri, 6 Mar 2020 09:12:06 +0100
- Subject: [PATCH 2/6] x86-64: Intel64 adjustments for conditional jumps
- References: <17ee93b3-33ea-5c10-23b2-408c7fb5b5a2@suse.com>
Just like for unconditional direct JMP, AMD and Intel differ in their
handling. Mirror JMP handling to Jcc.
gas/
2020-03-XX Jan Beulich <jbeulich@suse.com>
* testsuite/gas/i386/x86-64-branch-2.s,
testsuite/gas/i386/x86-64-branch-3.s: Add Jcc cases.
* testsuite/gas/i386/ilp32/x86-64-branch.d,
testsuite/gas/i386/opcode-suffix.d,
testsuite/gas/i386/x86-64-branch-2.d,
testsuite/gas/i386/x86-64-branch-3.d,
testsuite/gas/i386/x86-64-branch.d: Adjust expectations.
opcodes/
2020-03-XX Jan Beulich <jbeulich@suse.com>
* i386-dis.c (safe-ctype.h): Include.
(X86_64_0F8x): New enumerator.
(dis386): Extend comment ahead of it.
(dis386_twobyte): Vector Jcc to X86_64_0F8x.
(condition_code): New.
(x86_64_table): Add X86_64_0F8x entry.
(print_insn): Set condition_code. Move advancing of codep after
it.
(putop): Handle two-char escape case for 'C'. Handle 'C' prefix
case for 'P' and '@'.
* i386-opc.tbl (j<cc>): Split into AMD64 and Intel64 variants.
* i386-tbl.h: Re-generate.
---
I wonder if the suffix handling done here wouldn't also be the more
suitable one for JMP and CALL. In particular the 'q' suffix printed
unconditionally in 64-bit mode is more of a problem than helpful imo.
--- a/gas/testsuite/gas/i386/ilp32/x86-64-branch.d
+++ b/gas/testsuite/gas/i386/ilp32/x86-64-branch.d
@@ -22,7 +22,7 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 0x24 20: R_X86_64_PC32 \*ABS\*\+0x10003c
[ ]*[a-f0-9]+: 66 e8 00 00 00 00 data16 callq 0x2a 26: R_X86_64_PLT32 foo-0x4
[ ]*[a-f0-9]+: 66 e9 00 00 00 00 data16 jmpq 0x30 2c: R_X86_64_PLT32 foo-0x4
-[ ]*[a-f0-9]+: 66 0f 82 00 00 00 00 data16 jb 0x37 33: R_X86_64_PLT32 foo-0x4
+[ ]*[a-f0-9]+: 66 0f 82 00 00 00 00 data16 jbq 0x37 33: R_X86_64_PLT32 foo-0x4
[ ]*[a-f0-9]+: 66 c3 data16 retq *
[ ]*[a-f0-9]+: 66 c2 08 00 data16 retq \$0x8
[ ]*[a-f0-9]+: ff d0 callq \*%rax
--- a/gas/testsuite/gas/i386/opcode-suffix.d
+++ b/gas/testsuite/gas/i386/opcode-suffix.d
@@ -305,22 +305,22 @@ Disassembly of section .text:
*[0-9a-f]+: 0f 77[ ]+emms[ ]+
*[0-9a-f]+: 0f 7e 90 90 90 90 90[ ]+movd[ ]+%mm2,-0x6f6f6f70\(%eax\)
*[0-9a-f]+: 0f 7f 90 90 90 90 90[ ]+movq[ ]+%mm2,-0x6f6f6f70\(%eax\)
- *[0-9a-f]+: 0f 80 90 90 90 90[ ]+jo[ ]+909094e2 <foo\+0x909094e2>
- *[0-9a-f]+: 0f 81 90 90 90 90[ ]+jno[ ]+909094e8 <foo\+0x909094e8>
- *[0-9a-f]+: 0f 82 90 90 90 90[ ]+jb[ ]+909094ee <foo\+0x909094ee>
- *[0-9a-f]+: 0f 83 90 90 90 90[ ]+jae[ ]+909094f4 <foo\+0x909094f4>
- *[0-9a-f]+: 0f 84 90 90 90 90[ ]+je[ ]+909094fa <foo\+0x909094fa>
- *[0-9a-f]+: 0f 85 90 90 90 90[ ]+jne[ ]+90909500 <foo\+0x90909500>
- *[0-9a-f]+: 0f 86 90 90 90 90[ ]+jbe[ ]+90909506 <foo\+0x90909506>
- *[0-9a-f]+: 0f 87 90 90 90 90[ ]+ja[ ]+9090950c <foo\+0x9090950c>
- *[0-9a-f]+: 0f 88 90 90 90 90[ ]+js[ ]+90909512 <foo\+0x90909512>
- *[0-9a-f]+: 0f 89 90 90 90 90[ ]+jns[ ]+90909518 <foo\+0x90909518>
- *[0-9a-f]+: 0f 8a 90 90 90 90[ ]+jp[ ]+9090951e <foo\+0x9090951e>
- *[0-9a-f]+: 0f 8b 90 90 90 90[ ]+jnp[ ]+90909524 <foo\+0x90909524>
- *[0-9a-f]+: 0f 8c 90 90 90 90[ ]+jl[ ]+9090952a <foo\+0x9090952a>
- *[0-9a-f]+: 0f 8d 90 90 90 90[ ]+jge[ ]+90909530 <foo\+0x90909530>
- *[0-9a-f]+: 0f 8e 90 90 90 90[ ]+jle[ ]+90909536 <foo\+0x90909536>
- *[0-9a-f]+: 0f 8f 90 90 90 90[ ]+jg[ ]+9090953c <foo\+0x9090953c>
+ *[0-9a-f]+: 0f 80 90 90 90 90[ ]+jol[ ]+909094e2 <foo\+0x909094e2>
+ *[0-9a-f]+: 0f 81 90 90 90 90[ ]+jnol[ ]+909094e8 <foo\+0x909094e8>
+ *[0-9a-f]+: 0f 82 90 90 90 90[ ]+jbl[ ]+909094ee <foo\+0x909094ee>
+ *[0-9a-f]+: 0f 83 90 90 90 90[ ]+jael[ ]+909094f4 <foo\+0x909094f4>
+ *[0-9a-f]+: 0f 84 90 90 90 90[ ]+jel[ ]+909094fa <foo\+0x909094fa>
+ *[0-9a-f]+: 0f 85 90 90 90 90[ ]+jnel[ ]+90909500 <foo\+0x90909500>
+ *[0-9a-f]+: 0f 86 90 90 90 90[ ]+jbel[ ]+90909506 <foo\+0x90909506>
+ *[0-9a-f]+: 0f 87 90 90 90 90[ ]+jal[ ]+9090950c <foo\+0x9090950c>
+ *[0-9a-f]+: 0f 88 90 90 90 90[ ]+jsl[ ]+90909512 <foo\+0x90909512>
+ *[0-9a-f]+: 0f 89 90 90 90 90[ ]+jnsl[ ]+90909518 <foo\+0x90909518>
+ *[0-9a-f]+: 0f 8a 90 90 90 90[ ]+jpl[ ]+9090951e <foo\+0x9090951e>
+ *[0-9a-f]+: 0f 8b 90 90 90 90[ ]+jnpl[ ]+90909524 <foo\+0x90909524>
+ *[0-9a-f]+: 0f 8c 90 90 90 90[ ]+jll[ ]+9090952a <foo\+0x9090952a>
+ *[0-9a-f]+: 0f 8d 90 90 90 90[ ]+jgel[ ]+90909530 <foo\+0x90909530>
+ *[0-9a-f]+: 0f 8e 90 90 90 90[ ]+jlel[ ]+90909536 <foo\+0x90909536>
+ *[0-9a-f]+: 0f 8f 90 90 90 90[ ]+jgl[ ]+9090953c <foo\+0x9090953c>
*[0-9a-f]+: 0f 90 80 90 90 90 90[ ]+seto[ ]+-0x6f6f6f70\(%eax\)
*[0-9a-f]+: 0f 91 80 90 90 90 90[ ]+setno[ ]+-0x6f6f6f70\(%eax\)
*[0-9a-f]+: 0f 92 80 90 90 90 90[ ]+setb[ ]+-0x6f6f6f70\(%eax\)
--- a/gas/testsuite/gas/i386/x86-64-branch-2.d
+++ b/gas/testsuite/gas/i386/x86-64-branch-2.d
@@ -16,4 +16,6 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: 66 48 e8 00 00 00 00 data16 callq 18 <bar\+0xd> 14: R_X86_64_PLT32 foo-0x4
[ ]*[a-f0-9]+: 66 c3 retw *
[ ]*[a-f0-9]+: 66 c2 08 00 retw \$0x8
+[ ]*[a-f0-9]+: 66 0f 84 00 00 jew 23 <bar\+0x18> 21: R_X86_64_PC16 foo-0x2
+[ ]*[a-f0-9]+: 66 48 0f 85 00 00 00 00 data16 jneq 2b <bar\+0x20> 27: R_X86_64_PLT32 foo-0x4
#pass
--- a/gas/testsuite/gas/i386/x86-64-branch-2.s
+++ b/gas/testsuite/gas/i386/x86-64-branch-2.s
@@ -10,3 +10,6 @@ bar:
retw
retw $8
+
+ data16 je foo
+ data16 rex.w jne foo
--- a/gas/testsuite/gas/i386/x86-64-branch-3.d
+++ b/gas/testsuite/gas/i386/x86-64-branch-3.d
@@ -18,4 +18,6 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: 66 48 c7 f8 00 00 00 00 data16 xbeginq 29 <bar\+0x1c> 25: R_X86_64_PLT32 foo-0x4
[ ]*[a-f0-9]+: 48 ff 18 lcallq \*\(%rax\)
[ ]*[a-f0-9]+: 48 ff 29 ljmpq \*\(%rcx\)
+[ ]*[a-f0-9]+: 66 0f 84 00 00 00 00 data16 jeq 36 <bar\+0x29> 32: R_X86_64_PLT32 foo-0x4
+[ ]*[a-f0-9]+: 66 48 0f 85 00 00 00 00 data16 rex\.W jneq 3e <bar\+0x31> 3a: R_X86_64_PLT32 foo-0x4
#pass
--- a/gas/testsuite/gas/i386/x86-64-branch-3.s
+++ b/gas/testsuite/gas/i386/x86-64-branch-3.s
@@ -13,3 +13,6 @@ bar:
lcallq *(%rax)
ljmpq *(%rcx)
+
+ data16 je foo
+ data16 rex.w jne foo
--- a/gas/testsuite/gas/i386/x86-64-branch.d
+++ b/gas/testsuite/gas/i386/x86-64-branch.d
@@ -21,7 +21,7 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: e9 (00|60) 00 (00|10) 00 jmpq (0x24|100084 <.text\+0x100084>)
[ ]*[a-f0-9]+: 66 e8 00 00 00 00 data16 callq (0x2a|2a <.text\+0x2a>)
[ ]*[a-f0-9]+: 66 e9 00 00 00 00 data16 jmpq (0x30|30 <.text\+0x30>)
-[ ]*[a-f0-9]+: 66 0f 82 00 00 00 00 data16 jb (0x37|37 <.text\+0x37>)
+[ ]*[a-f0-9]+: 66 0f 82 00 00 00 00 data16 jbq (0x37|37 <.text\+0x37>)
[ ]*[a-f0-9]+: 66 c3 data16 retq *
[ ]*[a-f0-9]+: 66 c2 08 00 data16 retq \$0x8
[ ]*[a-f0-9]+: ff d0 callq \*%rax
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -37,6 +37,7 @@
#include "opintl.h"
#include "opcode/i386.h"
#include "libiberty.h"
+#include "safe-ctype.h"
#include <setjmp.h>
@@ -1771,7 +1772,8 @@ enum
X86_64_0F01_REG_0,
X86_64_0F01_REG_1,
X86_64_0F01_REG_2,
- X86_64_0F01_REG_3
+ X86_64_0F01_REG_3,
+ X86_64_0F8x,
};
enum
@@ -2341,6 +2343,10 @@ struct dis386 {
otherwise
2 upper case letter macros:
+ "CP" => print condition encoding and continue like P if there's any form
+ of size override present, or if suffix_always is true
+ "C@" => print condition encoding and continue like @ if there's any form
+ of size override present, or if suffix_always is true
"XY" => print 'x' or 'y' if suffix_always is true or no register
operands and no broadcast.
"XZ" => print 'x', 'y', or 'z' if suffix_always is true or no
@@ -2799,23 +2805,23 @@ static const struct dis386 dis386_twobyt
{ PREFIX_TABLE (PREFIX_0F7E) },
{ PREFIX_TABLE (PREFIX_0F7F) },
/* 80 */
- { "joH", { Jv, BND, cond_jump_flag }, 0 },
- { "jnoH", { Jv, BND, cond_jump_flag }, 0 },
- { "jbH", { Jv, BND, cond_jump_flag }, 0 },
- { "jaeH", { Jv, BND, cond_jump_flag }, 0 },
- { "jeH", { Jv, BND, cond_jump_flag }, 0 },
- { "jneH", { Jv, BND, cond_jump_flag }, 0 },
- { "jbeH", { Jv, BND, cond_jump_flag }, 0 },
- { "jaH", { Jv, BND, cond_jump_flag }, 0 },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
/* 88 */
- { "jsH", { Jv, BND, cond_jump_flag }, 0 },
- { "jnsH", { Jv, BND, cond_jump_flag }, 0 },
- { "jpH", { Jv, BND, cond_jump_flag }, 0 },
- { "jnpH", { Jv, BND, cond_jump_flag }, 0 },
- { "jlH", { Jv, BND, cond_jump_flag }, 0 },
- { "jgeH", { Jv, BND, cond_jump_flag }, 0 },
- { "jleH", { Jv, BND, cond_jump_flag }, 0 },
- { "jgH", { Jv, BND, cond_jump_flag }, 0 },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
+ { X86_64_TABLE (X86_64_0F8x) },
/* 90 */
{ "seto", { Eb }, 0 },
{ "setno", { Eb }, 0 },
@@ -3021,6 +3027,7 @@ static struct
}
modrm;
static unsigned char need_modrm;
+static unsigned char condition_code;
static struct
{
int scale;
@@ -6984,6 +6991,12 @@ static const struct dis386 x86_64_table[
{ "lidt{Q|Q}", { M }, 0 },
{ "lidt", { M }, 0 },
},
+
+ /* X86_64_0F8x */
+ {
+ { "j%CPH", { Jv, BND, cond_jump_flag }, 0 },
+ { "j%C@H", { Jv, BND, cond_jump_flag }, 0 },
+ },
};
static const struct dis386 three_byte_table[][256] = {
@@ -12097,15 +12110,16 @@ print_insn (bfd_vma pc, disassemble_info
threebyte = *codep;
dp = &dis386_twobyte[threebyte];
need_modrm = twobyte_has_modrm[*codep];
- codep++;
}
else
{
dp = &dis386[*codep];
need_modrm = onebyte_has_modrm[*codep];
- codep++;
}
+ condition_code = *codep & 0xf;
+ codep++;
+
/* Save sizeflag for printing the extra prefixes later before updating
it for mnemonic and operand processing. The prefix names depend
only on the address mode. */
@@ -12828,6 +12842,11 @@ putop (const char *in_template, int size
}
break;
case 'C':
+ if (l != 0 || len != 1)
+ {
+ SAVE_LAST (*p);
+ break;
+ }
if (intel_syntax && !alt)
break;
if ((prefixes & PREFIX_DATA) || (sizeflag & SUFFIX_ALWAYS))
@@ -13043,14 +13062,22 @@ putop (const char *in_template, int size
}
}
}
- else
+ else if (l != 1 || len != 2)
+ {
+ SAVE_LAST (*p);
+ }
+ else if (last[0] == 'C')
+ {
+ for (p = dis386[0x70 | condition_code].name + 1;
+ ISLOWER(*p); ++p)
+ *obufp++ = *p;
+ if ((sizeflag & SUFFIX_ALWAYS)
+ || (prefixes & PREFIX_DATA)
+ || (rex & REX_W))
+ goto case_P;
+ }
+ else if (last[0] == 'L')
{
- if (l != 1 || len != 2 || last[0] != 'L')
- {
- SAVE_LAST (*p);
- break;
- }
-
if ((prefixes & PREFIX_DATA)
|| (rex & REX_W)
|| (sizeflag & SUFFIX_ALWAYS))
@@ -13068,6 +13095,8 @@ putop (const char *in_template, int size
}
}
}
+ else
+ SAVE_LAST (*p);
break;
case 'U':
if (intel_syntax)
@@ -13321,6 +13350,16 @@ putop (const char *in_template, int size
}
break;
case '@':
+ if (l == 1 && last[0] == 'C')
+ {
+ for (p = dis386[0x70 | condition_code].name + 1;
+ ISLOWER(*p); ++p)
+ *obufp++ = *p;
+ if (!((sizeflag & SUFFIX_ALWAYS))
+ && !(prefixes & PREFIX_DATA)
+ && !(rex & REX_W))
+ break;
+ }
if (intel_syntax)
break;
if (address_mode == mode_64bit
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -424,7 +424,8 @@ leave, 0, 0xc9, None, 1, Cpu64, DefaultS
s:8, ns:9, p:a, pe:a, np:b, po:b, l:c, nge:c, nl:d, ge:d, le:e, ng:e, nle:f, g:f>
// Conditional jumps.
-j<cc>, 1, 0x7<cc:opc>, None, 1, 0, Jump|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|BNDPrefixOk, { Disp8|Disp16|Disp32|Disp32S }
+j<cc>, 1, 0x7<cc:opc>, None, 1, 0, Amd64|Jump|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|BNDPrefixOk, { Disp8|Disp16|Disp32|Disp32S }
+j<cc>, 1, 0x7<cc:opc>, None, 1, Cpu64, Intel64|Jump|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|BNDPrefixOk, { Disp8|Disp32S }
// jcxz vs. jecxz is chosen on the basis of the address size prefix.
jcxz, 1, 0xe3, None, 1, CpuNo64, JumpByte|Size16|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Disp8 }