public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* "=rXX" asm constraints on powerpc?
@ 2003-09-22 16:16 Marcus Brinkmann
  2003-09-22 17:29 ` Marcus Brinkmann
  0 siblings, 1 reply; 2+ messages in thread
From: Marcus Brinkmann @ 2003-09-22 16:16 UTC (permalink / raw)
  To: gcc-help

Hi,

I want to implement system call stubs on PPC.  The code I want to end up
this is the following ("tlbia" is really used as a slow system call here,
that returns a pointer and three ints in r3 to r6):

00000000 <get_kip>:
 0:   7c 6a 1b 78     mr      r10,r3
 4:   7c 88 23 78     mr      r8,r4
 8:   7c a7 2b 78     mr      r7,r5
 c:   7c 00 02 e4     tlbia
10:   90 8a 00 00     stw     r4,0(r10)
14:   90 a8 00 00     stw     r5,0(r8)
18:   90 c7 00 00     stw     r6,0(r7)
1c:   4e 80 00 20     blr

Normally, I would do this like this (which works on ia32 for EAX, EBX, etc):

void *get_kip (int *r_version, int *r_flags, int *r_id)
{
  void *kip;
  asm ("tlbia\n"
       : "=r3" (kip), "=r4" (*r_version), "=r5" (*r_flags), "=r6" (*r_id));
  return kip;
}

However, "=rX" are not valid output register constraints, as defined in
rs6000.h.  You can only specify generic register classes, not individual
registers.  But the system calls are laid out to allow maximum performance
if you make proper use of it.  For example, what you want to return from the C
function is usually already in r3 (and r3/r4 if it is 64 bit).

I tried various things, like using local variables, mr and stw instructions
to move data around.  The best I could come up with is this:

void *
get_kip (int *r_version, int *r_flags, int *r_id)
{
  void *kip;
                                                                                
  asm ("tlbia\n"
       "stw %%r4, 0(%1)\n"
       "stw %%r5, 0(%2)\n"
       "stw %%r6, 0(%3)\n"
       "mr %0, %%r3\n"
       : "=&r" (kip)
       : "r" (r_version), "r" (r_flags), "r" (r_id)
       : "r3", "r4", "r5", "r6");
                                                                                
  return kip;
}

Which is assembled to:
00000000 <get_kip>:
   0:   7c 6a 1b 78     mr      r10,r3
   4:   7c 8b 23 78     mr      r11,r4
   8:   7c a0 2b 78     mr      r0,r5
   c:   7c 00 02 e4     tlbia
  10:   90 8a 00 00     stw     r4,0(r10)
  14:   90 ab 00 00     stw     r5,0(r11)
  18:   90 c0 00 00     stw     r6,0(r0)
  1c:   7c 69 1b 78     mr      r9,r3
  20:   7d 23 4b 78     mr      r3,r9
  24:   4e 80 00 20     blr

That comes close, but unnecessarily moves r3 to r9 forth and back.  GCC
doesn't opimize such inline assembler, and I can not remove the mr
instruction because I can not otherwise ensure that register r3 is used.

It gets funny if you specify register variables:

void *
get_kip (int *r_version, int *r_flags, int *r_id)
{
  register void *kip asm ("r3");
  register int version asm ("r4");
  register int flags asm ("r5");
  register int id asm ("r6");
 
  asm ("tlbia\n"
       "mr %0, %%r3\n"
       "mr %1, %%r4\n"
       "mr %2, %%r5\n"
       "mr %3, %%r6\n"
       : "=r" (kip), "=r" (version), "=r" (flags), "=r" (id) : );
 
  *r_version = version;
  *r_flags = flags;
  *r_id = id;
 
  return kip;
}

Which is compiled to:
00000000 <get_kip>:
   0:   7c 69 1b 78     mr      r9,r3
   4:   7c 8b 23 78     mr      r11,r4
   8:   7c aa 2b 78     mr      r10,r5
   c:   7c 00 02 e4     tlbia
  10:   7c 63 1b 78     mr      r3,r3
  14:   7c 84 23 78     mr      r4,r4
  18:   7c a5 2b 78     mr      r5,r5
  1c:   7c c6 33 78     mr      r6,r6
  20:   90 89 00 00     stw     r4,0(r9)
  24:   90 ab 00 00     stw     r5,0(r11)
  28:   90 ca 00 00     stw     r6,0(r10)
  2c:   4e 80 00 20     blr

It's clear what goes wrong here: gcc already allocates the right register
for all variables, but it can not take advantage of that fact because it can
not optimize away the mr instructions.

This shows to me that the rX output constraints should be supported, to make
programming such things possible.  Or am I overlooking something?

Thanks,
Marcus





-- 
`Rhubarb is no Egyptian god.' GNU      http://www.gnu.org    marcus@gnu.org
Marcus Brinkmann              The Hurd http://www.gnu.org/software/hurd/
Marcus.Brinkmann@ruhr-uni-bochum.de
http://www.marcus-brinkmann.de/

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: "=rXX" asm constraints on powerpc?
  2003-09-22 16:16 "=rXX" asm constraints on powerpc? Marcus Brinkmann
@ 2003-09-22 17:29 ` Marcus Brinkmann
  0 siblings, 0 replies; 2+ messages in thread
From: Marcus Brinkmann @ 2003-09-22 17:29 UTC (permalink / raw)
  To: gcc-help

On Mon, Sep 22, 2003 at 06:13:48PM +0200, Marcus Brinkmann wrote:
> I want to implement system call stubs on PPC.  The code I want to end up
> this is the following ("tlbia" is really used as a slow system call here,
> that returns a pointer and three ints in r3 to r6):

I might just have misunderstood the wording in the gcc manual.  It seemed to
me that gcc doesn't guarantee me that a register I allocate for a local
variable is really used for that variable.  But the manual only says that it
is not tied to that variable _at all times_.  At some times, and I assume
now that at all times it matters to me (in the asm statement), it will be
tied to that variable.

In that circumstances, I can do what I want to do with local vars in the
right registers, without explicit mr instructions.

Thanks,
Marcus

-- 
`Rhubarb is no Egyptian god.' GNU      http://www.gnu.org    marcus@gnu.org
Marcus Brinkmann              The Hurd http://www.gnu.org/software/hurd/
Marcus.Brinkmann@ruhr-uni-bochum.de
http://www.marcus-brinkmann.de/

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2003-09-22 17:29 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-09-22 16:16 "=rXX" asm constraints on powerpc? Marcus Brinkmann
2003-09-22 17:29 ` Marcus Brinkmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).