[2/6] x86-64: Intel64 adjustments for conditional jumps

Message ID da820d1f-252e-0984-04ad-fc4cf135f12d@suse.com
State New
Headers show
Series
  • x86: introduce "templated" insn templates
Related show

Commit Message

Jan Beulich March 6, 2020, 8:12 a.m.
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.

Comments

H.J. Lu March 6, 2020, 2:39 p.m. | #1
On Fri, Mar 6, 2020 at 12:12 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> 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


I think it is a very bad idea to add suffix to jcc.

-- 
H.J.
Jan Beulich March 6, 2020, 2:53 p.m. | #2
On 06.03.2020 15:39, H.J. Lu wrote:
> On Fri, Mar 6, 2020 at 12:12 AM Jan Beulich <jbeulich@suse.com> wrote:

>>

>> 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

> 

> I think it is a very bad idea to add suffix to jcc.


Well, do you have an alternative suggestion, also in line with
JMP then? (See the somewhat related post-commit-message remark
above as well.) I'd like to note that a suffix gets put there
_only_ if there's also a data16 prefix (to be able to tell
apart the different cases).

Jan
H.J. Lu March 6, 2020, 3:35 p.m. | #3
On Fri, Mar 6, 2020 at 6:53 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> On 06.03.2020 15:39, H.J. Lu wrote:

> > On Fri, Mar 6, 2020 at 12:12 AM Jan Beulich <jbeulich@suse.com> wrote:

> >>

> >> 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

> >

> > I think it is a very bad idea to add suffix to jcc.

>

> Well, do you have an alternative suggestion, also in line with

> JMP then? (See the somewhat related post-commit-message remark


Since assembly doesn't require `q' suffix, can we drop it from disassembler?

> above as well.) I'd like to note that a suffix gets put there

> _only_ if there's also a data16 prefix (to be able to tell

> apart the different cases).




-- 
H.J.
Jan Beulich March 9, 2020, 7:11 a.m. | #4
On 06.03.2020 16:35, H.J. Lu wrote:
> On Fri, Mar 6, 2020 at 6:53 AM Jan Beulich <jbeulich@suse.com> wrote:

>>

>> On 06.03.2020 15:39, H.J. Lu wrote:

>>> On Fri, Mar 6, 2020 at 12:12 AM Jan Beulich <jbeulich@suse.com> wrote:

>>>>

>>>> 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

>>>

>>> I think it is a very bad idea to add suffix to jcc.

>>

>> Well, do you have an alternative suggestion, also in line with

>> JMP then? (See the somewhat related post-commit-message remark

> 

> Since assembly doesn't require `q' suffix, can we drop it from disassembler?


Why would we not be in the position to do so? But if we do,
can we then please settle on doing so uniformly (i.e. for
all near branch insns), i.e. in the above snippet e.g. not
just CALL and JMP, but also RET?

The other question then is what to do in suffix-always mode:
I'd like to have things consistent there as well, and hence
I think we should emit suffixes in that case also for Jcc.

Jan
H.J. Lu March 9, 2020, 12:13 p.m. | #5
On Mon, Mar 9, 2020 at 12:11 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> On 06.03.2020 16:35, H.J. Lu wrote:

> > On Fri, Mar 6, 2020 at 6:53 AM Jan Beulich <jbeulich@suse.com> wrote:

> >>

> >> On 06.03.2020 15:39, H.J. Lu wrote:

> >>> On Fri, Mar 6, 2020 at 12:12 AM Jan Beulich <jbeulich@suse.com> wrote:

> >>>>

> >>>> 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

> >>>

> >>> I think it is a very bad idea to add suffix to jcc.

> >>

> >> Well, do you have an alternative suggestion, also in line with

> >> JMP then? (See the somewhat related post-commit-message remark

> >

> > Since assembly doesn't require `q' suffix, can we drop it from disassembler?

>

> Why would we not be in the position to do so? But if we do,

> can we then please settle on doing so uniformly (i.e. for

> all near branch insns), i.e. in the above snippet e.g. not

> just CALL and JMP, but also RET?


Let's drop 'q' suffix on them.

> The other question then is what to do in suffix-always mode:

> I'd like to have things consistent there as well, and hence

> I think we should emit suffixes in that case also for Jcc.


Since current assembler doesn't take 'q' suffix on Jcc:

[hjl@gnu-cfl-2 tmp]$ cat x.s
jbq 1f
1:
nop
[hjl@gnu-cfl-2 tmp]$ gcc -c x.s
x.s: Assembler messages:
x.s:1: Error: invalid instruction suffix for `jb'
[hjl@gnu-cfl-2 tmp]$

disassembler should never add 'q' suffix on Jcc.  But we can
drop 'q' suffix on CALL/JMP/RET in suffix-always mode.

-- 
H.J.
Jan Beulich March 11, 2020, 8:59 a.m. | #6
On 09.03.2020 13:13, H.J. Lu wrote:
> On Mon, Mar 9, 2020 at 12:11 AM Jan Beulich <jbeulich@suse.com> wrote:

>> On 06.03.2020 16:35, H.J. Lu wrote:

>>> On Fri, Mar 6, 2020 at 6:53 AM Jan Beulich <jbeulich@suse.com> wrote:

>>>> Well, do you have an alternative suggestion, also in line with

>>>> JMP then? (See the somewhat related post-commit-message remark

>>>

>>> Since assembly doesn't require `q' suffix, can we drop it from disassembler?

>>

>> Why would we not be in the position to do so? But if we do,

>> can we then please settle on doing so uniformly (i.e. for

>> all near branch insns), i.e. in the above snippet e.g. not

>> just CALL and JMP, but also RET?

> 

> Let's drop 'q' suffix on them.


Obviously this then also affect PUSH/POP. There's an anomaly with
32-bit code - with a memory operand, these get an 'L' suffix
appended, whereas with an immediate or segment register operand
(where operand size is in principle as ambiguous) they don't.
Since the assembler accepts them (intentionally) silently without
suffix, I'd prefer to adjust the memory operand form too even
outside of 64-bit mode (in effect meaning to drop the 'U' macro,
instead using the same one as for other PUSH/POP). Thoughts?

Jan
Martin Sebor via Binutils March 11, 2020, 10:32 a.m. | #7
On Wed, Mar 11, 2020 at 1:59 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> On 09.03.2020 13:13, H.J. Lu wrote:

> > On Mon, Mar 9, 2020 at 12:11 AM Jan Beulich <jbeulich@suse.com> wrote:

> >> On 06.03.2020 16:35, H.J. Lu wrote:

> >>> On Fri, Mar 6, 2020 at 6:53 AM Jan Beulich <jbeulich@suse.com> wrote:

> >>>> Well, do you have an alternative suggestion, also in line with

> >>>> JMP then? (See the somewhat related post-commit-message remark

> >>>

> >>> Since assembly doesn't require `q' suffix, can we drop it from disassembler?

> >>

> >> Why would we not be in the position to do so? But if we do,

> >> can we then please settle on doing so uniformly (i.e. for

> >> all near branch insns), i.e. in the above snippet e.g. not

> >> just CALL and JMP, but also RET?

> >

> > Let's drop 'q' suffix on them.

>

> Obviously this then also affect PUSH/POP. There's an anomaly with

> 32-bit code - with a memory operand, these get an 'L' suffix

> appended, whereas with an immediate or segment register operand

> (where operand size is in principle as ambiguous) they don't.

> Since the assembler accepts them (intentionally) silently without

> suffix, I'd prefer to adjust the memory operand form too even

> outside of 64-bit mode (in effect meaning to drop the 'U' macro,

> instead using the same one as for other PUSH/POP). Thoughts?

>


That is fine as long as disassembler agrees with assembler.

Thanks.

-- 
H.J.
Jan Beulich April 24, 2020, 6:36 a.m. | #8
On 09.03.2020 13:13, H.J. Lu wrote:
> On Mon, Mar 9, 2020 at 12:11 AM Jan Beulich <jbeulich@suse.com> wrote:

>>

>> On 06.03.2020 16:35, H.J. Lu wrote:

>>> On Fri, Mar 6, 2020 at 6:53 AM Jan Beulich <jbeulich@suse.com> wrote:

>>>>

>>>> On 06.03.2020 15:39, H.J. Lu wrote:

>>>>> On Fri, Mar 6, 2020 at 12:12 AM Jan Beulich <jbeulich@suse.com> wrote:

>>>>>>

>>>>>> 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

>>>>>

>>>>> I think it is a very bad idea to add suffix to jcc.

>>>>

>>>> Well, do you have an alternative suggestion, also in line with

>>>> JMP then? (See the somewhat related post-commit-message remark

>>>

>>> Since assembly doesn't require `q' suffix, can we drop it from disassembler?

>>

>> Why would we not be in the position to do so? But if we do,

>> can we then please settle on doing so uniformly (i.e. for

>> all near branch insns), i.e. in the above snippet e.g. not

>> just CALL and JMP, but also RET?

> 

> Let's drop 'q' suffix on them.

> 

>> The other question then is what to do in suffix-always mode:

>> I'd like to have things consistent there as well, and hence

>> I think we should emit suffixes in that case also for Jcc.

> 

> Since current assembler doesn't take 'q' suffix on Jcc:

> 

> [hjl@gnu-cfl-2 tmp]$ cat x.s

> jbq 1f

> 1:

> nop

> [hjl@gnu-cfl-2 tmp]$ gcc -c x.s

> x.s: Assembler messages:

> x.s:1: Error: invalid instruction suffix for `jb'

> [hjl@gnu-cfl-2 tmp]$

> 

> disassembler should never add 'q' suffix on Jcc.  But we can

> drop 'q' suffix on CALL/JMP/RET in suffix-always mode.


Coming back to this, in the hope of being able to resume work
on the patch at some point. I think I've gone a little too far
with the changes done so far (after this conversation), in
that I've made things disassemble e.g. like this:

[a-f0-9]+:	66 e9 00 00 00 00    	data16 jmp 6 <bar-0x7>	2: R_X86_64_PLT32	foo-0x4
[a-f0-9]+:	66 48 e9 00 00 00 00 	data16 jmpq d <bar>	9: R_X86_64_PLT32	foo-0x4

i.e. the redundant (other than for nullifying the operand size
override) REX.W gets transformed into a 'q' suffix. I'm now
thinking that instead all redundant prefixes would better be
printed as prefixes, despite the more cluttered resulting
output. If you agree, I'll have to go through all the adjusted
test cases again, hence my desire to have your general consent
up front. (Of course I mean to extend this underlying rule to
things like PUSH, in separate patches.)

That way I can then also avoid adding 'q' suffixes to Jcc.
What I'm not going to be able to avoid though is adding
'w' suffixes in AMD64 mode (and for 32-bit), as it's neither
reasonable to express this via prefix, nor would this be
consistent with JMP (and other insns).

Jan
Martin Sebor via Binutils April 24, 2020, 12:58 p.m. | #9
On Thu, Apr 23, 2020 at 11:36 PM Jan Beulich <jbeulich@suse.com> wrote:
>

> On 09.03.2020 13:13, H.J. Lu wrote:

> > On Mon, Mar 9, 2020 at 12:11 AM Jan Beulich <jbeulich@suse.com> wrote:

> >>

> >> On 06.03.2020 16:35, H.J. Lu wrote:

> >>> On Fri, Mar 6, 2020 at 6:53 AM Jan Beulich <jbeulich@suse.com> wrote:

> >>>>

> >>>> On 06.03.2020 15:39, H.J. Lu wrote:

> >>>>> On Fri, Mar 6, 2020 at 12:12 AM Jan Beulich <jbeulich@suse.com> wrote:

> >>>>>>

> >>>>>> 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

> >>>>>

> >>>>> I think it is a very bad idea to add suffix to jcc.

> >>>>

> >>>> Well, do you have an alternative suggestion, also in line with

> >>>> JMP then? (See the somewhat related post-commit-message remark

> >>>

> >>> Since assembly doesn't require `q' suffix, can we drop it from disassembler?

> >>

> >> Why would we not be in the position to do so? But if we do,

> >> can we then please settle on doing so uniformly (i.e. for

> >> all near branch insns), i.e. in the above snippet e.g. not

> >> just CALL and JMP, but also RET?

> >

> > Let's drop 'q' suffix on them.

> >

> >> The other question then is what to do in suffix-always mode:

> >> I'd like to have things consistent there as well, and hence

> >> I think we should emit suffixes in that case also for Jcc.

> >

> > Since current assembler doesn't take 'q' suffix on Jcc:

> >

> > [hjl@gnu-cfl-2 tmp]$ cat x.s

> > jbq 1f

> > 1:

> > nop

> > [hjl@gnu-cfl-2 tmp]$ gcc -c x.s

> > x.s: Assembler messages:

> > x.s:1: Error: invalid instruction suffix for `jb'

> > [hjl@gnu-cfl-2 tmp]$

> >

> > disassembler should never add 'q' suffix on Jcc.  But we can

> > drop 'q' suffix on CALL/JMP/RET in suffix-always mode.

>

> Coming back to this, in the hope of being able to resume work

> on the patch at some point. I think I've gone a little too far

> with the changes done so far (after this conversation), in

> that I've made things disassemble e.g. like this:

>

> [a-f0-9]+:      66 e9 00 00 00 00       data16 jmp 6 <bar-0x7>  2: R_X86_64_PLT32       foo-0x4

> [a-f0-9]+:      66 48 e9 00 00 00 00    data16 jmpq d <bar>     9: R_X86_64_PLT32       foo-0x4

>

> i.e. the redundant (other than for nullifying the operand size

> override) REX.W gets transformed into a 'q' suffix. I'm now

> thinking that instead all redundant prefixes would better be

> printed as prefixes, despite the more cluttered resulting


Sounds good to me.

> output. If you agree, I'll have to go through all the adjusted

> test cases again, hence my desire to have your general consent

> up front. (Of course I mean to extend this underlying rule to

> things like PUSH, in separate patches.)

>

> That way I can then also avoid adding 'q' suffixes to Jcc.


That is very much desirable.

> What I'm not going to be able to avoid though is adding

> 'w' suffixes in AMD64 mode (and for 32-bit), as it's neither


Adding 'w' to Jcc?  I guess it is OK.  Does assembler support it?

> reasonable to express this via prefix, nor would this be

> consistent with JMP (and other insns).

>

> Jan


Thanks.

-- 
H.J.

Patch

--- 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 }