port for tahoe from Nir peleg of CCI
[unix-history] / usr / src / usr.bin / pascal / pdx / machine / nextaddr.c
CommitLineData
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
8static 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
33LOCAL ADDRESS docase(), dofor();
34
35ADDRESS nextaddr(beginaddr, isnext)
36ADDRESS beginaddr;
37BOOLEAN 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
290LOCAL ADDRESS docase(ncases, size, addr)
291int ncases;
292int size;
293ADDRESS 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
325LOCAL ADDRESS dofor(size, addr, subop, incr)
326int size;
327ADDRESS addr;
328short subop;
329int 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
366BOOLEAN isendofproc(addr)
367ADDRESS addr;
368{
369 PXOP op;
370
371 iread(&op, addr, sizeof(op));
372 return (op == O_END);
373}