1*48101Sbostic /*- 2*48101Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48101Sbostic * All rights reserved. 4*48101Sbostic * 5*48101Sbostic * %sccs.include.redist.c% 622363Sdist */ 75483Slinton 822363Sdist #ifndef lint 9*48101Sbostic static char sccsid[] = "@(#)nextaddr.c 5.3 (Berkeley) 04/16/91"; 10*48101Sbostic #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 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 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 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 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