[PATCH 4/5] x86-64: Intel64 adjustments for conditional jumps
Jan Beulich
jbeulich@suse.com
Tue Jul 14 10:13:49 GMT 2020
Just like for unconditional direct JMP (and CALL), AMD and Intel differ
in their handling. Mirror JMP handling to Jcc.
gas/
2020-07-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/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-07-XX Jan Beulich <jbeulich@suse.com>
* i386-dis.c (X86_64_0F8x): New enumerator.
(dis386): Describe "CP" and "C@".
(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 CP and C@.
* i386-opc.tbl (j<cc>): Split into AMD64 and Intel64 variants.
* i386-tbl.h: Re-generate.
--- 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
@@ -17,4 +17,6 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: 66 48 e8 00 00 00 00 data16 rex\.W call 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 rex\.W jne 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
@@ -19,4 +19,6 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: 66 48 c7 f8 00 00 00 00 data16 rex\.W xbegin 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 je 36 <bar\+0x29> 32: R_X86_64_PLT32 foo-0x4
+[ ]*[a-f0-9]+: 66 48 0f 85 00 00 00 00 data16 rex\.W jne 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/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -1165,6 +1165,7 @@ enum
X86_64_0F01_REG_3,
X86_64_0F24,
X86_64_0F26,
+ X86_64_0F8x,
X86_64_VEX_0F3849,
X86_64_VEX_0F384B,
X86_64_VEX_0F385C,
@@ -1761,6 +1762,10 @@ struct dis386 {
nothing otherwise; behave as 'P' in all other cases
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
@@ -2221,23 +2226,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 },
@@ -2443,6 +2448,7 @@ static struct
}
modrm;
static unsigned char need_modrm;
+static unsigned char condition_code;
static struct
{
int scale;
@@ -4161,6 +4167,12 @@ static const struct dis386 x86_64_table[
{ "movZ", { Td, Em }, 0 },
},
+ /* X86_64_0F8x */
+ {
+ { "j%CPH", { Jv, BND, cond_jump_flag }, 0 },
+ { "j%C@H", { Jv, BND, cond_jump_flag }, 0 },
+ },
+
/* X86_64_VEX_0F3849 */
{
{ Bad_Opcode },
@@ -9778,15 +9790,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. */
@@ -10638,6 +10651,12 @@ putop (const char *in_template, int size
&& (isa64 == intel64 || (rex & REX_W)
|| !(prefixes & PREFIX_DATA)))
{
+ if (l == 1 && last[0] == 'C')
+ {
+ for (p = dis386[0x70 | condition_code].name + 1;
+ ISLOWER(*p); ++p)
+ *obufp++ = *p;
+ }
if (sizeflag & SUFFIX_ALWAYS)
*obufp++ = 'q';
break;
@@ -10646,6 +10665,7 @@ putop (const char *in_template, int size
case 'P':
if (l == 0)
{
+ case_P:
if (((need_modrm && modrm.mod == 3) || !cond)
&& !(sizeflag & SUFFIX_ALWAYS))
break;
@@ -10662,6 +10682,13 @@ putop (const char *in_template, int size
else if (sizeflag & SUFFIX_ALWAYS)
*obufp++ = 'q';
}
+ else if (l == 1 && last[0] == 'C')
+ {
+ for (p = dis386[0x70 | condition_code].name + 1;
+ ISLOWER(*p); ++p)
+ *obufp++ = *p;
+ goto case_P;
+ }
else if (l == 1 && last[0] == 'L')
{
if ((prefixes & PREFIX_DATA)
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -430,7 +430,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 }
More information about the Binutils
mailing list