[3/9] x86: correct MPX insn w/o base or index encoding in 16-bit mode

Message ID 77f0a1e8-f146-e043-2d30-23b54b08755d@suse.com
State New
Headers show
Series
  • x86: (mainly) misc IgnoreSize related adjustments
Related show

Commit Message

Jan Beulich March 4, 2020, 9:38 a.m.
Since 16-bit addressing isn't allowed, Disp32 needs to be forced; Disp16
fails to match the templates.

The SDM leaves open whether BNDC[LNU] with a GPR operand require an
operand size override; this aspect is therefore left untouched here.

gas/
2020-03-XX  Jan Beulich  <jbeulich@suse.com>

	* config/tc-i386.c (i386_addressing_mode): For 32-bit
	addressing for MPX insns without base/index.
	* testsuite/gas/i386/mpx-16bit.s,
	* testsuite/gas/i386/mpx-16bit.d: New.
	* testsuite/gas/i386/i386.exp: Run new test.

opcodes/
2020-03-XX  Jan Beulich  <jbeulich@suse.com>

	* i386-dis.c (OP_E_memory): Exclude recording of used address
	prefix for "bnd" modes only in 64-bit mode. Don't decode 16-bit
	addressed memory operands for MPX insns.

Comments

H.J. Lu March 4, 2020, 11:45 a.m. | #1
On Wed, Mar 4, 2020 at 1:38 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> Since 16-bit addressing isn't allowed, Disp32 needs to be forced; Disp16

> fails to match the templates.

>

> The SDM leaves open whether BNDC[LNU] with a GPR operand require an

> operand size override; this aspect is therefore left untouched here.

>

> gas/

> 2020-03-XX  Jan Beulich  <jbeulich@suse.com>

>

>         * config/tc-i386.c (i386_addressing_mode): For 32-bit

>         addressing for MPX insns without base/index.

>         * testsuite/gas/i386/mpx-16bit.s,

>         * testsuite/gas/i386/mpx-16bit.d: New.

>         * testsuite/gas/i386/i386.exp: Run new test.

>

> opcodes/

> 2020-03-XX  Jan Beulich  <jbeulich@suse.com>

>

>         * i386-dis.c (OP_E_memory): Exclude recording of used address

>         prefix for "bnd" modes only in 64-bit mode. Don't decode 16-bit

>         addressed memory operands for MPX insns.

>

> --- a/gas/config/tc-i386.c

> +++ b/gas/config/tc-i386.c

> @@ -10297,6 +10297,21 @@ i386_addressing_mode (void)

>

>    if (i.prefix[ADDR_PREFIX])

>      addr_mode = flag_code == CODE_32BIT ? CODE_16BIT : CODE_32BIT;

> +  else if (flag_code == CODE_16BIT

> +          && current_templates->start->cpu_flags.bitfield.cpumpx

> +          /* Avoid replacing the "16-bit addressing not allowed" diagnostic

> +             from md_assemble() by "is not a valid base/index expression"

> +             when there is a base and/or index.  */

> +          && !i.types[this_operand].bitfield.baseindex)

> +    {

> +      /* MPX insn memory operands with neither base nor index must be forced

> +        to use 32-bit addressing in 16-bit mode.  */

> +      addr_mode = CODE_32BIT;

> +      i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;

> +      ++i.prefixes;

> +      gas_assert (!i.types[this_operand].bitfield.disp16);

> +      gas_assert (!i.types[this_operand].bitfield.disp32);

> +    }

>    else

>      {


Since MPX isn't available in 16-bit mode, should they be disallowed? Given that
MPX has been deprecated, I prefer an error here.

-- 
H.J.
Jan Beulich March 4, 2020, 11:50 a.m. | #2
On 04.03.2020 12:45, H.J. Lu wrote:
> On Wed, Mar 4, 2020 at 1:38 AM Jan Beulich <jbeulich@suse.com> wrote:

>> --- a/gas/config/tc-i386.c

>> +++ b/gas/config/tc-i386.c

>> @@ -10297,6 +10297,21 @@ i386_addressing_mode (void)

>>

>>    if (i.prefix[ADDR_PREFIX])

>>      addr_mode = flag_code == CODE_32BIT ? CODE_16BIT : CODE_32BIT;

>> +  else if (flag_code == CODE_16BIT

>> +          && current_templates->start->cpu_flags.bitfield.cpumpx

>> +          /* Avoid replacing the "16-bit addressing not allowed" diagnostic

>> +             from md_assemble() by "is not a valid base/index expression"

>> +             when there is a base and/or index.  */

>> +          && !i.types[this_operand].bitfield.baseindex)

>> +    {

>> +      /* MPX insn memory operands with neither base nor index must be forced

>> +        to use 32-bit addressing in 16-bit mode.  */

>> +      addr_mode = CODE_32BIT;

>> +      i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;

>> +      ++i.prefixes;

>> +      gas_assert (!i.types[this_operand].bitfield.disp16);

>> +      gas_assert (!i.types[this_operand].bitfield.disp32);

>> +    }

>>    else

>>      {

> 

> Since MPX isn't available in 16-bit mode, should they be disallowed?


How is it not available? As per my understanding, one just needs
to use 32-bit addressing.

> Given that MPX has been deprecated, I prefer an error here.


The use of "here" is confusing - just for the broken case (no
base/index), or for MPX insns in general? (Asking just in case
my understanding expressed above is wrong.)

Jan
H.J. Lu March 4, 2020, 11:54 a.m. | #3
On Wed, Mar 4, 2020 at 3:50 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> On 04.03.2020 12:45, H.J. Lu wrote:

> > On Wed, Mar 4, 2020 at 1:38 AM Jan Beulich <jbeulich@suse.com> wrote:

> >> --- a/gas/config/tc-i386.c

> >> +++ b/gas/config/tc-i386.c

> >> @@ -10297,6 +10297,21 @@ i386_addressing_mode (void)

> >>

> >>    if (i.prefix[ADDR_PREFIX])

> >>      addr_mode = flag_code == CODE_32BIT ? CODE_16BIT : CODE_32BIT;

> >> +  else if (flag_code == CODE_16BIT

> >> +          && current_templates->start->cpu_flags.bitfield.cpumpx

> >> +          /* Avoid replacing the "16-bit addressing not allowed" diagnostic

> >> +             from md_assemble() by "is not a valid base/index expression"

> >> +             when there is a base and/or index.  */

> >> +          && !i.types[this_operand].bitfield.baseindex)

> >> +    {

> >> +      /* MPX insn memory operands with neither base nor index must be forced

> >> +        to use 32-bit addressing in 16-bit mode.  */

> >> +      addr_mode = CODE_32BIT;

> >> +      i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;

> >> +      ++i.prefixes;

> >> +      gas_assert (!i.types[this_operand].bitfield.disp16);

> >> +      gas_assert (!i.types[this_operand].bitfield.disp32);

> >> +    }

> >>    else

> >>      {

> >

> > Since MPX isn't available in 16-bit mode, should they be disallowed?

>

> How is it not available? As per my understanding, one just needs

> to use 32-bit addressing.


0x67 prefix is special for MPX.  It can't be used as address prefix on MPX
instructions.

> > Given that MPX has been deprecated, I prefer an error here.

>

> The use of "here" is confusing - just for the broken case (no

> base/index), or for MPX insns in general? (Asking just in case

> my understanding expressed above is wrong.)


flag_code == CODE_16BIT && current_templates->start->cpu_flags.bitfield.cpumpx

should be an error.

-- 
H.J.
Jan Beulich March 4, 2020, 12:58 p.m. | #4
On 04.03.2020 12:54, H.J. Lu wrote:
> On Wed, Mar 4, 2020 at 3:50 AM Jan Beulich <jbeulich@suse.com> wrote:

>>

>> On 04.03.2020 12:45, H.J. Lu wrote:

>>> On Wed, Mar 4, 2020 at 1:38 AM Jan Beulich <jbeulich@suse.com> wrote:

>>>> --- a/gas/config/tc-i386.c

>>>> +++ b/gas/config/tc-i386.c

>>>> @@ -10297,6 +10297,21 @@ i386_addressing_mode (void)

>>>>

>>>>    if (i.prefix[ADDR_PREFIX])

>>>>      addr_mode = flag_code == CODE_32BIT ? CODE_16BIT : CODE_32BIT;

>>>> +  else if (flag_code == CODE_16BIT

>>>> +          && current_templates->start->cpu_flags.bitfield.cpumpx

>>>> +          /* Avoid replacing the "16-bit addressing not allowed" diagnostic

>>>> +             from md_assemble() by "is not a valid base/index expression"

>>>> +             when there is a base and/or index.  */

>>>> +          && !i.types[this_operand].bitfield.baseindex)

>>>> +    {

>>>> +      /* MPX insn memory operands with neither base nor index must be forced

>>>> +        to use 32-bit addressing in 16-bit mode.  */

>>>> +      addr_mode = CODE_32BIT;

>>>> +      i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;

>>>> +      ++i.prefixes;

>>>> +      gas_assert (!i.types[this_operand].bitfield.disp16);

>>>> +      gas_assert (!i.types[this_operand].bitfield.disp32);

>>>> +    }

>>>>    else

>>>>      {

>>>

>>> Since MPX isn't available in 16-bit mode, should they be disallowed?

>>

>> How is it not available? As per my understanding, one just needs

>> to use 32-bit addressing.

> 

> 0x67 prefix is special for MPX.  It can't be used as address prefix on MPX

> instructions.


It not only can, but is required to be in 16-bit mode. Let me quote
BNDMK's SDM page:

Protected Mode Exceptions
#UD If the LOCK prefix is used.
If ModRM.r/m encodes BND4-BND7 when Intel MPX is enabled.
If 67H prefix is not used and CS.D=0.
If 67H prefix is used and CS.D=1.

Real-Address Mode Exceptions
#UD If the LOCK prefix is used.
If ModRM.r/m encodes BND4-BND7 when Intel MPX is enabled.
If 16-bit addressing is used.

Virtual-8086 Mode Exceptions
#UD If the LOCK prefix is used.
If ModRM.r/m encodes BND4-BND7 when Intel MPX is enabled.
If 16-bit addressing is used.

It is quite clear to me from this that (a) MPX is allowed
in 16-bit mode (and even in all forms of it, other than
e.g. VEX/EVEX-encoded insns) and (b) the 67 prefix acts
as a normal address size override there. Its use simply is
mandatory in 16-bit mode.

>>> Given that MPX has been deprecated, I prefer an error here.

>>

>> The use of "here" is confusing - just for the broken case (no

>> base/index), or for MPX insns in general? (Asking just in case

>> my understanding expressed above is wrong.)

> 

> flag_code == CODE_16BIT && current_templates->start->cpu_flags.bitfield.cpumpx

> 

> should be an error.


As per above, I see no reason for such behavior.

Jan
H.J. Lu March 4, 2020, 1:25 p.m. | #5
On Wed, Mar 4, 2020 at 4:58 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> On 04.03.2020 12:54, H.J. Lu wrote:

> > On Wed, Mar 4, 2020 at 3:50 AM Jan Beulich <jbeulich@suse.com> wrote:

> >>

> >> On 04.03.2020 12:45, H.J. Lu wrote:

> >>> On Wed, Mar 4, 2020 at 1:38 AM Jan Beulich <jbeulich@suse.com> wrote:

> >>>> --- a/gas/config/tc-i386.c

> >>>> +++ b/gas/config/tc-i386.c

> >>>> @@ -10297,6 +10297,21 @@ i386_addressing_mode (void)

> >>>>

> >>>>    if (i.prefix[ADDR_PREFIX])

> >>>>      addr_mode = flag_code == CODE_32BIT ? CODE_16BIT : CODE_32BIT;

> >>>> +  else if (flag_code == CODE_16BIT

> >>>> +          && current_templates->start->cpu_flags.bitfield.cpumpx

> >>>> +          /* Avoid replacing the "16-bit addressing not allowed" diagnostic

> >>>> +             from md_assemble() by "is not a valid base/index expression"

> >>>> +             when there is a base and/or index.  */

> >>>> +          && !i.types[this_operand].bitfield.baseindex)

> >>>> +    {

> >>>> +      /* MPX insn memory operands with neither base nor index must be forced

> >>>> +        to use 32-bit addressing in 16-bit mode.  */

> >>>> +      addr_mode = CODE_32BIT;

> >>>> +      i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;

> >>>> +      ++i.prefixes;

> >>>> +      gas_assert (!i.types[this_operand].bitfield.disp16);

> >>>> +      gas_assert (!i.types[this_operand].bitfield.disp32);

> >>>> +    }

> >>>>    else

> >>>>      {

> >>>

> >>> Since MPX isn't available in 16-bit mode, should they be disallowed?

> >>

> >> How is it not available? As per my understanding, one just needs

> >> to use 32-bit addressing.

> >

> > 0x67 prefix is special for MPX.  It can't be used as address prefix on MPX

> > instructions.

>

> It not only can, but is required to be in 16-bit mode. Let me quote

> BNDMK's SDM page:

>

> Protected Mode Exceptions

> #UD If the LOCK prefix is used.

> If ModRM.r/m encodes BND4-BND7 when Intel MPX is enabled.

> If 67H prefix is not used and CS.D=0.

> If 67H prefix is used and CS.D=1.

>

> Real-Address Mode Exceptions

> #UD If the LOCK prefix is used.

> If ModRM.r/m encodes BND4-BND7 when Intel MPX is enabled.

> If 16-bit addressing is used.

>

> Virtual-8086 Mode Exceptions

> #UD If the LOCK prefix is used.

> If ModRM.r/m encodes BND4-BND7 when Intel MPX is enabled.

> If 16-bit addressing is used.

>

> It is quite clear to me from this that (a) MPX is allowed

> in 16-bit mode (and even in all forms of it, other than

> e.g. VEX/EVEX-encoded insns) and (b) the 67 prefix acts

> as a normal address size override there. Its use simply is

> mandatory in 16-bit mode.

>

> >>> Given that MPX has been deprecated, I prefer an error here.

> >>

> >> The use of "here" is confusing - just for the broken case (no

> >> base/index), or for MPX insns in general? (Asking just in case

> >> my understanding expressed above is wrong.)

> >

> > flag_code == CODE_16BIT && current_templates->start->cpu_flags.bitfield.cpumpx

> >

> > should be an error.

>

> As per above, I see no reason for such behavior.

>


Patch is OK.

Thanks.

-- 
H.J.

Patch

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -10297,6 +10297,21 @@  i386_addressing_mode (void)
 
   if (i.prefix[ADDR_PREFIX])
     addr_mode = flag_code == CODE_32BIT ? CODE_16BIT : CODE_32BIT;
+  else if (flag_code == CODE_16BIT
+	   && current_templates->start->cpu_flags.bitfield.cpumpx
+	   /* Avoid replacing the "16-bit addressing not allowed" diagnostic
+	      from md_assemble() by "is not a valid base/index expression"
+	      when there is a base and/or index.  */
+	   && !i.types[this_operand].bitfield.baseindex)
+    {
+      /* MPX insn memory operands with neither base nor index must be forced
+	 to use 32-bit addressing in 16-bit mode.  */
+      addr_mode = CODE_32BIT;
+      i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
+      ++i.prefixes;
+      gas_assert (!i.types[this_operand].bitfield.disp16);
+      gas_assert (!i.types[this_operand].bitfield.disp32);
+    }
   else
     {
       addr_mode = flag_code;
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -329,6 +329,7 @@  if [expr ([istarget "i*86-*-*"] ||  [ist
     run_list_test "mpx-inval-1" "-al"
     run_list_test "mpx-inval-2" "-al"
     run_dump_test "mpx-add-bnd-prefix"
+    run_dump_test "mpx-16bit"
     run_list_test "bnd" "-al"
     run_dump_test "sha"
     run_dump_test "clflushopt"
--- /dev/null
+++ b/gas/testsuite/gas/i386/mpx-16bit.d
@@ -0,0 +1,145 @@ 
+#as: -I${srcdir}/$subdir
+#objdump: -drw -Mi8086
+#name: i386 MPX (16-bit)
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <start>:
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 08       	bndmk  \(%eax\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 0d 99 03 00 00 	addr32 bndmk 0x399,%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 4a 03    	bndmk  0x3\(%edx\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 0c 08    	bndmk  \(%eax,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 0c 0d 00 00 00 00 	bndmk  0x0\(,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 4c 01 03 	bndmk  0x3\(%ecx,%eax,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 66 0f 1a 08       	bndmov \(%eax\),%bnd1
+[ 	]*[a-f0-9]+:	67 66 0f 1a 0d 99 03 00 00 	addr32 bndmov 0x399,%bnd1
+[ 	]*[a-f0-9]+:	67 66 0f 1a 52 03    	bndmov 0x3\(%edx\),%bnd2
+[ 	]*[a-f0-9]+:	67 66 0f 1a 14 10    	bndmov \(%eax,%edx,1\),%bnd2
+[ 	]*[a-f0-9]+:	67 66 0f 1a 14 05 00 00 00 00 	bndmov 0x0\(,%eax,1\),%bnd2
+[ 	]*[a-f0-9]+:	67 66 0f 1a 4c 01 03 	bndmov 0x3\(%ecx,%eax,1\),%bnd1
+[ 	]*[a-f0-9]+:	66 0f 1a c2          	bndmov %bnd2,%bnd0
+[ 	]*[a-f0-9]+:	67 66 0f 1b 08       	bndmov %bnd1,\(%eax\)
+[ 	]*[a-f0-9]+:	67 66 0f 1b 0d 99 03 00 00 	addr32 bndmov %bnd1,0x399
+[ 	]*[a-f0-9]+:	67 66 0f 1b 52 03    	bndmov %bnd2,0x3\(%edx\)
+[ 	]*[a-f0-9]+:	67 66 0f 1b 14 10    	bndmov %bnd2,\(%eax,%edx,1\)
+[ 	]*[a-f0-9]+:	67 66 0f 1b 14 05 00 00 00 00 	bndmov %bnd2,0x0\(,%eax,1\)
+[ 	]*[a-f0-9]+:	67 66 0f 1b 4c 01 03 	bndmov %bnd1,0x3\(%ecx,%eax,1\)
+[ 	]*[a-f0-9]+:	66 0f 1a d0          	bndmov %bnd0,%bnd2
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 09       	bndcl  \(%ecx\),%bnd1
+[ 	]*[a-f0-9]+:	f3 0f 1a c9          	bndcl  %ecx,%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 0d 99 03 00 00 	addr32 bndcl 0x399,%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 4a 03    	bndcl  0x3\(%edx\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 0c 08    	bndcl  \(%eax,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 0c 0d 00 00 00 00 	bndcl  0x0\(,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 4c 01 03 	bndcl  0x3\(%ecx,%eax,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 09       	bndcu  \(%ecx\),%bnd1
+[ 	]*[a-f0-9]+:	f2 0f 1a c9          	bndcu  %ecx,%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 0d 99 03 00 00 	addr32 bndcu 0x399,%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 4a 03    	bndcu  0x3\(%edx\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 0c 08    	bndcu  \(%eax,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 0c 0d 00 00 00 00 	bndcu  0x0\(,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 4c 01 03 	bndcu  0x3\(%ecx,%eax,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 09       	bndcn  \(%ecx\),%bnd1
+[ 	]*[a-f0-9]+:	f2 0f 1b c9          	bndcn  %ecx,%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 0d 99 03 00 00 	addr32 bndcn 0x399,%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 4a 03    	bndcn  0x3\(%edx\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 0c 08    	bndcn  \(%eax,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 0c 0d 00 00 00 00 	bndcn  0x0\(,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 4c 01 03 	bndcn  0x3\(%ecx,%eax,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 0f 1b 44 18 03    	bndstx %bnd0,0x3\(%eax,%ebx,1\)
+[ 	]*[a-f0-9]+:	67 0f 1b 54 13 03    	bndstx %bnd2,0x3\(%ebx,%edx,1\)
+[ 	]*[a-f0-9]+:	67 0f 1b 14 15 03 00 00 00 	bndstx %bnd2,0x3\(,%edx,1\)
+[ 	]*[a-f0-9]+:	67 0f 1b 9a 99 03 00 00 	bndstx %bnd3,0x399\(%edx\)
+[ 	]*[a-f0-9]+:	67 0f 1b 93 34 12 00 00 	bndstx %bnd2,0x1234\(%ebx\)
+[ 	]*[a-f0-9]+:	67 0f 1b 53 03       	bndstx %bnd2,0x3\(%ebx\)
+[ 	]*[a-f0-9]+:	67 0f 1b 0a          	bndstx %bnd1,\(%edx\)
+[ 	]*[a-f0-9]+:	67 0f 1a 44 18 03    	bndldx 0x3\(%eax,%ebx,1\),%bnd0
+[ 	]*[a-f0-9]+:	67 0f 1a 54 13 03    	bndldx 0x3\(%ebx,%edx,1\),%bnd2
+[ 	]*[a-f0-9]+:	67 0f 1a 14 15 03 00 00 00 	bndldx 0x3\(,%edx,1\),%bnd2
+[ 	]*[a-f0-9]+:	67 0f 1a 9a 99 03 00 00 	bndldx 0x399\(%edx\),%bnd3
+[ 	]*[a-f0-9]+:	67 0f 1a 93 34 12 00 00 	bndldx 0x1234\(%ebx\),%bnd2
+[ 	]*[a-f0-9]+:	67 0f 1a 53 03       	bndldx 0x3\(%ebx\),%bnd2
+[ 	]*[a-f0-9]+:	67 0f 1a 0a          	bndldx \(%edx\),%bnd1
+[ 	]*[a-f0-9]+:	f2 e8 91 01          	bnd call [a-f0-9]+ <foo>
+[ 	]*[a-f0-9]+:	67 f2 ff 10          	bnd call \*\(%eax\)
+[ 	]*[a-f0-9]+:	f2 0f 84 88 01       	bnd je [a-f0-9]+ <foo>
+[ 	]*[a-f0-9]+:	f2 e9 84 01          	bnd jmp [a-f0-9]+ <foo>
+[ 	]*[a-f0-9]+:	67 f2 ff 21          	bnd jmp \*\(%ecx\)
+[ 	]*[a-f0-9]+:	f2 c3                	bnd ret *
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 08       	bndmk  \(%eax\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 0d 99 03 00 00 	addr32 bndmk 0x399,%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 49 03    	bndmk  0x3\(%ecx\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 0c 08    	bndmk  \(%eax,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 0c 0d 00 00 00 00 	bndmk  0x0\(,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1b 4c 02 03 	bndmk  0x3\(%edx,%eax,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 66 0f 1a 08       	bndmov \(%eax\),%bnd1
+[ 	]*[a-f0-9]+:	67 66 0f 1a 0d 99 03 00 00 	addr32 bndmov 0x399,%bnd1
+[ 	]*[a-f0-9]+:	67 66 0f 1a 49 03    	bndmov 0x3\(%ecx\),%bnd1
+[ 	]*[a-f0-9]+:	67 66 0f 1a 0c 08    	bndmov \(%eax,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 66 0f 1a 0c 0d 00 00 00 00 	bndmov 0x0\(,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 66 0f 1a 4c 02 03 	bndmov 0x3\(%edx,%eax,1\),%bnd1
+[ 	]*[a-f0-9]+:	66 0f 1a c1          	bndmov %bnd1,%bnd0
+[ 	]*[a-f0-9]+:	67 66 0f 1b 08       	bndmov %bnd1,\(%eax\)
+[ 	]*[a-f0-9]+:	67 66 0f 1b 0d 99 03 00 00 	addr32 bndmov %bnd1,0x399
+[ 	]*[a-f0-9]+:	67 66 0f 1b 49 03    	bndmov %bnd1,0x3\(%ecx\)
+[ 	]*[a-f0-9]+:	67 66 0f 1b 0c 08    	bndmov %bnd1,\(%eax,%ecx,1\)
+[ 	]*[a-f0-9]+:	67 66 0f 1b 0c 0d 00 00 00 00 	bndmov %bnd1,0x0\(,%ecx,1\)
+[ 	]*[a-f0-9]+:	67 66 0f 1b 4c 02 03 	bndmov %bnd1,0x3\(%edx,%eax,1\)
+[ 	]*[a-f0-9]+:	66 0f 1a c8          	bndmov %bnd0,%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 08       	bndcl  \(%eax\),%bnd1
+[ 	]*[a-f0-9]+:	f3 0f 1a c9          	bndcl  %ecx,%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 0d 99 03 00 00 	addr32 bndcl 0x399,%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 49 03    	bndcl  0x3\(%ecx\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 0c 08    	bndcl  \(%eax,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 0c 0d 00 00 00 00 	bndcl  0x0\(,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f3 0f 1a 4c 02 03 	bndcl  0x3\(%edx,%eax,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 08       	bndcu  \(%eax\),%bnd1
+[ 	]*[a-f0-9]+:	f2 0f 1a c9          	bndcu  %ecx,%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 0d 99 03 00 00 	addr32 bndcu 0x399,%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 49 03    	bndcu  0x3\(%ecx\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 0c 08    	bndcu  \(%eax,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 0c 0d 00 00 00 00 	bndcu  0x0\(,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1a 4c 02 03 	bndcu  0x3\(%edx,%eax,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 08       	bndcn  \(%eax\),%bnd1
+[ 	]*[a-f0-9]+:	f2 0f 1b c9          	bndcn  %ecx,%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 0d 99 03 00 00 	addr32 bndcn 0x399,%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 49 03    	bndcn  0x3\(%ecx\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 0c 08    	bndcn  \(%eax,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 0c 0d 00 00 00 00 	bndcn  0x0\(,%ecx,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 f2 0f 1b 4c 02 03 	bndcn  0x3\(%edx,%eax,1\),%bnd1
+[ 	]*[a-f0-9]+:	67 0f 1b 44 18 03    	bndstx %bnd0,0x3\(%eax,%ebx,1\)
+[ 	]*[a-f0-9]+:	67 0f 1b 54 13 03    	bndstx %bnd2,0x3\(%ebx,%edx,1\)
+[ 	]*[a-f0-9]+:	67 0f 1b 14 0d 00 00 00 00 	bndstx %bnd2,0x0\(,%ecx,1\)
+[ 	]*[a-f0-9]+:	67 0f 1b 9a 99 03 00 00 	bndstx %bnd3,0x399\(%edx\)
+[ 	]*[a-f0-9]+:	67 0f 1b 14 1d 03 00 00 00 	bndstx %bnd2,0x3\(,%ebx,1\)
+[ 	]*[a-f0-9]+:	67 0f 1b 0a          	bndstx %bnd1,\(%edx\)
+[ 	]*[a-f0-9]+:	67 0f 1a 44 18 03    	bndldx 0x3\(%eax,%ebx,1\),%bnd0
+[ 	]*[a-f0-9]+:	67 0f 1a 54 13 03    	bndldx 0x3\(%ebx,%edx,1\),%bnd2
+[ 	]*[a-f0-9]+:	67 0f 1a 14 0d 00 00 00 00 	bndldx 0x0\(,%ecx,1\),%bnd2
+[ 	]*[a-f0-9]+:	67 0f 1a 9a 99 03 00 00 	bndldx 0x399\(%edx\),%bnd3
+[ 	]*[a-f0-9]+:	67 0f 1a 14 1d 03 00 00 00 	bndldx 0x3\(,%ebx,1\),%bnd2
+[ 	]*[a-f0-9]+:	67 0f 1a 0a          	bndldx \(%edx\),%bnd1
+[ 	]*[a-f0-9]+:	f2 e8 10 00          	bnd call [a-f0-9]+ <foo>
+[ 	]*[a-f0-9]+:	66 f2 ff d0          	bnd calll? \*%eax
+[ 	]*[a-f0-9]+:	f2 74 09             	bnd je [a-f0-9]+ <foo>
+[ 	]*[a-f0-9]+:	f2 eb 06             	bnd jmp [a-f0-9]+ <foo>
+[ 	]*[a-f0-9]+:	66 f2 ff e1          	bnd jmpl? \*%ecx
+[ 	]*[a-f0-9]+:	f2 c3                	bnd ret *
+
+[a-f0-9]+ <foo>:
+[ 	]*[a-f0-9]+:	f2 c3                	bnd ret *
+
+[a-f0-9]+ <bad>:
+#...
+[a-f0-9]+ <bad16>:
+[ 	]*[a-f0-9]+:	f3 0f 1b 00          	bndmk  \(bad\),%bnd0
+[ 	]*[a-f0-9]+:	66 0f 1a 00          	bndmov \(bad\),%bnd0
+[ 	]*[a-f0-9]+:	f3 0f 1a 00          	bndcl  \(bad\),%bnd0
+[ 	]*[a-f0-9]+:	f2 0f 1b 00          	bndcn  \(bad\),%bnd0
+[ 	]*[a-f0-9]+:	f2 0f 1a 00          	bndcu  \(bad\),%bnd0
+[ 	]*[a-f0-9]+:	0f 1b 00             	bndstx %bnd0,\(bad\)
+[ 	]*[a-f0-9]+:	0f 1a 00             	bndldx \(bad\),%bnd0
+#pass
--- /dev/null
+++ b/gas/testsuite/gas/i386/mpx-16bit.s
@@ -0,0 +1,13 @@ 
+	.code16
+	.include "mpx.s"
+
+	.att_syntax prefix
+	.code32
+bad16: # 16-bit addressing mode seen by the disassembler
+	bndmk	(%eax), %bnd0
+	bndmov	(%eax), %bnd0
+	bndcl	(%eax), %bnd0
+	bndcn	(%eax), %bnd0
+	bndcu	(%eax), %bnd0
+	bndstx	%bnd0, (%eax)
+	bndldx	(%eax), %bnd0
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -14272,10 +14272,11 @@  OP_E_memory (int bytemode, int sizeflag)
 	  }
 
       if ((havebase || haveindex || needindex || needaddr32 || riprel)
-	  && (bytemode != v_bnd_mode)
-	  && (bytemode != v_bndmk_mode)
-	  && (bytemode != bnd_mode)
-	  && (bytemode != bnd_swap_mode))
+	  && (address_mode != mode_64bit
+	      || ((bytemode != v_bnd_mode)
+		  && (bytemode != v_bndmk_mode)
+		  && (bytemode != bnd_mode)
+		  && (bytemode != bnd_swap_mode))))
 	used_prefixes |= PREFIX_ADDR;
 
       if (havedisp || (intel_syntax && riprel))
@@ -14356,6 +14357,14 @@  OP_E_memory (int bytemode, int sizeflag)
 	    }
 	}
     }
+  else if (bytemode == v_bnd_mode
+	   || bytemode == v_bndmk_mode
+	   || bytemode == bnd_mode
+	   || bytemode == bnd_swap_mode)
+    {
+      oappend ("(bad)");
+      return;
+    }
   else
     {
       /* 16 bit address mode */