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