[2/2] Support APX zero-upper

Message ID 20240515063158.3960697-3-lili.cui@intel.com
State New
Headers
Series Support APX zero-upper |

Checks

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

Commit Message

Cui, Lili May 15, 2024, 6:31 a.m. UTC
  gas/ChangeLog:

        * config/tc-i386.c (build_apx_evex_prefix): Handle ZU.
        * testsuite/gas/i386/x86-64.exp: Added new tests for ZU.
        * testsuite/gas/i386/x86-64.exp: Added new tests for ZU.
        * testsuite/gas/i386/x86-64-apx-zu-intel.d: New test.
        * testsuite/gas/i386/x86-64-apx-zu-inval.l: Ditto.
        * testsuite/gas/i386/x86-64-apx-zu-inval.s: Ditto.
        * testsuite/gas/i386/x86-64-apx-zu.d: Ditto.
        * testsuite/gas/i386/x86-64-apx-zu.s: Ditto.

opcodes/ChangeLog:

        * i386-dis-evex-prefix.h: Handle PREFIX_EVEX_MAP4_40 ~
        PREFIX_EVEX_MAP4_4F.
        * i386-dis-evex.h: Ditto.
        * i386-dis.c (struct dis386): Add new micro 'ZU'.
        (putop): Handle %ZU.
        * i386-gen.c: Added ZU.
        * i386-opc.h: Ditto.
        * i386-opc.tbl: Added new templates to support ZU.
---
 gas/config/tc-i386.c                         |   5 +-
 gas/testsuite/gas/i386/x86-64-apx-zu-intel.d |  78 +++++++++++++
 gas/testsuite/gas/i386/x86-64-apx-zu-inval.l |  25 +++++
 gas/testsuite/gas/i386/x86-64-apx-zu-inval.s |  28 +++++
 gas/testsuite/gas/i386/x86-64-apx-zu.d       |  78 +++++++++++++
 gas/testsuite/gas/i386/x86-64-apx-zu.s       |  73 ++++++++++++
 gas/testsuite/gas/i386/x86-64.exp            |   3 +
 opcodes/i386-dis-evex-prefix.h               | 112 +++++++++++++++++++
 opcodes/i386-dis-evex.h                      |  36 +++---
 opcodes/i386-dis.c                           |  35 ++++++
 opcodes/i386-gen.c                           |   1 +
 opcodes/i386-opc.h                           |   4 +
 opcodes/i386-opc.tbl                         |   6 +
 13 files changed, 464 insertions(+), 20 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu-intel.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu-inval.l
 create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu-inval.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu.s
  

Comments

Jan Beulich May 17, 2024, 12:21 p.m. UTC | #1
On 15.05.2024 08:31, Cui, Lili wrote:
> gas/ChangeLog:
> 
>         * config/tc-i386.c (build_apx_evex_prefix): Handle ZU.
>         * testsuite/gas/i386/x86-64.exp: Added new tests for ZU.
>         * testsuite/gas/i386/x86-64.exp: Added new tests for ZU.
>         * testsuite/gas/i386/x86-64-apx-zu-intel.d: New test.
>         * testsuite/gas/i386/x86-64-apx-zu-inval.l: Ditto.
>         * testsuite/gas/i386/x86-64-apx-zu-inval.s: Ditto.
>         * testsuite/gas/i386/x86-64-apx-zu.d: Ditto.
>         * testsuite/gas/i386/x86-64-apx-zu.s: Ditto.
> 
> opcodes/ChangeLog:
> 
>         * i386-dis-evex-prefix.h: Handle PREFIX_EVEX_MAP4_40 ~
>         PREFIX_EVEX_MAP4_4F.
>         * i386-dis-evex.h: Ditto.
>         * i386-dis.c (struct dis386): Add new micro 'ZU'.
>         (putop): Handle %ZU.
>         * i386-gen.c: Added ZU.
>         * i386-opc.h: Ditto.
>         * i386-opc.tbl: Added new templates to support ZU.
> ---
>  gas/config/tc-i386.c                         |   5 +-
>  gas/testsuite/gas/i386/x86-64-apx-zu-intel.d |  78 +++++++++++++
>  gas/testsuite/gas/i386/x86-64-apx-zu-inval.l |  25 +++++
>  gas/testsuite/gas/i386/x86-64-apx-zu-inval.s |  28 +++++
>  gas/testsuite/gas/i386/x86-64-apx-zu.d       |  78 +++++++++++++
>  gas/testsuite/gas/i386/x86-64-apx-zu.s       |  73 ++++++++++++
>  gas/testsuite/gas/i386/x86-64.exp            |   3 +
>  opcodes/i386-dis-evex-prefix.h               | 112 +++++++++++++++++++
>  opcodes/i386-dis-evex.h                      |  36 +++---
>  opcodes/i386-dis.c                           |  35 ++++++
>  opcodes/i386-gen.c                           |   1 +
>  opcodes/i386-opc.h                           |   4 +
>  opcodes/i386-opc.tbl                         |   6 +
>  13 files changed, 464 insertions(+), 20 deletions(-)
>  create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu-intel.d
>  create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu-inval.l
>  create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu-inval.s
>  create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu.d
>  create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu.s
> 

This is (at least) v2, isn't it? Just to repeat an earlier request: Please
provide a brief summary of what has changed from the prior version, to aid
reviewers.

> @@ -10877,6 +10894,24 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
>  	      abort ();
>  	    }
>  	  break;
> +	case 'U':
> +	  if (l == 1 && (last[0] == 'Z'))
> +	    {
> +	      /* Although IMUL/SETcc does not support NDD, the EVEX.ND bit is
> +		 used to control whether its destination register has its upper
> +		 bits zeroed when OSIZE is 16b/8b.  */
> +	      if (ins->vex.nd)
> +		{
> +		  oappend (ins, "zu");
> +		  /* When we print zu for the EVEX instruction, we no longer
> +		     need prefix {evex}. */
> +		  if (evex_printed == true && startswith (ins->obufp, "{evex}"))
> +		    ins->obufp += 6;

Is this (a) necessary and (b) correct? I ask in particular because I'd have
expected an increment by 7 to also skip the separating blank. Things being
okay with 6 suggests this path isn't really taken (or tested). The extra
startswith() check also looks somewhat questionable: If evex_printed is
true, there ought to be an {evex} prefix. It may not be at the start, but
then you'd still want to zap it (if any zapping is needed here in the first
place).

As to necessary: Isn't what you're trying to undo here the output of {evex}
pretty close to the top of the function? That's under !ins->vex.nd, while
here you check that ins->vex.nd is true. IOW both can't happen at the same
time. It also can't be the one output for %NF, as that's evex-from-vex only.

Assuming it's still needed for a reason I can't spot right now: I also have
to admit I'm slightly wary of such an increment. Elsewhere we always
re-arrange buffer contents, I think.

> @@ -529,6 +533,8 @@ loopne, 0xe0, x64, JumpByte|No_bSuf|No_wSuf|No_sSuf|NoRex64, { Disp8 }
>  
>  // Set byte on flag instructions.
>  set<cc>, 0xf9<cc:opc>/0, i386, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf, { Reg8|Unspecified|BaseIndex }
> +set<cc>, 0xf24<cc:opc>/0, APX_F, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|VexWIG|EVexMap4, { Reg8 }
> +setzu<cc>, 0xf24<cc:opc>/0, APX_F, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|VexWIG|EVexMap4|ZU, { Reg8 }

If you really insist on not adding the extended form right away that I've
been keeping to ask for, please say a sentence or two towards that in the
(sadly so far again empty) description.

Jan
  
Cui, Lili May 20, 2024, 2:06 a.m. UTC | #2
> On 15.05.2024 08:31, Cui, Lili wrote:
> > gas/ChangeLog:
> >
> >         * config/tc-i386.c (build_apx_evex_prefix): Handle ZU.
> >         * testsuite/gas/i386/x86-64.exp: Added new tests for ZU.
> >         * testsuite/gas/i386/x86-64.exp: Added new tests for ZU.
> >         * testsuite/gas/i386/x86-64-apx-zu-intel.d: New test.
> >         * testsuite/gas/i386/x86-64-apx-zu-inval.l: Ditto.
> >         * testsuite/gas/i386/x86-64-apx-zu-inval.s: Ditto.
> >         * testsuite/gas/i386/x86-64-apx-zu.d: Ditto.
> >         * testsuite/gas/i386/x86-64-apx-zu.s: Ditto.
> >
> > opcodes/ChangeLog:
> >
> >         * i386-dis-evex-prefix.h: Handle PREFIX_EVEX_MAP4_40 ~
> >         PREFIX_EVEX_MAP4_4F.
> >         * i386-dis-evex.h: Ditto.
> >         * i386-dis.c (struct dis386): Add new micro 'ZU'.
> >         (putop): Handle %ZU.
> >         * i386-gen.c: Added ZU.
> >         * i386-opc.h: Ditto.
> >         * i386-opc.tbl: Added new templates to support ZU.
> > ---
> >  gas/config/tc-i386.c                         |   5 +-
> >  gas/testsuite/gas/i386/x86-64-apx-zu-intel.d |  78 +++++++++++++
> > gas/testsuite/gas/i386/x86-64-apx-zu-inval.l |  25 +++++
> > gas/testsuite/gas/i386/x86-64-apx-zu-inval.s |  28 +++++
> >  gas/testsuite/gas/i386/x86-64-apx-zu.d       |  78 +++++++++++++
> >  gas/testsuite/gas/i386/x86-64-apx-zu.s       |  73 ++++++++++++
> >  gas/testsuite/gas/i386/x86-64.exp            |   3 +
> >  opcodes/i386-dis-evex-prefix.h               | 112 +++++++++++++++++++
> >  opcodes/i386-dis-evex.h                      |  36 +++---
> >  opcodes/i386-dis.c                           |  35 ++++++
> >  opcodes/i386-gen.c                           |   1 +
> >  opcodes/i386-opc.h                           |   4 +
> >  opcodes/i386-opc.tbl                         |   6 +
> >  13 files changed, 464 insertions(+), 20 deletions(-)  create mode
> > 100644 gas/testsuite/gas/i386/x86-64-apx-zu-intel.d
> >  create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu-inval.l
> >  create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu-inval.s
> >  create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu.d
> >  create mode 100644 gas/testsuite/gas/i386/x86-64-apx-zu.s
> >
> 
> This is (at least) v2, isn't it? Just to repeat an earlier request: Please provide a
> brief summary of what has changed from the prior version, to aid reviewers.
> 

They are placed in patch 0/2 cover letters.

A bug was found when adding operand %ah to an invalid test case, so patch 1/2 was added to fix it. And made the following changes to the old patch.

 1. Removed two redundant judgment codes in zu.
 2. Added various types of register sizes in invalid test cases (found a bug about AH/BH/CH/DH).
 3. Removed IMUL_Fixup and added a macros 'ZU' for imul and setcc in EVEX format.
 4. Added VexWIG to EVEX format setzu/set to remove an ugly judgement.
 5. Added more test cases for imulzu and setzu.

> > @@ -10877,6 +10894,24 @@ putop (instr_info *ins, const char
> *in_template, int sizeflag)
> >  	      abort ();
> >  	    }
> >  	  break;
> > +	case 'U':
> > +	  if (l == 1 && (last[0] == 'Z'))
> > +	    {
> > +	      /* Although IMUL/SETcc does not support NDD, the EVEX.ND bit is
> > +		 used to control whether its destination register has its upper
> > +		 bits zeroed when OSIZE is 16b/8b.  */
> > +	      if (ins->vex.nd)
> > +		{
> > +		  oappend (ins, "zu");
> > +		  /* When we print zu for the EVEX instruction, we no longer
> > +		     need prefix {evex}. */
> > +		  if (evex_printed == true && startswith (ins->obufp, "{evex}"))
> > +		    ins->obufp += 6;
> 
> Is this (a) necessary and (b) correct? I ask in particular because I'd have
> expected an increment by 7 to also skip the separating blank. Things being
> okay with 6 suggests this path isn't really taken (or tested). The extra
> startswith() check also looks somewhat questionable: If evex_printed is true,
> there ought to be an {evex} prefix. It may not be at the start, but then you'd
> still want to zap it (if any zapping is needed here in the first place).
> 
> As to necessary: Isn't what you're trying to undo here the output of {evex}
> pretty close to the top of the function? That's under !ins->vex.nd, while here
> you check that ins->vex.nd is true. IOW both can't happen at the same time. It
> also can't be the one output for %NF, as that's evex-from-vex only.
> 
> Assuming it's still needed for a reason I can't spot right now: I also have to
> admit I'm slightly wary of such an increment. Elsewhere we always re-arrange
> buffer contents, I think.
> 

Yes, you are right, the 'ins->vex.nd' of imulzu and setzu are true and both are placed in MAP4, putop will not print {evex} for them, I will delete this redundant code.

I mistakenly thought putop would print {evex} for them here.

      switch (*p)
        {
        default:
          if (ins->evex_type == evex_from_legacy && !ins->vex.nd
              && !(ins->rex2 & 7) && !evex_printed)
            {
              oappend (ins, "{evex} ");
              evex_printed = true;
            }
          *ins->obufp++ = *p;
          break;

> > @@ -529,6 +533,8 @@ loopne, 0xe0, x64,
> > JumpByte|No_bSuf|No_wSuf|No_sSuf|NoRex64, { Disp8 }
> >
> >  // Set byte on flag instructions.
> >  set<cc>, 0xf9<cc:opc>/0, i386,
> Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf,
> > { Reg8|Unspecified|BaseIndex }
> > +set<cc>, 0xf24<cc:opc>/0, APX_F,
> > +Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|VexWIG|EVexMap4, { Reg8 }
> > +setzu<cc>, 0xf24<cc:opc>/0, APX_F,
> > +Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|VexWIG|EVexMap4|ZU,
> { Reg8 }
> 
> If you really insist on not adding the extended form right away that I've been
> keeping to ask for, please say a sentence or two towards that in the (sadly so
> far again empty) description.
> 
OK.

Thanks,
Lili.
  

Patch

diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 18d06371321..86d177591b3 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -4285,8 +4285,9 @@  build_apx_evex_prefix (void)
     i.vex.bytes[3] &= ~0x08;
 
   /* Encode the NDD bit of the instruction promoted from the legacy
-     space.  */
-  if (i.vex.register_specifier && i.tm.opcode_space == SPACE_EVEXMAP4)
+     space. ZU shares the same bit with NDD.  */
+  if ((i.vex.register_specifier && i.tm.opcode_space == SPACE_EVEXMAP4)
+      || i.tm.opcode_modifier.zu)
     i.vex.bytes[3] |= 0x10;
 
   /* Encode the NF bit.  */
diff --git a/gas/testsuite/gas/i386/x86-64-apx-zu-intel.d b/gas/testsuite/gas/i386/x86-64-apx-zu-intel.d
new file mode 100644
index 00000000000..9b61d50fd2f
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-apx-zu-intel.d
@@ -0,0 +1,78 @@ 
+#as:
+#objdump: -dw -Mintel
+#name: x86-64 APX ZU instructions with evex prefix encoding(Intel disassembly)
+#source: x86-64-apx-zu.s
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+\s*[a-f0-9]+:\s*62 f4 7d 18 6b c3 0a[ 	]+imulzu ax,bx,0xa
+\s*[a-f0-9]+:\s*67 62 f4 7d 18 6b 00 0a[ 	]+imulzu ax,WORD PTR \[eax\],0xa
+\s*[a-f0-9]+:\s*62 ec 7d 18 6b c1 0a[ 	]+imulzu r16w,r17w,0xa
+\s*[a-f0-9]+:\s*67 62 6c 7d 18 6b 38 0a[ 	]+imulzu r31w,WORD PTR \[r16d\],0xa
+\s*[a-f0-9]+:\s*62 4c 7d 18 6b ff 0a[ 	]+imulzu r31w,r31w,0xa
+\s*[a-f0-9]+:\s*62 f4 7d 18 69 c3 82 23[ 	]+imulzu ax,bx,0x2382
+\s*[a-f0-9]+:\s*67 62 f4 7d 18 69 00 82 23[ 	]+imulzu ax,WORD PTR \[eax\],0x2382
+\s*[a-f0-9]+:\s*62 ec 7d 18 69 c1 82 23[ 	]+imulzu r16w,r17w,0x2382
+\s*[a-f0-9]+:\s*67 62 6c 7d 18 69 38 82 23[ 	]+imulzu r31w,WORD PTR \[r16d\],0x2382
+\s*[a-f0-9]+:\s*62 4c 7d 18 69 ff 82 23[ 	]+imulzu r31w,r31w,0x2382
+\s*[a-f0-9]+:\s*62 f4 7d 1c 6b c3 0a[ 	]+\{nf\} imulzu ax,bx,0xa
+\s*[a-f0-9]+:\s*67 62 f4 7d 1c 6b 00 0a[ 	]+\{nf\} imulzu ax,WORD PTR \[eax\],0xa
+\s*[a-f0-9]+:\s*62 f4 7d 0c 6b c3 0a[ 	]+\{nf\} imul ax,bx,0xa
+\s*[a-f0-9]+:\s*67 62 f4 7d 0c 6b 00 0a[ 	]+\{nf\} imul ax,WORD PTR \[eax\],0xa
+\s*[a-f0-9]+:\s*62 f4 7d 08 6b c3 0a[ 	]+\{evex\} imul ax,bx,0xa
+\s*[a-f0-9]+:\s*67 62 f4 7d 08 6b 00 0a[ 	]+\{evex\} imul ax,WORD PTR \[eax\],0xa
+\s*[a-f0-9]+:\s*62 f4 7f 18 41 c0[ 	]+setzuno al
+\s*[a-f0-9]+:\s*62 f4 7f 18 42 c3[ 	]+setzub bl
+\s*[a-f0-9]+:\s*62 d4 7f 18 43 c0[ 	]+setzuae r8b
+\s*[a-f0-9]+:\s*62 d4 7f 18 44 c1[ 	]+setzue r9b
+\s*[a-f0-9]+:\s*62 d4 7f 18 45 c2[ 	]+setzune r10b
+\s*[a-f0-9]+:\s*62 fc 7f 18 46 c0[ 	]+setzube r16b
+\s*[a-f0-9]+:\s*62 fc 7f 18 47 c1[ 	]+setzua r17b
+\s*[a-f0-9]+:\s*62 fc 7f 18 48 c2[ 	]+setzus r18b
+\s*[a-f0-9]+:\s*62 fc 7f 18 49 c3[ 	]+setzuns r19b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4a c4[ 	]+setzup r20b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4b c5[ 	]+setzunp r21b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4c c6[ 	]+setzul r22b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4d c7[ 	]+setzuge r23b
+\s*[a-f0-9]+:\s*62 dc 7f 18 4e c0[ 	]+setzule r24b
+\s*[a-f0-9]+:\s*62 dc 7f 18 4f c1[ 	]+setzug r25b
+\s*[a-f0-9]+:\s*d5 91 9f c1[ 	]+setg   r25b
+\s*[a-f0-9]+:\s*62 f4 7f 08 4f c0[ 	]+\{evex\} setg al
+\s*[a-f0-9]+:\s*62 f4 7d 18 6b c3 0a[ 	]+imulzu ax,bx,0xa
+\s*[a-f0-9]+:\s*67 62 f4 7d 18 6b 00 0a[ 	]+imulzu ax,WORD PTR \[eax\],0xa
+\s*[a-f0-9]+:\s*62 ec 7d 18 6b c1 0a[ 	]+imulzu r16w,r17w,0xa
+\s*[a-f0-9]+:\s*67 62 6c 7d 18 6b 38 0a[ 	]+imulzu r31w,WORD PTR \[r16d\],0xa
+\s*[a-f0-9]+:\s*62 4c 7d 18 6b ff 0a[ 	]+imulzu r31w,r31w,0xa
+\s*[a-f0-9]+:\s*62 f4 7d 18 69 c3 82 23[ 	]+imulzu ax,bx,0x2382
+\s*[a-f0-9]+:\s*67 62 f4 7d 18 69 00 82 23[ 	]+imulzu ax,WORD PTR \[eax\],0x2382
+\s*[a-f0-9]+:\s*62 ec 7d 18 69 c1 82 23[ 	]+imulzu r16w,r17w,0x2382
+\s*[a-f0-9]+:\s*67 62 6c 7d 18 69 38 82 23[ 	]+imulzu r31w,WORD PTR \[r16d\],0x2382
+\s*[a-f0-9]+:\s*62 4c 7d 18 69 ff 82 23[ 	]+imulzu r31w,r31w,0x2382
+\s*[a-f0-9]+:\s*62 f4 7d 1c 6b c3 0a[ 	]+\{nf\} imulzu ax,bx,0xa
+\s*[a-f0-9]+:\s*67 62 f4 7d 1c 6b 00 0a[ 	]+\{nf\} imulzu ax,WORD PTR \[eax\],0xa
+\s*[a-f0-9]+:\s*62 f4 7d 0c 6b c3 0a[ 	]+\{nf\} imul ax,bx,0xa
+\s*[a-f0-9]+:\s*67 62 f4 7d 0c 6b 00 0a[ 	]+\{nf\} imul ax,WORD PTR \[eax\],0xa
+\s*[a-f0-9]+:\s*62 f4 7d 08 6b c3 0a[ 	]+\{evex\} imul ax,bx,0xa
+\s*[a-f0-9]+:\s*67 62 f4 7d 08 6b 00 0a[ 	]+\{evex\} imul ax,WORD PTR \[eax\],0xa
+\s*[a-f0-9]+:\s*62 f4 7f 18 41 c0[ 	]+setzuno al
+\s*[a-f0-9]+:\s*62 f4 7f 18 42 c3[ 	]+setzub bl
+\s*[a-f0-9]+:\s*62 d4 7f 18 43 c0[ 	]+setzuae r8b
+\s*[a-f0-9]+:\s*62 d4 7f 18 44 c1[ 	]+setzue r9b
+\s*[a-f0-9]+:\s*62 d4 7f 18 45 c2[ 	]+setzune r10b
+\s*[a-f0-9]+:\s*62 fc 7f 18 46 c0[ 	]+setzube r16b
+\s*[a-f0-9]+:\s*62 fc 7f 18 47 c1[ 	]+setzua r17b
+\s*[a-f0-9]+:\s*62 fc 7f 18 48 c2[ 	]+setzus r18b
+\s*[a-f0-9]+:\s*62 fc 7f 18 49 c3[ 	]+setzuns r19b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4a c4[ 	]+setzup r20b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4b c5[ 	]+setzunp r21b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4c c6[ 	]+setzul r22b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4d c7[ 	]+setzuge r23b
+\s*[a-f0-9]+:\s*62 dc 7f 18 4e c0[ 	]+setzule r24b
+\s*[a-f0-9]+:\s*62 dc 7f 18 4f c1[ 	]+setzug r25b
+\s*[a-f0-9]+:\s*d5 91 9f c1[ 	]+setg   r25b
+\s*[a-f0-9]+:\s*62 f4 7f 08 4f c0[ 	]+\{evex\} setg al
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-apx-zu-inval.l b/gas/testsuite/gas/i386/x86-64-apx-zu-inval.l
new file mode 100644
index 00000000000..978acc1e3e9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-apx-zu-inval.l
@@ -0,0 +1,25 @@ 
+.* Assembler messages:
+.*:6: Error: invalid instruction suffix for `imulzu'
+.*:7: Error: no such instruction: `imulzud \$0xa,%ebx,%eax'
+.*:8: Error: operand size mismatch for `imulzu'
+.*:9: Error: invalid instruction suffix for `imulzu'
+.*:10: Error: no such instruction: `imulzud \$0xaaaa,%ebx,%eax'
+.*:11: Error: operand size mismatch for `imulzu'
+.*:12: Error: operand size mismatch for `imulzu'
+.*:13: Error: operand size mismatch for `imulzu'
+.*:14: Error: can't encode register 'ah' in an  EVEX/VEX prefix instruction
+.*:15: Error: operand size mismatch for `setzub'
+.*:16: Error: operand size mismatch for `setzuae'
+.*:17: Error: operand size mismatch for `setzue'
+.*:18: Error: operand size mismatch for `setzune'
+.*:19: Error: operand size mismatch for `setzube'
+.*:20: Error: operand size mismatch for `setzua'
+.*:21: Error: operand size mismatch for `setzus'
+.*:22: Error: operand size mismatch for `setzuns'
+.*:23: Error: operand size mismatch for `setzup'
+.*:24: Error: operand size mismatch for `setzunp'
+.*:25: Error: operand size mismatch for `setzul'
+.*:26: Error: operand size mismatch for `setzuge'
+.*:27: Error: operand size mismatch for `setzule'
+.*:28: Error: operand size mismatch for `setzug'
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-apx-zu-inval.s b/gas/testsuite/gas/i386/x86-64-apx-zu-inval.s
new file mode 100644
index 00000000000..bd81b41ff3f
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-apx-zu-inval.s
@@ -0,0 +1,28 @@ 
+# Check illegal APX-ZU instructions
+
+	.allow_index_reg
+	.text
+_start:
+	imulzub $0xa,%bl,%al
+	imulzud $0xa,%ebx,%eax
+	imulzu $0xa,%rbx,%rax
+	imulzub $0xaaaa,%bl,%al
+	imulzud $0xaaaa,%ebx,%eax
+	imulzu $0xaaaa,%rbx,%rax
+	imulzu $0xaaaa,%ebx,%rax
+	imulzu $0xaaaa,%ebx,%rax
+	setzuno  %ah
+	setzub   %bx
+	setzuae  %r8w
+	setzue   %r9
+	setzune  %r10d
+	setzube  %eax
+	setzua   %ebx
+	setzus   %r18w
+	setzuns  %r19w
+	setzup   %r20d
+	setzunp  %r21w
+	setzul   %r22w
+	setzuge  %r23d
+	setzule  %r24w
+	setzug   %r25w
diff --git a/gas/testsuite/gas/i386/x86-64-apx-zu.d b/gas/testsuite/gas/i386/x86-64-apx-zu.d
new file mode 100644
index 00000000000..c6b0cc45d76
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-apx-zu.d
@@ -0,0 +1,78 @@ 
+#as:
+#objdump: -dw
+#name: x86-64 APX ZU instructions with evex prefix encoding
+#source: x86-64-apx-zu.s
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+\s*[a-f0-9]+:\s*62 f4 7d 18 6b c3 0a[ 	]+imulzu \$0xa,%bx,%ax
+\s*[a-f0-9]+:\s*67 62 f4 7d 18 6b 00 0a[ 	]+imulzu \$0xa,\(%eax\),%ax
+\s*[a-f0-9]+:\s*62 ec 7d 18 6b c1 0a[ 	]+imulzu \$0xa,%r17w,%r16w
+\s*[a-f0-9]+:\s*67 62 6c 7d 18 6b 38 0a[ 	]+imulzu \$0xa,\(%r16d\),%r31w
+\s*[a-f0-9]+:\s*62 4c 7d 18 6b ff 0a[ 	]+imulzu \$0xa,%r31w,%r31w
+\s*[a-f0-9]+:\s*62 f4 7d 18 69 c3 82 23[ 	]+imulzu \$0x2382,%bx,%ax
+\s*[a-f0-9]+:\s*67 62 f4 7d 18 69 00 82 23[ 	]+imulzu \$0x2382,\(%eax\),%ax
+\s*[a-f0-9]+:\s*62 ec 7d 18 69 c1 82 23[ 	]+imulzu \$0x2382,%r17w,%r16w
+\s*[a-f0-9]+:\s*67 62 6c 7d 18 69 38 82 23[ 	]+imulzu \$0x2382,\(%r16d\),%r31w
+\s*[a-f0-9]+:\s*62 4c 7d 18 69 ff 82 23[ 	]+imulzu \$0x2382,%r31w,%r31w
+\s*[a-f0-9]+:\s*62 f4 7d 1c 6b c3 0a[ 	]+\{nf\} imulzu \$0xa,%bx,%ax
+\s*[a-f0-9]+:\s*67 62 f4 7d 1c 6b 00 0a[ 	]+\{nf\} imulzu \$0xa,\(%eax\),%ax
+\s*[a-f0-9]+:\s*62 f4 7d 0c 6b c3 0a[ 	]+\{nf\} imul \$0xa,%bx,%ax
+\s*[a-f0-9]+:\s*67 62 f4 7d 0c 6b 00 0a[ 	]+\{nf\} imul \$0xa,\(%eax\),%ax
+\s*[a-f0-9]+:\s*62 f4 7d 08 6b c3 0a[ 	]+\{evex\} imul \$0xa,%bx,%ax
+\s*[a-f0-9]+:\s*67 62 f4 7d 08 6b 00 0a[ 	]+\{evex\} imul \$0xa,\(%eax\),%ax
+\s*[a-f0-9]+:\s*62 f4 7f 18 41 c0[ 	]+setzuno %al
+\s*[a-f0-9]+:\s*62 f4 7f 18 42 c3[ 	]+setzub %bl
+\s*[a-f0-9]+:\s*62 d4 7f 18 43 c0[ 	]+setzuae %r8b
+\s*[a-f0-9]+:\s*62 d4 7f 18 44 c1[ 	]+setzue %r9b
+\s*[a-f0-9]+:\s*62 d4 7f 18 45 c2[ 	]+setzune %r10b
+\s*[a-f0-9]+:\s*62 fc 7f 18 46 c0[ 	]+setzube %r16b
+\s*[a-f0-9]+:\s*62 fc 7f 18 47 c1[ 	]+setzua %r17b
+\s*[a-f0-9]+:\s*62 fc 7f 18 48 c2[ 	]+setzus %r18b
+\s*[a-f0-9]+:\s*62 fc 7f 18 49 c3[ 	]+setzuns %r19b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4a c4[ 	]+setzup %r20b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4b c5[ 	]+setzunp %r21b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4c c6[ 	]+setzul %r22b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4d c7[ 	]+setzuge %r23b
+\s*[a-f0-9]+:\s*62 dc 7f 18 4e c0[ 	]+setzule %r24b
+\s*[a-f0-9]+:\s*62 dc 7f 18 4f c1[ 	]+setzug %r25b
+\s*[a-f0-9]+:\s*d5 91 9f c1[ 	]+setg   %r25b
+\s*[a-f0-9]+:\s*62 f4 7f 08 4f c0[ 	]+\{evex\} setg %al
+\s*[a-f0-9]+:\s*62 f4 7d 18 6b c3 0a[ 	]+imulzu \$0xa,%bx,%ax
+\s*[a-f0-9]+:\s*67 62 f4 7d 18 6b 00 0a[ 	]+imulzu \$0xa,\(%eax\),%ax
+\s*[a-f0-9]+:\s*62 ec 7d 18 6b c1 0a[ 	]+imulzu \$0xa,%r17w,%r16w
+\s*[a-f0-9]+:\s*67 62 6c 7d 18 6b 38 0a[ 	]+imulzu \$0xa,\(%r16d\),%r31w
+\s*[a-f0-9]+:\s*62 4c 7d 18 6b ff 0a[ 	]+imulzu \$0xa,%r31w,%r31w
+\s*[a-f0-9]+:\s*62 f4 7d 18 69 c3 82 23[ 	]+imulzu \$0x2382,%bx,%ax
+\s*[a-f0-9]+:\s*67 62 f4 7d 18 69 00 82 23[ 	]+imulzu \$0x2382,\(%eax\),%ax
+\s*[a-f0-9]+:\s*62 ec 7d 18 69 c1 82 23[ 	]+imulzu \$0x2382,%r17w,%r16w
+\s*[a-f0-9]+:\s*67 62 6c 7d 18 69 38 82 23[ 	]+imulzu \$0x2382,\(%r16d\),%r31w
+\s*[a-f0-9]+:\s*62 4c 7d 18 69 ff 82 23[ 	]+imulzu \$0x2382,%r31w,%r31w
+\s*[a-f0-9]+:\s*62 f4 7d 1c 6b c3 0a[ 	]+\{nf\} imulzu \$0xa,%bx,%ax
+\s*[a-f0-9]+:\s*67 62 f4 7d 1c 6b 00 0a[ 	]+\{nf\} imulzu \$0xa,\(%eax\),%ax
+\s*[a-f0-9]+:\s*62 f4 7d 0c 6b c3 0a[ 	]+\{nf\} imul \$0xa,%bx,%ax
+\s*[a-f0-9]+:\s*67 62 f4 7d 0c 6b 00 0a[  	]+\{nf\} imul \$0xa,\(%eax\),%ax
+\s*[a-f0-9]+:\s*62 f4 7d 08 6b c3 0a[ 	]+\{evex\} imul \$0xa,%bx,%ax
+\s*[a-f0-9]+:\s*67 62 f4 7d 08 6b 00 0a[ 	]+\{evex\} imul \$0xa,\(%eax\),%ax
+\s*[a-f0-9]+:\s*62 f4 7f 18 41 c0[ 	]+setzuno %al
+\s*[a-f0-9]+:\s*62 f4 7f 18 42 c3[ 	]+setzub %bl
+\s*[a-f0-9]+:\s*62 d4 7f 18 43 c0[ 	]+setzuae %r8b
+\s*[a-f0-9]+:\s*62 d4 7f 18 44 c1[ 	]+setzue %r9b
+\s*[a-f0-9]+:\s*62 d4 7f 18 45 c2[ 	]+setzune %r10b
+\s*[a-f0-9]+:\s*62 fc 7f 18 46 c0[ 	]+setzube %r16b
+\s*[a-f0-9]+:\s*62 fc 7f 18 47 c1[ 	]+setzua %r17b
+\s*[a-f0-9]+:\s*62 fc 7f 18 48 c2[ 	]+setzus %r18b
+\s*[a-f0-9]+:\s*62 fc 7f 18 49 c3[ 	]+setzuns %r19b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4a c4[ 	]+setzup %r20b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4b c5[ 	]+setzunp %r21b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4c c6[ 	]+setzul %r22b
+\s*[a-f0-9]+:\s*62 fc 7f 18 4d c7[ 	]+setzuge %r23b
+\s*[a-f0-9]+:\s*62 dc 7f 18 4e c0[ 	]+setzule %r24b
+\s*[a-f0-9]+:\s*62 dc 7f 18 4f c1[ 	]+setzug %r25b
+\s*[a-f0-9]+:\s*d5 91 9f c1[ 	]+setg   %r25b
+\s*[a-f0-9]+:\s*62 f4 7f 08 4f c0[ 	]+\{evex\} setg %al
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-apx-zu.s b/gas/testsuite/gas/i386/x86-64-apx-zu.s
new file mode 100644
index 00000000000..0c287b8aa89
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-apx-zu.s
@@ -0,0 +1,73 @@ 
+# Check 64bit APX ZU instructions with evex prefix encoding
+
+	.allow_index_reg
+	.text
+_start:
+	imulzu $10, %bx, %ax
+	imulzu $10, (%eax), %ax
+	imulzu $10, %r17w, %r16w
+	imulzu $10, (%r16d), %r31w
+	imulzu $10, %r31w
+	imulzu $9090, %bx, %ax
+	imulzu $9090, (%eax), %ax
+	imulzu $9090, %r17w, %r16w
+	imulzu $9090, (%r16d), %r31w
+	imulzu $9090, %r31w
+	{nf}   imulzu $10, %bx, %ax
+	{nf}   imulzu $10, (%eax), %ax
+	{nf}   imul $10, %bx, %ax       # ZU=0
+	{nf}   imul $10, (%eax), %ax    # ZU=0
+	{evex} imul $10, %bx, %ax       # ZU=0
+	{evex} imul $10, (%eax), %ax    # ZU=0
+	setzuno  %al
+	setzub   %bl
+	setzuae  %r8b
+	setzue   %r9b
+	setzune  %r10b
+	setzube  %r16b
+	setzua   %r17b
+	setzus   %r18b
+	setzuns  %r19b
+	setzup   %r20b
+	setzunp  %r21b
+	setzul   %r22b
+	setzuge  %r23b
+	setzule  %r24b
+	setzug   %r25b
+	setg     %r25b
+	{evex} setg  %al
+
+	.intel_syntax noprefix
+	imulzu ax,bx, 10
+	imulzu ax,WORD PTR [eax],10
+	imulzu r16w,r17w,10
+	imulzu r31w,WORD PTR [r16d],10
+	imulzu r31w,r31w,10
+	imulzu ax,bx,9090
+	imulzu ax,WORD PTR [eax],9090
+	imulzu r16w,r17w,9090
+	imulzu r31w,WORD PTR [r16d],9090
+	imulzu r31w,r31w,9090
+	{nf} imulzu ax,bx, 10
+	{nf} imulzu ax,WORD PTR [eax],10
+	{nf} imul ax,bx, 10               # ZU=0
+	{nf} imul ax,WORD PTR [eax],10    # ZU=0
+	{evex} imul ax,bx, 10             # ZU=0
+	{evex} imul ax,WORD PTR [eax],10  # ZU=0
+	setzuno  al
+	setzub   bl
+	setzuae  r8b
+	setzue   r9b
+	setzune  r10b
+	setzube  r16b
+	setzua   r17b
+	setzus   r18b
+	setzuns  r19b
+	setzup   r20b
+	setzunp  r21b
+	setzul   r22b
+	setzuge  r23b
+	setzule  r24b
+	setzug   r25b
+	setg     r25b
+	{evex} setg  al
diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-64.exp
index a50865f6b21..ef1ad2dfe8a 100644
--- a/gas/testsuite/gas/i386/x86-64.exp
+++ b/gas/testsuite/gas/i386/x86-64.exp
@@ -389,6 +389,9 @@  run_dump_test "x86-64-apx-jmpabs-intel"
 run_dump_test "x86-64-apx-jmpabs-inval"
 run_dump_test "x86-64-apx-nf"
 run_dump_test "x86-64-apx-nf-intel"
+run_dump_test "x86-64-apx-zu"
+run_dump_test "x86-64-apx-zu-intel"
+run_list_test "x86-64-apx-zu-inval"
 run_dump_test "x86-64-apx_f-evex"
 run_dump_test "sse2avx-apx"
 run_dump_test "sse2avx-evex"
diff --git a/opcodes/i386-dis-evex-prefix.h b/opcodes/i386-dis-evex-prefix.h
index 5e6423790b5..947fd868dd6 100644
--- a/opcodes/i386-dis-evex-prefix.h
+++ b/opcodes/i386-dis-evex-prefix.h
@@ -338,6 +338,118 @@ 
     { "vcmpp%XH", { MaskG, Vex, EXxh, EXxEVexS, CMP }, 0 },
     { "vcmps%XH", { MaskG, VexScalar, EXw, EXxEVexS, CMP }, 0 },
   },
+  /* PREFIX_EVEX_MAP4_40 */
+  {
+    { "%CFcmovoS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovoS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUo",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_41 */
+  {
+    { "%CFcmovnoS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovnoS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUno",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_42 */
+  {
+    { "%CFcmovbS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovbS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUb",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_43 */
+  {
+    { "%CFcmovaeS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovaeS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUae",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_44 */
+  {
+    { "%CFcmoveS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmoveS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUe",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_45 */
+  {
+    { "%CFcmovneS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovneS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUne",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_46 */
+  {
+    { "%CFcmovbeS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovbeS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUbe",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_47 */
+  {
+    { "%CFcmovaS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovaS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUa",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_48 */
+  {
+    { "%CFcmovsS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovsS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUs",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_49 */
+  {
+    { "%CFcmovnsS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovnsS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUns",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_4A */
+  {
+    { "%CFcmovpS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovpS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUp",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_4B */
+  {
+    { "%CFcmovnpS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovnpS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUnp",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_4C */
+  {
+    { "%CFcmovlS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovlS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUl",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_4D */
+  {
+    { "%CFcmovgeS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovgeS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUge",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_4E */
+  {
+    { "%CFcmovleS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovleS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUle",	{ Eb }, 0 },
+  },
+  /* PREFIX_EVEX_MAP4_4F */
+  {
+    { "%CFcmovgS",	{ VexGv, Gv, Ev }, 0 },
+    { Bad_Opcode },
+    { "%CFcmovgS",	{ VexGv, Gv, Ev }, 0 },
+    { "set%ZUg",	{ Eb }, 0 },
+  },
   /* PREFIX_EVEX_MAP4_F0 */
   {
     { "crc32A", { Gdq, Eb }, 0 },
diff --git a/opcodes/i386-dis-evex.h b/opcodes/i386-dis-evex.h
index b158f2b0b89..ebb3cc20aea 100644
--- a/opcodes/i386-dis-evex.h
+++ b/opcodes/i386-dis-evex.h
@@ -947,23 +947,23 @@  static const struct dis386 evex_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     /* 40 */
-    { "%CFcmovoS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovnoS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovbS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovaeS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmoveS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovneS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovbeS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovaS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_40) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_41) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_42) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_43) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_44) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_45) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_46) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_47) },
     /* 48 */
-    { "%CFcmovsS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovnsS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovpS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovnpS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovlS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovgeS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovleS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
-    { "%CFcmovgS",	{ VexGv, Gv, Ev }, PREFIX_NP_OR_DATA },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_48) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_49) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_4A) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_4B) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_4C) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_4D) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_4E) },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP4_4F) },
     /* 50 */
     { Bad_Opcode },
     { Bad_Opcode },
@@ -993,9 +993,9 @@  static const struct dis386 evex_table[][256] = {
     { Bad_Opcode },
     /* 68 */
     { Bad_Opcode },
-    { "%NFimulS",	{ Gv, Ev, Iv }, PREFIX_NP_OR_DATA },
+    { "%NFimul%ZUS",	{ Gv, Ev, Iv }, PREFIX_NP_OR_DATA },
     { Bad_Opcode },
-    { "%NFimulS",	{ Gv, Ev, sIb }, PREFIX_NP_OR_DATA },
+    { "%NFimul%ZUS",	{ Gv, Ev, sIb }, PREFIX_NP_OR_DATA },
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 53f2d6cf6d8..fad9188b259 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -1199,6 +1199,22 @@  enum
   PREFIX_EVEX_0F3A67,
   PREFIX_EVEX_0F3AC2,
 
+  PREFIX_EVEX_MAP4_40,
+  PREFIX_EVEX_MAP4_41,
+  PREFIX_EVEX_MAP4_42,
+  PREFIX_EVEX_MAP4_43,
+  PREFIX_EVEX_MAP4_44,
+  PREFIX_EVEX_MAP4_45,
+  PREFIX_EVEX_MAP4_46,
+  PREFIX_EVEX_MAP4_47,
+  PREFIX_EVEX_MAP4_48,
+  PREFIX_EVEX_MAP4_49,
+  PREFIX_EVEX_MAP4_4A,
+  PREFIX_EVEX_MAP4_4B,
+  PREFIX_EVEX_MAP4_4C,
+  PREFIX_EVEX_MAP4_4D,
+  PREFIX_EVEX_MAP4_4E,
+  PREFIX_EVEX_MAP4_4F,
   PREFIX_EVEX_MAP4_F0,
   PREFIX_EVEX_MAP4_F1,
   PREFIX_EVEX_MAP4_F2,
@@ -1816,6 +1832,7 @@  struct dis386 {
 	   instruction.
    "NF" => print "{nf} " pseudo prefix when EVEX.NF = 1 and print "{evex} "
 	   pseudo prefix when instructions without NF, EGPR and VVVV,
+   "ZU" => print 'zu' if EVEX.ZU=1.
    "YK" keep unused, to avoid ambiguity with the combined use of Y and K.
    "YX" keep unused, to avoid ambiguity with the combined use of Y and X.
    "LQ" => print 'l' ('d' in Intel mode) or 'q' for memory operand, cond
@@ -10877,6 +10894,24 @@  putop (instr_info *ins, const char *in_template, int sizeflag)
 	      abort ();
 	    }
 	  break;
+	case 'U':
+	  if (l == 1 && (last[0] == 'Z'))
+	    {
+	      /* Although IMUL/SETcc does not support NDD, the EVEX.ND bit is
+		 used to control whether its destination register has its upper
+		 bits zeroed when OSIZE is 16b/8b.  */
+	      if (ins->vex.nd)
+		{
+		  oappend (ins, "zu");
+		  /* When we print zu for the EVEX instruction, we no longer
+		     need prefix {evex}. */
+		  if (evex_printed == true && startswith (ins->obufp, "{evex}"))
+		    ins->obufp += 6;
+		}
+	    }
+	  else
+	    abort ();
+	  break;
 	case 'V':
 	  if (l == 0)
 	    {
diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
index 35e2f27df3b..fb4e78df3a2 100644
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -491,6 +491,7 @@  static bitfield opcode_modifiers[] =
   BITFIELD (NoEgpr),
   BITFIELD (NF),
   BITFIELD (Rex2),
+  BITFIELD (ZU),
 };
 
 #define CLASS(n) #n, n
diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
index fa482ca3d37..b63ad7c13f5 100644
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -754,6 +754,9 @@  enum
   /* Instrucion requires REX2 prefix.  */
   Rex2,
 
+  /* Support zero upper */
+  ZU,
+
   /* The last bitfield in i386_opcode_modifier.  */
   Opcode_Modifier_Num
 };
@@ -801,6 +804,7 @@  typedef struct i386_opcode_modifier
   unsigned int noegpr:1;
   unsigned int nf:1;
   unsigned int rex2:1;
+  unsigned int zu:1;
 } i386_opcode_modifier;
 
 /* Operand classes.  */
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index 0bcda7ea8e1..faaa92c8d11 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -400,15 +400,19 @@  imul, 0xfaf, i386, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|U
 imul, 0xaf, APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
 imul, 0x6b, i186, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
 imul, 0x6b, APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+imulzu, 0x6b, APX_F, Modrm|No_bSuf|No_sSuf|EVexMap4|NF|ZU, { Imm8S, Reg16|Unspecified|BaseIndex, Reg16 }
 imul, 0x69, i186, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Imm16|Imm32|Imm32S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
 imul, 0x69, APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { Imm16|Imm32|Imm32S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+imulzu, 0x69, APX_F, Modrm|No_bSuf|No_sSuf|EVexMap4|NF|ZU, { Imm16, Reg16|Unspecified|BaseIndex, Reg16 }
 // imul with 2 operands mimics imul with 3 by putting the register in
 // both i.rm.reg & i.rm.regmem fields.  RegKludge enables this
 // transformation.
 imul, 0x6b, i186, Modrm|No_bSuf|No_sSuf|RegKludge, { Imm8S, Reg16|Reg32|Reg64 }
 imul, 0x6b, APX_F, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF, { Imm8S, Reg16|Reg32|Reg64 }
+imulzu, 0x6b, APX_F, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF|ZU, { Imm8S, Reg16 }
 imul, 0x69, i186, Modrm|No_bSuf|No_sSuf|RegKludge, { Imm16|Imm32|Imm32S, Reg16|Reg32|Reg64 }
 imul, 0x69, APX_F, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF, { Imm16|Imm32|Imm32S, Reg16|Reg32|Reg64 }
+imulzu, 0x69, APX_F, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF|ZU, { Imm16, Reg16 }
 
 <mul>
 
@@ -529,6 +533,8 @@  loopne, 0xe0, x64, JumpByte|No_bSuf|No_wSuf|No_sSuf|NoRex64, { Disp8 }
 
 // Set byte on flag instructions.
 set<cc>, 0xf9<cc:opc>/0, i386, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf, { Reg8|Unspecified|BaseIndex }
+set<cc>, 0xf24<cc:opc>/0, APX_F, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|VexWIG|EVexMap4, { Reg8 }
+setzu<cc>, 0xf24<cc:opc>/0, APX_F, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|VexWIG|EVexMap4|ZU, { Reg8 }
 
 // String manipulation.
 cmps, 0xa6, 0, W|No_sSuf|RepPrefixOk, {}