1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)nextaddr.c 1.1 01/18/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_CASE1OP: 146 addr = docase(nextbyte, 1, addr); 147 break; 148 149 case O_CASE2OP: 150 addr = docase(nextbyte, 2, addr); 151 break; 152 153 case O_CASE4OP: 154 addr = docase(nextbyte, 4, addr); 155 break; 156 157 case O_FOR1U: 158 addr = dofor(2, addr, nextbyte, 1); 159 break; 160 161 case O_FOR2U: 162 addr = dofor(2, addr, nextbyte, 1); 163 break; 164 165 case O_FOR4U: 166 addr = dofor(4, addr, nextbyte, 1); 167 break; 168 169 case O_FOR1D: 170 addr = dofor(2, addr, nextbyte, -1); 171 break; 172 173 case O_FOR2D: 174 addr = dofor(2, addr, nextbyte, -1); 175 break; 176 177 case O_FOR4D: 178 addr = dofor(4, addr, nextbyte, -1); 179 break; 180 181 case O_IF: 182 stepto(addr - sizeof(short)); 183 dread(&offset, process->sp, sizeof(offset)); 184 if (offset == 0) { 185 iread(&offset, addr, sizeof(offset)); 186 addr += offset; 187 } else { 188 addr += sizeof(offset); 189 } 190 break; 191 192 default: { 193 # if (isvaxpx) 194 int i; 195 196 for (i = 0; optab[op].argtype[i] != 0; i++) { 197 switch(optab[op].argtype[i]) { 198 case ADDR4: 199 case LWORD: 200 addr += 4; 201 break; 202 203 case SUBOP: 204 break; 205 206 case ADDR2: 207 case HWORD: 208 case PSUBOP: 209 case DISP: 210 case VLEN: 211 if (i != 0 || nextbyte == 0) { 212 addr += sizeof(short); 213 } 214 break; 215 216 case STRING: { 217 char c; 218 219 while (nextbyte > 0) { 220 iread(&c, addr, 1); 221 if (c == '\0') { 222 break; 223 } 224 nextbyte--; 225 addr++; 226 } 227 addr++; 228 if ((addr&1) != 0) { 229 addr++; 230 } 231 break; 232 } 233 234 default: 235 panic("bad argtype"); 236 /*NOTREACHED*/ 237 } 238 } 239 # else 240 int oplen; 241 242 oplen = optab[op].nargs; 243 if (oplen < 0) { 244 oplen = (-oplen) - 1; 245 } else if (oplen > 0 && nextbyte != 0) { 246 oplen--; 247 } 248 oplen *= sizeof(int); 249 switch (op) { 250 case O_BEG: 251 case O_NODUMP: 252 oplen += 10; 253 break; 254 255 case O_CON: 256 oplen += ((nextbyte + 1)&~1); 257 break; 258 } 259 addr += oplen; 260 # endif 261 break; 262 } 263 } 264 return addr; 265 } 266 267 /* 268 * Find the next address that will be executed after the 269 * case statement at the given address. 270 */ 271 272 LOCAL ADDRESS docase(ncases, size, addr) 273 int ncases; 274 int size; 275 ADDRESS addr; 276 { 277 register ADDRESS i; 278 ADDRESS firstval, lastval, jmptable; 279 short offset; 280 long swtval, caseval; 281 282 stepto(addr - 2); 283 if (ncases == 0) { 284 iread(&ncases, addr, sizeof(ncases)); 285 addr += sizeof(short); 286 } 287 jmptable = addr; 288 firstval = jmptable + ncases*sizeof(short); 289 lastval = firstval + ncases*size; 290 if (size <= 2) { 291 dread(&swtval, process->sp, 2); 292 } else { 293 dread(&swtval, process->sp, size); 294 } 295 for (i = firstval; i < lastval; i += size) { 296 iread(&caseval, i, size); 297 if (cmp(&swtval, &caseval, size) == 0) { 298 i = ((i - firstval) / size) * sizeof(offset); 299 iread(&offset, jmptable + i, sizeof(offset)); 300 addr = jmptable + offset; 301 return addr; 302 } 303 } 304 return((lastval+1)&~1); 305 } 306 307 LOCAL ADDRESS dofor(size, addr, subop, incr) 308 int size; 309 ADDRESS addr; 310 short subop; 311 int incr; 312 { 313 register PROCESS *p; 314 long i, limit, lower; 315 ADDRESS valaddr; 316 short offset; 317 318 stepto(addr - sizeof(short)); 319 p = process; 320 i = limit = 0; 321 if (subop == 0) { 322 addr += size; 323 } 324 dread(&valaddr, p->sp, sizeof(valaddr)); 325 dread(&i, valaddr, size); 326 dread(&limit, p->sp + sizeof(valaddr), size); 327 i += (incr << (8*(sizeof(i) - size))); 328 addr += size; 329 /* 330 * It is very slow to go through the loop again and again. 331 * So for the time being, we just skip to the end. 332 * 333 if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) { 334 iread(&offset, addr, sizeof(offset)); 335 return(addr + offset); 336 } else { 337 */ 338 return(addr + sizeof(short)); 339 /* 340 } 341 */ 342 } 343