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