sccsid
[unix-history] / usr / src / usr.bin / pascal / pdx / machine / nextaddr.c
CommitLineData
4e4050a1
ML
1/* Copyright (c) 1982 Regents of the University of California */
2
3static 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
28LOCAL ADDRESS docase(), dofor();
29
30ADDRESS nextaddr(beginaddr, isnext)
31ADDRESS beginaddr;
32BOOLEAN 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
272LOCAL ADDRESS docase(ncases, size, addr)
273int ncases;
274int size;
275ADDRESS 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
307LOCAL ADDRESS dofor(size, addr, subop, incr)
308int size;
309ADDRESS addr;
310short subop;
311int 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}