[PATCH 2/2] x86: permit non-immediate offset operands with direct far branches

H.J. Lu hjl.tools@gmail.com
Mon Oct 14 06:50:44 GMT 2024


On Mon, Oct 14, 2024, 2:39 PM Jan Beulich <jbeulich@suse.com> wrote:

> While Intel syntax permits such already (as can be observed by there
> not being a need to prefix the respective operand with "offset"), AT&T
> syntax so far strictly insists on two immediate operands. Multiple
> (successive) immediate operands are somewhat problematic anyway, as
> it's never really clear what their order ought to be. While there's no
> apparent way of dealing with this for ENTER, EXTRQ, and INSERTQ, for
> LCALL and LJMP we can aid programmers by permitting alternative forms,
> with the offset operand being a "displacement" rather than an
> "immediate". The order of the two operands the doesn't matter; they're
> distinguished by type.
>
> Mark the new templates AT&T-only; the original ones really should have
> been so, too. For backwards compatibility reasons we can't really
> correct that mistake ...
> ---
> While the proper Intel syntax operand form is sel:offset, for some
> reason we also support two (comma separated) operands. The ambiguity
> there is being left alone, as the sel:offset form is enough to avoid it.
>

I don't think this is a good idea.  $ is used to denote an immediate
operand in
AT&T syntax.  This change serves no practical purposes for programmers.


> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -7061,13 +7061,16 @@ i386_assemble (char *line)
>      swap_operands ();
>
>    /* The order of the immediates should be reversed for 2-immediates EXTRQ
> -     and INSERTQ instructions.  Also UWRMSR wants its immediate to be in
> the
> -     "canonical" place (first), despite it appearing last (in AT&T
> syntax, or
> -     because of the swapping above) in the incoming set of operands.  */
> +     and INSERTQ instructions.  Also direct far branches and UWRMSR want
> their
> +     immediate to be in the "canonical" place (first), despite it
> (possibly)
> +     appearing last (in AT&T syntax, or because of the swapping above) in
> the
> +     incoming set of operands.  */
>    if ((i.imm_operands == 2
>         && (t->mnem_off == MN_extrq || t->mnem_off == MN_insertq))
> -      || (t->mnem_off == MN_uwrmsr && i.imm_operands
> -         && i.operands > i.imm_operands))
> +      || (((t->opcode_modifier.jump == JUMP_INTERSEGMENT
> +           && !operand_type_check (i.types[0], imm))
> +          || t->mnem_off == MN_uwrmsr)
> +         && i.imm_operands && i.operands > i.imm_operands))
>        swap_2_operands (0, 1);
>
>    if (i.imm_operands)
> @@ -11621,6 +11624,7 @@ output_interseg_jump (void)
>    int size;
>    int prefix;
>    int code16;
> +  const expressionS *exp1;
>
>    code16 = 0;
>    if (flag_code == CODE_16BIT)
> @@ -11659,9 +11663,11 @@ output_interseg_jump (void)
>      *p++ = i.prefix[REX_PREFIX];
>
>    *p++ = i.tm.base_opcode;
> -  if (i.op[1].imms->X_op == O_constant)
> +  exp1 = operand_type_check (i.types[0], imm) ? i.op[1].imms
> +                                             : i.op[1].disps;
> +  if (exp1->X_op == O_constant)
>      {
> -      offsetT n = i.op[1].imms->X_add_number;
> +      offsetT n = exp1->X_add_number;
>
>        if (size == 2
>           && !fits_in_unsigned_word (n)
> @@ -11674,7 +11680,7 @@ output_interseg_jump (void)
>      }
>    else
>      fix_new_exp (frag_now, p - frag_now->fr_literal, size,
> -                i.op[1].imms, 0, reloc (size, 0, 0, i.reloc[1]));
> +                exp1, 0, reloc (size, 0, 0, i.reloc[1]));
>
>    p += size;
>    if (i.op[0].imms->X_op == O_constant)
> --- a/gas/testsuite/gas/i386/jump.d
> +++ b/gas/testsuite/gas/i386/jump.d
> @@ -15,28 +15,32 @@ Disassembly of section .text:
>  [      ]*[a-f0-9]+:    66 ff 2c bd 00 00 00 00         ljmpw
> \*0x0\(,%edi,4\) 1c: (R_386_)?(dir)?32   xxx
>  [      ]*[a-f0-9]+:    ff 2d 00 00 00 00       ljmp   \*0x0    22:
> (R_386_)?(dir)?32   xxx
>  [      ]*[a-f0-9]+:    66 ff 2d 00 00 00 00    ljmpw  \*0x0    29:
> (R_386_)?(dir)?32   xxx
> -[      ]*[a-f0-9]+:    ea 00 00 00 00 34 12    ljmp   \$0x1234,\$0x0
>  2e: (R_386_)?(dir)?32   xxx
> -[      ]*[a-f0-9]+:    e8 c7 ff ff ff          call   (0x0|0 <.text>)
> -[      ]*[a-f0-9]+:    e8 ((fc|c2) ff ff ff|00 00 00 00)
>  call   (0x)?(0|3a|3e)( <.text(\+0x3e)?>)?       3a: (R_386_PC)?(DISP)?32
>       xxx
> -[      ]*[a-f0-9]+:    ff 15 00 00 00 00       call   \*0x0    40:
> (R_386_)?(dir)?32   xxx
> +[      ]*[a-f0-9]+:    ea 00 00 00 00 34 12    ljmp   \$0x1234,\$0x0[
> ]+[a-f0-9]+: (R_386_|dir)?32    xxx
> +[      ]*[a-f0-9]+:    ea 00 00 00 00 34 12    ljmp   \$0x1234,\$0x0[
> ]+[a-f0-9]+: (R_386_|dir)?32    xxx
> +[      ]*[a-f0-9]+:    ea 00 00 00 00 34 12    ljmp   \$0x1234,\$0x0[
> ]+[a-f0-9]+: (R_386_|dir)?32    xxx
> +[      ]*[a-f0-9]+:    e8 b9 ff ff ff          call   (0x0|0 <.text>)
> +[      ]*[a-f0-9]+:    e8 ((fc|b4) ff ff ff|00 00 00 00)
>  call   (0x)?(0|48|4c)( <.text(\+0x4c)?>)?[      ]+[a-f0-9]+:
> (R_386_PC|DISP)32  xxx
> +[      ]*[a-f0-9]+:    ff 15 00 00 00 00       call   \*0x0[
>  ]+[a-f0-9]+: (R_386_|dir)?32    xxx
>  [      ]*[a-f0-9]+:    ff d7                   call   \*%edi
>  [      ]*[a-f0-9]+:    ff 17                   call   \*\(%edi\)
> -[      ]*[a-f0-9]+:    ff 1c bd 00 00 00 00    lcall  \*0x0\(,%edi,4\)
> 4b: (R_386_)?(dir)?32   xxx
> -[      ]*[a-f0-9]+:    66 ff 1c bd 00 00 00 00         lcallw
> \*0x0\(,%edi,4\) 53: (R_386_)?(dir)?32   xxx
> -[      ]*[a-f0-9]+:    ff 1d 00 00 00 00       lcall  \*0x0    59:
> (R_386_)?(dir)?32   xxx
> -[      ]*[a-f0-9]+:    66 ff 1d 00 00 00 00    lcallw \*0x0    60:
> (R_386_)?(dir)?32   xxx
> -[      ]*[a-f0-9]+:    9a 00 00 00 00 34 12    lcall  \$0x1234,\$0x0
>  65: (R_386_)?(dir)?32   xxx
> +[      ]*[a-f0-9]+:    ff 1c bd 00 00 00 00    lcall  \*0x0\(,%edi,4\)[
>       ]+[a-f0-9]+: (R_386_|dir)?32    xxx
> +[      ]*[a-f0-9]+:    66 ff 1c bd 00 00 00 00         lcallw
> \*0x0\(,%edi,4\)[        ]+[a-f0-9]+: (R_386_|dir)?32    xxx
> +[      ]*[a-f0-9]+:    ff 1d 00 00 00 00       lcall  \*0x0[
>  ]+[a-f0-9]+: (R_386_|dir)?32    xxx
> +[      ]*[a-f0-9]+:    66 ff 1d 00 00 00 00    lcallw \*0x0[
>  ]+[a-f0-9]+: (R_386_|dir)?32    xxx
> +[      ]*[a-f0-9]+:    9a 00 00 00 00 34 12    lcall  \$0x1234,\$0x0[
> ]+[a-f0-9]+: (R_386_|dir)?32    xxx
> +[      ]*[a-f0-9]+:    9a 00 00 00 00 34 12    lcall  \$0x1234,\$0x0[
> ]+[a-f0-9]+: (R_386_|dir)?32    xxx
> +[      ]*[a-f0-9]+:    9a 00 00 00 00 34 12    lcall  \$0x1234,\$0x0[
> ]+[a-f0-9]+: (R_386_|dir)?32    xxx
>  [      ]*[a-f0-9]+:    66 ff 13                callw  \*\(%ebx\)
>  [      ]*[a-f0-9]+:    ff 13                   call   \*\(%ebx\)
>  [      ]*[a-f0-9]+:    ff 1b                   lcall  \*\(%ebx\)
>  [      ]*[a-f0-9]+:    66 ff 23                jmpw   \*\(%ebx\)
>  [      ]*[a-f0-9]+:    ff 23                   jmp    \*\(%ebx\)
>  [      ]*[a-f0-9]+:    ff 2b                   ljmp   \*\(%ebx\)
> -[      ]*[a-f0-9]+:    eb 00                   jmp    (0x)?7b(
> <.text(\+0x7b)?>)?
> +[      ]*[a-f0-9]+:    eb 00                   jmp    (0x)?97(
> <.text(\+0x97)?>)?
>  [      ]*[a-f0-9]+:    90                      nop
> -[      ]*[a-f0-9]+:    e3 00                   jecxz  (0x)?7e(
> <.text(\+0x7e)?>)?
> +[      ]*[a-f0-9]+:    e3 00                   jecxz  (0x)?9a(
> <.text(\+0x9a)?>)?
>  [      ]*[a-f0-9]+:    90                      nop
> -[      ]*[a-f0-9]+:    eb 00                   jmp    (0x)?81(
> <.text(\+0x81)?>)?
> +[      ]*[a-f0-9]+:    eb 00                   jmp    (0x)?9d(
> <.text(\+0x9d)?>)?
>  [      ]*[a-f0-9]+:    90                      nop
>  [      ]*[a-f0-9]+:    9a 90 90 90 90 90 90    lcall
> \$0x9090,\$0x90909090
>  [      ]*[a-f0-9]+:    9a 90 90 90 90 90 90    lcall
> \$0x9090,\$0x90909090
> --- a/gas/testsuite/gas/i386/jump.s
> +++ b/gas/testsuite/gas/i386/jump.s
> @@ -13,6 +13,8 @@
>         ljmp    *xxx
>         ljmpw   *xxx
>         ljmp    $0x1234,$xxx
> +       ljmp    $0x1234,xxx
> +       ljmp    xxx,$0x1234
>
>         call    1b
>         call    xxx
> @@ -24,6 +26,8 @@
>         lcall   *xxx
>         lcallw  *xxx
>         lcall   $0x1234,$xxx
> +       lcall   $0x1234,xxx
> +       lcall   xxx,$0x1234
>
>         .intel_syntax noprefix
>         call    word ptr [ebx]
> --- a/opcodes/i386-opc.tbl
> +++ b/opcodes/i386-opc.tbl
> @@ -494,6 +494,7 @@ call, 0x9a, No64, JumpInterSegment|Impli
>  call, 0xff/3, 0,
> Amd64|Modrm|JumpAbsolute|ImplicitStackOp|DefaultSize|NoSuf, {
> Dword|Fword|BaseIndex }
>  call, 0xff/3, x64, Intel64|Modrm|JumpAbsolute|ImplicitStackOp|NoSuf, {
> Dword|Fword|Tbyte|BaseIndex }
>  lcall, 0x9a, No64, JumpInterSegment|DefaultSize|No_bSuf|No_sSuf|No_qSuf,
> { Imm16, Imm16|Imm32 }
> +lcall, 0x9a, No64,
> JumpInterSegment|DefaultSize|No_bSuf|No_sSuf|No_qSuf|ATTSyntax, { Imm16,
> Disp16|Disp32 }
>  lcall, 0xff/3, 0,
> Amd64|Modrm|JumpAbsolute|DefaultSize|No_bSuf|No_sSuf|No_qSuf, {
> Unspecified|BaseIndex }
>  lcall, 0xff/3, x64, Intel64|Modrm|JumpAbsolute|No_bSuf|No_sSuf, {
> Unspecified|BaseIndex }
>
> @@ -507,6 +508,7 @@ jmp, 0xea, No64, JumpInterSegment|No_bSu
>  jmp, 0xff/5, 0, Amd64|Modrm|JumpAbsolute|NoSuf, { Dword|Fword|BaseIndex }
>  jmp, 0xff/5, x64, Intel64|Modrm|JumpAbsolute|NoSuf, {
> Dword|Fword|Tbyte|BaseIndex }
>  ljmp, 0xea, No64, JumpInterSegment|No_bSuf|No_sSuf|No_qSuf, { Imm16,
> Imm16|Imm32 }
> +ljmp, 0xea, No64, JumpInterSegment|No_bSuf|No_sSuf|No_qSuf|ATTSyntax, {
> Imm16, Disp16|Disp32 }
>  ljmp, 0xff/5, 0, Amd64|Modrm|JumpAbsolute|No_bSuf|No_sSuf|No_qSuf, {
> Unspecified|BaseIndex }
>  ljmp, 0xff/5, x64, Intel64|Modrm|JumpAbsolute|No_bSuf|No_sSuf, {
> Unspecified|BaseIndex }
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/binutils/attachments/20241014/e6e2a8f4/attachment-0001.htm>


More information about the Binutils mailing list