1*22363Sdist /*
2*22363Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22363Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22363Sdist  * specifies the terms and conditions for redistribution.
5*22363Sdist  */
65483Slinton 
7*22363Sdist #ifndef lint
8*22363Sdist static char sccsid[] = "@(#)nextaddr.c	5.1 (Berkeley) 06/06/85";
9*22363Sdist #endif not lint
105483Slinton /*
115483Slinton  * Calculate the next address that will be executed from the current one.
125483Slinton  *
135483Slinton  * If the next address depends on runtime data (e.g. a conditional
145483Slinton  * branch will depend on the value on top of the stack),
155483Slinton  * we must execute up to the given address with "stepto".
165483Slinton  *
175483Slinton  * If the second argument is TRUE, we treat a CALL instruction as
185483Slinton  * straight line rather than following it as a branch.
195483Slinton  */
205483Slinton 
215483Slinton #include "defs.h"
225483Slinton #include "machine.h"
235483Slinton #include "process.h"
245483Slinton #include "breakpoint.h"
255483Slinton #include "sym.h"
265483Slinton #include "pxops.h"
275483Slinton #include "optab.h"
285483Slinton #include "mappings.h"
295483Slinton #include "runtime.h"
305483Slinton #include "process/pxinfo.h"
315483Slinton #include "process/process.rep"
325483Slinton 
335483Slinton LOCAL ADDRESS docase(), dofor();
345483Slinton 
355483Slinton ADDRESS nextaddr(beginaddr, isnext)
365483Slinton ADDRESS beginaddr;
375483Slinton BOOLEAN isnext;
385483Slinton {
395742Slinton     register PXOP op;
405742Slinton     ADDRESS addr;
415742Slinton     short offset;
425742Slinton     int nextbyte;
435742Slinton     SYM *s;
445742Slinton     union {
455742Slinton 	short word;
465742Slinton 	char byte[2];
475742Slinton     } o;
485483Slinton 
495742Slinton     addr = beginaddr;
505742Slinton     iread(&o.word, addr, sizeof(o.word));
515742Slinton     op = (PXOP) o.byte[0];
525742Slinton     nextbyte = o.byte[1];
535742Slinton     addr += sizeof(short);
545742Slinton     switch(op) {
555483Slinton 
565742Slinton #   if (isvaxpx)
575742Slinton     /*
585742Slinton      * The version of px on the VAX assumes that the instruction
595742Slinton      * at the entry point of a function is a TRA4 to the beginning
605742Slinton      * of the block.
615742Slinton      */
625742Slinton #   endif
635742Slinton 	case O_CALL: {
645742Slinton 	    ADDRESS eaddr;
655483Slinton 
665742Slinton 	    if (isnext) {
675742Slinton 		addr += sizeof(int);
685742Slinton 	    } else {
695742Slinton #               if (isvaxpx)
705742Slinton 		    iread(&eaddr, addr, sizeof(eaddr));
715742Slinton 		    addr = eaddr + sizeof(short);
725742Slinton 		    iread(&addr, addr, sizeof(addr));
735742Slinton #               else
745742Slinton 		    iread(&offset, addr, sizeof(offset));
755742Slinton 		    addr += offset;
765742Slinton #               endif
775742Slinton 		stepto(addr);
785742Slinton 		if (linelookup(addr) == 0) {
795742Slinton 		    bpact();
805742Slinton 		    addr = pc;
815483Slinton 		}
825742Slinton 		if (ss_lines && trcond()) {
835742Slinton 		    s = whatblock(addr);
845742Slinton 		    if (s == NIL) {
855742Slinton 			panic("bad call addr");
865742Slinton 		    }
875742Slinton 		    printentry(s);
885742Slinton 		}
895742Slinton 	    }
905742Slinton 	    break;
915742Slinton 	}
925483Slinton 
935742Slinton #   if (isvaxpx)
945742Slinton 	case O_FCALL: {
955742Slinton 	    ADDRESS eaddr;
965742Slinton 	    ADDRESS *fparam;
975483Slinton 
985742Slinton 	    if (!isnext) {
995742Slinton 		stepto(addr - sizeof(short));
1005742Slinton 		dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam));
1015742Slinton 		dread(&eaddr, fparam, sizeof(eaddr));
1025742Slinton 		addr = eaddr - ENDOFF;
1035742Slinton 		stepto(addr);
1045742Slinton 		if (linelookup(addr) == 0) {
1055742Slinton 		    bpact();
1065742Slinton 		    addr = pc;
1075483Slinton 		}
1085742Slinton 		if (ss_lines && trcond()) {
1095742Slinton 		    s = whatblock(addr);
1105742Slinton 		    if (s == NIL) {
1115742Slinton 			panic("bad call addr");
1125742Slinton 		    }
1135742Slinton 		    printentry(s);
1145742Slinton 		}
1155742Slinton 	    }
1165742Slinton 	    break;
1175742Slinton 	}
1185742Slinton #   endif
1195483Slinton 
1205742Slinton 	case O_END:
1215742Slinton 	    if ((addr - sizeof(short)) == lastaddr()) {
1225742Slinton 		stepto(addr - sizeof(short));
1235742Slinton 		endprogram();
1245742Slinton 	    } else {
1255742Slinton 		addr = return_addr();
1265742Slinton 		s = whatblock(pc);
1275742Slinton 		stepto(addr);
1285742Slinton 		if (ss_lines && trcond()) {
1295742Slinton 		    printexit(s);
1305742Slinton 		}
1315742Slinton 		if (linelookup(addr) == 0) {
1325742Slinton 		    bpact();
1335742Slinton 		    addr = pc;
1345742Slinton 		}
1355742Slinton 	    }
1365742Slinton 	    break;
1375483Slinton 
1385742Slinton #   if (isvaxpx)
1395742Slinton 	case O_TRA4:
1405742Slinton 	case O_GOTO:
1415742Slinton 	    iread(&addr, addr, sizeof(addr));
1425742Slinton 	    break;
1435742Slinton #   endif
1445483Slinton 
1455742Slinton 	case O_TRA:
1465742Slinton 	    iread(&offset, addr, sizeof(offset));
1475742Slinton 	    addr += offset;
1485742Slinton 	    break;
1495483Slinton 
1505742Slinton 	case O_CON: {
1515742Slinton 	    short consize;
1525483Slinton 
1535742Slinton 	    if (nextbyte == 0) {
1545742Slinton 		iread(&consize, addr, sizeof(consize));
1555742Slinton 		addr += sizeof(consize);
1565742Slinton 	    } else {
1575742Slinton 		consize = nextbyte;
1585742Slinton 	    }
1595742Slinton 	    addr += consize;
1605742Slinton 	    break;
1615742Slinton 	}
1625483Slinton 
1635742Slinton 	case O_CASE1OP:
1645742Slinton 	    addr = docase(nextbyte, 1, addr);
1655742Slinton 	    break;
1665483Slinton 
1675742Slinton 	case O_CASE2OP:
1685742Slinton 	    addr = docase(nextbyte, 2, addr);
1695742Slinton 	    break;
1705483Slinton 
1715742Slinton 	case O_CASE4OP:
1725742Slinton 	    addr = docase(nextbyte, 4, addr);
1735742Slinton 	    break;
1745483Slinton 
1755742Slinton 	case O_FOR1U:
1765742Slinton 	    addr = dofor(2, addr, nextbyte, 1);
1775742Slinton 	    break;
1785483Slinton 
1795742Slinton 	case O_FOR2U:
1805742Slinton 	    addr = dofor(2, addr, nextbyte, 1);
1815742Slinton 	    break;
1825483Slinton 
1835742Slinton 	case O_FOR4U:
1845742Slinton 	    addr = dofor(4, addr, nextbyte, 1);
1855742Slinton 	    break;
1865483Slinton 
1875742Slinton 	case O_FOR1D:
1885742Slinton 	    addr = dofor(2, addr, nextbyte, -1);
1895742Slinton 	    break;
1905483Slinton 
1915742Slinton 	case O_FOR2D:
1925742Slinton 	    addr = dofor(2, addr, nextbyte, -1);
1935742Slinton 	    break;
1945483Slinton 
1955742Slinton 	case O_FOR4D:
1965742Slinton 	    addr = dofor(4, addr, nextbyte, -1);
1975742Slinton 	    break;
1985483Slinton 
1995742Slinton 	case O_IF:
2005742Slinton 	    stepto(addr - sizeof(short));
2015742Slinton 	    dread(&offset, process->sp, sizeof(offset));
2025742Slinton 	    if (offset == 0) {
2035742Slinton 		iread(&offset, addr, sizeof(offset));
2045742Slinton 		addr += offset;
2055742Slinton 	    } else {
2065742Slinton 		addr += sizeof(offset);
2075742Slinton 	    }
2085742Slinton 	    break;
2095483Slinton 
2105742Slinton 	default: {
2115742Slinton #   if (isvaxpx)
2125742Slinton 	    int i;
2135483Slinton 
2145742Slinton 	    for (i = 0; optab[op].argtype[i] != 0; i++) {
2155742Slinton 		switch(optab[op].argtype[i]) {
2165742Slinton 		    case ADDR4:
2175742Slinton 		    case LWORD:
2185742Slinton 			addr += 4;
2195742Slinton 			break;
2205483Slinton 
2215742Slinton 		    case SUBOP:
2225742Slinton 			break;
2235483Slinton 
2245742Slinton 		    case ADDR2:
2255742Slinton 		    case HWORD:
2265742Slinton 		    case PSUBOP:
2275742Slinton 		    case DISP:
2285742Slinton 		    case VLEN:
2295742Slinton 			if (i != 0 || nextbyte == 0) {
2305742Slinton 			    addr += sizeof(short);
2315483Slinton 			}
2325742Slinton 			break;
2335483Slinton 
2345742Slinton 		    case STRING: {
2355742Slinton 			char c;
2365483Slinton 
2375742Slinton 			while (nextbyte > 0) {
2385742Slinton 			    iread(&c, addr, 1);
2395742Slinton 			    if (c == '\0') {
2405742Slinton 				break;
2415742Slinton 			    }
2425742Slinton 			    nextbyte--;
2435742Slinton 			    addr++;
2445483Slinton 			}
2455742Slinton 			addr++;
2465742Slinton 			if ((addr&1) != 0) {
2475742Slinton 			    addr++;
2485742Slinton 			}
2495483Slinton 			break;
2505742Slinton 		    }
2515742Slinton 
2525742Slinton 		    default:
2535742Slinton 			panic("bad argtype");
2545742Slinton 			/*NOTREACHED*/
2555483Slinton 		}
2565742Slinton 	    }
2575742Slinton #   else
2585742Slinton 	    int oplen;
2595742Slinton 
2605742Slinton 	    oplen = optab[op].nargs;
2615742Slinton 	    if (oplen < 0) {
2625742Slinton 		oplen = (-oplen) - 1;
2635742Slinton 	    } else  if (oplen > 0 && nextbyte != 0) {
2645742Slinton 		oplen--;
2655742Slinton 	    }
2665742Slinton 	    oplen *= sizeof(int);
2675742Slinton 	    switch (op) {
2685742Slinton 		case O_BEG:
2695742Slinton 		case O_NODUMP:
2705742Slinton 		    oplen += 10;
2715742Slinton 		    break;
2725742Slinton 
2735742Slinton 		case O_CON:
2745742Slinton 		    oplen += ((nextbyte + 1)&~1);
2755742Slinton 		    break;
2765742Slinton 	    }
2775742Slinton 	    addr += oplen;
2785742Slinton #   endif
2795742Slinton 	    break;
2805483Slinton 	}
2815742Slinton     }
2825742Slinton     return addr;
2835483Slinton }
2845483Slinton 
2855483Slinton /*
2865483Slinton  * Find the next address that will be executed after the
2875483Slinton  * case statement at the given address.
2885483Slinton  */
2895483Slinton 
2905483Slinton LOCAL ADDRESS docase(ncases, size, addr)
2915483Slinton int ncases;
2925483Slinton int size;
2935483Slinton ADDRESS addr;
2945483Slinton {
2955742Slinton     register ADDRESS i;
2965742Slinton     ADDRESS firstval, lastval, jmptable;
2975742Slinton     short offset;
2985742Slinton     long swtval, caseval;
2995483Slinton 
3005742Slinton     stepto(addr - 2);
3015742Slinton     if (ncases == 0) {
3025742Slinton 	iread(&ncases, addr, sizeof(ncases));
3035742Slinton 	addr += sizeof(short);
3045742Slinton     }
3055742Slinton     jmptable = addr;
3065742Slinton     firstval = jmptable + ncases*sizeof(short);
3075742Slinton     lastval = firstval + ncases*size;
3085742Slinton     if (size <= 2) {
3095742Slinton 	dread(&swtval, process->sp, 2);
3105742Slinton     } else {
3115742Slinton 	dread(&swtval, process->sp, size);
3125742Slinton     }
3135742Slinton     for (i = firstval; i < lastval; i += size) {
3145742Slinton 	iread(&caseval, i, size);
3155742Slinton 	if (cmp(&swtval, &caseval, size) == 0) {
3165742Slinton 	    i = ((i - firstval) / size) * sizeof(offset);
3175742Slinton 	    iread(&offset, jmptable + i, sizeof(offset));
3185742Slinton 	    addr = jmptable + offset;
3195742Slinton 	    return addr;
3205483Slinton 	}
3215742Slinton     }
3225742Slinton     return((lastval+1)&~1);
3235483Slinton }
3245483Slinton 
3255483Slinton LOCAL ADDRESS dofor(size, addr, subop, incr)
3265483Slinton int size;
3275483Slinton ADDRESS addr;
3285483Slinton short subop;
3295483Slinton int incr;
3305483Slinton {
3315742Slinton     register PROCESS *p;
3325742Slinton     long i, limit, lower;
3335742Slinton     ADDRESS valaddr;
3345742Slinton     short offset;
3355483Slinton 
3365742Slinton     stepto(addr - sizeof(short));
3375742Slinton     p = process;
3385742Slinton     i = limit = 0;
3395742Slinton     if (subop == 0) {
3405483Slinton 	addr += size;
3415742Slinton     }
3425742Slinton     dread(&valaddr, p->sp, sizeof(valaddr));
3435742Slinton     dread(&i, valaddr, size);
3445742Slinton     dread(&limit, p->sp + sizeof(valaddr), size);
3455742Slinton     i += (incr << (8*(sizeof(i) - size)));
3465742Slinton     addr += size;
3475874Slinton 
3485483Slinton /*
3495483Slinton  * It is very slow to go through the loop again and again.
3505874Slinton  * If it is desired to just skip to the end, the next 4 lines
3515874Slinton  * should be skipped.
3525874Slinton  */
3535742Slinton     if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) {
3545742Slinton 	iread(&offset, addr, sizeof(offset));
3555742Slinton 	return(addr + offset);
3565742Slinton     } else {
3575742Slinton 	return(addr + sizeof(short));
3585742Slinton     }
3595483Slinton }
3606080Slinton 
3616080Slinton /*
3626080Slinton  * Determine whether or not the given address corresponds to the
3636080Slinton  * end of a procedure.
3646080Slinton  */
3656080Slinton 
3666080Slinton BOOLEAN isendofproc(addr)
3676080Slinton ADDRESS addr;
3686080Slinton {
3696080Slinton     PXOP op;
3706080Slinton 
3716080Slinton     iread(&op, addr, sizeof(op));
3726080Slinton     return (op == O_END);
3736080Slinton }
374