public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
From: Marcus Brinkmann <Marcus.Brinkmann@ruhr-uni-bochum.de>
To: gcc-help@gnu.org
Subject: "=rXX" asm constraints on powerpc?
Date: Mon, 22 Sep 2003 16:16:00 -0000	[thread overview]
Message-ID: <20030922161348.GD627@212.23.136.22> (raw)

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/

             reply	other threads:[~2003-09-22 16:16 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-09-22 16:16 Marcus Brinkmann [this message]
2003-09-22 17:29 ` Marcus Brinkmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030922161348.GD627@212.23.136.22 \
    --to=marcus.brinkmann@ruhr-uni-bochum.de \
    --cc=gcc-help@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).