Commit | Line | Data |
---|---|---|
505bf312 KB |
1 | /*- |
2 | * Copyright (c) 1980 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
af359dea C |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * 3. All advertising materials mentioning features or use of this software | |
14 | * must display the following acknowledgement: | |
15 | * This product includes software developed by the University of | |
16 | * California, Berkeley and its contributors. | |
17 | * 4. Neither the name of the University nor the names of its contributors | |
18 | * may be used to endorse or promote products derived from this software | |
19 | * without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
31 | * SUCH DAMAGE. | |
e7d8eb31 | 32 | */ |
4e4050a1 | 33 | |
e7d8eb31 | 34 | #ifndef lint |
af359dea | 35 | static char sccsid[] = "@(#)nextaddr.c 5.3 (Berkeley) 4/16/91"; |
505bf312 | 36 | #endif /* not lint */ |
82d3cd01 | 37 | |
4e4050a1 ML |
38 | /* |
39 | * Calculate the next address that will be executed from the current one. | |
40 | * | |
41 | * If the next address depends on runtime data (e.g. a conditional | |
42 | * branch will depend on the value on top of the stack), | |
43 | * we must execute up to the given address with "stepto". | |
44 | * | |
45 | * If the second argument is TRUE, we treat a CALL instruction as | |
46 | * straight line rather than following it as a branch. | |
47 | */ | |
48 | ||
49 | #include "defs.h" | |
50 | #include "machine.h" | |
51 | #include "process.h" | |
52 | #include "breakpoint.h" | |
53 | #include "sym.h" | |
54 | #include "pxops.h" | |
55 | #include "optab.h" | |
56 | #include "mappings.h" | |
57 | #include "runtime.h" | |
58 | #include "process/pxinfo.h" | |
59 | #include "process/process.rep" | |
60 | ||
82d3cd01 KM |
61 | #ifdef tahoe |
62 | #define EVEN 3 | |
63 | #else | |
64 | #define EVEN 1 | |
65 | #endif | |
66 | ||
4e4050a1 ML |
67 | LOCAL ADDRESS docase(), dofor(); |
68 | ||
69 | ADDRESS nextaddr(beginaddr, isnext) | |
70 | ADDRESS beginaddr; | |
71 | BOOLEAN isnext; | |
72 | { | |
635ecd43 ML |
73 | register PXOP op; |
74 | ADDRESS addr; | |
75 | short offset; | |
76 | int nextbyte; | |
77 | SYM *s; | |
78 | union { | |
79 | short word; | |
80 | char byte[2]; | |
81 | } o; | |
82 | ||
82d3cd01 KM |
83 | #ifdef tahoe |
84 | doret(process); | |
85 | #endif | |
635ecd43 ML |
86 | addr = beginaddr; |
87 | iread(&o.word, addr, sizeof(o.word)); | |
88 | op = (PXOP) o.byte[0]; | |
89 | nextbyte = o.byte[1]; | |
90 | addr += sizeof(short); | |
91 | switch(op) { | |
92 | ||
635ecd43 | 93 | /* |
82d3cd01 | 94 | * The version of px we are using assumes that the instruction |
635ecd43 ML |
95 | * at the entry point of a function is a TRA4 to the beginning |
96 | * of the block. | |
97 | */ | |
635ecd43 ML |
98 | case O_CALL: { |
99 | ADDRESS eaddr; | |
100 | ||
101 | if (isnext) { | |
102 | addr += sizeof(int); | |
82d3cd01 KM |
103 | #ifdef tahoe |
104 | addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN); | |
105 | #endif | |
635ecd43 | 106 | } else { |
82d3cd01 KM |
107 | #ifdef tahoe |
108 | addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN); | |
109 | #endif | |
110 | iread(&eaddr, addr, sizeof(eaddr)); | |
111 | addr = eaddr + sizeof(short); | |
112 | #ifdef tahoe | |
113 | addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN); | |
114 | #endif | |
115 | iread(&addr, addr, sizeof(addr)); | |
635ecd43 ML |
116 | stepto(addr); |
117 | if (linelookup(addr) == 0) { | |
118 | bpact(); | |
119 | addr = pc; | |
4e4050a1 | 120 | } |
635ecd43 ML |
121 | if (ss_lines && trcond()) { |
122 | s = whatblock(addr); | |
123 | if (s == NIL) { | |
124 | panic("bad call addr"); | |
125 | } | |
126 | printentry(s); | |
127 | } | |
128 | } | |
129 | break; | |
130 | } | |
4e4050a1 | 131 | |
635ecd43 ML |
132 | case O_FCALL: { |
133 | ADDRESS eaddr; | |
134 | ADDRESS *fparam; | |
135 | ||
136 | if (!isnext) { | |
137 | stepto(addr - sizeof(short)); | |
82d3cd01 KM |
138 | #ifdef tahoe |
139 | doret(process); | |
140 | #endif | |
635ecd43 ML |
141 | dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam)); |
142 | dread(&eaddr, fparam, sizeof(eaddr)); | |
143 | addr = eaddr - ENDOFF; | |
144 | stepto(addr); | |
82d3cd01 KM |
145 | #ifdef tahoe |
146 | doret(process); | |
147 | #endif | |
635ecd43 ML |
148 | if (linelookup(addr) == 0) { |
149 | bpact(); | |
150 | addr = pc; | |
4e4050a1 | 151 | } |
635ecd43 ML |
152 | if (ss_lines && trcond()) { |
153 | s = whatblock(addr); | |
154 | if (s == NIL) { | |
155 | panic("bad call addr"); | |
156 | } | |
157 | printentry(s); | |
158 | } | |
159 | } | |
160 | break; | |
161 | } | |
635ecd43 ML |
162 | |
163 | case O_END: | |
164 | if ((addr - sizeof(short)) == lastaddr()) { | |
165 | stepto(addr - sizeof(short)); | |
166 | endprogram(); | |
167 | } else { | |
168 | addr = return_addr(); | |
169 | s = whatblock(pc); | |
170 | stepto(addr); | |
171 | if (ss_lines && trcond()) { | |
172 | printexit(s); | |
173 | } | |
174 | if (linelookup(addr) == 0) { | |
175 | bpact(); | |
176 | addr = pc; | |
177 | } | |
178 | } | |
179 | break; | |
180 | ||
635ecd43 ML |
181 | case O_TRA4: |
182 | case O_GOTO: | |
82d3cd01 KM |
183 | #ifdef tahoe |
184 | addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN); | |
185 | #endif | |
635ecd43 ML |
186 | iread(&addr, addr, sizeof(addr)); |
187 | break; | |
635ecd43 ML |
188 | |
189 | case O_TRA: | |
190 | iread(&offset, addr, sizeof(offset)); | |
191 | addr += offset; | |
192 | break; | |
193 | ||
194 | case O_CON: { | |
195 | short consize; | |
196 | ||
197 | if (nextbyte == 0) { | |
82d3cd01 KM |
198 | #ifdef tahoe |
199 | addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN); | |
200 | #endif | |
635ecd43 ML |
201 | iread(&consize, addr, sizeof(consize)); |
202 | addr += sizeof(consize); | |
203 | } else { | |
204 | consize = nextbyte; | |
205 | } | |
206 | addr += consize; | |
207 | break; | |
208 | } | |
4e4050a1 | 209 | |
635ecd43 ML |
210 | case O_CASE1OP: |
211 | addr = docase(nextbyte, 1, addr); | |
212 | break; | |
4e4050a1 | 213 | |
635ecd43 ML |
214 | case O_CASE2OP: |
215 | addr = docase(nextbyte, 2, addr); | |
216 | break; | |
4e4050a1 | 217 | |
635ecd43 ML |
218 | case O_CASE4OP: |
219 | addr = docase(nextbyte, 4, addr); | |
220 | break; | |
4e4050a1 | 221 | |
635ecd43 ML |
222 | case O_FOR1U: |
223 | addr = dofor(2, addr, nextbyte, 1); | |
224 | break; | |
4e4050a1 | 225 | |
635ecd43 ML |
226 | case O_FOR2U: |
227 | addr = dofor(2, addr, nextbyte, 1); | |
228 | break; | |
4e4050a1 | 229 | |
635ecd43 ML |
230 | case O_FOR4U: |
231 | addr = dofor(4, addr, nextbyte, 1); | |
232 | break; | |
4e4050a1 | 233 | |
635ecd43 ML |
234 | case O_FOR1D: |
235 | addr = dofor(2, addr, nextbyte, -1); | |
236 | break; | |
4e4050a1 | 237 | |
635ecd43 ML |
238 | case O_FOR2D: |
239 | addr = dofor(2, addr, nextbyte, -1); | |
240 | break; | |
4e4050a1 | 241 | |
635ecd43 ML |
242 | case O_FOR4D: |
243 | addr = dofor(4, addr, nextbyte, -1); | |
244 | break; | |
4e4050a1 | 245 | |
635ecd43 ML |
246 | case O_IF: |
247 | stepto(addr - sizeof(short)); | |
82d3cd01 KM |
248 | #ifdef tahoe |
249 | doret(process); | |
250 | dread(&offset, process->sp+sizeof(int)-sizeof(offset), sizeof(offset)); | |
251 | #else | |
635ecd43 | 252 | dread(&offset, process->sp, sizeof(offset)); |
82d3cd01 | 253 | #endif |
635ecd43 ML |
254 | if (offset == 0) { |
255 | iread(&offset, addr, sizeof(offset)); | |
256 | addr += offset; | |
257 | } else { | |
258 | addr += sizeof(offset); | |
259 | } | |
260 | break; | |
261 | ||
262 | default: { | |
635ecd43 ML |
263 | int i; |
264 | ||
265 | for (i = 0; optab[op].argtype[i] != 0; i++) { | |
266 | switch(optab[op].argtype[i]) { | |
267 | case ADDR4: | |
268 | case LWORD: | |
269 | addr += 4; | |
82d3cd01 KM |
270 | #ifdef tahoe |
271 | addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN); | |
272 | #endif | |
4e4050a1 ML |
273 | break; |
274 | ||
635ecd43 | 275 | case SUBOP: |
4e4050a1 ML |
276 | break; |
277 | ||
635ecd43 ML |
278 | case ADDR2: |
279 | case HWORD: | |
280 | case PSUBOP: | |
281 | case DISP: | |
282 | case VLEN: | |
283 | if (i != 0 || nextbyte == 0) { | |
284 | addr += sizeof(short); | |
4e4050a1 ML |
285 | } |
286 | break; | |
287 | ||
635ecd43 ML |
288 | case STRING: { |
289 | char c; | |
290 | ||
291 | while (nextbyte > 0) { | |
292 | iread(&c, addr, 1); | |
293 | if (c == '\0') { | |
294 | break; | |
295 | } | |
296 | nextbyte--; | |
297 | addr++; | |
4e4050a1 | 298 | } |
635ecd43 | 299 | addr++; |
82d3cd01 | 300 | addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN); |
4e4050a1 | 301 | break; |
635ecd43 ML |
302 | } |
303 | ||
304 | default: | |
305 | panic("bad argtype"); | |
306 | /*NOTREACHED*/ | |
4e4050a1 | 307 | } |
635ecd43 | 308 | } |
635ecd43 | 309 | break; |
4e4050a1 | 310 | } |
635ecd43 ML |
311 | } |
312 | return addr; | |
4e4050a1 ML |
313 | } |
314 | ||
315 | /* | |
316 | * Find the next address that will be executed after the | |
317 | * case statement at the given address. | |
318 | */ | |
319 | ||
320 | LOCAL ADDRESS docase(ncases, size, addr) | |
321 | int ncases; | |
322 | int size; | |
323 | ADDRESS addr; | |
324 | { | |
635ecd43 ML |
325 | register ADDRESS i; |
326 | ADDRESS firstval, lastval, jmptable; | |
327 | short offset; | |
328 | long swtval, caseval; | |
329 | ||
330 | stepto(addr - 2); | |
82d3cd01 KM |
331 | #ifdef tahoe |
332 | doret(process); | |
333 | #endif | |
635ecd43 ML |
334 | if (ncases == 0) { |
335 | iread(&ncases, addr, sizeof(ncases)); | |
336 | addr += sizeof(short); | |
337 | } | |
338 | jmptable = addr; | |
339 | firstval = jmptable + ncases*sizeof(short); | |
82d3cd01 KM |
340 | #ifdef tahoe |
341 | if (size == 4) { | |
342 | firstval = (ADDRESS)(((int)firstval + EVEN) & ~EVEN); | |
343 | } | |
344 | #endif | |
635ecd43 | 345 | lastval = firstval + ncases*size; |
82d3cd01 KM |
346 | #ifdef tahoe |
347 | if (size <= 4) { | |
348 | dread(&swtval, process->sp, 4); | |
349 | #else | |
635ecd43 ML |
350 | if (size <= 2) { |
351 | dread(&swtval, process->sp, 2); | |
82d3cd01 | 352 | #endif |
635ecd43 ML |
353 | } else { |
354 | dread(&swtval, process->sp, size); | |
355 | } | |
356 | for (i = firstval; i < lastval; i += size) { | |
82d3cd01 KM |
357 | caseval = 0; |
358 | #ifdef tahoe | |
359 | iread((char *)&caseval + sizeof caseval - size, i, size); | |
360 | if (swtval == caseval) | |
361 | #else | |
635ecd43 | 362 | iread(&caseval, i, size); |
82d3cd01 KM |
363 | if (cmp(&swtval, &caseval, size) == 0) |
364 | #endif | |
365 | { | |
635ecd43 ML |
366 | i = ((i - firstval) / size) * sizeof(offset); |
367 | iread(&offset, jmptable + i, sizeof(offset)); | |
368 | addr = jmptable + offset; | |
369 | return addr; | |
4e4050a1 | 370 | } |
635ecd43 ML |
371 | } |
372 | return((lastval+1)&~1); | |
4e4050a1 ML |
373 | } |
374 | ||
375 | LOCAL ADDRESS dofor(size, addr, subop, incr) | |
376 | int size; | |
377 | ADDRESS addr; | |
378 | short subop; | |
379 | int incr; | |
380 | { | |
635ecd43 | 381 | register PROCESS *p; |
82d3cd01 | 382 | long i, limit; |
635ecd43 | 383 | ADDRESS valaddr; |
635ecd43 ML |
384 | |
385 | stepto(addr - sizeof(short)); | |
386 | p = process; | |
82d3cd01 KM |
387 | #ifdef tahoe |
388 | doret(p); | |
389 | #endif | |
635ecd43 ML |
390 | i = limit = 0; |
391 | if (subop == 0) { | |
82d3cd01 KM |
392 | dread(&subop, addr, sizeof (short)); |
393 | addr += sizeof (short); | |
635ecd43 ML |
394 | } |
395 | dread(&valaddr, p->sp, sizeof(valaddr)); | |
82d3cd01 KM |
396 | #ifdef tahoe |
397 | dread((char *)&i + sizeof i - size, valaddr, size); | |
398 | #else | |
635ecd43 | 399 | dread(&i, valaddr, size); |
82d3cd01 KM |
400 | #endif |
401 | dread(&limit, p->sp + sizeof(valaddr), sizeof limit); | |
402 | i += incr; | |
cf2f3812 | 403 | |
4e4050a1 ML |
404 | /* |
405 | * It is very slow to go through the loop again and again. | |
cf2f3812 ML |
406 | * If it is desired to just skip to the end, the next 4 lines |
407 | * should be skipped. | |
408 | */ | |
635ecd43 | 409 | if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) { |
82d3cd01 | 410 | return(addr + subop); |
635ecd43 | 411 | } else { |
82d3cd01 | 412 | return(addr); |
635ecd43 | 413 | } |
4e4050a1 | 414 | } |
b0231b44 ML |
415 | |
416 | /* | |
417 | * Determine whether or not the given address corresponds to the | |
418 | * end of a procedure. | |
419 | */ | |
420 | ||
421 | BOOLEAN isendofproc(addr) | |
422 | ADDRESS addr; | |
423 | { | |
424 | PXOP op; | |
425 | ||
426 | iread(&op, addr, sizeof(op)); | |
427 | return (op == O_END); | |
428 | } |