Add additional default-generation entries for usb2-5, most new PCs these
[dragonfly.git] / usr.bin / gprof / vax.c
1 /*
2  * Copyright (c) 1983, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#)vax.c    8.1 (Berkeley) 6/6/93
34  *
35  * $DragonFly: src/usr.bin/gprof/Attic/vax.c,v 1.3 2003/10/04 20:36:45 hmp Exp $
36  */
37
38 #include        "gprof.h"
39
40     /*
41      *  a namelist entry to be the child of indirect calls
42      */
43 nltype  indirectchild = {
44         "(*)" ,                         /* the name */
45         (unsigned long) 0 ,             /* the pc entry point */
46         (unsigned long) 0 ,             /* entry point aligned to histogram */
47         (double) 0.0 ,                  /* ticks in this routine */
48         (double) 0.0 ,                  /* cumulative ticks in children */
49         (long) 0 ,                      /* how many times called */
50         (long) 0 ,                      /* how many calls to self */
51         (double) 1.0 ,                  /* propagation fraction */
52         (double) 0.0 ,                  /* self propagation time */
53         (double) 0.0 ,                  /* child propagation time */
54         (bool) 0 ,                      /* print flag */
55         (int) 0 ,                       /* index in the graph list */
56         (int) 0 ,                       /* graph call chain top-sort order */
57         (int) 0 ,                       /* internal number of cycle on */
58         (struct nl *) &indirectchild ,  /* pointer to head of cycle */
59         (struct nl *) 0 ,               /* pointer to next member of cycle */
60         (arctype *) 0 ,                 /* list of caller arcs */
61         (arctype *) 0                   /* list of callee arcs */
62     };
63
64 operandenum
65 operandmode(struct modebyte *modep)
66 {
67     long        usesreg = modep -> regfield;
68
69     switch ( modep -> modefield ) {
70         case 0:
71         case 1:
72         case 2:
73         case 3:
74             return literal;
75         case 4:
76             return indexed;
77         case 5:
78             return reg;
79         case 6:
80             return regdef;
81         case 7:
82             return autodec;
83         case 8:
84             return ( usesreg != PC ? autoinc : immediate );
85         case 9:
86             return ( usesreg != PC ? autoincdef : absolute );
87         case 10:
88             return ( usesreg != PC ? bytedisp : byterel );
89         case 11:
90             return ( usesreg != PC ? bytedispdef : bytereldef );
91         case 12:
92             return ( usesreg != PC ? worddisp : wordrel );
93         case 13:
94             return ( usesreg != PC ? worddispdef : wordreldef );
95         case 14:
96             return ( usesreg != PC ? longdisp : longrel );
97         case 15:
98             return ( usesreg != PC ? longdispdef : longreldef );
99     }
100     /* NOTREACHED */
101 }
102
103 char *
104 operandname(operandname mode)
105 {
106
107     switch ( mode ) {
108         case literal:
109             return "literal";
110         case indexed:
111             return "indexed";
112         case reg:
113             return "register";
114         case regdef:
115             return "register deferred";
116         case autodec:
117             return "autodecrement";
118         case autoinc:
119             return "autoincrement";
120         case autoincdef:
121             return "autoincrement deferred";
122         case bytedisp:
123             return "byte displacement";
124         case bytedispdef:
125             return "byte displacement deferred";
126         case byterel:
127             return "byte relative";
128         case bytereldef:
129             return "byte relative deferred";
130         case worddisp:
131             return "word displacement";
132         case worddispdef:
133             return "word displacement deferred";
134         case wordrel:
135             return "word relative";
136         case wordreldef:
137             return "word relative deferred";
138         case immediate:
139             return "immediate";
140         case absolute:
141             return "absolute";
142         case longdisp:
143             return "long displacement";
144         case longdispdef:
145             return "long displacement deferred";
146         case longrel:
147             return "long relative";
148         case longreldef:
149             return "long relative deferred";
150     }
151     /* NOTREACHED */
152 }
153
154 long
155 operandlength(struct modebyte *modep)
156 {
157
158     switch ( operandmode( modep ) ) {
159         case literal:
160         case reg:
161         case regdef:
162         case autodec:
163         case autoinc:
164         case autoincdef:
165             return 1;
166         case bytedisp:
167         case bytedispdef:
168         case byterel:
169         case bytereldef:
170             return 2;
171         case worddisp:
172         case worddispdef:
173         case wordrel:
174         case wordreldef:
175             return 3;
176         case immediate:
177         case absolute:
178         case longdisp:
179         case longdispdef:
180         case longrel:
181         case longreldef:
182             return 5;
183         case indexed:
184             return 1+operandlength( (struct modebyte *) ((char *) modep) + 1 );
185     }
186     /* NOTREACHED */
187 }
188
189 unsigned long
190 reladdr(struct modebyte *modep)
191 {
192     operandenum mode = operandmode( modep );
193     char        *cp;
194     short       *sp;
195     long        *lp;
196
197     cp = (char *) modep;
198     cp += 1;                    /* skip over the mode */
199     switch ( mode ) {
200         default:
201             fprintf( stderr , "[reladdr] not relative address\n" );
202             return (unsigned long) modep;
203         case byterel:
204             return (unsigned long) ( cp + sizeof *cp + *cp );
205         case wordrel:
206             sp = (short *) cp;
207             return (unsigned long) ( cp + sizeof *sp + *sp );
208         case longrel:
209             lp = (long *) cp;
210             return (unsigned long) ( cp + sizeof *lp + *lp );
211     }
212 }
213
214 findcall(nltype *parentp, unsigned long p_lowpc, unsigned long p_highpc)
215 {
216     unsigned char       *instructp;
217     long                length;
218     nltype              *childp;
219     operandenum         mode;
220     operandenum         firstmode;
221     unsigned long       destpc;
222
223     if ( textspace == 0 ) {
224         return;
225     }
226     if ( p_lowpc < s_lowpc ) {
227         p_lowpc = s_lowpc;
228     }
229     if ( p_highpc > s_highpc ) {
230         p_highpc = s_highpc;
231     }
232 #   ifdef DEBUG
233         if ( debug & CALLDEBUG ) {
234             printf( "[findcall] %s: 0x%x to 0x%x\n" ,
235                     parentp -> name , p_lowpc , p_highpc );
236         }
237 #   endif DEBUG
238     for (   instructp = textspace + p_lowpc ;
239             instructp < textspace + p_highpc ;
240             instructp += length ) {
241         length = 1;
242         if ( *instructp == CALLS ) {
243                 /*
244                  *      maybe a calls, better check it out.
245                  *      skip the count of the number of arguments.
246                  */
247 #           ifdef DEBUG
248                 if ( debug & CALLDEBUG ) {
249                     printf( "[findcall]\t0x%x:calls" , instructp - textspace );
250                 }
251 #           endif DEBUG
252             firstmode = operandmode( (struct modebyte *) (instructp+length) );
253             switch ( firstmode ) {
254                 case literal:
255                 case immediate:
256                     break;
257                 default:
258                     goto botched;
259             }
260             length += operandlength( (struct modebyte *) (instructp+length) );
261             mode = operandmode( (struct modebyte *) ( instructp + length ) );
262 #           ifdef DEBUG
263                 if ( debug & CALLDEBUG ) {
264                     printf( "\tfirst operand is %s", operandname( firstmode ) );
265                     printf( "\tsecond operand is %s\n" , operandname( mode ) );
266                 }
267 #           endif DEBUG
268             switch ( mode ) {
269                 case regdef:
270                 case bytedispdef:
271                 case worddispdef:
272                 case longdispdef:
273                 case bytereldef:
274                 case wordreldef:
275                 case longreldef:
276                         /*
277                          *      indirect call: call through pointer
278                          *      either  *d(r)   as a parameter or local
279                          *              (r)     as a return value
280                          *              *f      as a global pointer
281                          *      [are there others that we miss?,
282                          *       e.g. arrays of pointers to functions???]
283                          */
284                     addarc( parentp , &indirectchild , (long) 0 );
285                     length += operandlength(
286                                 (struct modebyte *) ( instructp + length ) );
287                     continue;
288                 case byterel:
289                 case wordrel:
290                 case longrel:
291                         /*
292                          *      regular pc relative addressing
293                          *      check that this is the address of
294                          *      a function.
295                          */
296                     destpc = reladdr( (struct modebyte *) (instructp+length) )
297                                 - (unsigned long) textspace;
298                     if ( destpc >= s_lowpc && destpc <= s_highpc ) {
299                         childp = nllookup( destpc );
300 #                       ifdef DEBUG
301                             if ( debug & CALLDEBUG ) {
302                                 printf( "[findcall]\tdestpc 0x%x" , destpc );
303                                 printf( " childp->name %s" , childp -> name );
304                                 printf( " childp->value 0x%x\n" ,
305                                         childp -> value );
306                             }
307 #                       endif DEBUG
308                         if ( childp -> value == destpc ) {
309                                 /*
310                                  *      a hit
311                                  */
312                             addarc( parentp , childp , (long) 0 );
313                             length += operandlength( (struct modebyte *)
314                                             ( instructp + length ) );
315                             continue;
316                         }
317                         goto botched;
318                     }
319                         /*
320                          *      else:
321                          *      it looked like a calls,
322                          *      but it wasn't to anywhere.
323                          */
324                     goto botched;
325                 default:
326                 botched:
327                         /*
328                          *      something funny going on.
329                          */
330 #                   ifdef DEBUG
331                         if ( debug & CALLDEBUG ) {
332                             printf( "[findcall]\tbut it's a botch\n" );
333                         }
334 #                   endif DEBUG
335                     length = 1;
336                     continue;
337             }
338         }
339     }
340 }