148101Sbostic /*-
2*62133Sbostic  * Copyright (c) 1980, 1993
3*62133Sbostic  *	The Regents of the University of California.  All rights reserved.
448101Sbostic  *
548101Sbostic  * %sccs.include.redist.c%
622363Sdist  */
75483Slinton 
822363Sdist #ifndef lint
9*62133Sbostic static char sccsid[] = "@(#)nextaddr.c	8.1 (Berkeley) 06/06/93";
1048101Sbostic #endif /* not lint */
1130845Smckusick 
125483Slinton /*
135483Slinton  * Calculate the next address that will be executed from the current one.
145483Slinton  *
155483Slinton  * If the next address depends on runtime data (e.g. a conditional
165483Slinton  * branch will depend on the value on top of the stack),
175483Slinton  * we must execute up to the given address with "stepto".
185483Slinton  *
195483Slinton  * If the second argument is TRUE, we treat a CALL instruction as
205483Slinton  * straight line rather than following it as a branch.
215483Slinton  */
225483Slinton 
235483Slinton #include "defs.h"
245483Slinton #include "machine.h"
255483Slinton #include "process.h"
265483Slinton #include "breakpoint.h"
275483Slinton #include "sym.h"
285483Slinton #include "pxops.h"
295483Slinton #include "optab.h"
305483Slinton #include "mappings.h"
315483Slinton #include "runtime.h"
325483Slinton #include "process/pxinfo.h"
335483Slinton #include "process/process.rep"
345483Slinton 
3530845Smckusick #ifdef tahoe
3630845Smckusick #define EVEN 3
3730845Smckusick #else
3830845Smckusick #define EVEN 1
3930845Smckusick #endif
4030845Smckusick 
415483Slinton LOCAL ADDRESS docase(), dofor();
425483Slinton 
nextaddr(beginaddr,isnext)435483Slinton ADDRESS nextaddr(beginaddr, isnext)
445483Slinton ADDRESS beginaddr;
455483Slinton BOOLEAN isnext;
465483Slinton {
475742Slinton     register PXOP op;
485742Slinton     ADDRESS addr;
495742Slinton     short offset;
505742Slinton     int nextbyte;
515742Slinton     SYM *s;
525742Slinton     union {
535742Slinton 	short word;
545742Slinton 	char byte[2];
555742Slinton     } o;
565483Slinton 
5730845Smckusick #ifdef tahoe
5830845Smckusick     doret(process);
5930845Smckusick #endif
605742Slinton     addr = beginaddr;
615742Slinton     iread(&o.word, addr, sizeof(o.word));
625742Slinton     op = (PXOP) o.byte[0];
635742Slinton     nextbyte = o.byte[1];
645742Slinton     addr += sizeof(short);
655742Slinton     switch(op) {
665483Slinton 
675742Slinton     /*
6830845Smckusick      * The version of px we are using assumes that the instruction
695742Slinton      * at the entry point of a function is a TRA4 to the beginning
705742Slinton      * of the block.
715742Slinton      */
725742Slinton 	case O_CALL: {
735742Slinton 	    ADDRESS eaddr;
745483Slinton 
755742Slinton 	    if (isnext) {
765742Slinton 		addr += sizeof(int);
7730845Smckusick #ifdef tahoe
7830845Smckusick 	        addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
7930845Smckusick #endif
805742Slinton 	    } else {
8130845Smckusick #ifdef tahoe
8230845Smckusick 		addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
8330845Smckusick #endif
8430845Smckusick 		iread(&eaddr, addr, sizeof(eaddr));
8530845Smckusick 		addr = eaddr + sizeof(short);
8630845Smckusick #ifdef tahoe
8730845Smckusick 		addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
8830845Smckusick #endif
8930845Smckusick 		iread(&addr, addr, sizeof(addr));
905742Slinton 		stepto(addr);
915742Slinton 		if (linelookup(addr) == 0) {
925742Slinton 		    bpact();
935742Slinton 		    addr = pc;
945483Slinton 		}
955742Slinton 		if (ss_lines && trcond()) {
965742Slinton 		    s = whatblock(addr);
975742Slinton 		    if (s == NIL) {
985742Slinton 			panic("bad call addr");
995742Slinton 		    }
1005742Slinton 		    printentry(s);
1015742Slinton 		}
1025742Slinton 	    }
1035742Slinton 	    break;
1045742Slinton 	}
1055483Slinton 
1065742Slinton 	case O_FCALL: {
1075742Slinton 	    ADDRESS eaddr;
1085742Slinton 	    ADDRESS *fparam;
1095483Slinton 
1105742Slinton 	    if (!isnext) {
1115742Slinton 		stepto(addr - sizeof(short));
11230845Smckusick #ifdef tahoe
11330845Smckusick 		doret(process);
11430845Smckusick #endif
1155742Slinton 		dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam));
1165742Slinton 		dread(&eaddr, fparam, sizeof(eaddr));
1175742Slinton 		addr = eaddr - ENDOFF;
1185742Slinton 		stepto(addr);
11930845Smckusick #ifdef tahoe
12030845Smckusick 		doret(process);
12130845Smckusick #endif
1225742Slinton 		if (linelookup(addr) == 0) {
1235742Slinton 		    bpact();
1245742Slinton 		    addr = pc;
1255483Slinton 		}
1265742Slinton 		if (ss_lines && trcond()) {
1275742Slinton 		    s = whatblock(addr);
1285742Slinton 		    if (s == NIL) {
1295742Slinton 			panic("bad call addr");
1305742Slinton 		    }
1315742Slinton 		    printentry(s);
1325742Slinton 		}
1335742Slinton 	    }
1345742Slinton 	    break;
1355742Slinton 	}
1365483Slinton 
1375742Slinton 	case O_END:
1385742Slinton 	    if ((addr - sizeof(short)) == lastaddr()) {
1395742Slinton 		stepto(addr - sizeof(short));
1405742Slinton 		endprogram();
1415742Slinton 	    } else {
1425742Slinton 		addr = return_addr();
1435742Slinton 		s = whatblock(pc);
1445742Slinton 		stepto(addr);
1455742Slinton 		if (ss_lines && trcond()) {
1465742Slinton 		    printexit(s);
1475742Slinton 		}
1485742Slinton 		if (linelookup(addr) == 0) {
1495742Slinton 		    bpact();
1505742Slinton 		    addr = pc;
1515742Slinton 		}
1525742Slinton 	    }
1535742Slinton 	    break;
1545483Slinton 
1555742Slinton 	case O_TRA4:
1565742Slinton 	case O_GOTO:
15730845Smckusick #ifdef tahoe
15830845Smckusick 	    addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
15930845Smckusick #endif
1605742Slinton 	    iread(&addr, addr, sizeof(addr));
1615742Slinton 	    break;
1625483Slinton 
1635742Slinton 	case O_TRA:
1645742Slinton 	    iread(&offset, addr, sizeof(offset));
1655742Slinton 	    addr += offset;
1665742Slinton 	    break;
1675483Slinton 
1685742Slinton 	case O_CON: {
1695742Slinton 	    short consize;
1705483Slinton 
1715742Slinton 	    if (nextbyte == 0) {
17230845Smckusick #ifdef tahoe
17330845Smckusick 	        addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
17430845Smckusick #endif
1755742Slinton 		iread(&consize, addr, sizeof(consize));
1765742Slinton 		addr += sizeof(consize);
1775742Slinton 	    } else {
1785742Slinton 		consize = nextbyte;
1795742Slinton 	    }
1805742Slinton 	    addr += consize;
1815742Slinton 	    break;
1825742Slinton 	}
1835483Slinton 
1845742Slinton 	case O_CASE1OP:
1855742Slinton 	    addr = docase(nextbyte, 1, addr);
1865742Slinton 	    break;
1875483Slinton 
1885742Slinton 	case O_CASE2OP:
1895742Slinton 	    addr = docase(nextbyte, 2, addr);
1905742Slinton 	    break;
1915483Slinton 
1925742Slinton 	case O_CASE4OP:
1935742Slinton 	    addr = docase(nextbyte, 4, addr);
1945742Slinton 	    break;
1955483Slinton 
1965742Slinton 	case O_FOR1U:
1975742Slinton 	    addr = dofor(2, addr, nextbyte, 1);
1985742Slinton 	    break;
1995483Slinton 
2005742Slinton 	case O_FOR2U:
2015742Slinton 	    addr = dofor(2, addr, nextbyte, 1);
2025742Slinton 	    break;
2035483Slinton 
2045742Slinton 	case O_FOR4U:
2055742Slinton 	    addr = dofor(4, addr, nextbyte, 1);
2065742Slinton 	    break;
2075483Slinton 
2085742Slinton 	case O_FOR1D:
2095742Slinton 	    addr = dofor(2, addr, nextbyte, -1);
2105742Slinton 	    break;
2115483Slinton 
2125742Slinton 	case O_FOR2D:
2135742Slinton 	    addr = dofor(2, addr, nextbyte, -1);
2145742Slinton 	    break;
2155483Slinton 
2165742Slinton 	case O_FOR4D:
2175742Slinton 	    addr = dofor(4, addr, nextbyte, -1);
2185742Slinton 	    break;
2195483Slinton 
2205742Slinton 	case O_IF:
2215742Slinton 	    stepto(addr - sizeof(short));
22230845Smckusick #ifdef tahoe
22330845Smckusick 	    doret(process);
22430845Smckusick 	    dread(&offset, process->sp+sizeof(int)-sizeof(offset), sizeof(offset));
22530845Smckusick #else
2265742Slinton 	    dread(&offset, process->sp, sizeof(offset));
22730845Smckusick #endif
2285742Slinton 	    if (offset == 0) {
2295742Slinton 		iread(&offset, addr, sizeof(offset));
2305742Slinton 		addr += offset;
2315742Slinton 	    } else {
2325742Slinton 		addr += sizeof(offset);
2335742Slinton 	    }
2345742Slinton 	    break;
2355483Slinton 
2365742Slinton 	default: {
2375742Slinton 	    int i;
2385483Slinton 
2395742Slinton 	    for (i = 0; optab[op].argtype[i] != 0; i++) {
2405742Slinton 		switch(optab[op].argtype[i]) {
2415742Slinton 		    case ADDR4:
2425742Slinton 		    case LWORD:
2435742Slinton 			addr += 4;
24430845Smckusick #ifdef tahoe
24530845Smckusick 		        addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
24630845Smckusick #endif
2475742Slinton 			break;
2485483Slinton 
2495742Slinton 		    case SUBOP:
2505742Slinton 			break;
2515483Slinton 
2525742Slinton 		    case ADDR2:
2535742Slinton 		    case HWORD:
2545742Slinton 		    case PSUBOP:
2555742Slinton 		    case DISP:
2565742Slinton 		    case VLEN:
2575742Slinton 			if (i != 0 || nextbyte == 0) {
2585742Slinton 			    addr += sizeof(short);
2595483Slinton 			}
2605742Slinton 			break;
2615483Slinton 
2625742Slinton 		    case STRING: {
2635742Slinton 			char c;
2645483Slinton 
2655742Slinton 			while (nextbyte > 0) {
2665742Slinton 			    iread(&c, addr, 1);
2675742Slinton 			    if (c == '\0') {
2685742Slinton 				break;
2695742Slinton 			    }
2705742Slinton 			    nextbyte--;
2715742Slinton 			    addr++;
2725483Slinton 			}
2735742Slinton 			addr++;
27430845Smckusick 		        addr = (ADDRESS)(((int)addr + EVEN) & ~EVEN);
2755483Slinton 			break;
2765742Slinton 		    }
2775742Slinton 
2785742Slinton 		    default:
2795742Slinton 			panic("bad argtype");
2805742Slinton 			/*NOTREACHED*/
2815483Slinton 		}
2825742Slinton 	    }
2835742Slinton 	    break;
2845483Slinton 	}
2855742Slinton     }
2865742Slinton     return addr;
2875483Slinton }
2885483Slinton 
2895483Slinton /*
2905483Slinton  * Find the next address that will be executed after the
2915483Slinton  * case statement at the given address.
2925483Slinton  */
2935483Slinton 
docase(ncases,size,addr)2945483Slinton LOCAL ADDRESS docase(ncases, size, addr)
2955483Slinton int ncases;
2965483Slinton int size;
2975483Slinton ADDRESS addr;
2985483Slinton {
2995742Slinton     register ADDRESS i;
3005742Slinton     ADDRESS firstval, lastval, jmptable;
3015742Slinton     short offset;
3025742Slinton     long swtval, caseval;
3035483Slinton 
3045742Slinton     stepto(addr - 2);
30530845Smckusick #ifdef tahoe
30630845Smckusick     doret(process);
30730845Smckusick #endif
3085742Slinton     if (ncases == 0) {
3095742Slinton 	iread(&ncases, addr, sizeof(ncases));
3105742Slinton 	addr += sizeof(short);
3115742Slinton     }
3125742Slinton     jmptable = addr;
3135742Slinton     firstval = jmptable + ncases*sizeof(short);
31430845Smckusick #ifdef tahoe
31530845Smckusick     if (size == 4) {
31630845Smckusick 	firstval = (ADDRESS)(((int)firstval + EVEN) & ~EVEN);
31730845Smckusick     }
31830845Smckusick #endif
3195742Slinton     lastval = firstval + ncases*size;
32030845Smckusick #ifdef tahoe
32130845Smckusick     if (size <= 4) {
32230845Smckusick 	dread(&swtval, process->sp, 4);
32330845Smckusick #else
3245742Slinton     if (size <= 2) {
3255742Slinton 	dread(&swtval, process->sp, 2);
32630845Smckusick #endif
3275742Slinton     } else {
3285742Slinton 	dread(&swtval, process->sp, size);
3295742Slinton     }
3305742Slinton     for (i = firstval; i < lastval; i += size) {
33130845Smckusick 	caseval = 0;
33230845Smckusick #ifdef tahoe
33330845Smckusick 	iread((char *)&caseval + sizeof caseval - size, i, size);
33430845Smckusick 	if (swtval == caseval)
33530845Smckusick #else
3365742Slinton 	iread(&caseval, i, size);
33730845Smckusick 	if (cmp(&swtval, &caseval, size) == 0)
33830845Smckusick #endif
33930845Smckusick 	{
3405742Slinton 	    i = ((i - firstval) / size) * sizeof(offset);
3415742Slinton 	    iread(&offset, jmptable + i, sizeof(offset));
3425742Slinton 	    addr = jmptable + offset;
3435742Slinton 	    return addr;
3445483Slinton 	}
3455742Slinton     }
3465742Slinton     return((lastval+1)&~1);
3475483Slinton }
3485483Slinton 
dofor(size,addr,subop,incr)3495483Slinton LOCAL ADDRESS dofor(size, addr, subop, incr)
3505483Slinton int size;
3515483Slinton ADDRESS addr;
3525483Slinton short subop;
3535483Slinton int incr;
3545483Slinton {
3555742Slinton     register PROCESS *p;
35630845Smckusick     long i, limit;
3575742Slinton     ADDRESS valaddr;
3585483Slinton 
3595742Slinton     stepto(addr - sizeof(short));
3605742Slinton     p = process;
36130845Smckusick #ifdef tahoe
36230845Smckusick     doret(p);
36330845Smckusick #endif
3645742Slinton     i = limit = 0;
3655742Slinton     if (subop == 0) {
36630845Smckusick 	dread(&subop, addr, sizeof (short));
36730845Smckusick 	addr += sizeof (short);
3685742Slinton     }
3695742Slinton     dread(&valaddr, p->sp, sizeof(valaddr));
37030845Smckusick #ifdef tahoe
37130845Smckusick     dread((char *)&i + sizeof i - size, valaddr, size);
37230845Smckusick #else
3735742Slinton     dread(&i, valaddr, size);
37430845Smckusick #endif
37530845Smckusick     dread(&limit, p->sp + sizeof(valaddr), sizeof limit);
37630845Smckusick     i += incr;
3775874Slinton 
3785483Slinton /*
3795483Slinton  * It is very slow to go through the loop again and again.
3805874Slinton  * If it is desired to just skip to the end, the next 4 lines
3815874Slinton  * should be skipped.
3825874Slinton  */
3835742Slinton     if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) {
38430845Smckusick 	return(addr + subop);
3855742Slinton     } else {
38630845Smckusick 	return(addr);
3875742Slinton     }
3885483Slinton }
3896080Slinton 
3906080Slinton /*
3916080Slinton  * Determine whether or not the given address corresponds to the
3926080Slinton  * end of a procedure.
3936080Slinton  */
3946080Slinton 
isendofproc(addr)3956080Slinton BOOLEAN isendofproc(addr)
3966080Slinton ADDRESS addr;
3976080Slinton {
3986080Slinton     PXOP op;
3996080Slinton 
4006080Slinton     iread(&op, addr, sizeof(op));
4016080Slinton     return (op == O_END);
4026080Slinton }
403