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) 06/06/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 } 374