15483Slinton /* Copyright (c) 1982 Regents of the University of California */ 25483Slinton 3*5742Slinton static char sccsid[] = "@(#)nextaddr.c 1.2 02/10/82"; 45483Slinton 55483Slinton /* 65483Slinton * Calculate the next address that will be executed from the current one. 75483Slinton * 85483Slinton * If the next address depends on runtime data (e.g. a conditional 95483Slinton * branch will depend on the value on top of the stack), 105483Slinton * we must execute up to the given address with "stepto". 115483Slinton * 125483Slinton * If the second argument is TRUE, we treat a CALL instruction as 135483Slinton * straight line rather than following it as a branch. 145483Slinton */ 155483Slinton 165483Slinton #include "defs.h" 175483Slinton #include "machine.h" 185483Slinton #include "process.h" 195483Slinton #include "breakpoint.h" 205483Slinton #include "sym.h" 215483Slinton #include "pxops.h" 225483Slinton #include "optab.h" 235483Slinton #include "mappings.h" 245483Slinton #include "runtime.h" 255483Slinton #include "process/pxinfo.h" 265483Slinton #include "process/process.rep" 275483Slinton 285483Slinton LOCAL ADDRESS docase(), dofor(); 295483Slinton 305483Slinton ADDRESS nextaddr(beginaddr, isnext) 315483Slinton ADDRESS beginaddr; 325483Slinton BOOLEAN isnext; 335483Slinton { 34*5742Slinton register PXOP op; 35*5742Slinton ADDRESS addr; 36*5742Slinton short offset; 37*5742Slinton int nextbyte; 38*5742Slinton SYM *s; 39*5742Slinton union { 40*5742Slinton short word; 41*5742Slinton char byte[2]; 42*5742Slinton } o; 435483Slinton 44*5742Slinton addr = beginaddr; 45*5742Slinton iread(&o.word, addr, sizeof(o.word)); 46*5742Slinton op = (PXOP) o.byte[0]; 47*5742Slinton nextbyte = o.byte[1]; 48*5742Slinton addr += sizeof(short); 49*5742Slinton switch(op) { 505483Slinton 51*5742Slinton # if (isvaxpx) 52*5742Slinton /* 53*5742Slinton * The version of px on the VAX assumes that the instruction 54*5742Slinton * at the entry point of a function is a TRA4 to the beginning 55*5742Slinton * of the block. 56*5742Slinton */ 57*5742Slinton # endif 58*5742Slinton case O_CALL: { 59*5742Slinton ADDRESS eaddr; 605483Slinton 61*5742Slinton if (isnext) { 62*5742Slinton addr += sizeof(int); 63*5742Slinton } else { 64*5742Slinton # if (isvaxpx) 65*5742Slinton iread(&eaddr, addr, sizeof(eaddr)); 66*5742Slinton addr = eaddr + sizeof(short); 67*5742Slinton iread(&addr, addr, sizeof(addr)); 68*5742Slinton # else 69*5742Slinton iread(&offset, addr, sizeof(offset)); 70*5742Slinton addr += offset; 71*5742Slinton # endif 72*5742Slinton stepto(addr); 73*5742Slinton if (linelookup(addr) == 0) { 74*5742Slinton bpact(); 75*5742Slinton addr = pc; 765483Slinton } 77*5742Slinton if (ss_lines && trcond()) { 78*5742Slinton s = whatblock(addr); 79*5742Slinton if (s == NIL) { 80*5742Slinton panic("bad call addr"); 81*5742Slinton } 82*5742Slinton printentry(s); 83*5742Slinton } 84*5742Slinton } 85*5742Slinton break; 86*5742Slinton } 875483Slinton 88*5742Slinton # if (isvaxpx) 89*5742Slinton case O_FCALL: { 90*5742Slinton ADDRESS eaddr; 91*5742Slinton ADDRESS *fparam; 925483Slinton 93*5742Slinton if (!isnext) { 94*5742Slinton stepto(addr - sizeof(short)); 95*5742Slinton dread(&fparam, process->sp + sizeof(ADDRESS), sizeof(fparam)); 96*5742Slinton dread(&eaddr, fparam, sizeof(eaddr)); 97*5742Slinton addr = eaddr - ENDOFF; 98*5742Slinton stepto(addr); 99*5742Slinton if (linelookup(addr) == 0) { 100*5742Slinton bpact(); 101*5742Slinton addr = pc; 1025483Slinton } 103*5742Slinton if (ss_lines && trcond()) { 104*5742Slinton s = whatblock(addr); 105*5742Slinton if (s == NIL) { 106*5742Slinton panic("bad call addr"); 107*5742Slinton } 108*5742Slinton printentry(s); 109*5742Slinton } 110*5742Slinton } 111*5742Slinton break; 112*5742Slinton } 113*5742Slinton # endif 1145483Slinton 115*5742Slinton case O_END: 116*5742Slinton if ((addr - sizeof(short)) == lastaddr()) { 117*5742Slinton stepto(addr - sizeof(short)); 118*5742Slinton endprogram(); 119*5742Slinton } else { 120*5742Slinton addr = return_addr(); 121*5742Slinton s = whatblock(pc); 122*5742Slinton stepto(addr); 123*5742Slinton if (ss_lines && trcond()) { 124*5742Slinton printexit(s); 125*5742Slinton } 126*5742Slinton if (linelookup(addr) == 0) { 127*5742Slinton bpact(); 128*5742Slinton addr = pc; 129*5742Slinton } 130*5742Slinton } 131*5742Slinton break; 1325483Slinton 133*5742Slinton # if (isvaxpx) 134*5742Slinton case O_TRA4: 135*5742Slinton case O_GOTO: 136*5742Slinton iread(&addr, addr, sizeof(addr)); 137*5742Slinton break; 138*5742Slinton # endif 1395483Slinton 140*5742Slinton case O_TRA: 141*5742Slinton iread(&offset, addr, sizeof(offset)); 142*5742Slinton addr += offset; 143*5742Slinton break; 1445483Slinton 145*5742Slinton case O_CON: { 146*5742Slinton short consize; 1475483Slinton 148*5742Slinton if (nextbyte == 0) { 149*5742Slinton iread(&consize, addr, sizeof(consize)); 150*5742Slinton addr += sizeof(consize); 151*5742Slinton } else { 152*5742Slinton consize = nextbyte; 153*5742Slinton } 154*5742Slinton addr += consize; 155*5742Slinton break; 156*5742Slinton } 1575483Slinton 158*5742Slinton case O_CASE1OP: 159*5742Slinton addr = docase(nextbyte, 1, addr); 160*5742Slinton break; 1615483Slinton 162*5742Slinton case O_CASE2OP: 163*5742Slinton addr = docase(nextbyte, 2, addr); 164*5742Slinton break; 1655483Slinton 166*5742Slinton case O_CASE4OP: 167*5742Slinton addr = docase(nextbyte, 4, addr); 168*5742Slinton break; 1695483Slinton 170*5742Slinton case O_FOR1U: 171*5742Slinton addr = dofor(2, addr, nextbyte, 1); 172*5742Slinton break; 1735483Slinton 174*5742Slinton case O_FOR2U: 175*5742Slinton addr = dofor(2, addr, nextbyte, 1); 176*5742Slinton break; 1775483Slinton 178*5742Slinton case O_FOR4U: 179*5742Slinton addr = dofor(4, addr, nextbyte, 1); 180*5742Slinton break; 1815483Slinton 182*5742Slinton case O_FOR1D: 183*5742Slinton addr = dofor(2, addr, nextbyte, -1); 184*5742Slinton break; 1855483Slinton 186*5742Slinton case O_FOR2D: 187*5742Slinton addr = dofor(2, addr, nextbyte, -1); 188*5742Slinton break; 1895483Slinton 190*5742Slinton case O_FOR4D: 191*5742Slinton addr = dofor(4, addr, nextbyte, -1); 192*5742Slinton break; 1935483Slinton 194*5742Slinton case O_IF: 195*5742Slinton stepto(addr - sizeof(short)); 196*5742Slinton dread(&offset, process->sp, sizeof(offset)); 197*5742Slinton if (offset == 0) { 198*5742Slinton iread(&offset, addr, sizeof(offset)); 199*5742Slinton addr += offset; 200*5742Slinton } else { 201*5742Slinton addr += sizeof(offset); 202*5742Slinton } 203*5742Slinton break; 2045483Slinton 205*5742Slinton default: { 206*5742Slinton # if (isvaxpx) 207*5742Slinton int i; 2085483Slinton 209*5742Slinton for (i = 0; optab[op].argtype[i] != 0; i++) { 210*5742Slinton switch(optab[op].argtype[i]) { 211*5742Slinton case ADDR4: 212*5742Slinton case LWORD: 213*5742Slinton addr += 4; 214*5742Slinton break; 2155483Slinton 216*5742Slinton case SUBOP: 217*5742Slinton break; 2185483Slinton 219*5742Slinton case ADDR2: 220*5742Slinton case HWORD: 221*5742Slinton case PSUBOP: 222*5742Slinton case DISP: 223*5742Slinton case VLEN: 224*5742Slinton if (i != 0 || nextbyte == 0) { 225*5742Slinton addr += sizeof(short); 2265483Slinton } 227*5742Slinton break; 2285483Slinton 229*5742Slinton case STRING: { 230*5742Slinton char c; 2315483Slinton 232*5742Slinton while (nextbyte > 0) { 233*5742Slinton iread(&c, addr, 1); 234*5742Slinton if (c == '\0') { 235*5742Slinton break; 236*5742Slinton } 237*5742Slinton nextbyte--; 238*5742Slinton addr++; 2395483Slinton } 240*5742Slinton addr++; 241*5742Slinton if ((addr&1) != 0) { 242*5742Slinton addr++; 243*5742Slinton } 2445483Slinton break; 245*5742Slinton } 246*5742Slinton 247*5742Slinton default: 248*5742Slinton panic("bad argtype"); 249*5742Slinton /*NOTREACHED*/ 2505483Slinton } 251*5742Slinton } 252*5742Slinton # else 253*5742Slinton int oplen; 254*5742Slinton 255*5742Slinton oplen = optab[op].nargs; 256*5742Slinton if (oplen < 0) { 257*5742Slinton oplen = (-oplen) - 1; 258*5742Slinton } else if (oplen > 0 && nextbyte != 0) { 259*5742Slinton oplen--; 260*5742Slinton } 261*5742Slinton oplen *= sizeof(int); 262*5742Slinton switch (op) { 263*5742Slinton case O_BEG: 264*5742Slinton case O_NODUMP: 265*5742Slinton oplen += 10; 266*5742Slinton break; 267*5742Slinton 268*5742Slinton case O_CON: 269*5742Slinton oplen += ((nextbyte + 1)&~1); 270*5742Slinton break; 271*5742Slinton } 272*5742Slinton addr += oplen; 273*5742Slinton # endif 274*5742Slinton break; 2755483Slinton } 276*5742Slinton } 277*5742Slinton return addr; 2785483Slinton } 2795483Slinton 2805483Slinton /* 2815483Slinton * Find the next address that will be executed after the 2825483Slinton * case statement at the given address. 2835483Slinton */ 2845483Slinton 2855483Slinton LOCAL ADDRESS docase(ncases, size, addr) 2865483Slinton int ncases; 2875483Slinton int size; 2885483Slinton ADDRESS addr; 2895483Slinton { 290*5742Slinton register ADDRESS i; 291*5742Slinton ADDRESS firstval, lastval, jmptable; 292*5742Slinton short offset; 293*5742Slinton long swtval, caseval; 2945483Slinton 295*5742Slinton stepto(addr - 2); 296*5742Slinton if (ncases == 0) { 297*5742Slinton iread(&ncases, addr, sizeof(ncases)); 298*5742Slinton addr += sizeof(short); 299*5742Slinton } 300*5742Slinton jmptable = addr; 301*5742Slinton firstval = jmptable + ncases*sizeof(short); 302*5742Slinton lastval = firstval + ncases*size; 303*5742Slinton if (size <= 2) { 304*5742Slinton dread(&swtval, process->sp, 2); 305*5742Slinton } else { 306*5742Slinton dread(&swtval, process->sp, size); 307*5742Slinton } 308*5742Slinton for (i = firstval; i < lastval; i += size) { 309*5742Slinton iread(&caseval, i, size); 310*5742Slinton if (cmp(&swtval, &caseval, size) == 0) { 311*5742Slinton i = ((i - firstval) / size) * sizeof(offset); 312*5742Slinton iread(&offset, jmptable + i, sizeof(offset)); 313*5742Slinton addr = jmptable + offset; 314*5742Slinton return addr; 3155483Slinton } 316*5742Slinton } 317*5742Slinton return((lastval+1)&~1); 3185483Slinton } 3195483Slinton 3205483Slinton LOCAL ADDRESS dofor(size, addr, subop, incr) 3215483Slinton int size; 3225483Slinton ADDRESS addr; 3235483Slinton short subop; 3245483Slinton int incr; 3255483Slinton { 326*5742Slinton register PROCESS *p; 327*5742Slinton long i, limit, lower; 328*5742Slinton ADDRESS valaddr; 329*5742Slinton short offset; 3305483Slinton 331*5742Slinton stepto(addr - sizeof(short)); 332*5742Slinton p = process; 333*5742Slinton i = limit = 0; 334*5742Slinton if (subop == 0) { 3355483Slinton addr += size; 336*5742Slinton } 337*5742Slinton dread(&valaddr, p->sp, sizeof(valaddr)); 338*5742Slinton dread(&i, valaddr, size); 339*5742Slinton dread(&limit, p->sp + sizeof(valaddr), size); 340*5742Slinton i += (incr << (8*(sizeof(i) - size))); 341*5742Slinton addr += size; 3425483Slinton /* 3435483Slinton * It is very slow to go through the loop again and again. 3445483Slinton * So for the time being, we just skip to the end. 3455483Slinton * 346*5742Slinton if ((incr > 0 && i < limit) || (incr < 0 && i > limit)) { 347*5742Slinton iread(&offset, addr, sizeof(offset)); 348*5742Slinton return(addr + offset); 349*5742Slinton } else { 3505483Slinton */ 351*5742Slinton return(addr + sizeof(short)); 3525483Slinton /* 353*5742Slinton } 3545483Slinton */ 3555483Slinton } 356