OSDN Git Service

gcc:
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / gmon-sol2.c
index 35ac1c9..e0923a0 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
+ * 3. [rescinded 22 July 1999]
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * This code could easily be integrated with the original gmon.c and perhaps
  * should be.
  */
  * This code could easily be integrated with the original gmon.c and perhaps
  * should be.
  */
+#include "tconfig.h"
+#include "tsystem.h"
+#include <fcntl.h> /* for creat() */
 
 
-#ifndef lint
-static char sccsid[] = "@(#)gmon.c     5.3 (Berkeley) 5/22/91";
-#endif /* not lint */
-
-#if 0
-#include <unistd.h>
-
-#endif
 #ifdef DEBUG
 #include <stdio.h>
 #endif
 
 #ifdef DEBUG
 #include <stdio.h>
 #endif
 
-#if 0
-#include "i386/gmon.h"
+static void moncontrol (int);
+extern void monstartup (char *, char *);
+extern void _mcleanup (void);
+extern void internal_mcount (
+#ifdef __x86_64__
+                            char *, unsigned short *
 #else
 #else
+                            void
+#endif
+                            );
+
 
 struct phdr {
                 char    *lpc;
 
 struct phdr {
                 char    *lpc;
@@ -93,6 +93,7 @@ struct tostruct {
   long count;
   unsigned short link;
 };
   long count;
   unsigned short link;
 };
+
 struct rawarc {
     unsigned long       raw_frompc;
     unsigned long       raw_selfpc;
 struct rawarc {
     unsigned long       raw_frompc;
     unsigned long       raw_selfpc;
@@ -100,13 +101,11 @@ struct rawarc {
 };
 #define ROUNDDOWN(x,y)  (((x)/(y))*(y))
 #define ROUNDUP(x,y)    ((((x)+(y)-1)/(y))*(y))
 };
 #define ROUNDDOWN(x,y)  (((x)/(y))*(y))
 #define ROUNDUP(x,y)    ((((x)+(y)-1)/(y))*(y))
-#endif
 
 /* char *minbrk; */
 
 
 /* char *minbrk; */
 
-#ifdef __alpha
-extern char *sbrk ();
-#endif
+typedef __SIZE_TYPE__ size_t;
+typedef __PTRDIFF_TYPE__ intptr_t;
 
     /*
      * froms is actually a bunch of unsigned shorts indexing tos
 
     /*
      * froms is actually a bunch of unsigned shorts indexing tos
@@ -117,7 +116,7 @@ static struct tostruct      *tos = 0;
 static long            tolimit = 0;
 static char            *s_lowpc = 0;
 static char            *s_highpc = 0;
 static long            tolimit = 0;
 static char            *s_lowpc = 0;
 static char            *s_highpc = 0;
-static unsigned long   s_textsize = 0;
+static size_t          s_textsize = 0;
 
 static int     ssiz;
 static char    *sbuf;
 
 static int     ssiz;
 static char    *sbuf;
@@ -129,23 +128,24 @@ static int        s_scale;
 
 extern int errno;
 
 
 extern int errno;
 
-monstartup(lowpc, highpc)
-    char       *lowpc;
-    char       *highpc;
+extern void *sbrk (intptr_t);
+
+void
+monstartup(char *lowpc, char *highpc)
 {
 {
-    int                        monsize;
+    size_t             monsize;
     char               *buffer;
     char               *buffer;
-    register int       o;
+    register size_t    o;
 
        /*
         *      round lowpc and highpc to multiples of the density we're using
         *      so the rest of the scaling (here and in gprof) stays in ints.
         */
     lowpc = (char *)
 
        /*
         *      round lowpc and highpc to multiples of the density we're using
         *      so the rest of the scaling (here and in gprof) stays in ints.
         */
     lowpc = (char *)
-           ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
+           ROUNDDOWN((size_t)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
     s_lowpc = lowpc;
     highpc = (char *)
     s_lowpc = lowpc;
     highpc = (char *)
-           ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
+           ROUNDUP((size_t)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
     s_highpc = highpc;
     s_textsize = highpc - lowpc;
     monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
     s_highpc = highpc;
     s_textsize = highpc - lowpc;
     monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
@@ -206,7 +206,8 @@ monstartup(lowpc, highpc)
     moncontrol(1);
 }
 
     moncontrol(1);
 }
 
-_mcleanup()
+void
+_mcleanup (void)
 {
     int                        fd;
     int                        fromindex;
 {
     int                        fd;
     int                        fromindex;
@@ -223,7 +224,7 @@ _mcleanup()
     }
 #   ifdef DEBUG
        fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
     }
 #   ifdef DEBUG
        fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
-#   endif DEBUG
+#   endif /* DEBUG */
 
     write( fd , sbuf , ssiz );
     endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
 
     write( fd , sbuf , ssiz );
     endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
@@ -237,7 +238,7 @@ _mcleanup()
                fprintf( stderr ,
                        "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
                        frompc , tos[toindex].selfpc , tos[toindex].count );
                fprintf( stderr ,
                        "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
                        frompc , tos[toindex].selfpc , tos[toindex].count );
-#          endif DEBUG
+#          endif /* DEBUG */
            rawarc.raw_frompc = (unsigned long) frompc;
            rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
            rawarc.raw_count = tos[toindex].count;
            rawarc.raw_frompc = (unsigned long) frompc;
            rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
            rawarc.raw_count = tos[toindex].count;
@@ -247,20 +248,65 @@ _mcleanup()
     close( fd );
 }
 
     close( fd );
 }
 
+#ifdef __x86_64__
+/* See GLIBC for additional information about this technique.  */
+asm(".globl _mcount\n" 
+    "\t.type\t_mcount, @function\n"
+    "_mcount:\n"
+    /* The compiler calls _mcount after the prologue, and does not
+       save any of the registers.  Therefore we must preserve all
+       seven registers which may contain function arguments.  */
+    "\tsubq\t$0x38,%rsp\n"
+    "\tmovq\t%rax,(%rsp)\n"
+    "\tmovq\t%rcx,0x08(%rsp)\n"
+    "\tmovq\t%rdx,0x10(%rsp)\n"
+    "\tmovq\t%rsi,0x18(%rsp)\n"
+    "\tmovq\t%rdi,0x20(%rsp)\n"
+    "\tmovq\t%r8,0x28(%rsp)\n"
+    "\tmovq\t%r9,0x30(%rsp)\n"
+    /* Get SELFPC (pushed by the call to this function) and
+       FROMPCINDEX (via the frame pointer.  */
+    "\tmovq\t0x38(%rsp),%rdi\n"
+    "\tmovq\t0x8(%rbp),%rsi\n"
+    "\tcall\tinternal_mcount\n"
+    /* Restore the saved registers.  */
+    "\tmovq\t0x30(%rsp),%r9\n"
+    "\tmovq\t0x28(%rsp),%r8\n"
+    "\tmovq\t0x20(%rsp),%rdi\n"
+    "\tmovq\t0x18(%rsp),%rsi\n"
+    "\tmovq\t0x10(%rsp),%rdx\n"
+    "\tmovq\t0x08(%rsp),%rdx\n"
+    "\tmovq\t(%rsp),%rax\n"
+    "\taddq\t$0x38,%rsp\n"
+    "\tretq\n"
+    );
+#else
 /* Solaris 2 libraries use _mcount.  */
 asm(".globl _mcount; _mcount: jmp internal_mcount");
 /* This is for compatibility with old versions of gcc which used mcount.  */
 asm(".globl mcount; mcount: jmp internal_mcount");
 /* Solaris 2 libraries use _mcount.  */
 asm(".globl _mcount; _mcount: jmp internal_mcount");
 /* This is for compatibility with old versions of gcc which used mcount.  */
 asm(".globl mcount; mcount: jmp internal_mcount");
+#endif
 
 
-internal_mcount()
+void
+internal_mcount (
+#ifdef __x86_64__
+                char *selfpc,
+                unsigned short *frompcindex
+#else
+                void
+#endif
+                )
 {
 {
+#ifndef __x86_64__
        register char                   *selfpc;
        register unsigned short         *frompcindex;
        register char                   *selfpc;
        register unsigned short         *frompcindex;
+#endif
        register struct tostruct        *top;
        register struct tostruct        *prevtop;
        register long                   toindex;
        static char already_setup;
 
        register struct tostruct        *top;
        register struct tostruct        *prevtop;
        register long                   toindex;
        static char already_setup;
 
+#ifndef __x86_64__
        /*
         *      find the return address for mcount,
         *      and the return address for mcount's caller.
        /*
         *      find the return address for mcount,
         *      and the return address for mcount's caller.
@@ -272,12 +318,16 @@ internal_mcount()
        /* frompcindex = pc in preceding frame.
           This identifies the caller of the function just entered.  */
        frompcindex = (void *) __builtin_return_address (1);
        /* frompcindex = pc in preceding frame.
           This identifies the caller of the function just entered.  */
        frompcindex = (void *) __builtin_return_address (1);
+#endif
 
        if(!already_setup) {
 
        if(!already_setup) {
-          extern etext();
+          extern char etext[];
          already_setup = 1;
          already_setup = 1;
-/*       monstartup(0, etext); */
-         monstartup(0x08040000, etext);
+#ifdef __x86_64__
+         monstartup(0, etext);
+#else
+         monstartup((char*)0x08040000, etext);
+#endif
 #ifdef USE_ONEXIT
          on_exit(_mcleanup, 0);
 #else
 #ifdef USE_ONEXIT
          on_exit(_mcleanup, 0);
 #else
@@ -390,15 +440,15 @@ overflow:
  *     profiling is what mcount checks to see if
  *     all the data structures are ready.
  */
  *     profiling is what mcount checks to see if
  *     all the data structures are ready.
  */
-moncontrol(mode)
-    int mode;
+static void
+moncontrol(int mode)
 {
     if (mode)
     {
       /* start */
       profil((unsigned short *)(sbuf + sizeof(struct phdr)),
             ssiz - sizeof(struct phdr),
 {
     if (mode)
     {
       /* start */
       profil((unsigned short *)(sbuf + sizeof(struct phdr)),
             ssiz - sizeof(struct phdr),
-            (int)s_lowpc, s_scale);
+            (size_t)s_lowpc, s_scale);
       
       profiling = 0;
     } else {
       
       profiling = 0;
     } else {