[PATCH 2/2] x86/APX: support JMPABS also in assembler

H.J. Lu hjl.tools@gmail.com
Tue Oct 8 21:00:40 GMT 2024


On Tue, Oct 8, 2024 at 6:26 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> Without this APX support isn't really complete.
>
> Since which operand type to expect in source is ambiguous, permit both
> immediate and displacement forms. Make sure though that in Intel syntax
> truly memory operand forms (<xyz> ptr and/or square-bracketing) aren't
> accepted. Also make sure that no illegal prefixes can be used with the
> insn (LOCK is being dealt with more generally elsewhere).
> ---
> Instead of open-coding the check for JMPABS in establish_rex() we could
> of course also introduce a new "no sizing prefixes" operand constraint.
>
> Because of the similarity with the offset part of directl long/far
> branches, I'm actually inclined to introduce Disp<NN> variants there,
> too. That, when used in source code, would then also make more clear
> which one is which.
>
> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -4673,6 +4673,24 @@ static void establish_rex (void)
>
>    if (is_apx_rex2_encoding ())
>      {
> +      /* Most prefixes are not permitted with JMPABS.  */
> +      if (i.tm.mnem_off == MN_jmpabs)
> +       {
> +         if (i.prefix[DATA_PREFIX] || (i.prefix[REX_PREFIX] & REX_W))
> +           {
> +             as_bad (_("size override not allowed with `%s'"),
> +                     insn_name (&i.tm));
> +             i.prefix[DATA_PREFIX] = 0;
> +             i.prefix[REX_PREFIX] &= ~REX_W;
> +           }
> +         if (i.prefix[ADDR_PREFIX])
> +           {
> +             as_bad (_("address override not allowed with `%s'"),
> +                     insn_name (&i.tm));
> +             i.prefix[ADDR_PREFIX] = 0;
> +           }
> +       }
> +
>        build_rex2_prefix ();
>        /* The individual REX.RXBW bits got consumed.  */
>        i.rex &= REX_OPCODE;
> @@ -8214,7 +8232,8 @@ optimize_imm (void)
>                /* A more generic (but also more involved) way of dealing
>                   with the special case(s) would be to go look for
>                   DefaultSize attributes on any of the templates.  */
> -              && current_templates.start->mnem_off != MN_push))
> +              && current_templates.start->mnem_off != MN_push
> +              && current_templates.start->mnem_off != MN_jmpabs))
>      guess_suffix = LONG_MNEM_SUFFIX;
>
>    for (op = i.operands; --op >= 0;)
> @@ -8360,10 +8379,10 @@ optimize_disp (const insn_template *t)
>         }
>      }
>
> -  /* Don't optimize displacement for movabs since it only takes 64bit
> -     displacement.  */
> +  /* Don't optimize displacement for movabs / jmpabs since they only take
> +     64-bit displacement.  */
>    if (pp.disp_encoding > disp_encoding_8bit
> -      || (flag_code == CODE_64BIT && t->mnem_off == MN_movabs))
> +      || t->mnem_off == MN_movabs || t->mnem_off == MN_jmpabs)
>      return true;
>
>    for (op = i.operands; op-- > 0;)
> --- a/gas/config/tc-i386-intel.c
> +++ b/gas/config/tc-i386-intel.c
> @@ -907,7 +907,8 @@ i386_intel_operand (char *operand_string
>    /* Operands for jump/call need special consideration.  */
>    if (current_templates.start->opcode_modifier.jump == JUMP
>        || current_templates.start->opcode_modifier.jump == JUMP_DWORD
> -      || current_templates.start->opcode_modifier.jump == JUMP_INTERSEGMENT)
> +      || current_templates.start->opcode_modifier.jump == JUMP_INTERSEGMENT
> +      || current_templates.start->mnem_off == MN_jmpabs)
>      {
>        bool jumpabsolute = false;
>
> --- a/gas/testsuite/gas/i386/x86-64-apx-jmpabs.d
> +++ b/gas/testsuite/gas/i386/x86-64-apx-jmpabs.d
> @@ -1,5 +1,5 @@
>  #as:
> -#objdump: -dw
> +#objdump: -dwr
>  #name: x86_64 APX_F JMPABS insns
>  #source: x86-64-apx-jmpabs.s
>
> @@ -8,5 +8,16 @@
>  Disassembly of section \.text:
>
>  0+ <_start>:
> +\s*[a-f0-9]+:\s*d5 00 a1 00 00 00 00 00 00 00 00[       ]+jmpabs \$0x0\s*[a-f0-9]+: (R_X86_64_|IMAGE_REL_AMD64_ADDR)?64        thunk
>  \s*[a-f0-9]+:\s*d5 00 a1 02 00 00 00 00 00 00 00[       ]+jmpabs \$0x2
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 00 00 00 00[       ]+jmpabs \$0x87654321
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 09 00 00 00[       ]+jmpabs \$0x987654321
> +\s*[a-f0-9]+:\s*d5 00 a1 00 00 00 00 00 00 00 00[       ]+jmpabs \$0x0\s*[a-f0-9]+: (R_X86_64_|IMAGE_REL_AMD64_ADDR)?64        thunk
> +\s*[a-f0-9]+:\s*d5 00 a1 78 56 34 12 00 00 00 00[       ]+jmpabs \$0x12345678
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 00 00 00 00[       ]+jmpabs \$0x87654321
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 09 00 00 00[       ]+jmpabs \$0x987654321
> +\s*[a-f0-9]+:\s*d5 00 a1 00 00 00 00 00 00 00 00[       ]+jmpabs \$0x0\s*[a-f0-9]+: (R_X86_64_|IMAGE_REL_AMD64_ADDR)?64        thunk
> +\s*[a-f0-9]+:\s*d5 00 a1 78 56 34 12 00 00 00 00[       ]+jmpabs \$0x12345678
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 00 00 00 00[       ]+jmpabs \$0x87654321
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 09 00 00 00[       ]+jmpabs \$0x987654321
>  #pass
> --- a/gas/testsuite/gas/i386/x86-64-apx-jmpabs.s
> +++ b/gas/testsuite/gas/i386/x86-64-apx-jmpabs.s
> @@ -2,4 +2,18 @@
>
>         .text
>   _start:
> -       .byte 0xd5,0x00,0xa1,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00
> +       jmpabs  thunk
> +       jmpabs  2
> +       jmpabs  0x87654321
> +       jmpabs  0x987654321
> +
> +       jmpabs  $thunk
> +       jmpabs  $0x12345678
> +       jmpabs  $0x87654321
> +       jmpabs  $0x987654321
> +
> +       .intel_syntax noprefix
> +       jmpabs  thunk
> +       jmpabs  0x12345678
> +       jmpabs  0x87654321
> +       jmpabs  0x987654321
> --- a/gas/testsuite/gas/i386/x86-64-apx-jmpabs-intel.d
> +++ b/gas/testsuite/gas/i386/x86-64-apx-jmpabs-intel.d
> @@ -1,5 +1,5 @@
>  #as:
> -#objdump: -dw -Mintel
> +#objdump: -dwr -Mintel
>  #name: x86_64 APX_F JMPABS insns (Intel disassembly)
>  #source: x86-64-apx-jmpabs.s
>
> @@ -8,5 +8,16 @@
>  Disassembly of section \.text:
>
>  0+ <_start>:
> +\s*[a-f0-9]+:\s*d5 00 a1 00 00 00 00 00 00 00 00[       ]+jmpabs 0x0\s*[a-f0-9]+: (R_X86_64_|IMAGE_REL_AMD64_ADDR)?64  thunk
>  \s*[a-f0-9]+:\s*d5 00 a1 02 00 00 00 00 00 00 00[       ]+jmpabs 0x2
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 00 00 00 00[       ]+jmpabs 0x87654321
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 09 00 00 00[       ]+jmpabs 0x987654321
> +\s*[a-f0-9]+:\s*d5 00 a1 00 00 00 00 00 00 00 00[       ]+jmpabs 0x0\s*[a-f0-9]+: (R_X86_64_|IMAGE_REL_AMD64_ADDR)?64  thunk
> +\s*[a-f0-9]+:\s*d5 00 a1 78 56 34 12 00 00 00 00[       ]+jmpabs 0x12345678
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 00 00 00 00[       ]+jmpabs 0x87654321
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 09 00 00 00[       ]+jmpabs 0x987654321
> +\s*[a-f0-9]+:\s*d5 00 a1 00 00 00 00 00 00 00 00[       ]+jmpabs 0x0\s*[a-f0-9]+: (R_X86_64_|IMAGE_REL_AMD64_ADDR)?64  thunk
> +\s*[a-f0-9]+:\s*d5 00 a1 78 56 34 12 00 00 00 00[       ]+jmpabs 0x12345678
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 00 00 00 00[       ]+jmpabs 0x87654321
> +\s*[a-f0-9]+:\s*d5 00 a1 21 43 65 87 09 00 00 00[       ]+jmpabs 0x987654321
>  #pass
> --- a/opcodes/i386-opc.tbl
> +++ b/opcodes/i386-opc.tbl
> @@ -510,6 +510,11 @@ ljmp, 0xea, No64, JumpInterSegment|No_bS
>  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 }
>
> +// In particular for AT&T syntax permit both immediate and displacement form,
> +// to allow people to use what they see as the better fit.

Why do we need "jmpabs $xxx" when it is encoded the same
as "jmpabs xxx"?  "jmpabs xxx" is sufficient.

> +jmpabs, 0xa1, APX_F, NoSuf|Rex2, { Imm64 }
> +jmpabs, 0xa1, APX_F, NoSuf|Rex2, { Disp64|Unspecified }
> +
>  ret, 0xc3, No64, ImplicitStackOp|DefaultSize|No_bSuf|No_sSuf|No_qSuf|RepPrefixOk|BNDPrefixOk|IntelSuffix, {}
>  ret, 0xc2, No64, ImplicitStackOp|DefaultSize|No_bSuf|No_sSuf|No_qSuf|RepPrefixOk|BNDPrefixOk|IntelSuffix, { Imm16 }
>  ret, 0xc3, x64, Amd64|ImplicitStackOp|DefaultSize|No_bSuf|No_lSuf|No_sSuf|NoRex64|RepPrefixOk|BNDPrefixOk|IntelSuffix, {}
>


-- 
H.J.


More information about the Binutils mailing list