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