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