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