15483Slinton /* Copyright (c) 1982 Regents of the University of California */
25483Slinton 
3*5742Slinton static char sccsid[] = "@(#)nextaddr.c 1.2 02/10/82";
45483Slinton 
55483Slinton /*
65483Slinton  * Calculate the next address that will be executed from the current one.
75483Slinton  *
85483Slinton  * If the next address depends on runtime data (e.g. a conditional
95483Slinton  * branch will depend on the value on top of the stack),
105483Slinton  * we must execute up to the given address with "stepto".
115483Slinton  *
125483Slinton  * If the second argument is TRUE, we treat a CALL instruction as
135483Slinton  * straight line rather than following it as a branch.
145483Slinton  */
155483Slinton 
165483Slinton #include "defs.h"
175483Slinton #include "machine.h"
185483Slinton #include "process.h"
195483Slinton #include "breakpoint.h"
205483Slinton #include "sym.h"
215483Slinton #include "pxops.h"
225483Slinton #include "optab.h"
235483Slinton #include "mappings.h"
245483Slinton #include "runtime.h"
255483Slinton #include "process/pxinfo.h"
265483Slinton #include "process/process.rep"
275483Slinton 
285483Slinton LOCAL ADDRESS docase(), dofor();
295483Slinton 
305483Slinton ADDRESS nextaddr(beginaddr, isnext)
315483Slinton ADDRESS beginaddr;
325483Slinton BOOLEAN isnext;
335483Slinton {
34*5742Slinton     register PXOP op;
35*5742Slinton     ADDRESS addr;
36*5742Slinton     short offset;
37*5742Slinton     int nextbyte;
38*5742Slinton     SYM *s;
39*5742Slinton     union {
40*5742Slinton 	short word;
41*5742Slinton 	char byte[2];
42*5742Slinton     } o;
435483Slinton 
44*5742Slinton     addr = beginaddr;
45*5742Slinton     iread(&o.word, addr, sizeof(o.word));
46*5742Slinton     op = (PXOP) o.byte[0];
47*5742Slinton     nextbyte = o.byte[1];
48*5742Slinton     addr += sizeof(short);
49*5742Slinton     switch(op) {
505483Slinton 
51*5742Slinton #   if (isvaxpx)
52*5742Slinton     /*
53*5742Slinton      * The version of px on the VAX assumes that the instruction
54*5742Slinton      * at the entry point of a function is a TRA4 to the beginning
55*5742Slinton      * of the block.
56*5742Slinton      */
57*5742Slinton #   endif
58*5742Slinton 	case O_CALL: {
59*5742Slinton 	    ADDRESS eaddr;
605483Slinton 
61*5742Slinton 	    if (isnext) {
62*5742Slinton 		addr += sizeof(int);
63*5742Slinton 	    } else {
64*5742Slinton #               if (isvaxpx)
65*5742Slinton 		    iread(&eaddr, addr, sizeof(eaddr));
66*5742Slinton 		    addr = eaddr + sizeof(short);
67*5742Slinton 		    iread(&addr, addr, sizeof(addr));
68*5742Slinton #               else
69*5742Slinton 		    iread(&offset, addr, sizeof(offset));
70*5742Slinton 		    addr += offset;
71*5742Slinton #               endif
72*5742Slinton 		stepto(addr);
73*5742Slinton 		if (linelookup(addr) == 0) {
74*5742Slinton 		    bpact();
75*5742Slinton 		    addr = pc;
765483Slinton 		}
77*5742Slinton 		if (ss_lines && trcond()) {
78*5742Slinton 		    s = whatblock(addr);
79*5742Slinton 		    if (s == NIL) {
80*5742Slinton 			panic("bad call addr");
81*5742Slinton 		    }
82*5742Slinton 		    printentry(s);
83*5742Slinton 		}
84*5742Slinton 	    }
85*5742Slinton 	    break;
86*5742Slinton 	}
875483Slinton 
88*5742Slinton #   if (isvaxpx)
89*5742Slinton 	case O_FCALL: {
90*5742Slinton 	    ADDRESS eaddr;
91*5742Slinton 	    ADDRESS *fparam;
925483Slinton 
93*5742Slinton 	    if (!isnext) {
94*5742Slinton 		stepto(addr - sizeof(short));
95*5742Slinton 		dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam));
96*5742Slinton 		dread(&eaddr, fparam, sizeof(eaddr));
97*5742Slinton 		addr = eaddr - ENDOFF;
98*5742Slinton 		stepto(addr);
99*5742Slinton 		if (linelookup(addr) == 0) {
100*5742Slinton 		    bpact();
101*5742Slinton 		    addr = pc;
1025483Slinton 		}
103*5742Slinton 		if (ss_lines && trcond()) {
104*5742Slinton 		    s = whatblock(addr);
105*5742Slinton 		    if (s == NIL) {
106*5742Slinton 			panic("bad call addr");
107*5742Slinton 		    }
108*5742Slinton 		    printentry(s);
109*5742Slinton 		}
110*5742Slinton 	    }
111*5742Slinton 	    break;
112*5742Slinton 	}
113*5742Slinton #   endif
1145483Slinton 
115*5742Slinton 	case O_END:
116*5742Slinton 	    if ((addr - sizeof(short)) == lastaddr()) {
117*5742Slinton 		stepto(addr - sizeof(short));
118*5742Slinton 		endprogram();
119*5742Slinton 	    } else {
120*5742Slinton 		addr = return_addr();
121*5742Slinton 		s = whatblock(pc);
122*5742Slinton 		stepto(addr);
123*5742Slinton 		if (ss_lines && trcond()) {
124*5742Slinton 		    printexit(s);
125*5742Slinton 		}
126*5742Slinton 		if (linelookup(addr) == 0) {
127*5742Slinton 		    bpact();
128*5742Slinton 		    addr = pc;
129*5742Slinton 		}
130*5742Slinton 	    }
131*5742Slinton 	    break;
1325483Slinton 
133*5742Slinton #   if (isvaxpx)
134*5742Slinton 	case O_TRA4:
135*5742Slinton 	case O_GOTO:
136*5742Slinton 	    iread(&addr, addr, sizeof(addr));
137*5742Slinton 	    break;
138*5742Slinton #   endif
1395483Slinton 
140*5742Slinton 	case O_TRA:
141*5742Slinton 	    iread(&offset, addr, sizeof(offset));
142*5742Slinton 	    addr += offset;
143*5742Slinton 	    break;
1445483Slinton 
145*5742Slinton 	case O_CON: {
146*5742Slinton 	    short consize;
1475483Slinton 
148*5742Slinton 	    if (nextbyte == 0) {
149*5742Slinton 		iread(&consize, addr, sizeof(consize));
150*5742Slinton 		addr += sizeof(consize);
151*5742Slinton 	    } else {
152*5742Slinton 		consize = nextbyte;
153*5742Slinton 	    }
154*5742Slinton 	    addr += consize;
155*5742Slinton 	    break;
156*5742Slinton 	}
1575483Slinton 
158*5742Slinton 	case O_CASE1OP:
159*5742Slinton 	    addr = docase(nextbyte, 1, addr);
160*5742Slinton 	    break;
1615483Slinton 
162*5742Slinton 	case O_CASE2OP:
163*5742Slinton 	    addr = docase(nextbyte, 2, addr);
164*5742Slinton 	    break;
1655483Slinton 
166*5742Slinton 	case O_CASE4OP:
167*5742Slinton 	    addr = docase(nextbyte, 4, addr);
168*5742Slinton 	    break;
1695483Slinton 
170*5742Slinton 	case O_FOR1U:
171*5742Slinton 	    addr = dofor(2, addr, nextbyte, 1);
172*5742Slinton 	    break;
1735483Slinton 
174*5742Slinton 	case O_FOR2U:
175*5742Slinton 	    addr = dofor(2, addr, nextbyte, 1);
176*5742Slinton 	    break;
1775483Slinton 
178*5742Slinton 	case O_FOR4U:
179*5742Slinton 	    addr = dofor(4, addr, nextbyte, 1);
180*5742Slinton 	    break;
1815483Slinton 
182*5742Slinton 	case O_FOR1D:
183*5742Slinton 	    addr = dofor(2, addr, nextbyte, -1);
184*5742Slinton 	    break;
1855483Slinton 
186*5742Slinton 	case O_FOR2D:
187*5742Slinton 	    addr = dofor(2, addr, nextbyte, -1);
188*5742Slinton 	    break;
1895483Slinton 
190*5742Slinton 	case O_FOR4D:
191*5742Slinton 	    addr = dofor(4, addr, nextbyte, -1);
192*5742Slinton 	    break;
1935483Slinton 
194*5742Slinton 	case O_IF:
195*5742Slinton 	    stepto(addr - sizeof(short));
196*5742Slinton 	    dread(&offset, process->sp, sizeof(offset));
197*5742Slinton 	    if (offset == 0) {
198*5742Slinton 		iread(&offset, addr, sizeof(offset));
199*5742Slinton 		addr += offset;
200*5742Slinton 	    } else {
201*5742Slinton 		addr += sizeof(offset);
202*5742Slinton 	    }
203*5742Slinton 	    break;
2045483Slinton 
205*5742Slinton 	default: {
206*5742Slinton #   if (isvaxpx)
207*5742Slinton 	    int i;
2085483Slinton 
209*5742Slinton 	    for (i = 0; optab[op].argtype[i] != 0; i++) {
210*5742Slinton 		switch(optab[op].argtype[i]) {
211*5742Slinton 		    case ADDR4:
212*5742Slinton 		    case LWORD:
213*5742Slinton 			addr += 4;
214*5742Slinton 			break;
2155483Slinton 
216*5742Slinton 		    case SUBOP:
217*5742Slinton 			break;
2185483Slinton 
219*5742Slinton 		    case ADDR2:
220*5742Slinton 		    case HWORD:
221*5742Slinton 		    case PSUBOP:
222*5742Slinton 		    case DISP:
223*5742Slinton 		    case VLEN:
224*5742Slinton 			if (i != 0 || nextbyte == 0) {
225*5742Slinton 			    addr += sizeof(short);
2265483Slinton 			}
227*5742Slinton 			break;
2285483Slinton 
229*5742Slinton 		    case STRING: {
230*5742Slinton 			char c;
2315483Slinton 
232*5742Slinton 			while (nextbyte > 0) {
233*5742Slinton 			    iread(&c, addr, 1);
234*5742Slinton 			    if (c == '\0') {
235*5742Slinton 				break;
236*5742Slinton 			    }
237*5742Slinton 			    nextbyte--;
238*5742Slinton 			    addr++;
2395483Slinton 			}
240*5742Slinton 			addr++;
241*5742Slinton 			if ((addr&1) != 0) {
242*5742Slinton 			    addr++;
243*5742Slinton 			}
2445483Slinton 			break;
245*5742Slinton 		    }
246*5742Slinton 
247*5742Slinton 		    default:
248*5742Slinton 			panic("bad argtype");
249*5742Slinton 			/*NOTREACHED*/
2505483Slinton 		}
251*5742Slinton 	    }
252*5742Slinton #   else
253*5742Slinton 	    int oplen;
254*5742Slinton 
255*5742Slinton 	    oplen = optab[op].nargs;
256*5742Slinton 	    if (oplen < 0) {
257*5742Slinton 		oplen = (-oplen) - 1;
258*5742Slinton 	    } else  if (oplen > 0 && nextbyte != 0) {
259*5742Slinton 		oplen--;
260*5742Slinton 	    }
261*5742Slinton 	    oplen *= sizeof(int);
262*5742Slinton 	    switch (op) {
263*5742Slinton 		case O_BEG:
264*5742Slinton 		case O_NODUMP:
265*5742Slinton 		    oplen += 10;
266*5742Slinton 		    break;
267*5742Slinton 
268*5742Slinton 		case O_CON:
269*5742Slinton 		    oplen += ((nextbyte + 1)&~1);
270*5742Slinton 		    break;
271*5742Slinton 	    }
272*5742Slinton 	    addr += oplen;
273*5742Slinton #   endif
274*5742Slinton 	    break;
2755483Slinton 	}
276*5742Slinton     }
277*5742Slinton     return addr;
2785483Slinton }
2795483Slinton 
2805483Slinton /*
2815483Slinton  * Find the next address that will be executed after the
2825483Slinton  * case statement at the given address.
2835483Slinton  */
2845483Slinton 
2855483Slinton LOCAL ADDRESS docase(ncases, size, addr)
2865483Slinton int ncases;
2875483Slinton int size;
2885483Slinton ADDRESS addr;
2895483Slinton {
290*5742Slinton     register ADDRESS i;
291*5742Slinton     ADDRESS firstval, lastval, jmptable;
292*5742Slinton     short offset;
293*5742Slinton     long swtval, caseval;
2945483Slinton 
295*5742Slinton     stepto(addr - 2);
296*5742Slinton     if (ncases == 0) {
297*5742Slinton 	iread(&ncases, addr, sizeof(ncases));
298*5742Slinton 	addr += sizeof(short);
299*5742Slinton     }
300*5742Slinton     jmptable = addr;
301*5742Slinton     firstval = jmptable + ncases*sizeof(short);
302*5742Slinton     lastval = firstval + ncases*size;
303*5742Slinton     if (size <= 2) {
304*5742Slinton 	dread(&swtval, process->sp, 2);
305*5742Slinton     } else {
306*5742Slinton 	dread(&swtval, process->sp, size);
307*5742Slinton     }
308*5742Slinton     for (i = firstval; i < lastval; i += size) {
309*5742Slinton 	iread(&caseval, i, size);
310*5742Slinton 	if (cmp(&swtval, &caseval, size) == 0) {
311*5742Slinton 	    i = ((i - firstval) / size) * sizeof(offset);
312*5742Slinton 	    iread(&offset, jmptable + i, sizeof(offset));
313*5742Slinton 	    addr = jmptable + offset;
314*5742Slinton 	    return addr;
3155483Slinton 	}
316*5742Slinton     }
317*5742Slinton     return((lastval+1)&~1);
3185483Slinton }
3195483Slinton 
3205483Slinton LOCAL ADDRESS dofor(size, addr, subop, incr)
3215483Slinton int size;
3225483Slinton ADDRESS addr;
3235483Slinton short subop;
3245483Slinton int incr;
3255483Slinton {
326*5742Slinton     register PROCESS *p;
327*5742Slinton     long i, limit, lower;
328*5742Slinton     ADDRESS valaddr;
329*5742Slinton     short offset;
3305483Slinton 
331*5742Slinton     stepto(addr - sizeof(short));
332*5742Slinton     p = process;
333*5742Slinton     i = limit = 0;
334*5742Slinton     if (subop == 0) {
3355483Slinton 	addr += size;
336*5742Slinton     }
337*5742Slinton     dread(&valaddr, p->sp, sizeof(valaddr));
338*5742Slinton     dread(&i, valaddr, size);
339*5742Slinton     dread(&limit, p->sp + sizeof(valaddr), size);
340*5742Slinton     i += (incr << (8*(sizeof(i) - size)));
341*5742Slinton     addr += size;
3425483Slinton /*
3435483Slinton  * It is very slow to go through the loop again and again.
3445483Slinton  * So for the time being, we just skip to the end.
3455483Slinton  *
346*5742Slinton     if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) {
347*5742Slinton 	iread(&offset, addr, sizeof(offset));
348*5742Slinton 	return(addr + offset);
349*5742Slinton     } else {
3505483Slinton  */
351*5742Slinton 	return(addr + sizeof(short));
3525483Slinton /*
353*5742Slinton     }
3545483Slinton  */
3555483Slinton }
356