date and time created 91/04/16 14:59:08 by bostic
[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 7#ifndef lint
82d3cd01 8static char sccsid[] = "@(#)nextaddr.c 5.2 (Berkeley) %G%";
e7d8eb31 9#endif not lint
82d3cd01 10
4e4050a1
ML
11/*
12 * Calculate the next address that will be executed from the current one.
13 *
14 * If the next address depends on runtime data (e.g. a conditional
15 * branch will depend on the value on top of the stack),
16 * we must execute up to the given address with "stepto".
17 *
18 * If the second argument is TRUE, we treat a CALL instruction as
19 * straight line rather than following it as a branch.
20 */
21
22#include "defs.h"
23#include "machine.h"
24#include "process.h"
25#include "breakpoint.h"
26#include "sym.h"
27#include "pxops.h"
28#include "optab.h"
29#include "mappings.h"
30#include "runtime.h"
31#include "process/pxinfo.h"
32#include "process/process.rep"
33
82d3cd01
KM
34#ifdef tahoe
35#define EVEN 3
36#else
37#define EVEN 1
38#endif
39
4e4050a1
ML
40LOCAL ADDRESS docase(), dofor();
41
42ADDRESS nextaddr(beginaddr, isnext)
43ADDRESS beginaddr;
44BOOLEAN isnext;
45{
635ecd43
ML
46 register PXOP op;
47 ADDRESS addr;
48 short offset;
49 int nextbyte;
50 SYM *s;
51 union {
52 short word;
53 char byte[2];
54 } o;
55
82d3cd01
KM
56#ifdef tahoe
57 doret(process);
58#endif
635ecd43
ML
59 addr = beginaddr;
60 iread(&o.word, addr, sizeof(o.word));
61 op = (PXOP) o.byte[0];
62 nextbyte = o.byte[1];
63 addr += sizeof(short);
64 switch(op) {
65
635ecd43 66 /*
82d3cd01 67 * The version of px we are using assumes that the instruction
635ecd43
ML
68 * at the entry point of a function is a TRA4 to the beginning
69 * of the block.
70 */
635ecd43
ML
71 case O_CALL: {
72 ADDRESS eaddr;
73
74 if (isnext) {
75 addr += sizeof(int);
82d3cd01
KM
76#ifdef tahoe
77 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
78#endif
635ecd43 79 } else {
82d3cd01
KM
80#ifdef tahoe
81 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
82#endif
83 iread(&eaddr, addr, sizeof(eaddr));
84 addr = eaddr + sizeof(short);
85#ifdef tahoe
86 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
87#endif
88 iread(&addr, addr, sizeof(addr));
635ecd43
ML
89 stepto(addr);
90 if (linelookup(addr) == 0) {
91 bpact();
92 addr = pc;
4e4050a1 93 }
635ecd43
ML
94 if (ss_lines && trcond()) {
95 s = whatblock(addr);
96 if (s == NIL) {
97 panic("bad call addr");
98 }
99 printentry(s);
100 }
101 }
102 break;
103 }
4e4050a1 104
635ecd43
ML
105 case O_FCALL: {
106 ADDRESS eaddr;
107 ADDRESS *fparam;
108
109 if (!isnext) {
110 stepto(addr - sizeof(short));
82d3cd01
KM
111#ifdef tahoe
112 doret(process);
113#endif
635ecd43
ML
114 dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam));
115 dread(&eaddr, fparam, sizeof(eaddr));
116 addr = eaddr - ENDOFF;
117 stepto(addr);
82d3cd01
KM
118#ifdef tahoe
119 doret(process);
120#endif
635ecd43
ML
121 if (linelookup(addr) == 0) {
122 bpact();
123 addr = pc;
4e4050a1 124 }
635ecd43
ML
125 if (ss_lines && trcond()) {
126 s = whatblock(addr);
127 if (s == NIL) {
128 panic("bad call addr");
129 }
130 printentry(s);
131 }
132 }
133 break;
134 }
635ecd43
ML
135
136 case O_END:
137 if ((addr - sizeof(short)) == lastaddr()) {
138 stepto(addr - sizeof(short));
139 endprogram();
140 } else {
141 addr = return_addr();
142 s = whatblock(pc);
143 stepto(addr);
144 if (ss_lines && trcond()) {
145 printexit(s);
146 }
147 if (linelookup(addr) == 0) {
148 bpact();
149 addr = pc;
150 }
151 }
152 break;
153
635ecd43
ML
154 case O_TRA4:
155 case O_GOTO:
82d3cd01
KM
156#ifdef tahoe
157 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
158#endif
635ecd43
ML
159 iread(&addr, addr, sizeof(addr));
160 break;
635ecd43
ML
161
162 case O_TRA:
163 iread(&offset, addr, sizeof(offset));
164 addr += offset;
165 break;
166
167 case O_CON: {
168 short consize;
169
170 if (nextbyte == 0) {
82d3cd01
KM
171#ifdef tahoe
172 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
173#endif
635ecd43
ML
174 iread(&consize, addr, sizeof(consize));
175 addr += sizeof(consize);
176 } else {
177 consize = nextbyte;
178 }
179 addr += consize;
180 break;
181 }
4e4050a1 182
635ecd43
ML
183 case O_CASE1OP:
184 addr = docase(nextbyte, 1, addr);
185 break;
4e4050a1 186
635ecd43
ML
187 case O_CASE2OP:
188 addr = docase(nextbyte, 2, addr);
189 break;
4e4050a1 190
635ecd43
ML
191 case O_CASE4OP:
192 addr = docase(nextbyte, 4, addr);
193 break;
4e4050a1 194
635ecd43
ML
195 case O_FOR1U:
196 addr = dofor(2, addr, nextbyte, 1);
197 break;
4e4050a1 198
635ecd43
ML
199 case O_FOR2U:
200 addr = dofor(2, addr, nextbyte, 1);
201 break;
4e4050a1 202
635ecd43
ML
203 case O_FOR4U:
204 addr = dofor(4, addr, nextbyte, 1);
205 break;
4e4050a1 206
635ecd43
ML
207 case O_FOR1D:
208 addr = dofor(2, addr, nextbyte, -1);
209 break;
4e4050a1 210
635ecd43
ML
211 case O_FOR2D:
212 addr = dofor(2, addr, nextbyte, -1);
213 break;
4e4050a1 214
635ecd43
ML
215 case O_FOR4D:
216 addr = dofor(4, addr, nextbyte, -1);
217 break;
4e4050a1 218
635ecd43
ML
219 case O_IF:
220 stepto(addr - sizeof(short));
82d3cd01
KM
221#ifdef tahoe
222 doret(process);
223 dread(&offset, process->sp+sizeof(int)-sizeof(offset), sizeof(offset));
224#else
635ecd43 225 dread(&offset, process->sp, sizeof(offset));
82d3cd01 226#endif
635ecd43
ML
227 if (offset == 0) {
228 iread(&offset, addr, sizeof(offset));
229 addr += offset;
230 } else {
231 addr += sizeof(offset);
232 }
233 break;
234
235 default: {
635ecd43
ML
236 int i;
237
238 for (i = 0; optab[op].argtype[i] != 0; i++) {
239 switch(optab[op].argtype[i]) {
240 case ADDR4:
241 case LWORD:
242 addr += 4;
82d3cd01
KM
243#ifdef tahoe
244 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
245#endif
4e4050a1
ML
246 break;
247
635ecd43 248 case SUBOP:
4e4050a1
ML
249 break;
250
635ecd43
ML
251 case ADDR2:
252 case HWORD:
253 case PSUBOP:
254 case DISP:
255 case VLEN:
256 if (i != 0 || nextbyte == 0) {
257 addr += sizeof(short);
4e4050a1
ML
258 }
259 break;
260
635ecd43
ML
261 case STRING: {
262 char c;
263
264 while (nextbyte > 0) {
265 iread(&c, addr, 1);
266 if (c == '\0') {
267 break;
268 }
269 nextbyte--;
270 addr++;
4e4050a1 271 }
635ecd43 272 addr++;
82d3cd01 273 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
4e4050a1 274 break;
635ecd43
ML
275 }
276
277 default:
278 panic("bad argtype");
279 /*NOTREACHED*/
4e4050a1 280 }
635ecd43 281 }
635ecd43 282 break;
4e4050a1 283 }
635ecd43
ML
284 }
285 return addr;
4e4050a1
ML
286}
287
288/*
289 * Find the next address that will be executed after the
290 * case statement at the given address.
291 */
292
293LOCAL ADDRESS docase(ncases, size, addr)
294int ncases;
295int size;
296ADDRESS addr;
297{
635ecd43
ML
298 register ADDRESS i;
299 ADDRESS firstval, lastval, jmptable;
300 short offset;
301 long swtval, caseval;
302
303 stepto(addr - 2);
82d3cd01
KM
304#ifdef tahoe
305 doret(process);
306#endif
635ecd43
ML
307 if (ncases == 0) {
308 iread(&ncases, addr, sizeof(ncases));
309 addr += sizeof(short);
310 }
311 jmptable = addr;
312 firstval = jmptable + ncases*sizeof(short);
82d3cd01
KM
313#ifdef tahoe
314 if (size == 4) {
315 firstval = (ADDRESS)(((int)firstval + EVEN) & ~EVEN);
316 }
317#endif
635ecd43 318 lastval = firstval + ncases*size;
82d3cd01
KM
319#ifdef tahoe
320 if (size <= 4) {
321 dread(&swtval, process->sp, 4);
322#else
635ecd43
ML
323 if (size <= 2) {
324 dread(&swtval, process->sp, 2);
82d3cd01 325#endif
635ecd43
ML
326 } else {
327 dread(&swtval, process->sp, size);
328 }
329 for (i = firstval; i < lastval; i += size) {
82d3cd01
KM
330 caseval = 0;
331#ifdef tahoe
332 iread((char *)&caseval + sizeof caseval - size, i, size);
333 if (swtval == caseval)
334#else
635ecd43 335 iread(&caseval, i, size);
82d3cd01
KM
336 if (cmp(&swtval, &caseval, size) == 0)
337#endif
338 {
635ecd43
ML
339 i = ((i - firstval) / size) * sizeof(offset);
340 iread(&offset, jmptable + i, sizeof(offset));
341 addr = jmptable + offset;
342 return addr;
4e4050a1 343 }
635ecd43
ML
344 }
345 return((lastval+1)&~1);
4e4050a1
ML
346}
347
348LOCAL ADDRESS dofor(size, addr, subop, incr)
349int size;
350ADDRESS addr;
351short subop;
352int incr;
353{
635ecd43 354 register PROCESS *p;
82d3cd01 355 long i, limit;
635ecd43 356 ADDRESS valaddr;
635ecd43
ML
357
358 stepto(addr - sizeof(short));
359 p = process;
82d3cd01
KM
360#ifdef tahoe
361 doret(p);
362#endif
635ecd43
ML
363 i = limit = 0;
364 if (subop == 0) {
82d3cd01
KM
365 dread(&subop, addr, sizeof (short));
366 addr += sizeof (short);
635ecd43
ML
367 }
368 dread(&valaddr, p->sp, sizeof(valaddr));
82d3cd01
KM
369#ifdef tahoe
370 dread((char *)&i + sizeof i - size, valaddr, size);
371#else
635ecd43 372 dread(&i, valaddr, size);
82d3cd01
KM
373#endif
374 dread(&limit, p->sp + sizeof(valaddr), sizeof limit);
375 i += incr;
cf2f3812 376
4e4050a1
ML
377/*
378 * It is very slow to go through the loop again and again.
cf2f3812
ML
379 * If it is desired to just skip to the end, the next 4 lines
380 * should be skipped.
381 */
635ecd43 382 if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) {
82d3cd01 383 return(addr + subop);
635ecd43 384 } else {
82d3cd01 385 return(addr);
635ecd43 386 }
4e4050a1 387}
b0231b44
ML
388
389/*
390 * Determine whether or not the given address corresponds to the
391 * end of a procedure.
392 */
393
394BOOLEAN isendofproc(addr)
395ADDRESS addr;
396{
397 PXOP op;
398
399 iread(&op, addr, sizeof(op));
400 return (op == O_END);
401}