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