x86/APX: correct disassembly for EVEX.B4

Message ID a5d738fd-f86f-43e5-a057-a1bddfe2211b@suse.com
State New
Headers
Series x86/APX: correct disassembly for EVEX.B4 |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

Jan Beulich Sept. 5, 2024, 11:31 a.m. UTC
  EVEX.B4 is used only for GPR (or addressing of memory) operands. SIMD
registers encoded via ModR/M.rm (when ModR/M.mod == 3) have their top
bit in EVEX.X3. Supposedly (doc version 004) EVEX.B4 is ignored when
unused, hence also don't flag such encodings as invalid.
  

Comments

Cui, Lili Sept. 6, 2024, 2:04 a.m. UTC | #1
> -----Original Message-----
> From: Jan Beulich <jbeulich@suse.com>
> Sent: Thursday, September 5, 2024 7:31 PM
> To: Binutils <binutils@sourceware.org>
> Cc: Cui, Lili <lili.cui@intel.com>; H.J. Lu <hjl.tools@gmail.com>
> Subject: [PATCH] x86/APX: correct disassembly for EVEX.B4
> 
> EVEX.B4 is used only for GPR (or addressing of memory) operands. SIMD
> registers encoded via ModR/M.rm (when ModR/M.mod == 3) have their top bit
> in EVEX.X3. Supposedly (doc version 004) EVEX.B4 is ignored when unused,
> hence also don't flag such encodings as invalid.
> 
> --- a/opcodes/i386-dis.c
> +++ b/opcodes/i386-dis.c
> @@ -13001,14 +13001,15 @@ OP_EX (instr_info *ins, int bytemode, in
>    USED_REX (REX_B);
>    if (ins->rex & REX_B)
>      reg += 8;
> -  if (ins->rex2 & REX_B)
> -    reg += 16;
>    if (ins->vex.evex)
>      {
>        USED_REX (REX_X);
>        if ((ins->rex & REX_X))
>  	reg += 16;
> +      ins->rex2_used &= ~REX_B;
>      }
> +  else if (ins->rex2 & REX_B)
> +    reg += 16;
> 
>    if ((sizeflag & SUFFIX_ALWAYS)
>        && (bytemode == x_swap_mode

when setting ins->vex.evex , we use EVEX.X to decode SIMD, then ins->rex also needs to be put into the else branch since it uses REX_B right?

If (ins->vex.evex)
  {
     Use REX_X.
  }
else
  {
    Use REX_B.
  }

Lili.
  
Jan Beulich Sept. 6, 2024, 6:19 a.m. UTC | #2
On 06.09.2024 04:04, Cui, Lili wrote:
> 
> 
>> -----Original Message-----
>> From: Jan Beulich <jbeulich@suse.com>
>> Sent: Thursday, September 5, 2024 7:31 PM
>> To: Binutils <binutils@sourceware.org>
>> Cc: Cui, Lili <lili.cui@intel.com>; H.J. Lu <hjl.tools@gmail.com>
>> Subject: [PATCH] x86/APX: correct disassembly for EVEX.B4
>>
>> EVEX.B4 is used only for GPR (or addressing of memory) operands. SIMD
>> registers encoded via ModR/M.rm (when ModR/M.mod == 3) have their top bit
>> in EVEX.X3. Supposedly (doc version 004) EVEX.B4 is ignored when unused,
>> hence also don't flag such encodings as invalid.
>>
>> --- a/opcodes/i386-dis.c
>> +++ b/opcodes/i386-dis.c
>> @@ -13001,14 +13001,15 @@ OP_EX (instr_info *ins, int bytemode, in
>>    USED_REX (REX_B);
>>    if (ins->rex & REX_B)
>>      reg += 8;
>> -  if (ins->rex2 & REX_B)
>> -    reg += 16;
>>    if (ins->vex.evex)
>>      {
>>        USED_REX (REX_X);
>>        if ((ins->rex & REX_X))
>>  	reg += 16;
>> +      ins->rex2_used &= ~REX_B;
>>      }
>> +  else if (ins->rex2 & REX_B)
>> +    reg += 16;
>>
>>    if ((sizeflag & SUFFIX_ALWAYS)
>>        && (bytemode == x_swap_mode
> 
> when setting ins->vex.evex , we use EVEX.X to decode SIMD, then ins->rex also needs to be put into the else branch since it uses REX_B right?
> 
> If (ins->vex.evex)
>   {
>      Use REX_X.
>   }
> else
>   {
>     Use REX_B.
>   }

Except that at that point we don't know yet whether it's a GPR, a memory
operand, or a SIMD register.

Jan
  
Cui, Lili Sept. 6, 2024, 6:49 a.m. UTC | #3
> >> EVEX.B4 is used only for GPR (or addressing of memory) operands. SIMD
> >> registers encoded via ModR/M.rm (when ModR/M.mod == 3) have their top
> >> bit in EVEX.X3. Supposedly (doc version 004) EVEX.B4 is ignored when
> >> unused, hence also don't flag such encodings as invalid.
> >>
> >> --- a/opcodes/i386-dis.c
> >> +++ b/opcodes/i386-dis.c
> >> @@ -13001,14 +13001,15 @@ OP_EX (instr_info *ins, int bytemode, in
> >>    USED_REX (REX_B);
> >>    if (ins->rex & REX_B)
> >>      reg += 8;
> >> -  if (ins->rex2 & REX_B)
> >> -    reg += 16;
> >>    if (ins->vex.evex)
> >>      {
> >>        USED_REX (REX_X);
> >>        if ((ins->rex & REX_X))
> >>  	reg += 16;
> >> +      ins->rex2_used &= ~REX_B;
> >>      }
> >> +  else if (ins->rex2 & REX_B)
> >> +    reg += 16;
> >>
> >>    if ((sizeflag & SUFFIX_ALWAYS)
> >>        && (bytemode == x_swap_mode
> >
> > when setting ins->vex.evex , we use EVEX.X to decode SIMD, then ins->rex also
> needs to be put into the else branch since it uses REX_B right?
> >
> > If (ins->vex.evex)
> >   {
> >      Use REX_X.
> >   }
> > else
> >   {
> >     Use REX_B.
> >   }
> 
> Except that at that point we don't know yet whether it's a GPR, a memory
> operand, or a SIMD register.
> 
Oh, I saw that table, EVEX.X3 should be combined with EVEX.B3 to determine the number of SIMD registers, but the use of EVEX.X3 and EVEX.B4 are mutually exclusive.

Thanks,
Lili.
  

Patch

--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -13001,14 +13001,15 @@  OP_EX (instr_info *ins, int bytemode, in
   USED_REX (REX_B);
   if (ins->rex & REX_B)
     reg += 8;
-  if (ins->rex2 & REX_B)
-    reg += 16;
   if (ins->vex.evex)
     {
       USED_REX (REX_X);
       if ((ins->rex & REX_X))
 	reg += 16;
+      ins->rex2_used &= ~REX_B;
     }
+  else if (ins->rex2 & REX_B)
+    reg += 16;
 
   if ((sizeflag & SUFFIX_ALWAYS)
       && (bytemode == x_swap_mode