This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Segment register support for the i386


   From: torvalds@transmeta.com (Linus Torvalds) 
   Date: 28 Dec 1999 14:47:17 -0800 

   So what I think the original poster was after was more of a

   "Ok, I've set up %fs to be a thread-specific pointer, and %gs points to
   the global segment, and now I want gcc to treat this 32-bit pointer as
   a 'fs' pointer and that other 32-bit pointer as a 'gs' pointer, while
   the "normal" cases are all the default ds=ss pointer case"

That's indeed what I'm trying to accomplish (see also below).

   So it wouldn't ever be a case of "seg + offset". It would always be just
   "offset" together with a "address space attribute".

   That sounds easier to me than a full "different pointer lengths" kind of
   thing, modulo the CSE kind of issues.

Well, not exactly.  While the "address space attribute" approach would
be nice to have, it isn't that easy to implement, since there seems to
be no support for pointer attributes in GCC.  Instead I propose to
allow the segment registers to be used as register variables in GCC.

Some not-so-register-starved processors (like the Sparc) reserve a
special register for the "thread pointer".  The current LinuxThreads
code for Linux/Sparc defines a global register variable like:

   register struct thread_descr *__thread_self __asm__("%g6");

and then uses __thread_self to access data in the thread descriptor.

On the i386 we cannot spare an ordinary register for this purpose.
However one can use segmentation instead and use one of the spare
segment registers (%fs and %gs), to point to the thread descriptor.
Right now this is only possible by using inline assembler which makes
the code a bit more painful to write and a lot harder to read. 

It would be nice if I could write:

   register struct thread_descr *__thread_self __asm__("%gs");

such that I could use the same C code as in the Sparc case to access
and manipulate the thread descriptor.  It seems that it isn't that
hard to implement this in GCC.  I managed to get this working by only
changing a few lines of code in the i386 back-end code.

However, there are some problems with this approach.  While the
segment registers are indeed pointer-like because of what Intel calls
their "hidden" contents, their visible part is simply a 16-bit value.
That probably means that while

  register void *p __asm__("%gs");

would refer to the "hidden" part of the %gs register,

  register short s __asm__("%gs");

should refer to the "visible" part.  This could lead to unwanted
ambiguities.  The fact that P refers to the "hidden" contents of the
register also means that it doesn't really have a value.  It is
therefore not possible to write something like:

  void *
  foo (void)
  {
    return p;
  }

Code like that should somehow lead to an appropriate error message,
which only the back-end code can generate.

That's why I'm not sure if this approach is acceptable, and I'd like
to hear what other people think of this proposal before spending too
much time on finishing my current implementation.  I can imagine that
people say that this extension is really an ugly hack that should
never be allowed in GCC.

Mark

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]