1*5483Slinton /* Copyright (c) 1982 Regents of the University of California */
2*5483Slinton 
3*5483Slinton static char sccsid[] = "@(#)nextaddr.c 1.1 01/18/82";
4*5483Slinton 
5*5483Slinton /*
6*5483Slinton  * Calculate the next address that will be executed from the current one.
7*5483Slinton  *
8*5483Slinton  * If the next address depends on runtime data (e.g. a conditional
9*5483Slinton  * branch will depend on the value on top of the stack),
10*5483Slinton  * we must execute up to the given address with "stepto".
11*5483Slinton  *
12*5483Slinton  * If the second argument is TRUE, we treat a CALL instruction as
13*5483Slinton  * straight line rather than following it as a branch.
14*5483Slinton  */
15*5483Slinton 
16*5483Slinton #include "defs.h"
17*5483Slinton #include "machine.h"
18*5483Slinton #include "process.h"
19*5483Slinton #include "breakpoint.h"
20*5483Slinton #include "sym.h"
21*5483Slinton #include "pxops.h"
22*5483Slinton #include "optab.h"
23*5483Slinton #include "mappings.h"
24*5483Slinton #include "runtime.h"
25*5483Slinton #include "process/pxinfo.h"
26*5483Slinton #include "process/process.rep"
27*5483Slinton 
28*5483Slinton LOCAL ADDRESS docase(), dofor();
29*5483Slinton 
30*5483Slinton ADDRESS nextaddr(beginaddr, isnext)
31*5483Slinton ADDRESS beginaddr;
32*5483Slinton BOOLEAN isnext;
33*5483Slinton {
34*5483Slinton 	register PXOP op;
35*5483Slinton 	ADDRESS addr;
36*5483Slinton 	short offset;
37*5483Slinton 	int nextbyte;
38*5483Slinton 	SYM *s;
39*5483Slinton 	union {
40*5483Slinton 		short word;
41*5483Slinton 		char byte[2];
42*5483Slinton 	} o;
43*5483Slinton 
44*5483Slinton 	addr = beginaddr;
45*5483Slinton 	iread(&o.word, addr, sizeof(o.word));
46*5483Slinton 	op = (PXOP) o.byte[0];
47*5483Slinton 	nextbyte = o.byte[1];
48*5483Slinton 	addr += sizeof(short);
49*5483Slinton 	switch(op) {
50*5483Slinton 
51*5483Slinton #	if (isvaxpx)
52*5483Slinton 	/*
53*5483Slinton 	 * The version of px on the VAX assumes that the instruction
54*5483Slinton 	 * at the entry point of a function is a TRA4 to the beginning
55*5483Slinton 	 * of the block.
56*5483Slinton 	 */
57*5483Slinton #	endif
58*5483Slinton 		case O_CALL: {
59*5483Slinton 			ADDRESS eaddr;
60*5483Slinton 
61*5483Slinton 			if (isnext) {
62*5483Slinton 				addr += sizeof(int);
63*5483Slinton 			} else {
64*5483Slinton #				if (isvaxpx)
65*5483Slinton 					iread(&eaddr, addr, sizeof(eaddr));
66*5483Slinton 					addr = eaddr + sizeof(short);
67*5483Slinton 					iread(&addr, addr, sizeof(addr));
68*5483Slinton #				else
69*5483Slinton 					iread(&offset, addr, sizeof(offset));
70*5483Slinton 					addr += offset;
71*5483Slinton #				endif
72*5483Slinton 				stepto(addr);
73*5483Slinton 				if (linelookup(addr) == 0) {
74*5483Slinton 					bpact();
75*5483Slinton 					addr = pc;
76*5483Slinton 				}
77*5483Slinton 				if (ss_lines && trcond()) {
78*5483Slinton 					s = whatblock(addr);
79*5483Slinton 					if (s == NIL) {
80*5483Slinton 						panic("bad call addr");
81*5483Slinton 					}
82*5483Slinton 					printentry(s);
83*5483Slinton 				}
84*5483Slinton 			}
85*5483Slinton 			break;
86*5483Slinton 		}
87*5483Slinton 
88*5483Slinton #	if (isvaxpx)
89*5483Slinton 		case O_FCALL: {
90*5483Slinton 			ADDRESS eaddr;
91*5483Slinton 			ADDRESS *fparam;
92*5483Slinton 
93*5483Slinton 			if (!isnext) {
94*5483Slinton 				stepto(addr - sizeof(short));
95*5483Slinton 				dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam));
96*5483Slinton 				dread(&eaddr, fparam, sizeof(eaddr));
97*5483Slinton 				addr = eaddr - ENDOFF;
98*5483Slinton 				stepto(addr);
99*5483Slinton 				if (linelookup(addr) == 0) {
100*5483Slinton 					bpact();
101*5483Slinton 					addr = pc;
102*5483Slinton 				}
103*5483Slinton 				if (ss_lines && trcond()) {
104*5483Slinton 					s = whatblock(addr);
105*5483Slinton 					if (s == NIL) {
106*5483Slinton 						panic("bad call addr");
107*5483Slinton 					}
108*5483Slinton 					printentry(s);
109*5483Slinton 				}
110*5483Slinton 			}
111*5483Slinton 			break;
112*5483Slinton 		}
113*5483Slinton #	endif
114*5483Slinton 
115*5483Slinton 		case O_END:
116*5483Slinton 			if ((addr - sizeof(short)) == lastaddr()) {
117*5483Slinton 				stepto(addr - sizeof(short));
118*5483Slinton 				endprogram();
119*5483Slinton 			} else {
120*5483Slinton 				addr = return_addr();
121*5483Slinton 				s = whatblock(pc);
122*5483Slinton 				stepto(addr);
123*5483Slinton 				if (ss_lines && trcond()) {
124*5483Slinton 					printexit(s);
125*5483Slinton 				}
126*5483Slinton 				if (linelookup(addr) == 0) {
127*5483Slinton 					bpact();
128*5483Slinton 					addr = pc;
129*5483Slinton 				}
130*5483Slinton 			}
131*5483Slinton 			break;
132*5483Slinton 
133*5483Slinton #	if (isvaxpx)
134*5483Slinton 		case O_TRA4:
135*5483Slinton 		case O_GOTO:
136*5483Slinton 			iread(&addr, addr, sizeof(addr));
137*5483Slinton 			break;
138*5483Slinton #	endif
139*5483Slinton 
140*5483Slinton 		case O_TRA:
141*5483Slinton 			iread(&offset, addr, sizeof(offset));
142*5483Slinton 			addr += offset;
143*5483Slinton 			break;
144*5483Slinton 
145*5483Slinton 		case O_CASE1OP:
146*5483Slinton 			addr = docase(nextbyte, 1, addr);
147*5483Slinton 			break;
148*5483Slinton 
149*5483Slinton 		case O_CASE2OP:
150*5483Slinton 			addr = docase(nextbyte, 2, addr);
151*5483Slinton 			break;
152*5483Slinton 
153*5483Slinton 		case O_CASE4OP:
154*5483Slinton 			addr = docase(nextbyte, 4, addr);
155*5483Slinton 			break;
156*5483Slinton 
157*5483Slinton 		case O_FOR1U:
158*5483Slinton 			addr = dofor(2, addr, nextbyte, 1);
159*5483Slinton 			break;
160*5483Slinton 
161*5483Slinton 		case O_FOR2U:
162*5483Slinton 			addr = dofor(2, addr, nextbyte, 1);
163*5483Slinton 			break;
164*5483Slinton 
165*5483Slinton 		case O_FOR4U:
166*5483Slinton 			addr = dofor(4, addr, nextbyte, 1);
167*5483Slinton 			break;
168*5483Slinton 
169*5483Slinton 		case O_FOR1D:
170*5483Slinton 			addr = dofor(2, addr, nextbyte, -1);
171*5483Slinton 			break;
172*5483Slinton 
173*5483Slinton 		case O_FOR2D:
174*5483Slinton 			addr = dofor(2, addr, nextbyte, -1);
175*5483Slinton 			break;
176*5483Slinton 
177*5483Slinton 		case O_FOR4D:
178*5483Slinton 			addr = dofor(4, addr, nextbyte, -1);
179*5483Slinton 			break;
180*5483Slinton 
181*5483Slinton 		case O_IF:
182*5483Slinton 			stepto(addr - sizeof(short));
183*5483Slinton 			dread(&offset, process->sp, sizeof(offset));
184*5483Slinton 			if (offset == 0) {
185*5483Slinton 				iread(&offset, addr, sizeof(offset));
186*5483Slinton 				addr += offset;
187*5483Slinton 			} else {
188*5483Slinton 				addr += sizeof(offset);
189*5483Slinton 			}
190*5483Slinton 			break;
191*5483Slinton 
192*5483Slinton 		default: {
193*5483Slinton #	if (isvaxpx)
194*5483Slinton 			int i;
195*5483Slinton 
196*5483Slinton 			for (i = 0; optab[op].argtype[i] != 0; i++) {
197*5483Slinton 				switch(optab[op].argtype[i]) {
198*5483Slinton 					case ADDR4:
199*5483Slinton 					case LWORD:
200*5483Slinton 						addr += 4;
201*5483Slinton 						break;
202*5483Slinton 
203*5483Slinton 					case SUBOP:
204*5483Slinton 						break;
205*5483Slinton 
206*5483Slinton 					case ADDR2:
207*5483Slinton 					case HWORD:
208*5483Slinton 					case PSUBOP:
209*5483Slinton 					case DISP:
210*5483Slinton 					case VLEN:
211*5483Slinton 						if (i != 0 || nextbyte == 0) {
212*5483Slinton 							addr += sizeof(short);
213*5483Slinton 						}
214*5483Slinton 						break;
215*5483Slinton 
216*5483Slinton 					case STRING: {
217*5483Slinton 						char c;
218*5483Slinton 
219*5483Slinton 						while (nextbyte > 0) {
220*5483Slinton 							iread(&c, addr, 1);
221*5483Slinton 							if (c == '\0') {
222*5483Slinton 								break;
223*5483Slinton 							}
224*5483Slinton 							nextbyte--;
225*5483Slinton 							addr++;
226*5483Slinton 						}
227*5483Slinton 						addr++;
228*5483Slinton 						if ((addr&1) != 0) {
229*5483Slinton 							addr++;
230*5483Slinton 						}
231*5483Slinton 						break;
232*5483Slinton 					}
233*5483Slinton 
234*5483Slinton 					default:
235*5483Slinton 						panic("bad argtype");
236*5483Slinton 						/*NOTREACHED*/
237*5483Slinton 				}
238*5483Slinton 			}
239*5483Slinton #	else
240*5483Slinton 			int oplen;
241*5483Slinton 
242*5483Slinton 			oplen = optab[op].nargs;
243*5483Slinton 			if (oplen < 0) {
244*5483Slinton 				oplen = (-oplen) - 1;
245*5483Slinton 			} else  if (oplen > 0 && nextbyte != 0) {
246*5483Slinton 				oplen--;
247*5483Slinton 			}
248*5483Slinton 			oplen *= sizeof(int);
249*5483Slinton 			switch (op) {
250*5483Slinton 				case O_BEG:
251*5483Slinton 				case O_NODUMP:
252*5483Slinton 					oplen += 10;
253*5483Slinton 					break;
254*5483Slinton 
255*5483Slinton 				case O_CON:
256*5483Slinton 					oplen += ((nextbyte + 1)&~1);
257*5483Slinton 					break;
258*5483Slinton 			}
259*5483Slinton 			addr += oplen;
260*5483Slinton #	endif
261*5483Slinton 			break;
262*5483Slinton 		}
263*5483Slinton 	}
264*5483Slinton 	return addr;
265*5483Slinton }
266*5483Slinton 
267*5483Slinton /*
268*5483Slinton  * Find the next address that will be executed after the
269*5483Slinton  * case statement at the given address.
270*5483Slinton  */
271*5483Slinton 
272*5483Slinton LOCAL ADDRESS docase(ncases, size, addr)
273*5483Slinton int ncases;
274*5483Slinton int size;
275*5483Slinton ADDRESS addr;
276*5483Slinton {
277*5483Slinton 	register ADDRESS i;
278*5483Slinton 	ADDRESS firstval, lastval, jmptable;
279*5483Slinton 	short offset;
280*5483Slinton 	long swtval, caseval;
281*5483Slinton 
282*5483Slinton 	stepto(addr - 2);
283*5483Slinton 	if (ncases == 0) {
284*5483Slinton 		iread(&ncases, addr, sizeof(ncases));
285*5483Slinton 		addr += sizeof(short);
286*5483Slinton 	}
287*5483Slinton 	jmptable = addr;
288*5483Slinton 	firstval = jmptable + ncases*sizeof(short);
289*5483Slinton 	lastval = firstval + ncases*size;
290*5483Slinton 	if (size <= 2) {
291*5483Slinton 		dread(&swtval, process->sp, 2);
292*5483Slinton 	} else {
293*5483Slinton 		dread(&swtval, process->sp, size);
294*5483Slinton 	}
295*5483Slinton 	for (i = firstval; i < lastval; i += size) {
296*5483Slinton 		iread(&caseval, i, size);
297*5483Slinton 		if (cmp(&swtval, &caseval, size) == 0) {
298*5483Slinton 			i = ((i - firstval) / size) * sizeof(offset);
299*5483Slinton 			iread(&offset, jmptable + i, sizeof(offset));
300*5483Slinton 			addr = jmptable + offset;
301*5483Slinton 			return addr;
302*5483Slinton 		}
303*5483Slinton 	}
304*5483Slinton 	return((lastval+1)&~1);
305*5483Slinton }
306*5483Slinton 
307*5483Slinton LOCAL ADDRESS dofor(size, addr, subop, incr)
308*5483Slinton int size;
309*5483Slinton ADDRESS addr;
310*5483Slinton short subop;
311*5483Slinton int incr;
312*5483Slinton {
313*5483Slinton 	register PROCESS *p;
314*5483Slinton 	long i, limit, lower;
315*5483Slinton 	ADDRESS valaddr;
316*5483Slinton 	short offset;
317*5483Slinton 
318*5483Slinton 	stepto(addr - sizeof(short));
319*5483Slinton 	p = process;
320*5483Slinton 	i = limit = 0;
321*5483Slinton 	if (subop == 0) {
322*5483Slinton 		addr += size;
323*5483Slinton 	}
324*5483Slinton 	dread(&valaddr, p->sp, sizeof(valaddr));
325*5483Slinton 	dread(&i, valaddr, size);
326*5483Slinton 	dread(&limit, p->sp + sizeof(valaddr), size);
327*5483Slinton 	i += (incr << (8*(sizeof(i) - size)));
328*5483Slinton 	addr += size;
329*5483Slinton /*
330*5483Slinton  * It is very slow to go through the loop again and again.
331*5483Slinton  * So for the time being, we just skip to the end.
332*5483Slinton  *
333*5483Slinton 	if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) {
334*5483Slinton 		iread(&offset, addr, sizeof(offset));
335*5483Slinton 		return(addr + offset);
336*5483Slinton 	} else {
337*5483Slinton  */
338*5483Slinton 		return(addr + sizeof(short));
339*5483Slinton /*
340*5483Slinton 	}
341*5483Slinton  */
342*5483Slinton }
343