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