1*9668Slinton /* Copyright (c) 1982 Regents of the University of California */ 2*9668Slinton 3*9668Slinton static char sccsid[] = "@(#)@(#)vax.c 1.1 12/15/82"; 4*9668Slinton 5*9668Slinton /* 6*9668Slinton * Target machine dependent stuff. 7*9668Slinton */ 8*9668Slinton 9*9668Slinton #include "defs.h" 10*9668Slinton #include "machine.h" 11*9668Slinton #include "process.h" 12*9668Slinton #include "events.h" 13*9668Slinton #include "main.h" 14*9668Slinton #include "symbols.h" 15*9668Slinton #include "source.h" 16*9668Slinton #include "mappings.h" 17*9668Slinton #include "object.h" 18*9668Slinton #include "vaxops.h" 19*9668Slinton #include <signal.h> 20*9668Slinton 21*9668Slinton #ifndef public 22*9668Slinton typedef unsigned int Address; 23*9668Slinton typedef unsigned char Byte; 24*9668Slinton typedef unsigned int Word; 25*9668Slinton 26*9668Slinton #define NREG 16 27*9668Slinton 28*9668Slinton #define ARGP 12 29*9668Slinton #define FRP 13 30*9668Slinton #define STKP 14 31*9668Slinton #define PROGCTR 15 32*9668Slinton 33*9668Slinton #define BITSPERBYTE 8 34*9668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) 35*9668Slinton 36*9668Slinton #define nargspassed(frame) argn(0, frame) 37*9668Slinton 38*9668Slinton #include "source.h" 39*9668Slinton #include "symbols.h" 40*9668Slinton 41*9668Slinton Address pc; 42*9668Slinton Address prtaddr; 43*9668Slinton 44*9668Slinton #endif 45*9668Slinton 46*9668Slinton private Address printop(); 47*9668Slinton 48*9668Slinton /* 49*9668Slinton * Decode and print the instructions within the given address range. 50*9668Slinton */ 51*9668Slinton 52*9668Slinton public printinst(lowaddr, highaddr) 53*9668Slinton Address lowaddr; 54*9668Slinton Address highaddr; 55*9668Slinton { 56*9668Slinton register Address addr; 57*9668Slinton 58*9668Slinton for (addr = lowaddr; addr <= highaddr; ) { 59*9668Slinton addr = printop(addr); 60*9668Slinton } 61*9668Slinton prtaddr = addr; 62*9668Slinton } 63*9668Slinton 64*9668Slinton /* 65*9668Slinton * Another approach: print n instructions starting at the given address. 66*9668Slinton */ 67*9668Slinton 68*9668Slinton public printninst(count, addr) 69*9668Slinton int count; 70*9668Slinton Address addr; 71*9668Slinton { 72*9668Slinton register Integer i; 73*9668Slinton register Address newaddr; 74*9668Slinton 75*9668Slinton if (count <= 0) { 76*9668Slinton error("non-positive repetition count"); 77*9668Slinton } else { 78*9668Slinton newaddr = addr; 79*9668Slinton for (i = 0; i < count; i++) { 80*9668Slinton newaddr = printop(newaddr); 81*9668Slinton } 82*9668Slinton prtaddr = newaddr; 83*9668Slinton } 84*9668Slinton } 85*9668Slinton 86*9668Slinton /* 87*9668Slinton * Hacked version of adb's VAX instruction decoder. 88*9668Slinton */ 89*9668Slinton 90*9668Slinton private Address printop(addr) 91*9668Slinton Address addr; 92*9668Slinton { 93*9668Slinton Optab op; 94*9668Slinton VaxOpcode ins; 95*9668Slinton unsigned char mode; 96*9668Slinton int argtype, amode, argno, argval; 97*9668Slinton String reg; 98*9668Slinton Boolean indexf; 99*9668Slinton short offset; 100*9668Slinton 101*9668Slinton argval = 0; 102*9668Slinton indexf = false; 103*9668Slinton printf("%08x ", addr); 104*9668Slinton iread(&ins, addr, sizeof(ins)); 105*9668Slinton addr += 1; 106*9668Slinton op = optab[ins]; 107*9668Slinton printf("%s", op.iname); 108*9668Slinton for (argno = 0; argno < op.numargs; argno++) { 109*9668Slinton if (indexf == true) { 110*9668Slinton indexf = false; 111*9668Slinton } else if (argno == 0) { 112*9668Slinton printf("\t"); 113*9668Slinton } else { 114*9668Slinton printf(","); 115*9668Slinton } 116*9668Slinton argtype = op.argtype[argno]; 117*9668Slinton if (is_branch_disp(argtype)) { 118*9668Slinton mode = 0xAF + (typelen(argtype) << 5); 119*9668Slinton } else { 120*9668Slinton iread(&mode, addr, sizeof(mode)); 121*9668Slinton addr += 1; 122*9668Slinton } 123*9668Slinton reg = regname[regnm(mode)]; 124*9668Slinton amode = addrmode(mode); 125*9668Slinton switch (amode) { 126*9668Slinton case LITSHORT: 127*9668Slinton case LITUPTO31: 128*9668Slinton case LITUPTO47: 129*9668Slinton case LITUPTO63: 130*9668Slinton if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD) 131*9668Slinton printf("$%s", fltimm[mode]); 132*9668Slinton else 133*9668Slinton printf("$%x", mode); 134*9668Slinton argval = mode; 135*9668Slinton break; 136*9668Slinton 137*9668Slinton case INDEX: 138*9668Slinton printf("[%s]", reg); 139*9668Slinton indexf = true; 140*9668Slinton argno--; 141*9668Slinton break; 142*9668Slinton 143*9668Slinton case REG: 144*9668Slinton printf("%s", reg); 145*9668Slinton break; 146*9668Slinton 147*9668Slinton case REGDEF: 148*9668Slinton printf("(%s)", reg); 149*9668Slinton break; 150*9668Slinton 151*9668Slinton case AUTODEC: 152*9668Slinton printf("-(%s)", reg); 153*9668Slinton break; 154*9668Slinton 155*9668Slinton case AUTOINC: 156*9668Slinton if (reg != regname[PROGCTR]) { 157*9668Slinton printf("(%s)+", reg); 158*9668Slinton } else { 159*9668Slinton printf("$"); 160*9668Slinton switch (typelen(argtype)) { 161*9668Slinton case TYPB: 162*9668Slinton argval = printdisp(addr, 1, reg, amode); 163*9668Slinton addr += 1; 164*9668Slinton break; 165*9668Slinton 166*9668Slinton case TYPW: 167*9668Slinton argval = printdisp(addr, 2, reg, amode); 168*9668Slinton addr += 2; 169*9668Slinton break; 170*9668Slinton 171*9668Slinton case TYPL: 172*9668Slinton argval = printdisp(addr, 4, reg, amode); 173*9668Slinton addr += 4; 174*9668Slinton break; 175*9668Slinton 176*9668Slinton case TYPF: 177*9668Slinton iread(&argval, addr, sizeof(argval)); 178*9668Slinton printf("%06x", argval); 179*9668Slinton addr += 4; 180*9668Slinton break; 181*9668Slinton 182*9668Slinton case TYPQ: 183*9668Slinton case TYPD: 184*9668Slinton iread(&argval, addr, sizeof(argval)); 185*9668Slinton printf("%06x", argval); 186*9668Slinton iread(&argval, addr+4, sizeof(argval)); 187*9668Slinton printf("%06x", argval); 188*9668Slinton addr += 8; 189*9668Slinton break; 190*9668Slinton } 191*9668Slinton } 192*9668Slinton break; 193*9668Slinton 194*9668Slinton case AUTOINCDEF: 195*9668Slinton if (reg == regname[PROGCTR]) { 196*9668Slinton printf("*$"); 197*9668Slinton argval = printdisp(addr, 4, reg, amode); 198*9668Slinton addr += 4; 199*9668Slinton } else { 200*9668Slinton printf("*(%s)+", reg); 201*9668Slinton } 202*9668Slinton break; 203*9668Slinton 204*9668Slinton case BYTEDISP: 205*9668Slinton argval = printdisp(addr, 1, reg, amode); 206*9668Slinton addr += 1; 207*9668Slinton break; 208*9668Slinton 209*9668Slinton case BYTEDISPDEF: 210*9668Slinton printf("*"); 211*9668Slinton argval = printdisp(addr, 1, reg, amode); 212*9668Slinton addr += 1; 213*9668Slinton break; 214*9668Slinton 215*9668Slinton case WORDDISP: 216*9668Slinton argval = printdisp(addr, 2, reg, amode); 217*9668Slinton addr += 2; 218*9668Slinton break; 219*9668Slinton 220*9668Slinton case WORDDISPDEF: 221*9668Slinton printf("*"); 222*9668Slinton argval = printdisp(addr, 2, reg, amode); 223*9668Slinton addr += 2; 224*9668Slinton break; 225*9668Slinton 226*9668Slinton case LONGDISP: 227*9668Slinton argval = printdisp(addr, 4, reg, amode); 228*9668Slinton addr += 4; 229*9668Slinton break; 230*9668Slinton 231*9668Slinton case LONGDISPDEF: 232*9668Slinton printf("*"); 233*9668Slinton argval = printdisp(addr, 4, reg, amode); 234*9668Slinton addr += 4; 235*9668Slinton break; 236*9668Slinton } 237*9668Slinton } 238*9668Slinton if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) { 239*9668Slinton for (argno = 0; argno <= argval; argno++) { 240*9668Slinton iread(&offset, addr, sizeof(offset)); 241*9668Slinton printf("\n\t\t%d", offset); 242*9668Slinton addr += 2; 243*9668Slinton } 244*9668Slinton } 245*9668Slinton printf("\n"); 246*9668Slinton return addr; 247*9668Slinton } 248*9668Slinton 249*9668Slinton /* 250*9668Slinton * Print the displacement of an instruction that uses displacement 251*9668Slinton * addressing. 252*9668Slinton */ 253*9668Slinton 254*9668Slinton private int printdisp(addr, nbytes, reg, mode) 255*9668Slinton Address addr; 256*9668Slinton int nbytes; 257*9668Slinton char *reg; 258*9668Slinton int mode; 259*9668Slinton { 260*9668Slinton char byte; 261*9668Slinton short hword; 262*9668Slinton int argval; 263*9668Slinton 264*9668Slinton switch (nbytes) { 265*9668Slinton case 1: 266*9668Slinton iread(&byte, addr, sizeof(byte)); 267*9668Slinton argval = byte; 268*9668Slinton break; 269*9668Slinton 270*9668Slinton case 2: 271*9668Slinton iread(&hword, addr, sizeof(hword)); 272*9668Slinton argval = hword; 273*9668Slinton break; 274*9668Slinton 275*9668Slinton case 4: 276*9668Slinton iread(&argval, addr, sizeof(argval)); 277*9668Slinton break; 278*9668Slinton } 279*9668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 280*9668Slinton argval += addr + nbytes; 281*9668Slinton } 282*9668Slinton if (reg == regname[PROGCTR]) { 283*9668Slinton printf("%x", argval); 284*9668Slinton } else { 285*9668Slinton printf("%d(%s)", argval, reg); 286*9668Slinton } 287*9668Slinton return argval; 288*9668Slinton } 289*9668Slinton 290*9668Slinton /* 291*9668Slinton * Print the contents of the addresses within the given range 292*9668Slinton * according to the given format. 293*9668Slinton */ 294*9668Slinton 295*9668Slinton typedef struct { 296*9668Slinton String name; 297*9668Slinton String printfstring; 298*9668Slinton int length; 299*9668Slinton } Format; 300*9668Slinton 301*9668Slinton private Format fmt[] = { 302*9668Slinton { "d", " %d", sizeof(short) }, 303*9668Slinton { "D", " %ld", sizeof(long) }, 304*9668Slinton { "o", " %o", sizeof(short) }, 305*9668Slinton { "O", " %lo", sizeof(long) }, 306*9668Slinton { "x", " %04x", sizeof(short) }, 307*9668Slinton { "X", " %08x", sizeof(long) }, 308*9668Slinton { "b", " \\%o", sizeof(char) }, 309*9668Slinton { "c", " '%c'", sizeof(char) }, 310*9668Slinton { "s", "%c", sizeof(char) }, 311*9668Slinton { "f", " %f", sizeof(double) }, 312*9668Slinton { "g", " %g", sizeof(double) }, 313*9668Slinton { nil, nil, 0 } 314*9668Slinton }; 315*9668Slinton 316*9668Slinton public Address printdata(lowaddr, highaddr, format) 317*9668Slinton Address lowaddr; 318*9668Slinton Address highaddr; 319*9668Slinton String format; 320*9668Slinton { 321*9668Slinton register int n; 322*9668Slinton register Address addr; 323*9668Slinton register Format *f; 324*9668Slinton int value; 325*9668Slinton 326*9668Slinton if (lowaddr > highaddr) { 327*9668Slinton error("first address larger than second"); 328*9668Slinton } 329*9668Slinton f = &fmt[0]; 330*9668Slinton while (f->name != nil and not streq(f->name, format)) { 331*9668Slinton ++f; 332*9668Slinton } 333*9668Slinton if (f->name == nil) { 334*9668Slinton error("bad print format \"%s\"", format); 335*9668Slinton } 336*9668Slinton n = 0; 337*9668Slinton value = 0; 338*9668Slinton for (addr = lowaddr; addr <= highaddr; addr += f->length) { 339*9668Slinton if (n == 0) { 340*9668Slinton printf("%08x: ", addr); 341*9668Slinton } 342*9668Slinton dread(&value, addr, f->length); 343*9668Slinton printf(f->printfstring, value); 344*9668Slinton ++n; 345*9668Slinton if (n >= (16 div f->length)) { 346*9668Slinton putchar('\n'); 347*9668Slinton n = 0; 348*9668Slinton } 349*9668Slinton } 350*9668Slinton if (n != 0) { 351*9668Slinton putchar('\n'); 352*9668Slinton } 353*9668Slinton prtaddr = addr; 354*9668Slinton return addr; 355*9668Slinton } 356*9668Slinton 357*9668Slinton /* 358*9668Slinton * The other approach is to print n items starting with a given address. 359*9668Slinton */ 360*9668Slinton 361*9668Slinton public printndata(count, startaddr, format) 362*9668Slinton int count; 363*9668Slinton Address startaddr; 364*9668Slinton String format; 365*9668Slinton { 366*9668Slinton register int i, n; 367*9668Slinton register Address addr; 368*9668Slinton register Format *f; 369*9668Slinton register Boolean isstring; 370*9668Slinton int value; 371*9668Slinton 372*9668Slinton if (count <= 0) { 373*9668Slinton error("non-positive repetition count"); 374*9668Slinton } 375*9668Slinton f = &fmt[0]; 376*9668Slinton while (f->name != nil and not streq(f->name, format)) { 377*9668Slinton ++f; 378*9668Slinton } 379*9668Slinton if (f->name == nil) { 380*9668Slinton error("bad print format \"%s\"", format); 381*9668Slinton } 382*9668Slinton isstring = (Boolean) streq(f->name, "s"); 383*9668Slinton n = 0; 384*9668Slinton addr = startaddr; 385*9668Slinton value = 0; 386*9668Slinton for (i = 0; i < count; i++) { 387*9668Slinton if (n == 0) { 388*9668Slinton printf("%08x: ", addr); 389*9668Slinton } 390*9668Slinton if (isstring) { 391*9668Slinton putchar('"'); 392*9668Slinton dread(&value, addr, sizeof(char)); 393*9668Slinton while (value != '\0') { 394*9668Slinton printchar((char) value); 395*9668Slinton ++addr; 396*9668Slinton dread(&value, addr, sizeof(char)); 397*9668Slinton } 398*9668Slinton putchar('"'); 399*9668Slinton putchar('\n'); 400*9668Slinton n = 0; 401*9668Slinton addr += sizeof(String); 402*9668Slinton } else { 403*9668Slinton dread(&value, addr, f->length); 404*9668Slinton printf(f->printfstring, value); 405*9668Slinton ++n; 406*9668Slinton if (n >= (16 div f->length)) { 407*9668Slinton putchar('\n'); 408*9668Slinton n = 0; 409*9668Slinton } 410*9668Slinton addr += f->length; 411*9668Slinton } 412*9668Slinton } 413*9668Slinton if (n != 0) { 414*9668Slinton putchar('\n'); 415*9668Slinton } 416*9668Slinton prtaddr = addr; 417*9668Slinton } 418*9668Slinton 419*9668Slinton /* 420*9668Slinton * Print out an execution time error. 421*9668Slinton * 422*9668Slinton * Have to check if the -r option was specified; if so then 423*9668Slinton * the object file information hasn't been read in yet. 424*9668Slinton */ 425*9668Slinton 426*9668Slinton public printerror() 427*9668Slinton { 428*9668Slinton extern Integer sys_nsig; 429*9668Slinton extern String sys_siglist[]; 430*9668Slinton String filename; 431*9668Slinton Integer err; 432*9668Slinton 433*9668Slinton if (isfinished(process)) { 434*9668Slinton printf("\"%s\" exits with code %d\n", objname, exitcode(process)); 435*9668Slinton erecover(); 436*9668Slinton } 437*9668Slinton if (runfirst) { 438*9668Slinton fprintf(stderr, "Entering debugger ..."); 439*9668Slinton init(); 440*9668Slinton fprintf(stderr, " type 'help' for help\n"); 441*9668Slinton } 442*9668Slinton curline = srcline(pc); 443*9668Slinton curfunc = whatblock(pc); 444*9668Slinton filename = srcfilename(pc); 445*9668Slinton setsource(filename); 446*9668Slinton err = errnum(process); 447*9668Slinton if (err == SIGINT) { 448*9668Slinton printf("\n\ninterrupt "); 449*9668Slinton printloc(); 450*9668Slinton } else if (err == SIGTRAP) { 451*9668Slinton printf("\nerror "); 452*9668Slinton printloc(); 453*9668Slinton } else { 454*9668Slinton if (err < 0 or err > sys_nsig) { 455*9668Slinton printf("\nsignal %d ", err); 456*9668Slinton } else { 457*9668Slinton printf("\n%s ", sys_siglist[err]); 458*9668Slinton } 459*9668Slinton printloc(); 460*9668Slinton } 461*9668Slinton putchar('\n'); 462*9668Slinton if (curline > 0) { 463*9668Slinton printlines(curline, curline); 464*9668Slinton } else { 465*9668Slinton printinst(pc, pc); 466*9668Slinton } 467*9668Slinton erecover(); 468*9668Slinton } 469*9668Slinton 470*9668Slinton private printloc() 471*9668Slinton { 472*9668Slinton if (curline > 0) { 473*9668Slinton if (nlhdr.nfiles > 1) { 474*9668Slinton printf("at line %d in file %s", curline, cursource); 475*9668Slinton } else { 476*9668Slinton printf("at line %d", curline); 477*9668Slinton } 478*9668Slinton } else { 479*9668Slinton printf("in "); 480*9668Slinton printname(stdout, curfunc); 481*9668Slinton printf(" at 0x%x", pc); 482*9668Slinton } 483*9668Slinton } 484*9668Slinton 485*9668Slinton /* 486*9668Slinton * Note the termination of the program. We do this so as to avoid 487*9668Slinton * having the process exit, which would make the values of variables 488*9668Slinton * inaccessible. We do want to flush all output buffers here, 489*9668Slinton * otherwise it'll never get done. 490*9668Slinton */ 491*9668Slinton 492*9668Slinton public endprogram() 493*9668Slinton { 494*9668Slinton Integer exitcode; 495*9668Slinton 496*9668Slinton stepto(nextaddr(pc, true)); 497*9668Slinton printnews(); 498*9668Slinton exitcode = argn(1, nil); 499*9668Slinton printf("\nexecution completed, exit code is %d\n", exitcode); 500*9668Slinton getsrcpos(); 501*9668Slinton erecover(); 502*9668Slinton } 503*9668Slinton 504*9668Slinton /* 505*9668Slinton * Single step the machine a source line (or instruction if "inst_tracing" 506*9668Slinton * is true. If "isnext" is true, skip over procedure calls. 507*9668Slinton */ 508*9668Slinton 509*9668Slinton private Address getcall(); 510*9668Slinton 511*9668Slinton public dostep(isnext) 512*9668Slinton Boolean isnext; 513*9668Slinton { 514*9668Slinton register Address addr; 515*9668Slinton register Lineno line; 516*9668Slinton String filename; 517*9668Slinton 518*9668Slinton addr = nextaddr(pc, isnext); 519*9668Slinton if (not inst_tracing) { 520*9668Slinton line = linelookup(addr); 521*9668Slinton while (line == 0) { 522*9668Slinton addr = nextaddr(addr, isnext); 523*9668Slinton line = linelookup(addr); 524*9668Slinton } 525*9668Slinton } 526*9668Slinton stepto(addr); 527*9668Slinton curline = line; 528*9668Slinton filename = srcfilename(addr); 529*9668Slinton setsource(filename); 530*9668Slinton } 531*9668Slinton 532*9668Slinton /* 533*9668Slinton * Compute the next address that will be executed from the given one. 534*9668Slinton * If "isnext" is true then consider a procedure call as straight line code. 535*9668Slinton * 536*9668Slinton * We must unfortunately do much of the same work that is necessary 537*9668Slinton * to print instructions. In addition we have to deal with branches. 538*9668Slinton * Unconditional branches we just follow, for conditional branches 539*9668Slinton * we continue execution to the current location and then single step 540*9668Slinton * the machine. We assume that the last argument in an instruction 541*9668Slinton * that branches is the branch address (or relative offset). 542*9668Slinton */ 543*9668Slinton 544*9668Slinton public Address nextaddr(startaddr, isnext) 545*9668Slinton Address startaddr; 546*9668Slinton Boolean isnext; 547*9668Slinton { 548*9668Slinton register Address addr; 549*9668Slinton Optab op; 550*9668Slinton VaxOpcode ins; 551*9668Slinton unsigned char mode; 552*9668Slinton int argtype, amode, argno, argval; 553*9668Slinton String r; 554*9668Slinton Boolean indexf; 555*9668Slinton enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; 556*9668Slinton 557*9668Slinton argval = 0; 558*9668Slinton indexf = false; 559*9668Slinton addr = startaddr; 560*9668Slinton iread(&ins, addr, sizeof(ins)); 561*9668Slinton switch (ins) { 562*9668Slinton case O_BRB: 563*9668Slinton case O_BRW: 564*9668Slinton case O_JMP: 565*9668Slinton addrstatus = BRANCH; 566*9668Slinton break; 567*9668Slinton 568*9668Slinton case O_BSBB: 569*9668Slinton case O_BSBW: 570*9668Slinton case O_JSB: 571*9668Slinton case O_CALLG: 572*9668Slinton case O_CALLS: 573*9668Slinton if (isnext) { 574*9668Slinton addrstatus = SEQUENTIAL; 575*9668Slinton } else { 576*9668Slinton addrstatus = KNOWN; 577*9668Slinton stepto(addr); 578*9668Slinton pstep(process); 579*9668Slinton addr = reg(PROGCTR); 580*9668Slinton pc = addr; 581*9668Slinton callnews(/* iscall = */ true); 582*9668Slinton if (not isbperr()) { 583*9668Slinton printstatus(); 584*9668Slinton } else { 585*9668Slinton bpact(); 586*9668Slinton } 587*9668Slinton } 588*9668Slinton break; 589*9668Slinton 590*9668Slinton case O_RSB: 591*9668Slinton case O_RET: 592*9668Slinton addrstatus = KNOWN; 593*9668Slinton callnews(/* iscall = */ false); 594*9668Slinton addr = return_addr(); 595*9668Slinton stepto(addr); 596*9668Slinton break; 597*9668Slinton 598*9668Slinton case O_BNEQ: case O_BEQL: case O_BGTR: 599*9668Slinton case O_BLEQ: case O_BGEQ: case O_BLSS: 600*9668Slinton case O_BGTRU: case O_BLEQU: case O_BVC: 601*9668Slinton case O_BVS: case O_BCC: case O_BCS: 602*9668Slinton case O_CASEB: case O_CASEW: case O_CASEL: 603*9668Slinton case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 604*9668Slinton case O_BBSC: case O_BBCC: case O_BBSSI: 605*9668Slinton case O_BBCCI: case O_BLBS: case O_BLBC: 606*9668Slinton case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 607*9668Slinton case O_SOBGEQ: case O_SOBGTR: 608*9668Slinton addrstatus = KNOWN; 609*9668Slinton stepto(addr); 610*9668Slinton pstep(process); 611*9668Slinton addr = reg(PROGCTR); 612*9668Slinton pc = addr; 613*9668Slinton if (not isbperr()) { 614*9668Slinton printstatus(); 615*9668Slinton } 616*9668Slinton break; 617*9668Slinton 618*9668Slinton default: 619*9668Slinton addrstatus = SEQUENTIAL; 620*9668Slinton break; 621*9668Slinton } 622*9668Slinton if (addrstatus != KNOWN) { 623*9668Slinton addr += 1; 624*9668Slinton op = optab[ins]; 625*9668Slinton for (argno = 0; argno < op.numargs; argno++) { 626*9668Slinton if (indexf == true) { 627*9668Slinton indexf = false; 628*9668Slinton } 629*9668Slinton argtype = op.argtype[argno]; 630*9668Slinton if (is_branch_disp(argtype)) { 631*9668Slinton mode = 0xAF + (typelen(argtype) << 5); 632*9668Slinton } else { 633*9668Slinton iread(&mode, addr, sizeof(mode)); 634*9668Slinton addr += 1; 635*9668Slinton } 636*9668Slinton r = regname[regnm(mode)]; 637*9668Slinton amode = addrmode(mode); 638*9668Slinton switch (amode) { 639*9668Slinton case LITSHORT: 640*9668Slinton case LITUPTO31: 641*9668Slinton case LITUPTO47: 642*9668Slinton case LITUPTO63: 643*9668Slinton argval = mode; 644*9668Slinton break; 645*9668Slinton 646*9668Slinton case INDEX: 647*9668Slinton indexf = true; 648*9668Slinton --argno; 649*9668Slinton break; 650*9668Slinton 651*9668Slinton case REG: 652*9668Slinton case REGDEF: 653*9668Slinton case AUTODEC: 654*9668Slinton break; 655*9668Slinton 656*9668Slinton case AUTOINC: 657*9668Slinton if (r == regname[PROGCTR]) { 658*9668Slinton switch (typelen(argtype)) { 659*9668Slinton case TYPB: 660*9668Slinton argval = getdisp(addr, 1, r, amode); 661*9668Slinton addr += 1; 662*9668Slinton break; 663*9668Slinton 664*9668Slinton case TYPW: 665*9668Slinton argval = getdisp(addr, 2, r, amode); 666*9668Slinton addr += 2; 667*9668Slinton break; 668*9668Slinton 669*9668Slinton case TYPL: 670*9668Slinton argval = getdisp(addr, 4, r, amode); 671*9668Slinton addr += 4; 672*9668Slinton break; 673*9668Slinton 674*9668Slinton case TYPF: 675*9668Slinton iread(&argval, addr, sizeof(argval)); 676*9668Slinton addr += 4; 677*9668Slinton break; 678*9668Slinton 679*9668Slinton case TYPQ: 680*9668Slinton case TYPD: 681*9668Slinton iread(&argval, addr+4, sizeof(argval)); 682*9668Slinton addr += 8; 683*9668Slinton break; 684*9668Slinton } 685*9668Slinton } 686*9668Slinton break; 687*9668Slinton 688*9668Slinton case AUTOINCDEF: 689*9668Slinton if (r == regname[PROGCTR]) { 690*9668Slinton argval = getdisp(addr, 4, r, amode); 691*9668Slinton addr += 4; 692*9668Slinton } 693*9668Slinton break; 694*9668Slinton 695*9668Slinton case BYTEDISP: 696*9668Slinton case BYTEDISPDEF: 697*9668Slinton argval = getdisp(addr, 1, r, amode); 698*9668Slinton addr += 1; 699*9668Slinton break; 700*9668Slinton 701*9668Slinton case WORDDISP: 702*9668Slinton case WORDDISPDEF: 703*9668Slinton argval = getdisp(addr, 2, r, amode); 704*9668Slinton addr += 2; 705*9668Slinton break; 706*9668Slinton 707*9668Slinton case LONGDISP: 708*9668Slinton case LONGDISPDEF: 709*9668Slinton argval = getdisp(addr, 4, r, amode); 710*9668Slinton addr += 4; 711*9668Slinton break; 712*9668Slinton } 713*9668Slinton } 714*9668Slinton if (ins == O_CALLS or ins == O_CALLG) { 715*9668Slinton argval += 2; 716*9668Slinton } 717*9668Slinton if (addrstatus == BRANCH) { 718*9668Slinton addr = argval; 719*9668Slinton } 720*9668Slinton } 721*9668Slinton return addr; 722*9668Slinton } 723*9668Slinton 724*9668Slinton /* 725*9668Slinton * Get the displacement of an instruction that uses displacement addressing. 726*9668Slinton */ 727*9668Slinton 728*9668Slinton private int getdisp(addr, nbytes, reg, mode) 729*9668Slinton Address addr; 730*9668Slinton int nbytes; 731*9668Slinton String reg; 732*9668Slinton int mode; 733*9668Slinton { 734*9668Slinton char byte; 735*9668Slinton short hword; 736*9668Slinton int argval; 737*9668Slinton 738*9668Slinton switch (nbytes) { 739*9668Slinton case 1: 740*9668Slinton iread(&byte, addr, sizeof(byte)); 741*9668Slinton argval = byte; 742*9668Slinton break; 743*9668Slinton 744*9668Slinton case 2: 745*9668Slinton iread(&hword, addr, sizeof(hword)); 746*9668Slinton argval = hword; 747*9668Slinton break; 748*9668Slinton 749*9668Slinton case 4: 750*9668Slinton iread(&argval, addr, sizeof(argval)); 751*9668Slinton break; 752*9668Slinton } 753*9668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 754*9668Slinton argval += addr + nbytes; 755*9668Slinton } 756*9668Slinton return argval; 757*9668Slinton } 758*9668Slinton 759*9668Slinton #define BP_OP O_BPT /* breakpoint trap */ 760*9668Slinton #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 761*9668Slinton 762*9668Slinton /* 763*9668Slinton * Setting a breakpoint at a location consists of saving 764*9668Slinton * the word at the location and poking a BP_OP there. 765*9668Slinton * 766*9668Slinton * We save the locations and words on a list for use in unsetting. 767*9668Slinton */ 768*9668Slinton 769*9668Slinton typedef struct Savelist *Savelist; 770*9668Slinton 771*9668Slinton struct Savelist { 772*9668Slinton Address location; 773*9668Slinton Byte save; 774*9668Slinton Byte refcount; 775*9668Slinton Savelist link; 776*9668Slinton }; 777*9668Slinton 778*9668Slinton private Savelist savelist; 779*9668Slinton 780*9668Slinton /* 781*9668Slinton * Set a breakpoint at the given address. Only save the word there 782*9668Slinton * if it's not already a breakpoint. 783*9668Slinton */ 784*9668Slinton 785*9668Slinton public setbp(addr) 786*9668Slinton Address addr; 787*9668Slinton { 788*9668Slinton Byte w; 789*9668Slinton Byte save; 790*9668Slinton register Savelist newsave, s; 791*9668Slinton 792*9668Slinton for (s = savelist; s != nil; s = s->link) { 793*9668Slinton if (s->location == addr) { 794*9668Slinton s->refcount++; 795*9668Slinton return; 796*9668Slinton } 797*9668Slinton } 798*9668Slinton iread(&save, addr, sizeof(addr)); 799*9668Slinton newsave = new(Savelist); 800*9668Slinton newsave->location = addr; 801*9668Slinton newsave->save = save; 802*9668Slinton newsave->refcount = 1; 803*9668Slinton newsave->link = savelist; 804*9668Slinton savelist = newsave; 805*9668Slinton w = BP_OP; 806*9668Slinton iwrite(&w, addr, sizeof(w)); 807*9668Slinton } 808*9668Slinton 809*9668Slinton /* 810*9668Slinton * Unset a breakpoint; unfortunately we have to search the SAVELIST 811*9668Slinton * to find the saved value. The assumption is that the SAVELIST will 812*9668Slinton * usually be quite small. 813*9668Slinton */ 814*9668Slinton 815*9668Slinton public unsetbp(addr) 816*9668Slinton Address addr; 817*9668Slinton { 818*9668Slinton register Savelist s, prev; 819*9668Slinton 820*9668Slinton prev = nil; 821*9668Slinton for (s = savelist; s != nil; s = s->link) { 822*9668Slinton if (s->location == addr) { 823*9668Slinton iwrite(&s->save, addr, sizeof(s->save)); 824*9668Slinton s->refcount--; 825*9668Slinton if (s->refcount == 0) { 826*9668Slinton if (prev == nil) { 827*9668Slinton savelist = s->link; 828*9668Slinton } else { 829*9668Slinton prev->link = s->link; 830*9668Slinton } 831*9668Slinton dispose(s); 832*9668Slinton } 833*9668Slinton return; 834*9668Slinton } 835*9668Slinton prev = s; 836*9668Slinton } 837*9668Slinton panic("unsetbp: couldn't find address %d", addr); 838*9668Slinton } 839*9668Slinton 840*9668Slinton /* 841*9668Slinton * Predicate to test if the reason the process stopped was because 842*9668Slinton * of a breakpoint. 843*9668Slinton */ 844*9668Slinton 845*9668Slinton public Boolean isbperr() 846*9668Slinton { 847*9668Slinton return (Boolean) (not isfinished(process) and errnum(process) == SIGTRAP); 848*9668Slinton } 849*9668Slinton 850*9668Slinton /* 851*9668Slinton * Enter a procedure by creating and executing a call instruction. 852*9668Slinton */ 853*9668Slinton 854*9668Slinton #define CALLSIZE 7 /* size of call instruction */ 855*9668Slinton 856*9668Slinton public beginproc(p, argc) 857*9668Slinton Symbol p; 858*9668Slinton Integer argc; 859*9668Slinton { 860*9668Slinton char save[CALLSIZE]; 861*9668Slinton struct { 862*9668Slinton VaxOpcode op; 863*9668Slinton unsigned char numargs; 864*9668Slinton unsigned char mode; 865*9668Slinton char addr[sizeof(long)]; /* unaligned long */ 866*9668Slinton } call; 867*9668Slinton long dest; 868*9668Slinton 869*9668Slinton pc = 2; 870*9668Slinton iread(save, pc, sizeof(save)); 871*9668Slinton call.op = O_CALLS; 872*9668Slinton call.numargs = argc; 873*9668Slinton call.mode = 0xef; 874*9668Slinton dest = codeloc(p) - 2 - (pc + 7); 875*9668Slinton mov(&dest, call.addr, sizeof(call.addr)); 876*9668Slinton iwrite(&call, pc, sizeof(call)); 877*9668Slinton setreg(PROGCTR, pc); 878*9668Slinton pstep(process); 879*9668Slinton iwrite(save, pc, sizeof(save)); 880*9668Slinton pc = reg(PROGCTR); 881*9668Slinton if (not isbperr()) { 882*9668Slinton printstatus(); 883*9668Slinton } 884*9668Slinton } 885