[PATCH] x32: Generate 0x67 prefix for VSIB address without base

Jan Beulich JBeulich@suse.com
Mon Feb 25 16:18:00 GMT 2019


>>> On 25.02.19 at 16:55, <hjl.tools@gmail.com> wrote:
> On Mon, Feb 25, 2019 at 7:14 AM Jan Beulich <JBeulich@suse.com> wrote:
>>
>> >>> On 25.02.19 at 15:02, <hjl.tools@gmail.com> wrote:
>> > --- a/gas/config/tc-i386.c
>> > +++ b/gas/config/tc-i386.c
>> > @@ -8194,6 +8194,32 @@ output_insn (void)
>> >       }
>> >        else
>> >       {
>> > +#if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF)
>> > +       if (x86_elf_abi == X86_64_X32_ABI
>> > +           && i.tm.opcode_modifier.vecsib)
>> > +         {
>> > +           /* In x32, add ADDR_PREFIX_OPCODE prefix for VSIB address
>> > +              without base register so that vector index register
>> > +              won't be sign-extended to 64 bits.  */
>> > +           if (!i.base_reg)
>> > +             add_prefix (ADDR_PREFIX_OPCODE);
>>
>> Leaving aside the question of how one would go about overriding
>> this behavior (after all iirc it's not forbidden to use full 64-bit
>> addresses / base registers in x32) I understand this part, but ...
> 
> You can use a 64-bit base register to avoid 0x67 prefix,

I don't understand - this is about the no-base-register case. I was
referring to the 64-bit base register case merely for comparison
purposes. Don't forget that in the qword-index-element case you
now actively truncate index elements.

>> > +           /* In x32, we can't have ADDR_PREFIX_OPCODE prefix for
>> > +              VSIB if there is segment override since address will
>> > +              be segment override + zero-extended to 64 bits of
>> > +              (base + index * scale + disp).  */
>>
>> ... I don't understand this: What is it that goes wrong here in
>> x32 mode? "base" is either zero or a full 64-bit value anyway, so
> 
> "base" can be a 32-bit register:
> 
> vgatherdps %ymm12,%fs:0xc(%eax,%ymm15,1),%ymm11

Oh, sorry, I mixed up base and segment base (because of the
mention of a segment override here).

>> I'm struggling in the first place what (uniform) zero-extension the
>> comment is talking about. But I also don't understand why, if this
>> was needed at all, it would affect VSIB addressing only.
> 
> Segment override is applied AFTER "base + index * scale + disp".
> So memory address in
> 
> movl %fs:(%eax), %eax
> 
> is %fs + zero-extend (%eax), not zero-extend (%fs + %eax).

Sure.

> In x32, GCC avoids 32-bit base/index for TLS:
>[...]

I'm sorry, but this still doesn't make me see what's wrong with
segment overrides in x32 mode, and only with VSIB addressing.
 
>> > +           if (i.prefix[ADDR_PREFIX] && i.prefix[SEG_PREFIX])
>> > +             {
>> > +                const seg_entry *seg;
>> > +                if (i.seg[0])
>> > +                  seg = i.seg[0];
>> > +                else
>> > +                  seg = i.seg[1];
>> > +                as_bad (_("can't encode segment `%s' with 32-bit VSIB"),
>> > +                        seg->seg_name);
>>
>> Please don't emit the % prefix unconditionally, it should not be there
>> in no-prefix / Intel mode.
> 
> What % prefix?
> 
> [hjl@gnu-4 pr24263]$ cat y.s
> .text
> vgatherdps %ymm12,%fs:0xc(%eax,%ymm15,1),%ymm11
> vgatherdps %ymm12,%fs:0xc(,%ymm15,1),%ymm11
> [hjl@gnu-4 pr24263]$ ./as --x32  -o y.o y.s
> y.s: Assembler messages:
> y.s:2: Error: can't encode segment `fs' with 32-bit VSIB
> y.s:3: Error: can't encode segment `fs' with 32-bit VSIB
> [hjl@gnu-4 pr24263]$

Oops, sorry - I should have asked for a % prefix to be added outside
of no-prefix mode.

Jan




More information about the Binutils mailing list