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