Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / usr.bin / pascal / pdx / machine / nextaddr.c
CommitLineData
505bf312
KB
1/*-
2 * Copyright (c) 1980 The Regents of the University of California.
3 * All rights reserved.
4 *
af359dea
C
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
e7d8eb31 32 */
4e4050a1 33
e7d8eb31 34#ifndef lint
af359dea 35static char sccsid[] = "@(#)nextaddr.c 5.3 (Berkeley) 4/16/91";
505bf312 36#endif /* not lint */
82d3cd01 37
4e4050a1
ML
38/*
39 * Calculate the next address that will be executed from the current one.
40 *
41 * If the next address depends on runtime data (e.g. a conditional
42 * branch will depend on the value on top of the stack),
43 * we must execute up to the given address with "stepto".
44 *
45 * If the second argument is TRUE, we treat a CALL instruction as
46 * straight line rather than following it as a branch.
47 */
48
49#include "defs.h"
50#include "machine.h"
51#include "process.h"
52#include "breakpoint.h"
53#include "sym.h"
54#include "pxops.h"
55#include "optab.h"
56#include "mappings.h"
57#include "runtime.h"
58#include "process/pxinfo.h"
59#include "process/process.rep"
60
82d3cd01
KM
61#ifdef tahoe
62#define EVEN 3
63#else
64#define EVEN 1
65#endif
66
4e4050a1
ML
67LOCAL ADDRESS docase(), dofor();
68
69ADDRESS nextaddr(beginaddr, isnext)
70ADDRESS beginaddr;
71BOOLEAN isnext;
72{
635ecd43
ML
73 register PXOP op;
74 ADDRESS addr;
75 short offset;
76 int nextbyte;
77 SYM *s;
78 union {
79 short word;
80 char byte[2];
81 } o;
82
82d3cd01
KM
83#ifdef tahoe
84 doret(process);
85#endif
635ecd43
ML
86 addr = beginaddr;
87 iread(&o.word, addr, sizeof(o.word));
88 op = (PXOP) o.byte[0];
89 nextbyte = o.byte[1];
90 addr += sizeof(short);
91 switch(op) {
92
635ecd43 93 /*
82d3cd01 94 * The version of px we are using assumes that the instruction
635ecd43
ML
95 * at the entry point of a function is a TRA4 to the beginning
96 * of the block.
97 */
635ecd43
ML
98 case O_CALL: {
99 ADDRESS eaddr;
100
101 if (isnext) {
102 addr += sizeof(int);
82d3cd01
KM
103#ifdef tahoe
104 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
105#endif
635ecd43 106 } else {
82d3cd01
KM
107#ifdef tahoe
108 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
109#endif
110 iread(&eaddr, addr, sizeof(eaddr));
111 addr = eaddr + sizeof(short);
112#ifdef tahoe
113 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
114#endif
115 iread(&addr, addr, sizeof(addr));
635ecd43
ML
116 stepto(addr);
117 if (linelookup(addr) == 0) {
118 bpact();
119 addr = pc;
4e4050a1 120 }
635ecd43
ML
121 if (ss_lines && trcond()) {
122 s = whatblock(addr);
123 if (s == NIL) {
124 panic("bad call addr");
125 }
126 printentry(s);
127 }
128 }
129 break;
130 }
4e4050a1 131
635ecd43
ML
132 case O_FCALL: {
133 ADDRESS eaddr;
134 ADDRESS *fparam;
135
136 if (!isnext) {
137 stepto(addr - sizeof(short));
82d3cd01
KM
138#ifdef tahoe
139 doret(process);
140#endif
635ecd43
ML
141 dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam));
142 dread(&eaddr, fparam, sizeof(eaddr));
143 addr = eaddr - ENDOFF;
144 stepto(addr);
82d3cd01
KM
145#ifdef tahoe
146 doret(process);
147#endif
635ecd43
ML
148 if (linelookup(addr) == 0) {
149 bpact();
150 addr = pc;
4e4050a1 151 }
635ecd43
ML
152 if (ss_lines && trcond()) {
153 s = whatblock(addr);
154 if (s == NIL) {
155 panic("bad call addr");
156 }
157 printentry(s);
158 }
159 }
160 break;
161 }
635ecd43
ML
162
163 case O_END:
164 if ((addr - sizeof(short)) == lastaddr()) {
165 stepto(addr - sizeof(short));
166 endprogram();
167 } else {
168 addr = return_addr();
169 s = whatblock(pc);
170 stepto(addr);
171 if (ss_lines && trcond()) {
172 printexit(s);
173 }
174 if (linelookup(addr) == 0) {
175 bpact();
176 addr = pc;
177 }
178 }
179 break;
180
635ecd43
ML
181 case O_TRA4:
182 case O_GOTO:
82d3cd01
KM
183#ifdef tahoe
184 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
185#endif
635ecd43
ML
186 iread(&addr, addr, sizeof(addr));
187 break;
635ecd43
ML
188
189 case O_TRA:
190 iread(&offset, addr, sizeof(offset));
191 addr += offset;
192 break;
193
194 case O_CON: {
195 short consize;
196
197 if (nextbyte == 0) {
82d3cd01
KM
198#ifdef tahoe
199 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
200#endif
635ecd43
ML
201 iread(&consize, addr, sizeof(consize));
202 addr += sizeof(consize);
203 } else {
204 consize = nextbyte;
205 }
206 addr += consize;
207 break;
208 }
4e4050a1 209
635ecd43
ML
210 case O_CASE1OP:
211 addr = docase(nextbyte, 1, addr);
212 break;
4e4050a1 213
635ecd43
ML
214 case O_CASE2OP:
215 addr = docase(nextbyte, 2, addr);
216 break;
4e4050a1 217
635ecd43
ML
218 case O_CASE4OP:
219 addr = docase(nextbyte, 4, addr);
220 break;
4e4050a1 221
635ecd43
ML
222 case O_FOR1U:
223 addr = dofor(2, addr, nextbyte, 1);
224 break;
4e4050a1 225
635ecd43
ML
226 case O_FOR2U:
227 addr = dofor(2, addr, nextbyte, 1);
228 break;
4e4050a1 229
635ecd43
ML
230 case O_FOR4U:
231 addr = dofor(4, addr, nextbyte, 1);
232 break;
4e4050a1 233
635ecd43
ML
234 case O_FOR1D:
235 addr = dofor(2, addr, nextbyte, -1);
236 break;
4e4050a1 237
635ecd43
ML
238 case O_FOR2D:
239 addr = dofor(2, addr, nextbyte, -1);
240 break;
4e4050a1 241
635ecd43
ML
242 case O_FOR4D:
243 addr = dofor(4, addr, nextbyte, -1);
244 break;
4e4050a1 245
635ecd43
ML
246 case O_IF:
247 stepto(addr - sizeof(short));
82d3cd01
KM
248#ifdef tahoe
249 doret(process);
250 dread(&offset, process->sp+sizeof(int)-sizeof(offset), sizeof(offset));
251#else
635ecd43 252 dread(&offset, process->sp, sizeof(offset));
82d3cd01 253#endif
635ecd43
ML
254 if (offset == 0) {
255 iread(&offset, addr, sizeof(offset));
256 addr += offset;
257 } else {
258 addr += sizeof(offset);
259 }
260 break;
261
262 default: {
635ecd43
ML
263 int i;
264
265 for (i = 0; optab[op].argtype[i] != 0; i++) {
266 switch(optab[op].argtype[i]) {
267 case ADDR4:
268 case LWORD:
269 addr += 4;
82d3cd01
KM
270#ifdef tahoe
271 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
272#endif
4e4050a1
ML
273 break;
274
635ecd43 275 case SUBOP:
4e4050a1
ML
276 break;
277
635ecd43
ML
278 case ADDR2:
279 case HWORD:
280 case PSUBOP:
281 case DISP:
282 case VLEN:
283 if (i != 0 || nextbyte == 0) {
284 addr += sizeof(short);
4e4050a1
ML
285 }
286 break;
287
635ecd43
ML
288 case STRING: {
289 char c;
290
291 while (nextbyte > 0) {
292 iread(&c, addr, 1);
293 if (c == '\0') {
294 break;
295 }
296 nextbyte--;
297 addr++;
4e4050a1 298 }
635ecd43 299 addr++;
82d3cd01 300 addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
4e4050a1 301 break;
635ecd43
ML
302 }
303
304 default:
305 panic("bad argtype");
306 /*NOTREACHED*/
4e4050a1 307 }
635ecd43 308 }
635ecd43 309 break;
4e4050a1 310 }
635ecd43
ML
311 }
312 return addr;
4e4050a1
ML
313}
314
315/*
316 * Find the next address that will be executed after the
317 * case statement at the given address.
318 */
319
320LOCAL ADDRESS docase(ncases, size, addr)
321int ncases;
322int size;
323ADDRESS addr;
324{
635ecd43
ML
325 register ADDRESS i;
326 ADDRESS firstval, lastval, jmptable;
327 short offset;
328 long swtval, caseval;
329
330 stepto(addr - 2);
82d3cd01
KM
331#ifdef tahoe
332 doret(process);
333#endif
635ecd43
ML
334 if (ncases == 0) {
335 iread(&ncases, addr, sizeof(ncases));
336 addr += sizeof(short);
337 }
338 jmptable = addr;
339 firstval = jmptable + ncases*sizeof(short);
82d3cd01
KM
340#ifdef tahoe
341 if (size == 4) {
342 firstval = (ADDRESS)(((int)firstval + EVEN) & ~EVEN);
343 }
344#endif
635ecd43 345 lastval = firstval + ncases*size;
82d3cd01
KM
346#ifdef tahoe
347 if (size <= 4) {
348 dread(&swtval, process->sp, 4);
349#else
635ecd43
ML
350 if (size <= 2) {
351 dread(&swtval, process->sp, 2);
82d3cd01 352#endif
635ecd43
ML
353 } else {
354 dread(&swtval, process->sp, size);
355 }
356 for (i = firstval; i < lastval; i += size) {
82d3cd01
KM
357 caseval = 0;
358#ifdef tahoe
359 iread((char *)&caseval + sizeof caseval - size, i, size);
360 if (swtval == caseval)
361#else
635ecd43 362 iread(&caseval, i, size);
82d3cd01
KM
363 if (cmp(&swtval, &caseval, size) == 0)
364#endif
365 {
635ecd43
ML
366 i = ((i - firstval) / size) * sizeof(offset);
367 iread(&offset, jmptable + i, sizeof(offset));
368 addr = jmptable + offset;
369 return addr;
4e4050a1 370 }
635ecd43
ML
371 }
372 return((lastval+1)&~1);
4e4050a1
ML
373}
374
375LOCAL ADDRESS dofor(size, addr, subop, incr)
376int size;
377ADDRESS addr;
378short subop;
379int incr;
380{
635ecd43 381 register PROCESS *p;
82d3cd01 382 long i, limit;
635ecd43 383 ADDRESS valaddr;
635ecd43
ML
384
385 stepto(addr - sizeof(short));
386 p = process;
82d3cd01
KM
387#ifdef tahoe
388 doret(p);
389#endif
635ecd43
ML
390 i = limit = 0;
391 if (subop == 0) {
82d3cd01
KM
392 dread(&subop, addr, sizeof (short));
393 addr += sizeof (short);
635ecd43
ML
394 }
395 dread(&valaddr, p->sp, sizeof(valaddr));
82d3cd01
KM
396#ifdef tahoe
397 dread((char *)&i + sizeof i - size, valaddr, size);
398#else
635ecd43 399 dread(&i, valaddr, size);
82d3cd01
KM
400#endif
401 dread(&limit, p->sp + sizeof(valaddr), sizeof limit);
402 i += incr;
cf2f3812 403
4e4050a1
ML
404/*
405 * It is very slow to go through the loop again and again.
cf2f3812
ML
406 * If it is desired to just skip to the end, the next 4 lines
407 * should be skipped.
408 */
635ecd43 409 if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) {
82d3cd01 410 return(addr + subop);
635ecd43 411 } else {
82d3cd01 412 return(addr);
635ecd43 413 }
4e4050a1 414}
b0231b44
ML
415
416/*
417 * Determine whether or not the given address corresponds to the
418 * end of a procedure.
419 */
420
421BOOLEAN isendofproc(addr)
422ADDRESS addr;
423{
424 PXOP op;
425
426 iread(&op, addr, sizeof(op));
427 return (op == O_END);
428}