1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: static char sccsid[] = "@(#)nextaddr.c 5.1 (Berkeley) 6/6/85"; 9: #endif not lint 10: /* 11: * Calculate the next address that will be executed from the current one. 12: * 13: * If the next address depends on runtime data (e.g. a conditional 14: * branch will depend on the value on top of the stack), 15: * we must execute up to the given address with "stepto". 16: * 17: * If the second argument is TRUE, we treat a CALL instruction as 18: * straight line rather than following it as a branch. 19: */ 20: 21: #include "defs.h" 22: #include "machine.h" 23: #include "process.h" 24: #include "breakpoint.h" 25: #include "sym.h" 26: #include "pxops.h" 27: #include "optab.h" 28: #include "mappings.h" 29: #include "runtime.h" 30: #include "process/pxinfo.h" 31: #include "process/process.rep" 32: 33: LOCAL ADDRESS docase(), dofor(); 34: 35: ADDRESS nextaddr(beginaddr, isnext) 36: ADDRESS beginaddr; 37: BOOLEAN isnext; 38: { 39: register PXOP op; 40: ADDRESS addr; 41: short offset; 42: int nextbyte; 43: SYM *s; 44: union { 45: short word; 46: char byte[2]; 47: } o; 48: 49: addr = beginaddr; 50: iread(&o.word, addr, sizeof(o.word)); 51: op = (PXOP) o.byte[0]; 52: nextbyte = o.byte[1]; 53: addr += sizeof(short); 54: switch(op) { 55: 56: # if (isvaxpx) 57: /* 58: * The version of px on the VAX assumes that the instruction 59: * at the entry point of a function is a TRA4 to the beginning 60: * of the block. 61: */ 62: # endif 63: case O_CALL: { 64: ADDRESS eaddr; 65: 66: if (isnext) { 67: addr += sizeof(int); 68: } else { 69: # if (isvaxpx) 70: iread(&eaddr, addr, sizeof(eaddr)); 71: addr = eaddr + sizeof(short); 72: iread(&addr, addr, sizeof(addr)); 73: # else 74: iread(&offset, addr, sizeof(offset)); 75: addr += offset; 76: # endif 77: stepto(addr); 78: if (linelookup(addr) == 0) { 79: bpact(); 80: addr = pc; 81: } 82: if (ss_lines && trcond()) { 83: s = whatblock(addr); 84: if (s == NIL) { 85: panic("bad call addr"); 86: } 87: printentry(s); 88: } 89: } 90: break; 91: } 92: 93: # if (isvaxpx) 94: case O_FCALL: { 95: ADDRESS eaddr; 96: ADDRESS *fparam; 97: 98: if (!isnext) { 99: stepto(addr - sizeof(short)); 100: dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam)); 101: dread(&eaddr, fparam, sizeof(eaddr)); 102: addr = eaddr - ENDOFF; 103: stepto(addr); 104: if (linelookup(addr) == 0) { 105: bpact(); 106: addr = pc; 107: } 108: if (ss_lines && trcond()) { 109: s = whatblock(addr); 110: if (s == NIL) { 111: panic("bad call addr"); 112: } 113: printentry(s); 114: } 115: } 116: break; 117: } 118: # endif 119: 120: case O_END: 121: if ((addr - sizeof(short)) == lastaddr()) { 122: stepto(addr - sizeof(short)); 123: endprogram(); 124: } else { 125: addr = return_addr(); 126: s = whatblock(pc); 127: stepto(addr); 128: if (ss_lines && trcond()) { 129: printexit(s); 130: } 131: if (linelookup(addr) == 0) { 132: bpact(); 133: addr = pc; 134: } 135: } 136: break; 137: 138: # if (isvaxpx) 139: case O_TRA4: 140: case O_GOTO: 141: iread(&addr, addr, sizeof(addr)); 142: break; 143: # endif 144: 145: case O_TRA: 146: iread(&offset, addr, sizeof(offset)); 147: addr += offset; 148: break; 149: 150: case O_CON: { 151: short consize; 152: 153: if (nextbyte == 0) { 154: iread(&consize, addr, sizeof(consize)); 155: addr += sizeof(consize); 156: } else { 157: consize = nextbyte; 158: } 159: addr += consize; 160: break; 161: } 162: 163: case O_CASE1OP: 164: addr = docase(nextbyte, 1, addr); 165: break; 166: 167: case O_CASE2OP: 168: addr = docase(nextbyte, 2, addr); 169: break; 170: 171: case O_CASE4OP: 172: addr = docase(nextbyte, 4, addr); 173: break; 174: 175: case O_FOR1U: 176: addr = dofor(2, addr, nextbyte, 1); 177: break; 178: 179: case O_FOR2U: 180: addr = dofor(2, addr, nextbyte, 1); 181: break; 182: 183: case O_FOR4U: 184: addr = dofor(4, addr, nextbyte, 1); 185: break; 186: 187: case O_FOR1D: 188: addr = dofor(2, addr, nextbyte, -1); 189: break; 190: 191: case O_FOR2D: 192: addr = dofor(2, addr, nextbyte, -1); 193: break; 194: 195: case O_FOR4D: 196: addr = dofor(4, addr, nextbyte, -1); 197: break; 198: 199: case O_IF: 200: stepto(addr - sizeof(short)); 201: dread(&offset, process->sp, sizeof(offset)); 202: if (offset == 0) { 203: iread(&offset, addr, sizeof(offset)); 204: addr += offset; 205: } else { 206: addr += sizeof(offset); 207: } 208: break; 209: 210: default: { 211: # if (isvaxpx) 212: int i; 213: 214: for (i = 0; optab[op].argtype[i] != 0; i++) { 215: switch(optab[op].argtype[i]) { 216: case ADDR4: 217: case LWORD: 218: addr += 4; 219: break; 220: 221: case SUBOP: 222: break; 223: 224: case ADDR2: 225: case HWORD: 226: case PSUBOP: 227: case DISP: 228: case VLEN: 229: if (i != 0 || nextbyte == 0) { 230: addr += sizeof(short); 231: } 232: break; 233: 234: case STRING: { 235: char c; 236: 237: while (nextbyte > 0) { 238: iread(&c, addr, 1); 239: if (c == '\0') { 240: break; 241: } 242: nextbyte--; 243: addr++; 244: } 245: addr++; 246: if ((addr&1) != 0) { 247: addr++; 248: } 249: break; 250: } 251: 252: default: 253: panic("bad argtype"); 254: /*NOTREACHED*/ 255: } 256: } 257: # else 258: int oplen; 259: 260: oplen = optab[op].nargs; 261: if (oplen < 0) { 262: oplen = (-oplen) - 1; 263: } else if (oplen > 0 && nextbyte != 0) { 264: oplen--; 265: } 266: oplen *= sizeof(int); 267: switch (op) { 268: case O_BEG: 269: case O_NODUMP: 270: oplen += 10; 271: break; 272: 273: case O_CON: 274: oplen += ((nextbyte + 1)&~1); 275: break; 276: } 277: addr += oplen; 278: # endif 279: break; 280: } 281: } 282: return addr; 283: } 284: 285: /* 286: * Find the next address that will be executed after the 287: * case statement at the given address. 288: */ 289: 290: LOCAL ADDRESS docase(ncases, size, addr) 291: int ncases; 292: int size; 293: ADDRESS addr; 294: { 295: register ADDRESS i; 296: ADDRESS firstval, lastval, jmptable; 297: short offset; 298: long swtval, caseval; 299: 300: stepto(addr - 2); 301: if (ncases == 0) { 302: iread(&ncases, addr, sizeof(ncases)); 303: addr += sizeof(short); 304: } 305: jmptable = addr; 306: firstval = jmptable + ncases*sizeof(short); 307: lastval = firstval + ncases*size; 308: if (size <= 2) { 309: dread(&swtval, process->sp, 2); 310: } else { 311: dread(&swtval, process->sp, size); 312: } 313: for (i = firstval; i < lastval; i += size) { 314: iread(&caseval, i, size); 315: if (cmp(&swtval, &caseval, size) == 0) { 316: i = ((i - firstval) / size) * sizeof(offset); 317: iread(&offset, jmptable + i, sizeof(offset)); 318: addr = jmptable + offset; 319: return addr; 320: } 321: } 322: return((lastval+1)&~1); 323: } 324: 325: LOCAL ADDRESS dofor(size, addr, subop, incr) 326: int size; 327: ADDRESS addr; 328: short subop; 329: int incr; 330: { 331: register PROCESS *p; 332: long i, limit, lower; 333: ADDRESS valaddr; 334: short offset; 335: 336: stepto(addr - sizeof(short)); 337: p = process; 338: i = limit = 0; 339: if (subop == 0) { 340: addr += size; 341: } 342: dread(&valaddr, p->sp, sizeof(valaddr)); 343: dread(&i, valaddr, size); 344: dread(&limit, p->sp + sizeof(valaddr), size); 345: i += (incr << (8*(sizeof(i) - size))); 346: addr += size; 347: 348: /* 349: * It is very slow to go through the loop again and again. 350: * If it is desired to just skip to the end, the next 4 lines 351: * should be skipped. 352: */ 353: if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) { 354: iread(&offset, addr, sizeof(offset)); 355: return(addr + offset); 356: } else { 357: return(addr + sizeof(short)); 358: } 359: } 360: 361: /* 362: * Determine whether or not the given address corresponds to the 363: * end of a procedure. 364: */ 365: 366: BOOLEAN isendofproc(addr) 367: ADDRESS addr; 368: { 369: PXOP op; 370: 371: iread(&op, addr, sizeof(op)); 372: return (op == O_END); 373: }