15483Slinton /* Copyright (c) 1982 Regents of the University of California */ 25483Slinton 3*6080Slinton static char sccsid[] = "@(#)nextaddr.c 1.4 03/08/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 { 345742Slinton register PXOP op; 355742Slinton ADDRESS addr; 365742Slinton short offset; 375742Slinton int nextbyte; 385742Slinton SYM *s; 395742Slinton union { 405742Slinton short word; 415742Slinton char byte[2]; 425742Slinton } o; 435483Slinton 445742Slinton addr = beginaddr; 455742Slinton iread(&o.word, addr, sizeof(o.word)); 465742Slinton op = (PXOP) o.byte[0]; 475742Slinton nextbyte = o.byte[1]; 485742Slinton addr += sizeof(short); 495742Slinton switch(op) { 505483Slinton 515742Slinton # if (isvaxpx) 525742Slinton /* 535742Slinton * The version of px on the VAX assumes that the instruction 545742Slinton * at the entry point of a function is a TRA4 to the beginning 555742Slinton * of the block. 565742Slinton */ 575742Slinton # endif 585742Slinton case O_CALL: { 595742Slinton ADDRESS eaddr; 605483Slinton 615742Slinton if (isnext) { 625742Slinton addr += sizeof(int); 635742Slinton } else { 645742Slinton # if (isvaxpx) 655742Slinton iread(&eaddr, addr, sizeof(eaddr)); 665742Slinton addr = eaddr + sizeof(short); 675742Slinton iread(&addr, addr, sizeof(addr)); 685742Slinton # else 695742Slinton iread(&offset, addr, sizeof(offset)); 705742Slinton addr += offset; 715742Slinton # endif 725742Slinton stepto(addr); 735742Slinton if (linelookup(addr) == 0) { 745742Slinton bpact(); 755742Slinton addr = pc; 765483Slinton } 775742Slinton if (ss_lines && trcond()) { 785742Slinton s = whatblock(addr); 795742Slinton if (s == NIL) { 805742Slinton panic("bad call addr"); 815742Slinton } 825742Slinton printentry(s); 835742Slinton } 845742Slinton } 855742Slinton break; 865742Slinton } 875483Slinton 885742Slinton # if (isvaxpx) 895742Slinton case O_FCALL: { 905742Slinton ADDRESS eaddr; 915742Slinton ADDRESS *fparam; 925483Slinton 935742Slinton if (!isnext) { 945742Slinton stepto(addr - sizeof(short)); 955742Slinton dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam)); 965742Slinton dread(&eaddr, fparam, sizeof(eaddr)); 975742Slinton addr = eaddr - ENDOFF; 985742Slinton stepto(addr); 995742Slinton if (linelookup(addr) == 0) { 1005742Slinton bpact(); 1015742Slinton addr = pc; 1025483Slinton } 1035742Slinton if (ss_lines && trcond()) { 1045742Slinton s = whatblock(addr); 1055742Slinton if (s == NIL) { 1065742Slinton panic("bad call addr"); 1075742Slinton } 1085742Slinton printentry(s); 1095742Slinton } 1105742Slinton } 1115742Slinton break; 1125742Slinton } 1135742Slinton # endif 1145483Slinton 1155742Slinton case O_END: 1165742Slinton if ((addr - sizeof(short)) == lastaddr()) { 1175742Slinton stepto(addr - sizeof(short)); 1185742Slinton endprogram(); 1195742Slinton } else { 1205742Slinton addr = return_addr(); 1215742Slinton s = whatblock(pc); 1225742Slinton stepto(addr); 1235742Slinton if (ss_lines && trcond()) { 1245742Slinton printexit(s); 1255742Slinton } 1265742Slinton if (linelookup(addr) == 0) { 1275742Slinton bpact(); 1285742Slinton addr = pc; 1295742Slinton } 1305742Slinton } 1315742Slinton break; 1325483Slinton 1335742Slinton # if (isvaxpx) 1345742Slinton case O_TRA4: 1355742Slinton case O_GOTO: 1365742Slinton iread(&addr, addr, sizeof(addr)); 1375742Slinton break; 1385742Slinton # endif 1395483Slinton 1405742Slinton case O_TRA: 1415742Slinton iread(&offset, addr, sizeof(offset)); 1425742Slinton addr += offset; 1435742Slinton break; 1445483Slinton 1455742Slinton case O_CON: { 1465742Slinton short consize; 1475483Slinton 1485742Slinton if (nextbyte == 0) { 1495742Slinton iread(&consize, addr, sizeof(consize)); 1505742Slinton addr += sizeof(consize); 1515742Slinton } else { 1525742Slinton consize = nextbyte; 1535742Slinton } 1545742Slinton addr += consize; 1555742Slinton break; 1565742Slinton } 1575483Slinton 1585742Slinton case O_CASE1OP: 1595742Slinton addr = docase(nextbyte, 1, addr); 1605742Slinton break; 1615483Slinton 1625742Slinton case O_CASE2OP: 1635742Slinton addr = docase(nextbyte, 2, addr); 1645742Slinton break; 1655483Slinton 1665742Slinton case O_CASE4OP: 1675742Slinton addr = docase(nextbyte, 4, addr); 1685742Slinton break; 1695483Slinton 1705742Slinton case O_FOR1U: 1715742Slinton addr = dofor(2, addr, nextbyte, 1); 1725742Slinton break; 1735483Slinton 1745742Slinton case O_FOR2U: 1755742Slinton addr = dofor(2, addr, nextbyte, 1); 1765742Slinton break; 1775483Slinton 1785742Slinton case O_FOR4U: 1795742Slinton addr = dofor(4, addr, nextbyte, 1); 1805742Slinton break; 1815483Slinton 1825742Slinton case O_FOR1D: 1835742Slinton addr = dofor(2, addr, nextbyte, -1); 1845742Slinton break; 1855483Slinton 1865742Slinton case O_FOR2D: 1875742Slinton addr = dofor(2, addr, nextbyte, -1); 1885742Slinton break; 1895483Slinton 1905742Slinton case O_FOR4D: 1915742Slinton addr = dofor(4, addr, nextbyte, -1); 1925742Slinton break; 1935483Slinton 1945742Slinton case O_IF: 1955742Slinton stepto(addr - sizeof(short)); 1965742Slinton dread(&offset, process->sp, sizeof(offset)); 1975742Slinton if (offset == 0) { 1985742Slinton iread(&offset, addr, sizeof(offset)); 1995742Slinton addr += offset; 2005742Slinton } else { 2015742Slinton addr += sizeof(offset); 2025742Slinton } 2035742Slinton break; 2045483Slinton 2055742Slinton default: { 2065742Slinton # if (isvaxpx) 2075742Slinton int i; 2085483Slinton 2095742Slinton for (i = 0; optab[op].argtype[i] != 0; i++) { 2105742Slinton switch(optab[op].argtype[i]) { 2115742Slinton case ADDR4: 2125742Slinton case LWORD: 2135742Slinton addr += 4; 2145742Slinton break; 2155483Slinton 2165742Slinton case SUBOP: 2175742Slinton break; 2185483Slinton 2195742Slinton case ADDR2: 2205742Slinton case HWORD: 2215742Slinton case PSUBOP: 2225742Slinton case DISP: 2235742Slinton case VLEN: 2245742Slinton if (i != 0 || nextbyte == 0) { 2255742Slinton addr += sizeof(short); 2265483Slinton } 2275742Slinton break; 2285483Slinton 2295742Slinton case STRING: { 2305742Slinton char c; 2315483Slinton 2325742Slinton while (nextbyte > 0) { 2335742Slinton iread(&c, addr, 1); 2345742Slinton if (c == '\0') { 2355742Slinton break; 2365742Slinton } 2375742Slinton nextbyte--; 2385742Slinton addr++; 2395483Slinton } 2405742Slinton addr++; 2415742Slinton if ((addr&1) != 0) { 2425742Slinton addr++; 2435742Slinton } 2445483Slinton break; 2455742Slinton } 2465742Slinton 2475742Slinton default: 2485742Slinton panic("bad argtype"); 2495742Slinton /*NOTREACHED*/ 2505483Slinton } 2515742Slinton } 2525742Slinton # else 2535742Slinton int oplen; 2545742Slinton 2555742Slinton oplen = optab[op].nargs; 2565742Slinton if (oplen < 0) { 2575742Slinton oplen = (-oplen) - 1; 2585742Slinton } else if (oplen > 0 && nextbyte != 0) { 2595742Slinton oplen--; 2605742Slinton } 2615742Slinton oplen *= sizeof(int); 2625742Slinton switch (op) { 2635742Slinton case O_BEG: 2645742Slinton case O_NODUMP: 2655742Slinton oplen += 10; 2665742Slinton break; 2675742Slinton 2685742Slinton case O_CON: 2695742Slinton oplen += ((nextbyte + 1)&~1); 2705742Slinton break; 2715742Slinton } 2725742Slinton addr += oplen; 2735742Slinton # endif 2745742Slinton break; 2755483Slinton } 2765742Slinton } 2775742Slinton 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 { 2905742Slinton register ADDRESS i; 2915742Slinton ADDRESS firstval, lastval, jmptable; 2925742Slinton short offset; 2935742Slinton long swtval, caseval; 2945483Slinton 2955742Slinton stepto(addr - 2); 2965742Slinton if (ncases == 0) { 2975742Slinton iread(&ncases, addr, sizeof(ncases)); 2985742Slinton addr += sizeof(short); 2995742Slinton } 3005742Slinton jmptable = addr; 3015742Slinton firstval = jmptable + ncases*sizeof(short); 3025742Slinton lastval = firstval + ncases*size; 3035742Slinton if (size <= 2) { 3045742Slinton dread(&swtval, process->sp, 2); 3055742Slinton } else { 3065742Slinton dread(&swtval, process->sp, size); 3075742Slinton } 3085742Slinton for (i = firstval; i < lastval; i += size) { 3095742Slinton iread(&caseval, i, size); 3105742Slinton if (cmp(&swtval, &caseval, size) == 0) { 3115742Slinton i = ((i - firstval) / size) * sizeof(offset); 3125742Slinton iread(&offset, jmptable + i, sizeof(offset)); 3135742Slinton addr = jmptable + offset; 3145742Slinton return addr; 3155483Slinton } 3165742Slinton } 3175742Slinton 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 { 3265742Slinton register PROCESS *p; 3275742Slinton long i, limit, lower; 3285742Slinton ADDRESS valaddr; 3295742Slinton short offset; 3305483Slinton 3315742Slinton stepto(addr - sizeof(short)); 3325742Slinton p = process; 3335742Slinton i = limit = 0; 3345742Slinton if (subop == 0) { 3355483Slinton addr += size; 3365742Slinton } 3375742Slinton dread(&valaddr, p->sp, sizeof(valaddr)); 3385742Slinton dread(&i, valaddr, size); 3395742Slinton dread(&limit, p->sp + sizeof(valaddr), size); 3405742Slinton i += (incr << (8*(sizeof(i) - size))); 3415742Slinton addr += size; 3425874Slinton 3435483Slinton /* 3445483Slinton * It is very slow to go through the loop again and again. 3455874Slinton * If it is desired to just skip to the end, the next 4 lines 3465874Slinton * should be skipped. 3475874Slinton */ 3485742Slinton if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) { 3495742Slinton iread(&offset, addr, sizeof(offset)); 3505742Slinton return(addr + offset); 3515742Slinton } else { 3525742Slinton return(addr + sizeof(short)); 3535742Slinton } 3545483Slinton } 355*6080Slinton 356*6080Slinton /* 357*6080Slinton * Determine whether or not the given address corresponds to the 358*6080Slinton * end of a procedure. 359*6080Slinton */ 360*6080Slinton 361*6080Slinton BOOLEAN isendofproc(addr) 362*6080Slinton ADDRESS addr; 363*6080Slinton { 364*6080Slinton PXOP op; 365*6080Slinton 366*6080Slinton iread(&op, addr, sizeof(op)); 367*6080Slinton return (op == O_END); 368*6080Slinton } 369