On Thu, Nov 5, 2020 at 12:38 PM Alexander Monakov <amona...@ispras.ru> wrote:
>
> On Thu, 5 Nov 2020, Uros Bizjak via Gcc wrote:
>
> > > What is the usecase for stripping the address space for asm operands?
> >
> > Please see the end of [2], where the offset to <mem> is passed in %rsi
> > to the call to this_cpu_cmpxchg16b_emu. this_cpu_cmpxchg16b_emu
> > implements access with PER_CPU_VAR((%rsi)), which expands to
> > %gs:(%rsi), so it is the same as %gs:<mem> in cmpxchg16b alternative.
> > The offset is loaded by lea <mem>, %rsi to %rsi reg.
>
> I see, thanks. But then with the typeof-stripping-address-space solution
> you'd be making a very evil cast (producing address of an object that
> does not actually exist in the generic address space). I can write such
> a solution, but it is clearly Undefined Behavior:
>
> #define strip_as(mem) (*(__typeof(0?(mem):(mem))*)(intptr_t)&(mem))
>
> void foo(__seg_fs int *x)
> {
>   asm("# %0" :: "m"(x[1]));
>   asm("# %0" :: "m"(strip_as(x[1])));
> }
>
> yields
>
> foo:
>         # %fs:4(%rdi)
>         # 4(%rdi)
>         ret
>
>
> I think a clean future solution is adding a operand modifier that would
> print the memory operand without the segment prefix.

I was also thinking of introducing of operand modifier, but Richi
advises the following:

--cut here--
typedef __UINTPTR_TYPE__ uintptr_t;

__seg_fs int x;

uintptr_t test (void)
{
 uintptr_t *p = (uintptr_t *)(uintptr_t) &x;
 uintptr_t addr;

 asm volatile ("lea %1, %0" : "=r"(addr) : "m"(*p));

 return addr;
}
--cut here--

Please note that the gcc documentation says:

--q--
6.17.4 x86 Named Address Spaces
-------------------------------

On the x86 target, variables may be declared as being relative to the
'%fs' or '%gs' segments.

'__seg_fs'
'__seg_gs'
    The object is accessed with the respective segment override prefix.

    The respective segment base must be set via some method specific to
    the operating system.  Rather than require an expensive system call
    to retrieve the segment base, these address spaces are not
    considered to be subspaces of the generic (flat) address space.
    This means that explicit casts are required to convert pointers
    between these address spaces and the generic address space.  In
    practice the application should cast to 'uintptr_t' and apply the
    segment base offset that it installed previously.

    The preprocessor symbols '__SEG_FS' and '__SEG_GS' are defined when
    these address spaces are supported.
--/q--

Uros.

Reply via email to