122363Sdist /*
222363Sdist  * Copyright (c) 1980 Regents of the University of California.
322363Sdist  * All rights reserved.  The Berkeley software License Agreement
422363Sdist  * specifies the terms and conditions for redistribution.
522363Sdist  */
65483Slinton 
722363Sdist #ifndef lint
8*30845Smckusick static char sccsid[] = "@(#)nextaddr.c	5.2 (Berkeley) 04/07/87";
922363Sdist #endif not lint
10*30845Smckusick 
115483Slinton /*
125483Slinton  * Calculate the next address that will be executed from the current one.
135483Slinton  *
145483Slinton  * If the next address depends on runtime data (e.g. a conditional
155483Slinton  * branch will depend on the value on top of the stack),
165483Slinton  * we must execute up to the given address with "stepto".
175483Slinton  *
185483Slinton  * If the second argument is TRUE, we treat a CALL instruction as
195483Slinton  * straight line rather than following it as a branch.
205483Slinton  */
215483Slinton 
225483Slinton #include "defs.h"
235483Slinton #include "machine.h"
245483Slinton #include "process.h"
255483Slinton #include "breakpoint.h"
265483Slinton #include "sym.h"
275483Slinton #include "pxops.h"
285483Slinton #include "optab.h"
295483Slinton #include "mappings.h"
305483Slinton #include "runtime.h"
315483Slinton #include "process/pxinfo.h"
325483Slinton #include "process/process.rep"
335483Slinton 
34*30845Smckusick #ifdef tahoe
35*30845Smckusick #define EVEN 3
36*30845Smckusick #else
37*30845Smckusick #define EVEN 1
38*30845Smckusick #endif
39*30845Smckusick 
405483Slinton LOCAL ADDRESS docase(), dofor();
415483Slinton 
425483Slinton ADDRESS nextaddr(beginaddr, isnext)
435483Slinton ADDRESS beginaddr;
445483Slinton BOOLEAN isnext;
455483Slinton {
465742Slinton     register PXOP op;
475742Slinton     ADDRESS addr;
485742Slinton     short offset;
495742Slinton     int nextbyte;
505742Slinton     SYM *s;
515742Slinton     union {
525742Slinton 	short word;
535742Slinton 	char byte[2];
545742Slinton     } o;
555483Slinton 
56*30845Smckusick #ifdef tahoe
57*30845Smckusick     doret(process);
58*30845Smckusick #endif
595742Slinton     addr = beginaddr;
605742Slinton     iread(&o.word, addr, sizeof(o.word));
615742Slinton     op = (PXOP) o.byte[0];
625742Slinton     nextbyte = o.byte[1];
635742Slinton     addr += sizeof(short);
645742Slinton     switch(op) {
655483Slinton 
665742Slinton     /*
67*30845Smckusick      * The version of px we are using assumes that the instruction
685742Slinton      * at the entry point of a function is a TRA4 to the beginning
695742Slinton      * of the block.
705742Slinton      */
715742Slinton 	case O_CALL: {
725742Slinton 	    ADDRESS eaddr;
735483Slinton 
745742Slinton 	    if (isnext) {
755742Slinton 		addr += sizeof(int);
76*30845Smckusick #ifdef tahoe
77*30845Smckusick 	        addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
78*30845Smckusick #endif
795742Slinton 	    } else {
80*30845Smckusick #ifdef tahoe
81*30845Smckusick 		addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
82*30845Smckusick #endif
83*30845Smckusick 		iread(&eaddr, addr, sizeof(eaddr));
84*30845Smckusick 		addr = eaddr + sizeof(short);
85*30845Smckusick #ifdef tahoe
86*30845Smckusick 		addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
87*30845Smckusick #endif
88*30845Smckusick 		iread(&addr, addr, sizeof(addr));
895742Slinton 		stepto(addr);
905742Slinton 		if (linelookup(addr) == 0) {
915742Slinton 		    bpact();
925742Slinton 		    addr = pc;
935483Slinton 		}
945742Slinton 		if (ss_lines && trcond()) {
955742Slinton 		    s = whatblock(addr);
965742Slinton 		    if (s == NIL) {
975742Slinton 			panic("bad call addr");
985742Slinton 		    }
995742Slinton 		    printentry(s);
1005742Slinton 		}
1015742Slinton 	    }
1025742Slinton 	    break;
1035742Slinton 	}
1045483Slinton 
1055742Slinton 	case O_FCALL: {
1065742Slinton 	    ADDRESS eaddr;
1075742Slinton 	    ADDRESS *fparam;
1085483Slinton 
1095742Slinton 	    if (!isnext) {
1105742Slinton 		stepto(addr - sizeof(short));
111*30845Smckusick #ifdef tahoe
112*30845Smckusick 		doret(process);
113*30845Smckusick #endif
1145742Slinton 		dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam));
1155742Slinton 		dread(&eaddr, fparam, sizeof(eaddr));
1165742Slinton 		addr = eaddr - ENDOFF;
1175742Slinton 		stepto(addr);
118*30845Smckusick #ifdef tahoe
119*30845Smckusick 		doret(process);
120*30845Smckusick #endif
1215742Slinton 		if (linelookup(addr) == 0) {
1225742Slinton 		    bpact();
1235742Slinton 		    addr = pc;
1245483Slinton 		}
1255742Slinton 		if (ss_lines && trcond()) {
1265742Slinton 		    s = whatblock(addr);
1275742Slinton 		    if (s == NIL) {
1285742Slinton 			panic("bad call addr");
1295742Slinton 		    }
1305742Slinton 		    printentry(s);
1315742Slinton 		}
1325742Slinton 	    }
1335742Slinton 	    break;
1345742Slinton 	}
1355483Slinton 
1365742Slinton 	case O_END:
1375742Slinton 	    if ((addr - sizeof(short)) == lastaddr()) {
1385742Slinton 		stepto(addr - sizeof(short));
1395742Slinton 		endprogram();
1405742Slinton 	    } else {
1415742Slinton 		addr = return_addr();
1425742Slinton 		s = whatblock(pc);
1435742Slinton 		stepto(addr);
1445742Slinton 		if (ss_lines && trcond()) {
1455742Slinton 		    printexit(s);
1465742Slinton 		}
1475742Slinton 		if (linelookup(addr) == 0) {
1485742Slinton 		    bpact();
1495742Slinton 		    addr = pc;
1505742Slinton 		}
1515742Slinton 	    }
1525742Slinton 	    break;
1535483Slinton 
1545742Slinton 	case O_TRA4:
1555742Slinton 	case O_GOTO:
156*30845Smckusick #ifdef tahoe
157*30845Smckusick 	    addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
158*30845Smckusick #endif
1595742Slinton 	    iread(&addr, addr, sizeof(addr));
1605742Slinton 	    break;
1615483Slinton 
1625742Slinton 	case O_TRA:
1635742Slinton 	    iread(&offset, addr, sizeof(offset));
1645742Slinton 	    addr += offset;
1655742Slinton 	    break;
1665483Slinton 
1675742Slinton 	case O_CON: {
1685742Slinton 	    short consize;
1695483Slinton 
1705742Slinton 	    if (nextbyte == 0) {
171*30845Smckusick #ifdef tahoe
172*30845Smckusick 	        addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
173*30845Smckusick #endif
1745742Slinton 		iread(&consize, addr, sizeof(consize));
1755742Slinton 		addr += sizeof(consize);
1765742Slinton 	    } else {
1775742Slinton 		consize = nextbyte;
1785742Slinton 	    }
1795742Slinton 	    addr += consize;
1805742Slinton 	    break;
1815742Slinton 	}
1825483Slinton 
1835742Slinton 	case O_CASE1OP:
1845742Slinton 	    addr = docase(nextbyte, 1, addr);
1855742Slinton 	    break;
1865483Slinton 
1875742Slinton 	case O_CASE2OP:
1885742Slinton 	    addr = docase(nextbyte, 2, addr);
1895742Slinton 	    break;
1905483Slinton 
1915742Slinton 	case O_CASE4OP:
1925742Slinton 	    addr = docase(nextbyte, 4, addr);
1935742Slinton 	    break;
1945483Slinton 
1955742Slinton 	case O_FOR1U:
1965742Slinton 	    addr = dofor(2, addr, nextbyte, 1);
1975742Slinton 	    break;
1985483Slinton 
1995742Slinton 	case O_FOR2U:
2005742Slinton 	    addr = dofor(2, addr, nextbyte, 1);
2015742Slinton 	    break;
2025483Slinton 
2035742Slinton 	case O_FOR4U:
2045742Slinton 	    addr = dofor(4, addr, nextbyte, 1);
2055742Slinton 	    break;
2065483Slinton 
2075742Slinton 	case O_FOR1D:
2085742Slinton 	    addr = dofor(2, addr, nextbyte, -1);
2095742Slinton 	    break;
2105483Slinton 
2115742Slinton 	case O_FOR2D:
2125742Slinton 	    addr = dofor(2, addr, nextbyte, -1);
2135742Slinton 	    break;
2145483Slinton 
2155742Slinton 	case O_FOR4D:
2165742Slinton 	    addr = dofor(4, addr, nextbyte, -1);
2175742Slinton 	    break;
2185483Slinton 
2195742Slinton 	case O_IF:
2205742Slinton 	    stepto(addr - sizeof(short));
221*30845Smckusick #ifdef tahoe
222*30845Smckusick 	    doret(process);
223*30845Smckusick 	    dread(&offset, process->sp+sizeof(int)-sizeof(offset), sizeof(offset));
224*30845Smckusick #else
2255742Slinton 	    dread(&offset, process->sp, sizeof(offset));
226*30845Smckusick #endif
2275742Slinton 	    if (offset == 0) {
2285742Slinton 		iread(&offset, addr, sizeof(offset));
2295742Slinton 		addr += offset;
2305742Slinton 	    } else {
2315742Slinton 		addr += sizeof(offset);
2325742Slinton 	    }
2335742Slinton 	    break;
2345483Slinton 
2355742Slinton 	default: {
2365742Slinton 	    int i;
2375483Slinton 
2385742Slinton 	    for (i = 0; optab[op].argtype[i] != 0; i++) {
2395742Slinton 		switch(optab[op].argtype[i]) {
2405742Slinton 		    case ADDR4:
2415742Slinton 		    case LWORD:
2425742Slinton 			addr += 4;
243*30845Smckusick #ifdef tahoe
244*30845Smckusick 		        addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
245*30845Smckusick #endif
2465742Slinton 			break;
2475483Slinton 
2485742Slinton 		    case SUBOP:
2495742Slinton 			break;
2505483Slinton 
2515742Slinton 		    case ADDR2:
2525742Slinton 		    case HWORD:
2535742Slinton 		    case PSUBOP:
2545742Slinton 		    case DISP:
2555742Slinton 		    case VLEN:
2565742Slinton 			if (i != 0 || nextbyte == 0) {
2575742Slinton 			    addr += sizeof(short);
2585483Slinton 			}
2595742Slinton 			break;
2605483Slinton 
2615742Slinton 		    case STRING: {
2625742Slinton 			char c;
2635483Slinton 
2645742Slinton 			while (nextbyte > 0) {
2655742Slinton 			    iread(&c, addr, 1);
2665742Slinton 			    if (c == '\0') {
2675742Slinton 				break;
2685742Slinton 			    }
2695742Slinton 			    nextbyte--;
2705742Slinton 			    addr++;
2715483Slinton 			}
2725742Slinton 			addr++;
273*30845Smckusick 		        addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
2745483Slinton 			break;
2755742Slinton 		    }
2765742Slinton 
2775742Slinton 		    default:
2785742Slinton 			panic("bad argtype");
2795742Slinton 			/*NOTREACHED*/
2805483Slinton 		}
2815742Slinton 	    }
2825742Slinton 	    break;
2835483Slinton 	}
2845742Slinton     }
2855742Slinton     return addr;
2865483Slinton }
2875483Slinton 
2885483Slinton /*
2895483Slinton  * Find the next address that will be executed after the
2905483Slinton  * case statement at the given address.
2915483Slinton  */
2925483Slinton 
2935483Slinton LOCAL ADDRESS docase(ncases, size, addr)
2945483Slinton int ncases;
2955483Slinton int size;
2965483Slinton ADDRESS addr;
2975483Slinton {
2985742Slinton     register ADDRESS i;
2995742Slinton     ADDRESS firstval, lastval, jmptable;
3005742Slinton     short offset;
3015742Slinton     long swtval, caseval;
3025483Slinton 
3035742Slinton     stepto(addr - 2);
304*30845Smckusick #ifdef tahoe
305*30845Smckusick     doret(process);
306*30845Smckusick #endif
3075742Slinton     if (ncases == 0) {
3085742Slinton 	iread(&ncases, addr, sizeof(ncases));
3095742Slinton 	addr += sizeof(short);
3105742Slinton     }
3115742Slinton     jmptable = addr;
3125742Slinton     firstval = jmptable + ncases*sizeof(short);
313*30845Smckusick #ifdef tahoe
314*30845Smckusick     if (size == 4) {
315*30845Smckusick 	firstval = (ADDRESS)(((int)firstval + EVEN) & ~EVEN);
316*30845Smckusick     }
317*30845Smckusick #endif
3185742Slinton     lastval = firstval + ncases*size;
319*30845Smckusick #ifdef tahoe
320*30845Smckusick     if (size <= 4) {
321*30845Smckusick 	dread(&swtval, process->sp, 4);
322*30845Smckusick #else
3235742Slinton     if (size <= 2) {
3245742Slinton 	dread(&swtval, process->sp, 2);
325*30845Smckusick #endif
3265742Slinton     } else {
3275742Slinton 	dread(&swtval, process->sp, size);
3285742Slinton     }
3295742Slinton     for (i = firstval; i < lastval; i += size) {
330*30845Smckusick 	caseval = 0;
331*30845Smckusick #ifdef tahoe
332*30845Smckusick 	iread((char *)&caseval + sizeof caseval - size, i, size);
333*30845Smckusick 	if (swtval == caseval)
334*30845Smckusick #else
3355742Slinton 	iread(&caseval, i, size);
336*30845Smckusick 	if (cmp(&swtval, &caseval, size) == 0)
337*30845Smckusick #endif
338*30845Smckusick 	{
3395742Slinton 	    i = ((i - firstval) / size) * sizeof(offset);
3405742Slinton 	    iread(&offset, jmptable + i, sizeof(offset));
3415742Slinton 	    addr = jmptable + offset;
3425742Slinton 	    return addr;
3435483Slinton 	}
3445742Slinton     }
3455742Slinton     return((lastval+1)&~1);
3465483Slinton }
3475483Slinton 
3485483Slinton LOCAL ADDRESS dofor(size, addr, subop, incr)
3495483Slinton int size;
3505483Slinton ADDRESS addr;
3515483Slinton short subop;
3525483Slinton int incr;
3535483Slinton {
3545742Slinton     register PROCESS *p;
355*30845Smckusick     long i, limit;
3565742Slinton     ADDRESS valaddr;
3575483Slinton 
3585742Slinton     stepto(addr - sizeof(short));
3595742Slinton     p = process;
360*30845Smckusick #ifdef tahoe
361*30845Smckusick     doret(p);
362*30845Smckusick #endif
3635742Slinton     i = limit = 0;
3645742Slinton     if (subop == 0) {
365*30845Smckusick 	dread(&subop, addr, sizeof (short));
366*30845Smckusick 	addr += sizeof (short);
3675742Slinton     }
3685742Slinton     dread(&valaddr, p->sp, sizeof(valaddr));
369*30845Smckusick #ifdef tahoe
370*30845Smckusick     dread((char *)&i + sizeof i - size, valaddr, size);
371*30845Smckusick #else
3725742Slinton     dread(&i, valaddr, size);
373*30845Smckusick #endif
374*30845Smckusick     dread(&limit, p->sp + sizeof(valaddr), sizeof limit);
375*30845Smckusick     i += incr;
3765874Slinton 
3775483Slinton /*
3785483Slinton  * It is very slow to go through the loop again and again.
3795874Slinton  * If it is desired to just skip to the end, the next 4 lines
3805874Slinton  * should be skipped.
3815874Slinton  */
3825742Slinton     if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) {
383*30845Smckusick 	return(addr + subop);
3845742Slinton     } else {
385*30845Smckusick 	return(addr);
3865742Slinton     }
3875483Slinton }
3886080Slinton 
3896080Slinton /*
3906080Slinton  * Determine whether or not the given address corresponds to the
3916080Slinton  * end of a procedure.
3926080Slinton  */
3936080Slinton 
3946080Slinton BOOLEAN isendofproc(addr)
3956080Slinton ADDRESS addr;
3966080Slinton {
3976080Slinton     PXOP op;
3986080Slinton 
3996080Slinton     iread(&op, addr, sizeof(op));
4006080Slinton     return (op == O_END);
4016080Slinton }
402