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