do chmod last in install
[unix-history] / usr / src / usr.bin / gprof / vax.c
CommitLineData
a5040938
PK
1#ifndef lint
2 static char *sccsid = "@(#)vax.c 1.1 (Berkeley) %G%";
3#endif not lint
4
5#include "gprof.h"
6
7 /*
8 * a namelist entry to be the child of indirect calls
9 */
10nltype indirectchild = {
11 "(*)" , /* the name */
12 (unsigned long) 0 , /* the pc entry point */
13 (double) 0.0 , /* ticks in this routine */
14 (double) 0.0 , /* cumulative ticks in children */
15 (long) 0 , /* how many times called */
16 (long) 0 , /* how many calls to self */
17 (int) 0 , /* index in the graph list */
18 (int) 0 , /* graph call chain top-sort order */
19 (int) 0 , /* internal number of cycle on */
20 (struct nl *) &indirectchild , /* pointer to head of cycle */
21 (struct nl *) 0 , /* pointer to next member of cycle */
22 (arctype *) 0 , /* list of caller arcs */
23 (arctype *) 0 /* list of callee arcs */
24 };
25
26operandenum
27operandmode( modep )
28 struct modebyte *modep;
29{
30 long usesreg = modep -> regfield;
31
32 switch ( modep -> modefield ) {
33 case 0:
34 case 1:
35 case 2:
36 case 3:
37 return literal;
38 case 4:
39 return indexed;
40 case 5:
41 return reg;
42 case 6:
43 return regdef;
44 case 7:
45 return autodec;
46 case 8:
47 return ( usesreg != PC ? autoinc : immediate );
48 case 9:
49 return ( usesreg != PC ? autoincdef : absolute );
50 case 10:
51 return ( usesreg != PC ? bytedisp : byterel );
52 case 11:
53 return ( usesreg != PC ? bytedispdef : bytereldef );
54 case 12:
55 return ( usesreg != PC ? worddisp : wordrel );
56 case 13:
57 return ( usesreg != PC ? worddispdef : wordreldef );
58 case 14:
59 return ( usesreg != PC ? longdisp : longrel );
60 case 15:
61 return ( usesreg != PC ? longdispdef : longreldef );
62 }
63 /* NOTREACHED */
64}
65
66char *
67operandname( mode )
68 operandenum mode;
69{
70
71 switch ( mode ) {
72 case literal:
73 return "literal";
74 case indexed:
75 return "indexed";
76 case reg:
77 return "register";
78 case regdef:
79 return "register deferred";
80 case autodec:
81 return "autodecrement";
82 case autoinc:
83 return "autoincrement";
84 case autoincdef:
85 return "autoincrement deferred";
86 case bytedisp:
87 return "byte displacement";
88 case bytedispdef:
89 return "byte displacement deferred";
90 case byterel:
91 return "byte relative";
92 case bytereldef:
93 return "byte relative deferred";
94 case worddisp:
95 return "word displacement";
96 case worddispdef:
97 return "word displacement deferred";
98 case wordrel:
99 return "word relative";
100 case wordreldef:
101 return "word relative deferred";
102 case immediate:
103 return "immediate";
104 case absolute:
105 return "absolute";
106 case longdisp:
107 return "long displacement";
108 case longdispdef:
109 return "long displacement deferred";
110 case longrel:
111 return "long relative";
112 case longreldef:
113 return "long relative deferred";
114 }
115 /* NOTREACHED */
116}
117
118long
119operandlength( modep )
120 struct modebyte *modep;
121{
122
123 switch ( operandmode( modep ) ) {
124 case literal:
125 case reg:
126 case regdef:
127 case autodec:
128 case autoinc:
129 case autoincdef:
130 return 1;
131 case bytedisp:
132 case bytedispdef:
133 case byterel:
134 case bytereldef:
135 return 2;
136 case worddisp:
137 case worddispdef:
138 case wordrel:
139 case wordreldef:
140 return 3;
141 case immediate:
142 case absolute:
143 case longdisp:
144 case longdispdef:
145 case longrel:
146 case longreldef:
147 return 5;
148 case indexed:
149 return 1+operandlength( (struct modebyte *) ((char *) modep) + 1 );
150 }
151 /* NOTREACHED */
152}
153
154unsigned long
155reladdr( modep )
156 struct modebyte *modep;
157{
158 operandenum mode = operandmode( modep );
159 char *cp;
160 short *sp;
161 long *lp;
162
163 cp = (char *) modep;
164 cp += 1; /* skip over the mode */
165 switch ( mode ) {
166 default:
167 fprintf( stderr , "[reladdr] not relative address\n" );
168 return (unsigned long) modep;
169 case byterel:
170 return (unsigned long) ( cp + sizeof *cp + *cp );
171 case wordrel:
172 sp = (short *) cp;
173 return (unsigned long) ( cp + sizeof *sp + *sp );
174 case longrel:
175 lp = (long *) cp;
176 return (unsigned long) ( cp + sizeof *lp + *lp );
177 }
178}
179
180findcalls( parentp , p_lowpc , p_highpc )
181 nltype *parentp;
182 unsigned long p_lowpc;
183 unsigned long p_highpc;
184{
185 unsigned char *instructp;
186 long length;
187 nltype *childp;
188 operandenum mode;
189 operandenum firstmode;
190 unsigned long destpc;
191
192 if ( textspace == 0 ) {
193 return;
194 }
195 if ( p_lowpc < s_lowpc ) {
196 p_lowpc = s_lowpc;
197 }
198 if ( p_highpc > s_highpc ) {
199 p_highpc = s_highpc;
200 }
201# ifdef DEBUG
202 if ( debug & CALLSDEBUG ) {
203 printf( "[findcalls] %s: 0x%x to 0x%x\n" ,
204 parentp -> name , p_lowpc , p_highpc );
205 }
206# endif DEBUG
207 for ( instructp = textspace + p_lowpc ;
208 instructp < textspace + p_highpc ;
209 instructp += length ) {
210 length = 1;
211 if ( *instructp == CALLS ) {
212 /*
213 * maybe a calls, better check it out.
214 * skip the count of the number of arguments.
215 */
216# ifdef DEBUG
217 if ( debug & CALLSDEBUG ) {
218 printf( "[findcalls]\t0x%x:calls" , instructp - textspace );
219 }
220# endif DEBUG
221 firstmode = operandmode( (struct modebyte *) (instructp+length) );
222 switch ( firstmode ) {
223 case literal:
224 case immediate:
225 break;
226 default:
227 goto botched;
228 }
229 length += operandlength( (struct modebyte *) (instructp+length) );
230 mode = operandmode( (struct modebyte *) ( instructp + length ) );
231# ifdef DEBUG
232 if ( debug & CALLSDEBUG ) {
233 printf( "\tfirst operand is %s", operandname( firstmode ) );
234 printf( "\tsecond operand is %s\n" , operandname( mode ) );
235 }
236# endif DEBUG
237 switch ( mode ) {
238 case regdef:
239 case bytedispdef:
240 case worddispdef:
241 case longdispdef:
242 case bytereldef:
243 case wordreldef:
244 case longreldef:
245 /*
246 * indirect call: call through pointer
247 * either *d(r) as a parameter or local
248 * (r) as a return value
249 * *f as a global pointer
250 * [are there others that we miss?,
251 * e.g. arrays of pointers to functions???]
252 */
253 addarc( parentp , &indirectchild , (long) 0 );
254 length += operandlength(
255 (struct modebyte *) ( instructp + length ) );
256 continue;
257 case byterel:
258 case wordrel:
259 case longrel:
260 /*
261 * regular pc relative addressing
262 * check that this is the address of
263 * a function.
264 */
265 destpc = reladdr( (struct modebyte *) (instructp+length) )
266 - (unsigned long) textspace;
267 if ( destpc >= s_lowpc && destpc <= s_highpc ) {
268 childp = nllookup( destpc );
269# ifdef DEBUG
270 if ( debug & CALLSDEBUG ) {
271 printf( "[findcalls]\tdestpc 0x%x" , destpc );
272 printf( " childp->name %s" , childp -> name );
273 printf( " childp->value 0x%x\n" ,
274 childp -> value );
275 }
276# endif DEBUG
277 if ( childp -> value == destpc ) {
278 /*
279 * a hit
280 */
281 addarc( parentp , childp , (long) 0 );
282 length += operandlength( (struct modebyte *)
283 ( instructp + length ) );
284 continue;
285 }
286 goto botched;
287 }
288 /*
289 * else:
290 * it looked like a calls,
291 * but it wasn't to anywhere.
292 */
293 goto botched;
294 default:
295 botched:
296 /*
297 * something funny going on.
298 */
299# ifdef DEBUG
300 if ( debug & CALLSDEBUG ) {
301 printf( "[findcalls]\tbut it's a botch\n" );
302 }
303# endif DEBUG
304 length = 1;
305 continue;
306 }
307 }
308 }
309}