1*21608Sdist /* 2*21608Sdist * Copyright (c) 1983 Regents of the University of California. 3*21608Sdist * All rights reserved. The Berkeley software License Agreement 4*21608Sdist * specifies the terms and conditions for redistribution. 5*21608Sdist */ 69668Slinton 7*21608Sdist #ifndef lint 8*21608Sdist static char sccsid[] = "@(#)vax.c 5.1 (Berkeley) 05/31/85"; 9*21608Sdist #endif not lint 109668Slinton 1118222Slinton static char rcsid[] = "$Header: machine.c,v 1.5 84/12/26 10:40:05 linton Exp $"; 1218222Slinton 139668Slinton /* 149668Slinton * Target machine dependent stuff. 159668Slinton */ 169668Slinton 179668Slinton #include "defs.h" 189668Slinton #include "machine.h" 199668Slinton #include "process.h" 2016612Ssam #include "runtime.h" 219668Slinton #include "events.h" 229668Slinton #include "main.h" 239668Slinton #include "symbols.h" 249668Slinton #include "source.h" 259668Slinton #include "mappings.h" 269668Slinton #include "object.h" 2718222Slinton #include "keywords.h" 289693Slinton #include "ops.h" 299668Slinton #include <signal.h> 309668Slinton 319668Slinton #ifndef public 329668Slinton typedef unsigned int Address; 339668Slinton typedef unsigned char Byte; 349668Slinton typedef unsigned int Word; 359668Slinton 369668Slinton #define NREG 16 379668Slinton 389668Slinton #define ARGP 12 399668Slinton #define FRP 13 409668Slinton #define STKP 14 419668Slinton #define PROGCTR 15 429668Slinton 439668Slinton #define BITSPERBYTE 8 449668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) 459668Slinton 469668Slinton #define nargspassed(frame) argn(0, frame) 479668Slinton 489668Slinton #include "source.h" 499668Slinton #include "symbols.h" 509668Slinton 519668Slinton Address pc; 529668Slinton Address prtaddr; 539668Slinton 549668Slinton #endif 559668Slinton 569668Slinton private Address printop(); 579668Slinton 589668Slinton /* 599668Slinton * Decode and print the instructions within the given address range. 609668Slinton */ 619668Slinton 629668Slinton public printinst(lowaddr, highaddr) 639668Slinton Address lowaddr; 649668Slinton Address highaddr; 659668Slinton { 669668Slinton register Address addr; 679668Slinton 689668Slinton for (addr = lowaddr; addr <= highaddr; ) { 699668Slinton addr = printop(addr); 709668Slinton } 719668Slinton prtaddr = addr; 729668Slinton } 739668Slinton 749668Slinton /* 759668Slinton * Another approach: print n instructions starting at the given address. 769668Slinton */ 779668Slinton 789668Slinton public printninst(count, addr) 799668Slinton int count; 809668Slinton Address addr; 819668Slinton { 829668Slinton register Integer i; 839668Slinton register Address newaddr; 849668Slinton 859668Slinton if (count <= 0) { 869668Slinton error("non-positive repetition count"); 879668Slinton } else { 889668Slinton newaddr = addr; 899668Slinton for (i = 0; i < count; i++) { 909668Slinton newaddr = printop(newaddr); 919668Slinton } 929668Slinton prtaddr = newaddr; 939668Slinton } 949668Slinton } 959668Slinton 969668Slinton /* 979668Slinton * Hacked version of adb's VAX instruction decoder. 989668Slinton */ 999668Slinton 1009668Slinton private Address printop(addr) 1019668Slinton Address addr; 1029668Slinton { 1039668Slinton Optab op; 1049668Slinton VaxOpcode ins; 1059668Slinton unsigned char mode; 1069668Slinton int argtype, amode, argno, argval; 1079668Slinton String reg; 1089668Slinton Boolean indexf; 1099668Slinton short offset; 1109668Slinton 1119668Slinton argval = 0; 1129668Slinton indexf = false; 1139668Slinton printf("%08x ", addr); 1149668Slinton iread(&ins, addr, sizeof(ins)); 1159668Slinton addr += 1; 1169668Slinton op = optab[ins]; 1179668Slinton printf("%s", op.iname); 1189668Slinton for (argno = 0; argno < op.numargs; argno++) { 1199668Slinton if (indexf == true) { 1209668Slinton indexf = false; 1219668Slinton } else if (argno == 0) { 1229668Slinton printf("\t"); 1239668Slinton } else { 1249668Slinton printf(","); 1259668Slinton } 1269668Slinton argtype = op.argtype[argno]; 1279668Slinton if (is_branch_disp(argtype)) { 1289668Slinton mode = 0xAF + (typelen(argtype) << 5); 1299668Slinton } else { 1309668Slinton iread(&mode, addr, sizeof(mode)); 1319668Slinton addr += 1; 1329668Slinton } 1339668Slinton reg = regname[regnm(mode)]; 1349668Slinton amode = addrmode(mode); 1359668Slinton switch (amode) { 1369668Slinton case LITSHORT: 1379668Slinton case LITUPTO31: 1389668Slinton case LITUPTO47: 1399668Slinton case LITUPTO63: 1409668Slinton if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD) 1419668Slinton printf("$%s", fltimm[mode]); 1429668Slinton else 1439668Slinton printf("$%x", mode); 1449668Slinton argval = mode; 1459668Slinton break; 1469668Slinton 1479668Slinton case INDEX: 1489668Slinton printf("[%s]", reg); 1499668Slinton indexf = true; 1509668Slinton argno--; 1519668Slinton break; 1529668Slinton 1539668Slinton case REG: 1549668Slinton printf("%s", reg); 1559668Slinton break; 1569668Slinton 1579668Slinton case REGDEF: 1589668Slinton printf("(%s)", reg); 1599668Slinton break; 1609668Slinton 1619668Slinton case AUTODEC: 1629668Slinton printf("-(%s)", reg); 1639668Slinton break; 1649668Slinton 1659668Slinton case AUTOINC: 1669668Slinton if (reg != regname[PROGCTR]) { 1679668Slinton printf("(%s)+", reg); 1689668Slinton } else { 1699668Slinton printf("$"); 1709668Slinton switch (typelen(argtype)) { 1719668Slinton case TYPB: 1729668Slinton argval = printdisp(addr, 1, reg, amode); 1739668Slinton addr += 1; 1749668Slinton break; 1759668Slinton 1769668Slinton case TYPW: 1779668Slinton argval = printdisp(addr, 2, reg, amode); 1789668Slinton addr += 2; 1799668Slinton break; 1809668Slinton 1819668Slinton case TYPL: 1829668Slinton argval = printdisp(addr, 4, reg, amode); 1839668Slinton addr += 4; 1849668Slinton break; 1859668Slinton 1869668Slinton case TYPF: 1879668Slinton iread(&argval, addr, sizeof(argval)); 1889668Slinton printf("%06x", argval); 1899668Slinton addr += 4; 1909668Slinton break; 1919668Slinton 1929668Slinton case TYPQ: 1939668Slinton case TYPD: 1949668Slinton iread(&argval, addr, sizeof(argval)); 1959668Slinton printf("%06x", argval); 1969668Slinton iread(&argval, addr+4, sizeof(argval)); 1979668Slinton printf("%06x", argval); 1989668Slinton addr += 8; 1999668Slinton break; 2009668Slinton } 2019668Slinton } 2029668Slinton break; 2039668Slinton 2049668Slinton case AUTOINCDEF: 2059668Slinton if (reg == regname[PROGCTR]) { 2069668Slinton printf("*$"); 2079668Slinton argval = printdisp(addr, 4, reg, amode); 2089668Slinton addr += 4; 2099668Slinton } else { 2109668Slinton printf("*(%s)+", reg); 2119668Slinton } 2129668Slinton break; 2139668Slinton 2149668Slinton case BYTEDISP: 2159668Slinton argval = printdisp(addr, 1, reg, amode); 2169668Slinton addr += 1; 2179668Slinton break; 2189668Slinton 2199668Slinton case BYTEDISPDEF: 2209668Slinton printf("*"); 2219668Slinton argval = printdisp(addr, 1, reg, amode); 2229668Slinton addr += 1; 2239668Slinton break; 2249668Slinton 2259668Slinton case WORDDISP: 2269668Slinton argval = printdisp(addr, 2, reg, amode); 2279668Slinton addr += 2; 2289668Slinton break; 2299668Slinton 2309668Slinton case WORDDISPDEF: 2319668Slinton printf("*"); 2329668Slinton argval = printdisp(addr, 2, reg, amode); 2339668Slinton addr += 2; 2349668Slinton break; 2359668Slinton 2369668Slinton case LONGDISP: 2379668Slinton argval = printdisp(addr, 4, reg, amode); 2389668Slinton addr += 4; 2399668Slinton break; 2409668Slinton 2419668Slinton case LONGDISPDEF: 2429668Slinton printf("*"); 2439668Slinton argval = printdisp(addr, 4, reg, amode); 2449668Slinton addr += 4; 2459668Slinton break; 2469668Slinton } 2479668Slinton } 2489668Slinton if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) { 2499668Slinton for (argno = 0; argno <= argval; argno++) { 2509668Slinton iread(&offset, addr, sizeof(offset)); 2519668Slinton printf("\n\t\t%d", offset); 2529668Slinton addr += 2; 2539668Slinton } 2549668Slinton } 2559668Slinton printf("\n"); 2569668Slinton return addr; 2579668Slinton } 2589668Slinton 2599668Slinton /* 2609668Slinton * Print the displacement of an instruction that uses displacement 2619668Slinton * addressing. 2629668Slinton */ 2639668Slinton 2649668Slinton private int printdisp(addr, nbytes, reg, mode) 2659668Slinton Address addr; 2669668Slinton int nbytes; 2679668Slinton char *reg; 2689668Slinton int mode; 2699668Slinton { 2709668Slinton char byte; 2719668Slinton short hword; 2729668Slinton int argval; 27314338Slinton Symbol f; 2749668Slinton 2759668Slinton switch (nbytes) { 2769668Slinton case 1: 2779668Slinton iread(&byte, addr, sizeof(byte)); 2789668Slinton argval = byte; 2799668Slinton break; 2809668Slinton 2819668Slinton case 2: 2829668Slinton iread(&hword, addr, sizeof(hword)); 2839668Slinton argval = hword; 2849668Slinton break; 2859668Slinton 2869668Slinton case 4: 2879668Slinton iread(&argval, addr, sizeof(argval)); 2889668Slinton break; 2899668Slinton } 2909668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 2919668Slinton argval += addr + nbytes; 2929668Slinton } 2939668Slinton if (reg == regname[PROGCTR]) { 29414338Slinton f = whatblock((Address) argval + 2); 29514338Slinton if (codeloc(f) == argval + 2) { 29614338Slinton printf("%s", symname(f)); 29714338Slinton } else { 29814338Slinton printf("%x", argval); 29914338Slinton } 3009668Slinton } else { 30118222Slinton if (varIsSet("$hexoffsets")) { 30218222Slinton if (argval < 0) { 30318222Slinton printf("-%x(%s)", -(argval), reg); 30418222Slinton } else { 30518222Slinton printf("%x(%s)", argval, reg); 30618222Slinton } 30718222Slinton } else { 30818222Slinton printf("%d(%s)", argval, reg); 30918222Slinton } 3109668Slinton } 3119668Slinton return argval; 3129668Slinton } 3139668Slinton 3149668Slinton /* 3159668Slinton * Print the contents of the addresses within the given range 3169668Slinton * according to the given format. 3179668Slinton */ 3189668Slinton 3199668Slinton typedef struct { 3209668Slinton String name; 3219668Slinton String printfstring; 3229668Slinton int length; 3239668Slinton } Format; 3249668Slinton 3259668Slinton private Format fmt[] = { 3269668Slinton { "d", " %d", sizeof(short) }, 3279668Slinton { "D", " %ld", sizeof(long) }, 3289668Slinton { "o", " %o", sizeof(short) }, 3299668Slinton { "O", " %lo", sizeof(long) }, 3309668Slinton { "x", " %04x", sizeof(short) }, 3319668Slinton { "X", " %08x", sizeof(long) }, 3329668Slinton { "b", " \\%o", sizeof(char) }, 3339668Slinton { "c", " '%c'", sizeof(char) }, 3349668Slinton { "s", "%c", sizeof(char) }, 33514338Slinton { "f", " %f", sizeof(float) }, 3369668Slinton { "g", " %g", sizeof(double) }, 3379668Slinton { nil, nil, 0 } 3389668Slinton }; 3399668Slinton 34011174Slinton private Format *findformat(s) 34111174Slinton String s; 34211174Slinton { 34311174Slinton register Format *f; 34411174Slinton 34511174Slinton f = &fmt[0]; 34611174Slinton while (f->name != nil and not streq(f->name, s)) { 34711174Slinton ++f; 34811174Slinton } 34911174Slinton if (f->name == nil) { 35011174Slinton error("bad print format \"%s\"", s); 35111174Slinton } 35211174Slinton return f; 35311174Slinton } 35411174Slinton 3559668Slinton public Address printdata(lowaddr, highaddr, format) 3569668Slinton Address lowaddr; 3579668Slinton Address highaddr; 3589668Slinton String format; 3599668Slinton { 3609668Slinton register int n; 3619668Slinton register Address addr; 3629668Slinton register Format *f; 3639668Slinton int value; 3649668Slinton 3659668Slinton if (lowaddr > highaddr) { 3669668Slinton error("first address larger than second"); 3679668Slinton } 36811174Slinton f = findformat(format); 3699668Slinton n = 0; 3709668Slinton value = 0; 3719668Slinton for (addr = lowaddr; addr <= highaddr; addr += f->length) { 3729668Slinton if (n == 0) { 3739668Slinton printf("%08x: ", addr); 3749668Slinton } 3759668Slinton dread(&value, addr, f->length); 3769668Slinton printf(f->printfstring, value); 3779668Slinton ++n; 3789668Slinton if (n >= (16 div f->length)) { 3799668Slinton putchar('\n'); 3809668Slinton n = 0; 3819668Slinton } 3829668Slinton } 3839668Slinton if (n != 0) { 3849668Slinton putchar('\n'); 3859668Slinton } 3869668Slinton prtaddr = addr; 3879668Slinton return addr; 3889668Slinton } 3899668Slinton 3909668Slinton /* 3919668Slinton * The other approach is to print n items starting with a given address. 3929668Slinton */ 3939668Slinton 3949668Slinton public printndata(count, startaddr, format) 3959668Slinton int count; 3969668Slinton Address startaddr; 3979668Slinton String format; 3989668Slinton { 3999668Slinton register int i, n; 4009668Slinton register Address addr; 4019668Slinton register Format *f; 4029668Slinton register Boolean isstring; 40314338Slinton char c; 40414338Slinton union { 40514338Slinton char charv; 40614338Slinton short shortv; 40714338Slinton int intv; 40814338Slinton float floatv; 40914338Slinton double doublev; 41014338Slinton } value; 4119668Slinton 4129668Slinton if (count <= 0) { 4139668Slinton error("non-positive repetition count"); 4149668Slinton } 41511174Slinton f = findformat(format); 4169668Slinton isstring = (Boolean) streq(f->name, "s"); 4179668Slinton n = 0; 4189668Slinton addr = startaddr; 41914338Slinton value.intv = 0; 4209668Slinton for (i = 0; i < count; i++) { 4219668Slinton if (n == 0) { 4229668Slinton printf("%08x: ", addr); 4239668Slinton } 4249668Slinton if (isstring) { 4259668Slinton putchar('"'); 42614338Slinton dread(&c, addr, sizeof(char)); 42714338Slinton while (c != '\0') { 42814338Slinton printchar(c); 4299668Slinton ++addr; 43014338Slinton dread(&c, addr, sizeof(char)); 4319668Slinton } 4329668Slinton putchar('"'); 4339668Slinton putchar('\n'); 4349668Slinton n = 0; 4359668Slinton addr += sizeof(String); 4369668Slinton } else { 4379668Slinton dread(&value, addr, f->length); 4389668Slinton printf(f->printfstring, value); 4399668Slinton ++n; 4409668Slinton if (n >= (16 div f->length)) { 4419668Slinton putchar('\n'); 4429668Slinton n = 0; 4439668Slinton } 4449668Slinton addr += f->length; 4459668Slinton } 4469668Slinton } 4479668Slinton if (n != 0) { 4489668Slinton putchar('\n'); 4499668Slinton } 4509668Slinton prtaddr = addr; 4519668Slinton } 4529668Slinton 4539668Slinton /* 45411174Slinton * Print out a value according to the given format. 45511174Slinton */ 45611174Slinton 45711174Slinton public printvalue(v, format) 45811174Slinton long v; 45911174Slinton String format; 46011174Slinton { 46111174Slinton Format *f; 46211174Slinton char *p, *q; 46311174Slinton 46411174Slinton f = findformat(format); 46511174Slinton if (streq(f->name, "s")) { 46611174Slinton putchar('"'); 46711174Slinton p = (char *) &v; 46811174Slinton q = p + sizeof(v); 46911174Slinton while (p < q) { 47011174Slinton printchar(*p); 47111174Slinton ++p; 47211174Slinton } 47311174Slinton putchar('"'); 47411174Slinton } else { 47511174Slinton printf(f->printfstring, v); 47611174Slinton } 47711174Slinton putchar('\n'); 47811174Slinton } 47911174Slinton 48011174Slinton /* 4819668Slinton * Print out an execution time error. 4829842Slinton * Assumes the source position of the error has been calculated. 4839668Slinton * 4849668Slinton * Have to check if the -r option was specified; if so then 4859668Slinton * the object file information hasn't been read in yet. 4869668Slinton */ 4879668Slinton 4889668Slinton public printerror() 4899668Slinton { 4909668Slinton extern Integer sys_nsig; 4919668Slinton extern String sys_siglist[]; 49218222Slinton integer err; 4939668Slinton 4949668Slinton if (isfinished(process)) { 49516932Ssam err = exitcode(process); 49618222Slinton if (err == 0) { 49718222Slinton printf("\"%s\" terminated normally\n", objname); 49818222Slinton } else { 49918222Slinton printf("\"%s\" terminated abnormally (exit code %d)\n", 50018222Slinton objname, err 50118222Slinton ); 50218222Slinton } 5039668Slinton erecover(); 5049668Slinton } 5059668Slinton if (runfirst) { 50618222Slinton fprintf(stderr, "Entering debugger ...\n"); 5079668Slinton init(); 5089668Slinton } 5099668Slinton err = errnum(process); 5109668Slinton putchar('\n'); 51116932Ssam printsig(err); 51218222Slinton putchar(' '); 51316932Ssam printloc(); 51416932Ssam putchar('\n'); 5159668Slinton if (curline > 0) { 5169668Slinton printlines(curline, curline); 5179668Slinton } else { 5189668Slinton printinst(pc, pc); 5199668Slinton } 5209668Slinton erecover(); 5219668Slinton } 5229668Slinton 52318222Slinton /* 52418222Slinton * Print out a signal. 52518222Slinton */ 52618222Slinton 52716932Ssam private String illinames[] = { 52818222Slinton "reserved addressing fault", 52918222Slinton "priviliged instruction fault", 53018222Slinton "reserved operand fault" 53116932Ssam }; 53218222Slinton 53316932Ssam private String fpenames[] = { 53418222Slinton nil, 53518222Slinton "integer overflow trap", 53618222Slinton "integer divide by zero trap", 53718222Slinton "floating overflow trap", 53818222Slinton "floating/decimal divide by zero trap", 53918222Slinton "floating underflow trap", 54018222Slinton "decimal overflow trap", 54118222Slinton "subscript out of range trap", 54218222Slinton "floating overflow fault", 54318222Slinton "floating divide by zero fault", 54418222Slinton "floating undeflow fault" 54516932Ssam }; 54616932Ssam 54718222Slinton public printsig (signo) 54818222Slinton integer signo; 54916932Ssam { 55018222Slinton integer code; 55116932Ssam 55218222Slinton if (signo < 0 or signo > sys_nsig) { 55318222Slinton printf("[signal %d]", signo); 55418222Slinton } else { 55518222Slinton printf("%s", sys_siglist[signo]); 55616932Ssam } 55718222Slinton code = errcode(process); 55818222Slinton if (signo == SIGILL) { 55918222Slinton if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) { 56018222Slinton printf(" (%s)", illinames[code]); 56118222Slinton } 56218222Slinton } else if (signo == SIGFPE) { 56318222Slinton if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) { 56418222Slinton printf(" (%s)", fpenames[code]); 56518222Slinton } 56618222Slinton } 56716932Ssam } 56816932Ssam 5699668Slinton /* 5709668Slinton * Note the termination of the program. We do this so as to avoid 5719668Slinton * having the process exit, which would make the values of variables 5729668Slinton * inaccessible. We do want to flush all output buffers here, 5739668Slinton * otherwise it'll never get done. 5749668Slinton */ 5759668Slinton 5769668Slinton public endprogram() 5779668Slinton { 5789668Slinton Integer exitcode; 5799668Slinton 5809668Slinton stepto(nextaddr(pc, true)); 5819668Slinton printnews(); 5829668Slinton exitcode = argn(1, nil); 58318222Slinton if (exitcode != 0) { 58418222Slinton printf("\nexecution completed (exit code %d)\n", exitcode); 58518222Slinton } else { 58618222Slinton printf("\nexecution completed\n"); 58718222Slinton } 5889668Slinton getsrcpos(); 5899668Slinton erecover(); 5909668Slinton } 5919668Slinton 5929668Slinton /* 5939668Slinton * Single step the machine a source line (or instruction if "inst_tracing" 59410621Slinton * is true). If "isnext" is true, skip over procedure calls. 5959668Slinton */ 5969668Slinton 5979668Slinton private Address getcall(); 5989668Slinton 5999668Slinton public dostep(isnext) 6009668Slinton Boolean isnext; 6019668Slinton { 6029668Slinton register Address addr; 6039668Slinton register Lineno line; 6049668Slinton String filename; 60518222Slinton Address startaddr; 6069668Slinton 60716612Ssam startaddr = pc; 6089668Slinton addr = nextaddr(pc, isnext); 60910621Slinton if (not inst_tracing and nlhdr.nlines != 0) { 6109668Slinton line = linelookup(addr); 6119668Slinton while (line == 0) { 61218222Slinton addr = nextaddr(addr, isnext); 6139668Slinton line = linelookup(addr); 6149668Slinton } 61510621Slinton curline = line; 61610621Slinton } else { 61710621Slinton curline = 0; 6189668Slinton } 6199668Slinton stepto(addr); 6209668Slinton filename = srcfilename(addr); 6219668Slinton setsource(filename); 6229668Slinton } 6239668Slinton 6249668Slinton /* 6259668Slinton * Compute the next address that will be executed from the given one. 6269668Slinton * If "isnext" is true then consider a procedure call as straight line code. 6279668Slinton * 6289668Slinton * We must unfortunately do much of the same work that is necessary 6299668Slinton * to print instructions. In addition we have to deal with branches. 6309668Slinton * Unconditional branches we just follow, for conditional branches 6319668Slinton * we continue execution to the current location and then single step 6329668Slinton * the machine. We assume that the last argument in an instruction 6339668Slinton * that branches is the branch address (or relative offset). 6349668Slinton */ 6359668Slinton 63618222Slinton private Address findnextaddr(); 63718222Slinton 6389668Slinton public Address nextaddr(startaddr, isnext) 6399668Slinton Address startaddr; 64016612Ssam boolean isnext; 64116612Ssam { 64216612Ssam Address addr; 64316612Ssam 64416612Ssam addr = usignal(process); 64516612Ssam if (addr == 0 or addr == 1) { 64616612Ssam addr = findnextaddr(startaddr, isnext); 64716612Ssam } 64816612Ssam return addr; 64916612Ssam } 65016612Ssam 65118222Slinton /* 65218222Slinton * Determine if it's ok to skip function f entered by instruction ins. 65318222Slinton * If so, we're going to compute the return address and step to it. 65418222Slinton * Therefore we cannot skip over a function entered by a jsb or bsb, 65518222Slinton * since the return address is not easily computed for them. 65618222Slinton */ 65718222Slinton 65818222Slinton private boolean skipfunc (ins, f) 65918222Slinton VaxOpcode ins; 66018222Slinton Symbol f; 66118222Slinton { 66218222Slinton boolean b; 66318222Slinton 66418222Slinton b = (boolean) ( 66518222Slinton ins != O_JSB and ins != O_BSBB and ins != O_BSBW and 66618222Slinton not inst_tracing and nlhdr.nlines != 0 and 66718222Slinton nosource(curfunc) and canskip(curfunc) 66818222Slinton ); 66918222Slinton return b; 67018222Slinton } 67118222Slinton 67216612Ssam private Address findnextaddr(startaddr, isnext) 67316612Ssam Address startaddr; 6749668Slinton Boolean isnext; 6759668Slinton { 6769668Slinton register Address addr; 6779668Slinton Optab op; 6789668Slinton VaxOpcode ins; 6799668Slinton unsigned char mode; 6809668Slinton int argtype, amode, argno, argval; 6819668Slinton String r; 6829668Slinton Boolean indexf; 6839668Slinton enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; 6849668Slinton 6859668Slinton argval = 0; 6869668Slinton indexf = false; 6879668Slinton addr = startaddr; 6889668Slinton iread(&ins, addr, sizeof(ins)); 6899668Slinton switch (ins) { 69018222Slinton /* 69118222Slinton * It used to be that unconditional jumps and branches were handled 69218222Slinton * by taking their destination address as the next address. While 69318222Slinton * saving the cost of starting up the process, this approach 69418222Slinton * doesn't work when jumping indirect (since the value in the 69518222Slinton * register might not yet have been set). 69618222Slinton * 69718222Slinton * So unconditional jumps and branches are now handled the same way 69818222Slinton * as conditional jumps and branches. 69918222Slinton * 7009668Slinton case O_BRB: 7019668Slinton case O_BRW: 7029668Slinton addrstatus = BRANCH; 7039668Slinton break; 70418222Slinton * 70518222Slinton */ 7069668Slinton 7079668Slinton case O_BSBB: 7089668Slinton case O_BSBW: 7099668Slinton case O_JSB: 7109668Slinton case O_CALLG: 7119668Slinton case O_CALLS: 71218222Slinton addrstatus = KNOWN; 71318222Slinton stepto(addr); 71418222Slinton pstep(process, DEFSIG); 71518222Slinton addr = reg(PROGCTR); 71618222Slinton pc = addr; 71718222Slinton setcurfunc(whatblock(pc)); 71818222Slinton if (not isbperr()) { 71918222Slinton printstatus(); 72018222Slinton /* NOTREACHED */ 72118222Slinton } 72218222Slinton bpact(); 72318222Slinton if (isnext or skipfunc(ins, curfunc)) { 7249668Slinton addrstatus = KNOWN; 72518222Slinton addr = return_addr(); 7269668Slinton stepto(addr); 72711864Slinton bpact(); 72818222Slinton } else { 72918222Slinton callnews(/* iscall = */ true); 7309668Slinton } 7319668Slinton break; 7329668Slinton 7339668Slinton case O_RSB: 7349668Slinton case O_RET: 7359668Slinton addrstatus = KNOWN; 73618222Slinton stepto(addr); 7379668Slinton callnews(/* iscall = */ false); 73818222Slinton pstep(process, DEFSIG); 73918222Slinton addr = reg(PROGCTR); 74018222Slinton pc = addr; 74118222Slinton if (not isbperr()) { 74218222Slinton printstatus(); 74316612Ssam } 74411874Slinton bpact(); 7459668Slinton break; 7469668Slinton 74718222Slinton case O_BRB: case O_BRW: 74816612Ssam case O_JMP: /* because it may be jmp (r1) */ 7499668Slinton case O_BNEQ: case O_BEQL: case O_BGTR: 7509668Slinton case O_BLEQ: case O_BGEQ: case O_BLSS: 7519668Slinton case O_BGTRU: case O_BLEQU: case O_BVC: 7529668Slinton case O_BVS: case O_BCC: case O_BCS: 7539668Slinton case O_CASEB: case O_CASEW: case O_CASEL: 7549668Slinton case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 7559668Slinton case O_BBSC: case O_BBCC: case O_BBSSI: 7569668Slinton case O_BBCCI: case O_BLBS: case O_BLBC: 7579668Slinton case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 7589668Slinton case O_SOBGEQ: case O_SOBGTR: 7599668Slinton addrstatus = KNOWN; 7609668Slinton stepto(addr); 76116612Ssam pstep(process, DEFSIG); 7629668Slinton addr = reg(PROGCTR); 7639668Slinton pc = addr; 7649668Slinton if (not isbperr()) { 7659668Slinton printstatus(); 7669668Slinton } 7679668Slinton break; 7689668Slinton 7699668Slinton default: 7709668Slinton addrstatus = SEQUENTIAL; 7719668Slinton break; 7729668Slinton } 7739668Slinton if (addrstatus != KNOWN) { 7749668Slinton addr += 1; 7759668Slinton op = optab[ins]; 7769668Slinton for (argno = 0; argno < op.numargs; argno++) { 7779668Slinton if (indexf == true) { 7789668Slinton indexf = false; 7799668Slinton } 7809668Slinton argtype = op.argtype[argno]; 7819668Slinton if (is_branch_disp(argtype)) { 7829668Slinton mode = 0xAF + (typelen(argtype) << 5); 7839668Slinton } else { 7849668Slinton iread(&mode, addr, sizeof(mode)); 7859668Slinton addr += 1; 7869668Slinton } 7879668Slinton r = regname[regnm(mode)]; 7889668Slinton amode = addrmode(mode); 7899668Slinton switch (amode) { 7909668Slinton case LITSHORT: 7919668Slinton case LITUPTO31: 7929668Slinton case LITUPTO47: 7939668Slinton case LITUPTO63: 7949668Slinton argval = mode; 7959668Slinton break; 7969668Slinton 7979668Slinton case INDEX: 7989668Slinton indexf = true; 7999668Slinton --argno; 8009668Slinton break; 8019668Slinton 8029668Slinton case REG: 8039668Slinton case REGDEF: 8049668Slinton case AUTODEC: 8059668Slinton break; 8069668Slinton 8079668Slinton case AUTOINC: 8089668Slinton if (r == regname[PROGCTR]) { 8099668Slinton switch (typelen(argtype)) { 8109668Slinton case TYPB: 8119668Slinton argval = getdisp(addr, 1, r, amode); 8129668Slinton addr += 1; 8139668Slinton break; 8149668Slinton 8159668Slinton case TYPW: 8169668Slinton argval = getdisp(addr, 2, r, amode); 8179668Slinton addr += 2; 8189668Slinton break; 8199668Slinton 8209668Slinton case TYPL: 8219668Slinton argval = getdisp(addr, 4, r, amode); 8229668Slinton addr += 4; 8239668Slinton break; 8249668Slinton 8259668Slinton case TYPF: 8269668Slinton iread(&argval, addr, sizeof(argval)); 8279668Slinton addr += 4; 8289668Slinton break; 8299668Slinton 8309668Slinton case TYPQ: 8319668Slinton case TYPD: 8329668Slinton iread(&argval, addr+4, sizeof(argval)); 8339668Slinton addr += 8; 8349668Slinton break; 8359668Slinton } 8369668Slinton } 8379668Slinton break; 8389668Slinton 8399668Slinton case AUTOINCDEF: 8409668Slinton if (r == regname[PROGCTR]) { 8419668Slinton argval = getdisp(addr, 4, r, amode); 8429668Slinton addr += 4; 8439668Slinton } 8449668Slinton break; 8459668Slinton 8469668Slinton case BYTEDISP: 8479668Slinton case BYTEDISPDEF: 8489668Slinton argval = getdisp(addr, 1, r, amode); 8499668Slinton addr += 1; 8509668Slinton break; 8519668Slinton 8529668Slinton case WORDDISP: 8539668Slinton case WORDDISPDEF: 8549668Slinton argval = getdisp(addr, 2, r, amode); 8559668Slinton addr += 2; 8569668Slinton break; 8579668Slinton 8589668Slinton case LONGDISP: 8599668Slinton case LONGDISPDEF: 8609668Slinton argval = getdisp(addr, 4, r, amode); 8619668Slinton addr += 4; 8629668Slinton break; 8639668Slinton } 8649668Slinton } 8659668Slinton if (ins == O_CALLS or ins == O_CALLG) { 8669668Slinton argval += 2; 8679668Slinton } 8689668Slinton if (addrstatus == BRANCH) { 8699668Slinton addr = argval; 8709668Slinton } 8719668Slinton } 8729668Slinton return addr; 8739668Slinton } 8749668Slinton 8759668Slinton /* 8769668Slinton * Get the displacement of an instruction that uses displacement addressing. 8779668Slinton */ 8789668Slinton 8799668Slinton private int getdisp(addr, nbytes, reg, mode) 8809668Slinton Address addr; 8819668Slinton int nbytes; 8829668Slinton String reg; 8839668Slinton int mode; 8849668Slinton { 8859668Slinton char byte; 8869668Slinton short hword; 8879668Slinton int argval; 8889668Slinton 8899668Slinton switch (nbytes) { 8909668Slinton case 1: 8919668Slinton iread(&byte, addr, sizeof(byte)); 8929668Slinton argval = byte; 8939668Slinton break; 8949668Slinton 8959668Slinton case 2: 8969668Slinton iread(&hword, addr, sizeof(hword)); 8979668Slinton argval = hword; 8989668Slinton break; 8999668Slinton 9009668Slinton case 4: 9019668Slinton iread(&argval, addr, sizeof(argval)); 9029668Slinton break; 9039668Slinton } 9049668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 9059668Slinton argval += addr + nbytes; 9069668Slinton } 9079668Slinton return argval; 9089668Slinton } 9099668Slinton 9109668Slinton #define BP_OP O_BPT /* breakpoint trap */ 9119668Slinton #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 9129668Slinton 9139668Slinton /* 9149668Slinton * Setting a breakpoint at a location consists of saving 9159668Slinton * the word at the location and poking a BP_OP there. 9169668Slinton * 9179668Slinton * We save the locations and words on a list for use in unsetting. 9189668Slinton */ 9199668Slinton 9209668Slinton typedef struct Savelist *Savelist; 9219668Slinton 9229668Slinton struct Savelist { 9239668Slinton Address location; 9249668Slinton Byte save; 9259668Slinton Byte refcount; 9269668Slinton Savelist link; 9279668Slinton }; 9289668Slinton 9299668Slinton private Savelist savelist; 9309668Slinton 9319668Slinton /* 9329668Slinton * Set a breakpoint at the given address. Only save the word there 9339668Slinton * if it's not already a breakpoint. 9349668Slinton */ 9359668Slinton 9369668Slinton public setbp(addr) 9379668Slinton Address addr; 9389668Slinton { 9399668Slinton Byte w; 9409668Slinton Byte save; 9419668Slinton register Savelist newsave, s; 9429668Slinton 9439668Slinton for (s = savelist; s != nil; s = s->link) { 9449668Slinton if (s->location == addr) { 9459668Slinton s->refcount++; 9469668Slinton return; 9479668Slinton } 9489668Slinton } 94911174Slinton iread(&save, addr, sizeof(save)); 9509668Slinton newsave = new(Savelist); 9519668Slinton newsave->location = addr; 9529668Slinton newsave->save = save; 9539668Slinton newsave->refcount = 1; 9549668Slinton newsave->link = savelist; 9559668Slinton savelist = newsave; 9569668Slinton w = BP_OP; 9579668Slinton iwrite(&w, addr, sizeof(w)); 9589668Slinton } 9599668Slinton 9609668Slinton /* 9619668Slinton * Unset a breakpoint; unfortunately we have to search the SAVELIST 9629668Slinton * to find the saved value. The assumption is that the SAVELIST will 9639668Slinton * usually be quite small. 9649668Slinton */ 9659668Slinton 9669668Slinton public unsetbp(addr) 9679668Slinton Address addr; 9689668Slinton { 9699668Slinton register Savelist s, prev; 9709668Slinton 9719668Slinton prev = nil; 9729668Slinton for (s = savelist; s != nil; s = s->link) { 9739668Slinton if (s->location == addr) { 9749668Slinton iwrite(&s->save, addr, sizeof(s->save)); 9759668Slinton s->refcount--; 9769668Slinton if (s->refcount == 0) { 9779668Slinton if (prev == nil) { 9789668Slinton savelist = s->link; 9799668Slinton } else { 9809668Slinton prev->link = s->link; 9819668Slinton } 9829668Slinton dispose(s); 9839668Slinton } 9849668Slinton return; 9859668Slinton } 9869668Slinton prev = s; 9879668Slinton } 9889668Slinton panic("unsetbp: couldn't find address %d", addr); 9899668Slinton } 9909668Slinton 9919668Slinton /* 9929668Slinton * Enter a procedure by creating and executing a call instruction. 9939668Slinton */ 9949668Slinton 9959668Slinton #define CALLSIZE 7 /* size of call instruction */ 9969668Slinton 9979668Slinton public beginproc(p, argc) 9989668Slinton Symbol p; 9999668Slinton Integer argc; 10009668Slinton { 10019668Slinton char save[CALLSIZE]; 10029668Slinton struct { 10039668Slinton VaxOpcode op; 10049668Slinton unsigned char numargs; 10059668Slinton unsigned char mode; 10069668Slinton char addr[sizeof(long)]; /* unaligned long */ 10079668Slinton } call; 10089668Slinton long dest; 10099668Slinton 10109668Slinton pc = 2; 10119668Slinton iread(save, pc, sizeof(save)); 10129668Slinton call.op = O_CALLS; 10139668Slinton call.numargs = argc; 10149668Slinton call.mode = 0xef; 10159668Slinton dest = codeloc(p) - 2 - (pc + 7); 10169668Slinton mov(&dest, call.addr, sizeof(call.addr)); 10179668Slinton iwrite(&call, pc, sizeof(call)); 10189668Slinton setreg(PROGCTR, pc); 101916612Ssam pstep(process, DEFSIG); 10209668Slinton iwrite(save, pc, sizeof(save)); 10219668Slinton pc = reg(PROGCTR); 10229668Slinton if (not isbperr()) { 10239668Slinton printstatus(); 10249668Slinton } 10259668Slinton } 1026