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