|
|
1.1 root 1: /* Copyright (c) 1982 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)nextaddr.c 1.4 3/8/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:
356: /*
357: * Determine whether or not the given address corresponds to the
358: * end of a procedure.
359: */
360:
361: BOOLEAN isendofproc(addr)
362: ADDRESS addr;
363: {
364: PXOP op;
365:
366: iread(&op, addr, sizeof(op));
367: return (op == O_END);
368: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.