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