Commit | Line | Data |
---|---|---|
4e4050a1 ML |
1 | /* Copyright (c) 1982 Regents of the University of California */ |
2 | ||
3 | static char sccsid[] = "@(#)nextaddr.c 1.1 %G%"; | |
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_CASE1OP: | |
146 | addr = docase(nextbyte, 1, addr); | |
147 | break; | |
148 | ||
149 | case O_CASE2OP: | |
150 | addr = docase(nextbyte, 2, addr); | |
151 | break; | |
152 | ||
153 | case O_CASE4OP: | |
154 | addr = docase(nextbyte, 4, addr); | |
155 | break; | |
156 | ||
157 | case O_FOR1U: | |
158 | addr = dofor(2, addr, nextbyte, 1); | |
159 | break; | |
160 | ||
161 | case O_FOR2U: | |
162 | addr = dofor(2, addr, nextbyte, 1); | |
163 | break; | |
164 | ||
165 | case O_FOR4U: | |
166 | addr = dofor(4, addr, nextbyte, 1); | |
167 | break; | |
168 | ||
169 | case O_FOR1D: | |
170 | addr = dofor(2, addr, nextbyte, -1); | |
171 | break; | |
172 | ||
173 | case O_FOR2D: | |
174 | addr = dofor(2, addr, nextbyte, -1); | |
175 | break; | |
176 | ||
177 | case O_FOR4D: | |
178 | addr = dofor(4, addr, nextbyte, -1); | |
179 | break; | |
180 | ||
181 | case O_IF: | |
182 | stepto(addr - sizeof(short)); | |
183 | dread(&offset, process->sp, sizeof(offset)); | |
184 | if (offset == 0) { | |
185 | iread(&offset, addr, sizeof(offset)); | |
186 | addr += offset; | |
187 | } else { | |
188 | addr += sizeof(offset); | |
189 | } | |
190 | break; | |
191 | ||
192 | default: { | |
193 | # if (isvaxpx) | |
194 | int i; | |
195 | ||
196 | for (i = 0; optab[op].argtype[i] != 0; i++) { | |
197 | switch(optab[op].argtype[i]) { | |
198 | case ADDR4: | |
199 | case LWORD: | |
200 | addr += 4; | |
201 | break; | |
202 | ||
203 | case SUBOP: | |
204 | break; | |
205 | ||
206 | case ADDR2: | |
207 | case HWORD: | |
208 | case PSUBOP: | |
209 | case DISP: | |
210 | case VLEN: | |
211 | if (i != 0 || nextbyte == 0) { | |
212 | addr += sizeof(short); | |
213 | } | |
214 | break; | |
215 | ||
216 | case STRING: { | |
217 | char c; | |
218 | ||
219 | while (nextbyte > 0) { | |
220 | iread(&c, addr, 1); | |
221 | if (c == '\0') { | |
222 | break; | |
223 | } | |
224 | nextbyte--; | |
225 | addr++; | |
226 | } | |
227 | addr++; | |
228 | if ((addr&1) != 0) { | |
229 | addr++; | |
230 | } | |
231 | break; | |
232 | } | |
233 | ||
234 | default: | |
235 | panic("bad argtype"); | |
236 | /*NOTREACHED*/ | |
237 | } | |
238 | } | |
239 | # else | |
240 | int oplen; | |
241 | ||
242 | oplen = optab[op].nargs; | |
243 | if (oplen < 0) { | |
244 | oplen = (-oplen) - 1; | |
245 | } else if (oplen > 0 && nextbyte != 0) { | |
246 | oplen--; | |
247 | } | |
248 | oplen *= sizeof(int); | |
249 | switch (op) { | |
250 | case O_BEG: | |
251 | case O_NODUMP: | |
252 | oplen += 10; | |
253 | break; | |
254 | ||
255 | case O_CON: | |
256 | oplen += ((nextbyte + 1)&~1); | |
257 | break; | |
258 | } | |
259 | addr += oplen; | |
260 | # endif | |
261 | break; | |
262 | } | |
263 | } | |
264 | return addr; | |
265 | } | |
266 | ||
267 | /* | |
268 | * Find the next address that will be executed after the | |
269 | * case statement at the given address. | |
270 | */ | |
271 | ||
272 | LOCAL ADDRESS docase(ncases, size, addr) | |
273 | int ncases; | |
274 | int size; | |
275 | ADDRESS addr; | |
276 | { | |
277 | register ADDRESS i; | |
278 | ADDRESS firstval, lastval, jmptable; | |
279 | short offset; | |
280 | long swtval, caseval; | |
281 | ||
282 | stepto(addr - 2); | |
283 | if (ncases == 0) { | |
284 | iread(&ncases, addr, sizeof(ncases)); | |
285 | addr += sizeof(short); | |
286 | } | |
287 | jmptable = addr; | |
288 | firstval = jmptable + ncases*sizeof(short); | |
289 | lastval = firstval + ncases*size; | |
290 | if (size <= 2) { | |
291 | dread(&swtval, process->sp, 2); | |
292 | } else { | |
293 | dread(&swtval, process->sp, size); | |
294 | } | |
295 | for (i = firstval; i < lastval; i += size) { | |
296 | iread(&caseval, i, size); | |
297 | if (cmp(&swtval, &caseval, size) == 0) { | |
298 | i = ((i - firstval) / size) * sizeof(offset); | |
299 | iread(&offset, jmptable + i, sizeof(offset)); | |
300 | addr = jmptable + offset; | |
301 | return addr; | |
302 | } | |
303 | } | |
304 | return((lastval+1)&~1); | |
305 | } | |
306 | ||
307 | LOCAL ADDRESS dofor(size, addr, subop, incr) | |
308 | int size; | |
309 | ADDRESS addr; | |
310 | short subop; | |
311 | int incr; | |
312 | { | |
313 | register PROCESS *p; | |
314 | long i, limit, lower; | |
315 | ADDRESS valaddr; | |
316 | short offset; | |
317 | ||
318 | stepto(addr - sizeof(short)); | |
319 | p = process; | |
320 | i = limit = 0; | |
321 | if (subop == 0) { | |
322 | addr += size; | |
323 | } | |
324 | dread(&valaddr, p->sp, sizeof(valaddr)); | |
325 | dread(&i, valaddr, size); | |
326 | dread(&limit, p->sp + sizeof(valaddr), size); | |
327 | i += (incr << (8*(sizeof(i) - size))); | |
328 | addr += size; | |
329 | /* | |
330 | * It is very slow to go through the loop again and again. | |
331 | * So for the time being, we just skip to the end. | |
332 | * | |
333 | if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) { | |
334 | iread(&offset, addr, sizeof(offset)); | |
335 | return(addr + offset); | |
336 | } else { | |
337 | */ | |
338 | return(addr + sizeof(short)); | |
339 | /* | |
340 | } | |
341 | */ | |
342 | } |