Commit | Line | Data |
---|---|---|
e7d8eb31 DF |
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 | */ | |
4e4050a1 | 6 | |
e7d8eb31 DF |
7 | #ifndef lint |
8 | static char sccsid[] = "@(#)nextaddr.c 5.1 (Berkeley) %G%"; | |
9 | #endif not lint | |
4e4050a1 ML |
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 | { | |
635ecd43 ML |
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; | |
4e4050a1 | 81 | } |
635ecd43 ML |
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 | } | |
4e4050a1 | 92 | |
635ecd43 ML |
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; | |
4e4050a1 | 107 | } |
635ecd43 ML |
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 | } | |
4e4050a1 | 162 | |
635ecd43 ML |
163 | case O_CASE1OP: |
164 | addr = docase(nextbyte, 1, addr); | |
165 | break; | |
4e4050a1 | 166 | |
635ecd43 ML |
167 | case O_CASE2OP: |
168 | addr = docase(nextbyte, 2, addr); | |
169 | break; | |
4e4050a1 | 170 | |
635ecd43 ML |
171 | case O_CASE4OP: |
172 | addr = docase(nextbyte, 4, addr); | |
173 | break; | |
4e4050a1 | 174 | |
635ecd43 ML |
175 | case O_FOR1U: |
176 | addr = dofor(2, addr, nextbyte, 1); | |
177 | break; | |
4e4050a1 | 178 | |
635ecd43 ML |
179 | case O_FOR2U: |
180 | addr = dofor(2, addr, nextbyte, 1); | |
181 | break; | |
4e4050a1 | 182 | |
635ecd43 ML |
183 | case O_FOR4U: |
184 | addr = dofor(4, addr, nextbyte, 1); | |
185 | break; | |
4e4050a1 | 186 | |
635ecd43 ML |
187 | case O_FOR1D: |
188 | addr = dofor(2, addr, nextbyte, -1); | |
189 | break; | |
4e4050a1 | 190 | |
635ecd43 ML |
191 | case O_FOR2D: |
192 | addr = dofor(2, addr, nextbyte, -1); | |
193 | break; | |
4e4050a1 | 194 | |
635ecd43 ML |
195 | case O_FOR4D: |
196 | addr = dofor(4, addr, nextbyte, -1); | |
197 | break; | |
4e4050a1 | 198 | |
635ecd43 ML |
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; | |
4e4050a1 ML |
219 | break; |
220 | ||
635ecd43 | 221 | case SUBOP: |
4e4050a1 ML |
222 | break; |
223 | ||
635ecd43 ML |
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); | |
4e4050a1 ML |
231 | } |
232 | break; | |
233 | ||
635ecd43 ML |
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++; | |
4e4050a1 | 244 | } |
635ecd43 ML |
245 | addr++; |
246 | if ((addr&1) != 0) { | |
247 | addr++; | |
4e4050a1 | 248 | } |
4e4050a1 | 249 | break; |
635ecd43 ML |
250 | } |
251 | ||
252 | default: | |
253 | panic("bad argtype"); | |
254 | /*NOTREACHED*/ | |
4e4050a1 | 255 | } |
635ecd43 ML |
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; | |
4e4050a1 | 280 | } |
635ecd43 ML |
281 | } |
282 | return addr; | |
4e4050a1 ML |
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 | { | |
635ecd43 ML |
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; | |
4e4050a1 | 320 | } |
635ecd43 ML |
321 | } |
322 | return((lastval+1)&~1); | |
4e4050a1 ML |
323 | } |
324 | ||
325 | LOCAL ADDRESS dofor(size, addr, subop, incr) | |
326 | int size; | |
327 | ADDRESS addr; | |
328 | short subop; | |
329 | int incr; | |
330 | { | |
635ecd43 ML |
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) { | |
4e4050a1 | 340 | addr += size; |
635ecd43 ML |
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; | |
cf2f3812 | 347 | |
4e4050a1 ML |
348 | /* |
349 | * It is very slow to go through the loop again and again. | |
cf2f3812 ML |
350 | * If it is desired to just skip to the end, the next 4 lines |
351 | * should be skipped. | |
352 | */ | |
635ecd43 ML |
353 | if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) { |
354 | iread(&offset, addr, sizeof(offset)); | |
355 | return(addr + offset); | |
356 | } else { | |
635ecd43 | 357 | return(addr + sizeof(short)); |
635ecd43 | 358 | } |
4e4050a1 | 359 | } |
b0231b44 ML |
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 | } |