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