xref: /original-bsd/old/dbx/vax.c (revision 902755c9)
16724fc83Sdist /*
2be26f981Sbostic  * Copyright (c) 1983 The Regents of the University of California.
3be26f981Sbostic  * All rights reserved.
4be26f981Sbostic  *
5*902755c9Sbostic  * %sccs.include.redist.c%
66724fc83Sdist  */
773a32ae3Slinton 
86724fc83Sdist #ifndef lint
9*902755c9Sbostic static char sccsid[] = "@(#)vax.c	5.8 (Berkeley) 06/01/90";
10be26f981Sbostic #endif /* not lint */
1173a32ae3Slinton 
1273a32ae3Slinton /*
1373a32ae3Slinton  * Target machine dependent stuff.
1473a32ae3Slinton  */
1573a32ae3Slinton 
1673a32ae3Slinton #include "defs.h"
1773a32ae3Slinton #include "machine.h"
1873a32ae3Slinton #include "process.h"
19014c42d4Ssam #include "runtime.h"
2073a32ae3Slinton #include "events.h"
2173a32ae3Slinton #include "main.h"
2273a32ae3Slinton #include "symbols.h"
2373a32ae3Slinton #include "source.h"
2473a32ae3Slinton #include "mappings.h"
2573a32ae3Slinton #include "object.h"
26c6ec783fSdonn #include "tree.h"
27c6ec783fSdonn #include "eval.h"
28671f89b3Slinton #include "keywords.h"
2922f02337Slinton #include "ops.h"
3073a32ae3Slinton 
3173a32ae3Slinton #ifndef public
3273a32ae3Slinton typedef unsigned int Address;
3373a32ae3Slinton typedef unsigned char Byte;
3473a32ae3Slinton typedef unsigned int Word;
3573a32ae3Slinton 
3673a32ae3Slinton #define NREG 16
3773a32ae3Slinton 
3873a32ae3Slinton #define ARGP 12
3973a32ae3Slinton #define FRP 13
4073a32ae3Slinton #define STKP 14
4173a32ae3Slinton #define PROGCTR 15
4273a32ae3Slinton 
43c6ec783fSdonn #define CODESTART 0
44c6ec783fSdonn #define FUNCOFFSET 2
45c6ec783fSdonn 
46c6ec783fSdonn #define nargspassed(frame) argn(0, frame)
47c6ec783fSdonn 
4873a32ae3Slinton #define BITSPERBYTE 8
4973a32ae3Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
5073a32ae3Slinton 
511cb06afbSsam /*
52c6ec783fSdonn  * This magic macro enables us to look at the process' registers
53c6ec783fSdonn  * in its user structure.
541cb06afbSsam  */
551cb06afbSsam 
56c6ec783fSdonn #define regloc(reg)	(ctob(UPAGES) + (sizeof(Word) * (reg)))
571cb06afbSsam 
5873a32ae3Slinton #include "source.h"
5973a32ae3Slinton #include "symbols.h"
60c6ec783fSdonn #include <signal.h>
6107860b0dSsam #include <sys/param.h>
6207860b0dSsam #include <machine/psl.h>
6307860b0dSsam #include <machine/pte.h>
6407860b0dSsam #include <sys/user.h>
65c6ec783fSdonn #undef DELETE /* XXX */
6607860b0dSsam #include <sys/vm.h>
6707860b0dSsam #include <machine/reg.h>
6873a32ae3Slinton 
6973a32ae3Slinton Address pc;
7073a32ae3Slinton Address prtaddr;
7173a32ae3Slinton 
7273a32ae3Slinton #endif
7373a32ae3Slinton 
7473a32ae3Slinton /*
7507860b0dSsam  * Indices into u. for use in collecting registers values.
7607860b0dSsam  */
77c6ec783fSdonn public int rloc[] ={
78c6ec783fSdonn     R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC
79c6ec783fSdonn };
80c6ec783fSdonn 
81c6ec783fSdonn private Address printop();
82c6ec783fSdonn 
83c6ec783fSdonn private Optab *ioptab[256];	/* index by opcode to optab */
8439b89a1fSdonn private Optab *esctab[256];	/* for extended opcodes */
85c6ec783fSdonn 
86c6ec783fSdonn /*
87c6ec783fSdonn  * Initialize the opcode lookup table.
88c6ec783fSdonn  */
optab_init()89c6ec783fSdonn public optab_init()
90c6ec783fSdonn {
91c6ec783fSdonn     register Optab *p;
92c6ec783fSdonn 
9339b89a1fSdonn     for (p = optab; p->iname; p++) {
9439b89a1fSdonn 	if (p->format == O_ESCD) {
9539b89a1fSdonn 	    esctab[p->val] = p;
9639b89a1fSdonn 	} else if (p->format != O_ESCD && p->format != O_ESCE) {
9739b89a1fSdonn 	    ioptab[p->val] = p;
9839b89a1fSdonn 	}
9939b89a1fSdonn     }
100c6ec783fSdonn }
10107860b0dSsam 
10207860b0dSsam /*
10373a32ae3Slinton  * Decode and print the instructions within the given address range.
10473a32ae3Slinton  */
10573a32ae3Slinton 
printinst(lowaddr,highaddr)10673a32ae3Slinton public printinst(lowaddr, highaddr)
10773a32ae3Slinton Address lowaddr;
10873a32ae3Slinton Address highaddr;
10973a32ae3Slinton {
11073a32ae3Slinton     register Address addr;
11173a32ae3Slinton 
11273a32ae3Slinton     for (addr = lowaddr; addr <= highaddr; ) {
11373a32ae3Slinton 	addr = printop(addr);
11473a32ae3Slinton     }
11573a32ae3Slinton     prtaddr = addr;
11673a32ae3Slinton }
11773a32ae3Slinton 
11873a32ae3Slinton /*
11973a32ae3Slinton  * Another approach:  print n instructions starting at the given address.
12073a32ae3Slinton  */
12173a32ae3Slinton 
printninst(count,addr)12273a32ae3Slinton public printninst(count, addr)
12373a32ae3Slinton int count;
12473a32ae3Slinton Address addr;
12573a32ae3Slinton {
12673a32ae3Slinton     register Integer i;
12773a32ae3Slinton     register Address newaddr;
12873a32ae3Slinton 
12973a32ae3Slinton     if (count <= 0) {
13073a32ae3Slinton 	error("non-positive repetition count");
13173a32ae3Slinton     } else {
13273a32ae3Slinton 	newaddr = addr;
13373a32ae3Slinton 	for (i = 0; i < count; i++) {
13473a32ae3Slinton 	    newaddr = printop(newaddr);
13573a32ae3Slinton 	}
13673a32ae3Slinton 	prtaddr = newaddr;
13773a32ae3Slinton     }
13873a32ae3Slinton }
13973a32ae3Slinton 
140c6ec783fSdonn /*
141c6ec783fSdonn  * Print the contents of the addresses within the given range
142c6ec783fSdonn  * according to the given format.
143c6ec783fSdonn  */
1441cb06afbSsam 
145c6ec783fSdonn typedef struct {
146c6ec783fSdonn     String name;
147c6ec783fSdonn     String printfstring;
148c6ec783fSdonn     int length;
149c6ec783fSdonn } Format;
150c6ec783fSdonn 
151c6ec783fSdonn private Format fmt[] = {
152c6ec783fSdonn     { "d", " %d", sizeof(short) },
153c6ec783fSdonn     { "D", " %ld", sizeof(long) },
154c6ec783fSdonn     { "o", " %o", sizeof(short) },
155c6ec783fSdonn     { "O", " %lo", sizeof(long) },
156c6ec783fSdonn     { "x", " %04x", sizeof(short) },
157c6ec783fSdonn     { "X", " %08x", sizeof(long) },
158c6ec783fSdonn     { "b", " \\%o", sizeof(char) },
159c6ec783fSdonn     { "c", " '%c'", sizeof(char) },
160c6ec783fSdonn     { "s", "%c", sizeof(char) },
161c6ec783fSdonn     { "f", " %f", sizeof(float) },
162c6ec783fSdonn     { "g", " %g", sizeof(double) },
163c6ec783fSdonn     { nil, nil, 0 }
164c6ec783fSdonn };
165c6ec783fSdonn 
findformat(s)166c6ec783fSdonn private Format *findformat(s)
167c6ec783fSdonn String s;
168c6ec783fSdonn {
169c6ec783fSdonn     register Format *f;
170c6ec783fSdonn 
171c6ec783fSdonn     f = &fmt[0];
172c6ec783fSdonn     while (f->name != nil and not streq(f->name, s)) {
173c6ec783fSdonn 	++f;
174c6ec783fSdonn     }
175c6ec783fSdonn     if (f->name == nil) {
176c6ec783fSdonn 	error("bad print format \"%s\"", s);
177c6ec783fSdonn     }
178c6ec783fSdonn     return f;
1791cb06afbSsam }
1801cb06afbSsam 
18173a32ae3Slinton /*
182c6ec783fSdonn  * Retrieve and print out the appropriate data in the given format.
183c6ec783fSdonn  * Floats have to be handled specially to allow the compiler to
184c6ec783fSdonn  * convert them to doubles when passing to printf.
185c6ec783fSdonn  */
186c6ec783fSdonn 
printformat(f,addr)187c6ec783fSdonn private printformat (f, addr)
188c6ec783fSdonn Format *f;
189c6ec783fSdonn Address addr;
190c6ec783fSdonn {
191c6ec783fSdonn     union {
192c6ec783fSdonn 	char charv;
193c6ec783fSdonn 	short shortv;
194c6ec783fSdonn 	int intv;
195c6ec783fSdonn 	float floatv;
196c6ec783fSdonn 	double doublev;
197c6ec783fSdonn     } value;
198c6ec783fSdonn 
199c6ec783fSdonn     value.intv = 0;
200c6ec783fSdonn     dread(&value, addr, f->length);
201c6ec783fSdonn     if (streq(f->name, "f")) {
202c6ec783fSdonn 	printf(f->printfstring, value.floatv);
203c6ec783fSdonn     } else {
204c6ec783fSdonn 	printf(f->printfstring, value);
205c6ec783fSdonn     }
206c6ec783fSdonn }
207c6ec783fSdonn 
printdata(lowaddr,highaddr,format)208c6ec783fSdonn public Address printdata(lowaddr, highaddr, format)
209c6ec783fSdonn Address lowaddr;
210c6ec783fSdonn Address highaddr;
211c6ec783fSdonn String format;
212c6ec783fSdonn {
213c6ec783fSdonn     int n;
214c6ec783fSdonn     register Address addr;
215c6ec783fSdonn     Format *f;
216c6ec783fSdonn 
217c6ec783fSdonn     if (lowaddr > highaddr) {
218c6ec783fSdonn 	error("first address larger than second");
219c6ec783fSdonn     }
220c6ec783fSdonn     f = findformat(format);
221c6ec783fSdonn     n = 0;
222c6ec783fSdonn     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
223c6ec783fSdonn 	if (n == 0) {
224c6ec783fSdonn 	    printf("%08x: ", addr);
225c6ec783fSdonn 	}
226c6ec783fSdonn 	printformat(f, addr);
227c6ec783fSdonn 	++n;
228c6ec783fSdonn 	if (n >= (16 div f->length)) {
229c6ec783fSdonn 	    printf("\n");
230c6ec783fSdonn 	    n = 0;
231c6ec783fSdonn 	}
232c6ec783fSdonn     }
233c6ec783fSdonn     if (n != 0) {
234c6ec783fSdonn 	printf("\n");
235c6ec783fSdonn     }
236c6ec783fSdonn     prtaddr = addr;
237c6ec783fSdonn     return addr;
238c6ec783fSdonn }
239c6ec783fSdonn 
240c6ec783fSdonn /*
241c6ec783fSdonn  * The other approach is to print n items starting with a given address.
242c6ec783fSdonn  */
243c6ec783fSdonn 
printndata(count,startaddr,format)244c6ec783fSdonn public printndata(count, startaddr, format)
245c6ec783fSdonn int count;
246c6ec783fSdonn Address startaddr;
247c6ec783fSdonn String format;
248c6ec783fSdonn {
249c6ec783fSdonn     int i, n;
250c6ec783fSdonn     Address addr;
251c6ec783fSdonn     Format *f;
252c6ec783fSdonn     Boolean isstring;
253c6ec783fSdonn     char c;
254c6ec783fSdonn 
255c6ec783fSdonn     if (count <= 0) {
256c6ec783fSdonn 	error("non-positive repetition count");
257c6ec783fSdonn     }
258c6ec783fSdonn     f = findformat(format);
259c6ec783fSdonn     isstring = (Boolean) streq(f->name, "s");
260c6ec783fSdonn     n = 0;
261c6ec783fSdonn     addr = startaddr;
262c6ec783fSdonn     for (i = 0; i < count; i++) {
263c6ec783fSdonn 	if (n == 0) {
264c6ec783fSdonn 	    printf("%08x: ", addr);
265c6ec783fSdonn 	}
266c6ec783fSdonn 	if (isstring) {
267c6ec783fSdonn 	    printf("\"");
268c6ec783fSdonn 	    dread(&c, addr, sizeof(char));
269c6ec783fSdonn 	    while (c != '\0') {
270c6ec783fSdonn 		printchar(c);
271c6ec783fSdonn 		++addr;
272c6ec783fSdonn 		dread(&c, addr, sizeof(char));
273c6ec783fSdonn 	    }
274c6ec783fSdonn 	    printf("\"\n");
275c6ec783fSdonn 	    n = 0;
276c6ec783fSdonn 	    addr += sizeof(String);
277c6ec783fSdonn 	} else {
278c6ec783fSdonn 	    printformat(f, addr);
279c6ec783fSdonn 	    ++n;
280c6ec783fSdonn 	    if (n >= (16 div f->length)) {
281c6ec783fSdonn 		printf("\n");
282c6ec783fSdonn 		n = 0;
283c6ec783fSdonn 	    }
284c6ec783fSdonn 	    addr += f->length;
285c6ec783fSdonn 	}
286c6ec783fSdonn     }
287c6ec783fSdonn     if (n != 0) {
288c6ec783fSdonn 	printf("\n");
289c6ec783fSdonn     }
290c6ec783fSdonn     prtaddr = addr;
291c6ec783fSdonn }
292c6ec783fSdonn 
293c6ec783fSdonn /*
294c6ec783fSdonn  * Print out a value according to the given format.
295c6ec783fSdonn  */
296c6ec783fSdonn 
printvalue(v,format)297c6ec783fSdonn public printvalue(v, format)
298c6ec783fSdonn long v;
299c6ec783fSdonn String format;
300c6ec783fSdonn {
301c6ec783fSdonn     Format *f;
302c6ec783fSdonn     char *p, *q;
303c6ec783fSdonn 
304c6ec783fSdonn     f = findformat(format);
305c6ec783fSdonn     if (streq(f->name, "s")) {
306c6ec783fSdonn 	putchar('"');
307c6ec783fSdonn 	p = (char *) &v;
308c6ec783fSdonn 	q = p + sizeof(v);
309c6ec783fSdonn 	while (p < q) {
310c6ec783fSdonn 	    printchar(*p);
311c6ec783fSdonn 	    ++p;
312c6ec783fSdonn 	}
313c6ec783fSdonn 	putchar('"');
314c6ec783fSdonn     } else {
315c6ec783fSdonn 	printf(f->printfstring, v);
316c6ec783fSdonn     }
317c6ec783fSdonn     putchar('\n');
318c6ec783fSdonn }
319c6ec783fSdonn 
320c6ec783fSdonn /*
321c6ec783fSdonn  * Print out an execution time error.
322c6ec783fSdonn  * Assumes the source position of the error has been calculated.
323c6ec783fSdonn  *
324c6ec783fSdonn  * Have to check if the -r option was specified; if so then
325c6ec783fSdonn  * the object file information hasn't been read in yet.
326c6ec783fSdonn  */
327c6ec783fSdonn 
printerror()328c6ec783fSdonn public printerror()
329c6ec783fSdonn {
330c6ec783fSdonn     extern Integer sys_nsig;
331c6ec783fSdonn     extern String sys_siglist[];
332c6ec783fSdonn     integer err;
333c6ec783fSdonn 
334c6ec783fSdonn     if (isfinished(process)) {
335c6ec783fSdonn 	err = exitcode(process);
336c6ec783fSdonn 	if (err == 0) {
337c6ec783fSdonn 	    printf("\"%s\" terminated normally\n", objname);
338c6ec783fSdonn 	} else {
339c6ec783fSdonn 	    printf("\"%s\" terminated abnormally (exit code %d)\n",
340c6ec783fSdonn 		objname, err
341c6ec783fSdonn 	    );
342c6ec783fSdonn 	}
343c6ec783fSdonn 	erecover();
344c6ec783fSdonn     }
345c6ec783fSdonn     err = errnum(process);
346c6ec783fSdonn     putchar('\n');
347c6ec783fSdonn     printsig(err);
348c6ec783fSdonn     putchar(' ');
349c6ec783fSdonn     printloc();
350c6ec783fSdonn     putchar('\n');
351c6ec783fSdonn     if (curline > 0) {
352c6ec783fSdonn 	printlines(curline, curline);
353c6ec783fSdonn     } else {
354c6ec783fSdonn 	printinst(pc, pc);
355c6ec783fSdonn     }
356c6ec783fSdonn     erecover();
357c6ec783fSdonn }
358c6ec783fSdonn 
359c6ec783fSdonn /*
360c6ec783fSdonn  * Print out a signal.
361c6ec783fSdonn  */
362c6ec783fSdonn 
363c6ec783fSdonn private String illinames[] = {
364c6ec783fSdonn     "reserved addressing fault",
365c6ec783fSdonn     "privileged instruction fault",
366c6ec783fSdonn     "reserved operand fault"
367c6ec783fSdonn };
368c6ec783fSdonn 
369c6ec783fSdonn private String fpenames[] = {
370c6ec783fSdonn     nil,
371c6ec783fSdonn     "integer overflow trap",
372c6ec783fSdonn     "integer divide by zero trap",
373c6ec783fSdonn     "floating overflow trap",
374c6ec783fSdonn     "floating/decimal divide by zero trap",
375c6ec783fSdonn     "floating underflow trap",
376c6ec783fSdonn     "decimal overflow trap",
377c6ec783fSdonn     "subscript out of range trap",
378c6ec783fSdonn     "floating overflow fault",
379c6ec783fSdonn     "floating divide by zero fault",
380c6ec783fSdonn     "floating underflow fault"
381c6ec783fSdonn };
382c6ec783fSdonn 
printsig(signo)383c6ec783fSdonn public printsig (signo)
384c6ec783fSdonn integer signo;
385c6ec783fSdonn {
386c6ec783fSdonn     integer code;
387c6ec783fSdonn 
388c6ec783fSdonn     if (signo < 0 or signo > sys_nsig) {
389c6ec783fSdonn 	printf("[signal %d]", signo);
390c6ec783fSdonn     } else {
391c6ec783fSdonn 	printf("%s", sys_siglist[signo]);
392c6ec783fSdonn     }
393c6ec783fSdonn     code = errcode(process);
394c6ec783fSdonn     if (signo == SIGILL) {
395c6ec783fSdonn 	if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
396c6ec783fSdonn 	    printf(" (%s)", illinames[code]);
397c6ec783fSdonn 	}
398c6ec783fSdonn     } else if (signo == SIGFPE) {
399c6ec783fSdonn 	if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
400c6ec783fSdonn 	    printf(" (%s)", fpenames[code]);
401c6ec783fSdonn 	}
402c6ec783fSdonn     }
403c6ec783fSdonn }
404c6ec783fSdonn 
405c6ec783fSdonn /*
406c6ec783fSdonn  * Note the termination of the program.  We do this so as to avoid
407c6ec783fSdonn  * having the process exit, which would make the values of variables
408c6ec783fSdonn  * inaccessible.  We do want to flush all output buffers here,
409c6ec783fSdonn  * otherwise it'll never get done.
410c6ec783fSdonn  */
411c6ec783fSdonn 
endprogram()412c6ec783fSdonn public endprogram()
413c6ec783fSdonn {
414c6ec783fSdonn     Integer exitcode;
415c6ec783fSdonn 
416c6ec783fSdonn     stepto(nextaddr(pc, true));
417c6ec783fSdonn     printnews();
418c6ec783fSdonn     exitcode = argn(1, nil);
419c6ec783fSdonn     if (exitcode != 0) {
420c6ec783fSdonn 	printf("\nexecution completed (exit code %d)\n", exitcode);
421c6ec783fSdonn     } else {
422c6ec783fSdonn 	printf("\nexecution completed\n");
423c6ec783fSdonn     }
424c6ec783fSdonn     getsrcpos();
425c6ec783fSdonn     erecover();
426c6ec783fSdonn }
427c6ec783fSdonn 
428c6ec783fSdonn /*
429c6ec783fSdonn  * Single step the machine a source line (or instruction if "inst_tracing"
430c6ec783fSdonn  * is true).  If "isnext" is true, skip over procedure calls.
431c6ec783fSdonn  */
432c6ec783fSdonn 
433c6ec783fSdonn private Address getcall();
434c6ec783fSdonn 
dostep(isnext)435c6ec783fSdonn public dostep(isnext)
436c6ec783fSdonn Boolean isnext;
437c6ec783fSdonn {
438c6ec783fSdonn     register Address addr;
439c6ec783fSdonn     register Lineno line;
440c6ec783fSdonn     String filename;
441c6ec783fSdonn     Address startaddr;
442c6ec783fSdonn 
443c6ec783fSdonn     startaddr = pc;
444c6ec783fSdonn     addr = nextaddr(pc, isnext);
445c6ec783fSdonn     if (not inst_tracing and nlhdr.nlines != 0) {
446c6ec783fSdonn 	line = linelookup(addr);
447c6ec783fSdonn 	while (line == 0) {
448c6ec783fSdonn 	    addr = nextaddr(addr, isnext);
449c6ec783fSdonn 	    line = linelookup(addr);
450c6ec783fSdonn 	}
451c6ec783fSdonn 	curline = line;
452c6ec783fSdonn     } else {
453c6ec783fSdonn 	curline = 0;
454c6ec783fSdonn     }
455c6ec783fSdonn     stepto(addr);
456c6ec783fSdonn     filename = srcfilename(addr);
457c6ec783fSdonn     setsource(filename);
458c6ec783fSdonn }
459c6ec783fSdonn 
460c6ec783fSdonn typedef char Bpinst;
461c6ec783fSdonn 
462c6ec783fSdonn #define BP_OP       O_BPT       /* breakpoint trap */
463c6ec783fSdonn 
464c6ec783fSdonn #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
465c6ec783fSdonn 
466c6ec783fSdonn /*
467c6ec783fSdonn  * Setting a breakpoint at a location consists of saving
468c6ec783fSdonn  * the word at the location and poking a BP_OP there.
469c6ec783fSdonn  *
470c6ec783fSdonn  * We save the locations and words on a list for use in unsetting.
471c6ec783fSdonn  */
472c6ec783fSdonn 
473c6ec783fSdonn typedef struct Savelist *Savelist;
474c6ec783fSdonn 
475c6ec783fSdonn struct Savelist {
476c6ec783fSdonn     Address location;
477c6ec783fSdonn     Bpinst save;
478c6ec783fSdonn     short refcount;
479c6ec783fSdonn     Savelist link;
480c6ec783fSdonn };
481c6ec783fSdonn 
482c6ec783fSdonn private Savelist savelist;
483c6ec783fSdonn 
484c6ec783fSdonn /*
485c6ec783fSdonn  * Set a breakpoint at the given address.  Only save the word there
486c6ec783fSdonn  * if it's not already a breakpoint.
487c6ec783fSdonn  */
488c6ec783fSdonn 
setbp(addr)489c6ec783fSdonn public setbp(addr)
490c6ec783fSdonn Address addr;
491c6ec783fSdonn {
492c6ec783fSdonn     Bpinst w, save;
493c6ec783fSdonn     register Savelist newsave, s;
494c6ec783fSdonn 
495c6ec783fSdonn     for (s = savelist; s != nil; s = s->link) {
496c6ec783fSdonn 	if (s->location == addr) {
497c6ec783fSdonn 	    s->refcount++;
498c6ec783fSdonn 	    return;
499c6ec783fSdonn 	}
500c6ec783fSdonn     }
501c6ec783fSdonn     iread(&save, addr, sizeof(save));
502c6ec783fSdonn     newsave = new(Savelist);
503c6ec783fSdonn     newsave->location = addr;
504c6ec783fSdonn     newsave->save = save;
505c6ec783fSdonn     newsave->refcount = 1;
506c6ec783fSdonn     newsave->link = savelist;
507c6ec783fSdonn     savelist = newsave;
508c6ec783fSdonn     w = BP_OP;
509c6ec783fSdonn     iwrite(&w, addr, sizeof(w));
510c6ec783fSdonn }
511c6ec783fSdonn 
512c6ec783fSdonn /*
513c6ec783fSdonn  * Unset a breakpoint; unfortunately we have to search the SAVELIST
514c6ec783fSdonn  * to find the saved value.  The assumption is that the SAVELIST will
515c6ec783fSdonn  * usually be quite small.
516c6ec783fSdonn  */
517c6ec783fSdonn 
unsetbp(addr)518c6ec783fSdonn public unsetbp(addr)
519c6ec783fSdonn Address addr;
520c6ec783fSdonn {
521c6ec783fSdonn     register Savelist s, prev;
522c6ec783fSdonn 
523c6ec783fSdonn     prev = nil;
524c6ec783fSdonn     for (s = savelist; s != nil; s = s->link) {
525c6ec783fSdonn 	if (s->location == addr) {
526c6ec783fSdonn 	    iwrite(&s->save, addr, sizeof(s->save));
527c6ec783fSdonn 	    s->refcount--;
528c6ec783fSdonn 	    if (s->refcount == 0) {
529c6ec783fSdonn 		if (prev == nil) {
530c6ec783fSdonn 		    savelist = s->link;
531c6ec783fSdonn 		} else {
532c6ec783fSdonn 		    prev->link = s->link;
533c6ec783fSdonn 		}
534c6ec783fSdonn 		dispose(s);
535c6ec783fSdonn 	    }
536c6ec783fSdonn 	    return;
537c6ec783fSdonn 	}
538c6ec783fSdonn 	prev = s;
539c6ec783fSdonn     }
540c6ec783fSdonn     panic("unsetbp: couldn't find address %d", addr);
541c6ec783fSdonn }
542c6ec783fSdonn 
543c6ec783fSdonn /*
544c6ec783fSdonn  * VAX instruction decoder, derived from adb.
54573a32ae3Slinton  */
54673a32ae3Slinton 
printop(addr)54773a32ae3Slinton private Address printop(addr)
54873a32ae3Slinton Address addr;
54973a32ae3Slinton {
550c6ec783fSdonn     register Optab *op;
55173a32ae3Slinton     VaxOpcode ins;
55273a32ae3Slinton     unsigned char mode;
55373a32ae3Slinton     int argtype, amode, argno, argval;
55473a32ae3Slinton     String reg;
55573a32ae3Slinton     Boolean indexf;
55673a32ae3Slinton     short offset;
55773a32ae3Slinton 
55873a32ae3Slinton     argval = 0;
55973a32ae3Slinton     indexf = false;
56073a32ae3Slinton     printf("%08x  ", addr);
56173a32ae3Slinton     iread(&ins, addr, sizeof(ins));
56273a32ae3Slinton     addr += 1;
56339b89a1fSdonn     if (ins == O_ESCF) {
56439b89a1fSdonn 	iread(&ins, addr, sizeof(ins));
56539b89a1fSdonn 	addr += 1;
566c6ec783fSdonn 	op = ioptab[ins];
56739b89a1fSdonn     } else if (ins == O_ESCD) {
56839b89a1fSdonn 	iread(&ins, addr, sizeof(ins));
56939b89a1fSdonn 	addr += 1;
57039b89a1fSdonn 	op = esctab[ins];
57139b89a1fSdonn     } else {
57239b89a1fSdonn 	op = ioptab[ins];
57339b89a1fSdonn     }
57439b89a1fSdonn     if (op == nil) {
57539b89a1fSdonn 	printf("[unrecognized opcode %#0x]\n", ins);
57639b89a1fSdonn 	return addr;
57739b89a1fSdonn     }
578c6ec783fSdonn     printf("%s", op->iname);
579c6ec783fSdonn     for (argno = 0; argno < op->numargs; argno++) {
58073a32ae3Slinton 	if (indexf == true) {
58173a32ae3Slinton 	    indexf = false;
58273a32ae3Slinton 	} else if (argno == 0) {
58373a32ae3Slinton 	    printf("\t");
58473a32ae3Slinton 	} else {
58573a32ae3Slinton 	    printf(",");
58673a32ae3Slinton 	}
587c6ec783fSdonn 	argtype = op->argtype[argno];
58873a32ae3Slinton 	if (is_branch_disp(argtype)) {
58973a32ae3Slinton 	    mode = 0xAF + (typelen(argtype) << 5);
59073a32ae3Slinton 	} else {
59173a32ae3Slinton 	    iread(&mode, addr, sizeof(mode));
59273a32ae3Slinton 	    addr += 1;
59373a32ae3Slinton 	}
59473a32ae3Slinton 	reg = regname[regnm(mode)];
59573a32ae3Slinton 	amode = addrmode(mode);
59673a32ae3Slinton 	switch (amode) {
59773a32ae3Slinton 	    case LITSHORT:
59873a32ae3Slinton 	    case LITUPTO31:
59973a32ae3Slinton 	    case LITUPTO47:
60073a32ae3Slinton 	    case LITUPTO63:
60139b89a1fSdonn 		if (typelen(argtype) == TYPF || typelen(argtype) == TYPD ||
60239b89a1fSdonn 		    typelen(argtype) == TYPG || typelen(argtype) == TYPH)
60373a32ae3Slinton 		    printf("$%s", fltimm[mode]);
60473a32ae3Slinton 		else
60573a32ae3Slinton 		    printf("$%x", mode);
60673a32ae3Slinton 		argval = mode;
60773a32ae3Slinton 		break;
60873a32ae3Slinton 
60973a32ae3Slinton 	    case INDEX:
61073a32ae3Slinton 		printf("[%s]", reg);
61173a32ae3Slinton 		indexf = true;
61273a32ae3Slinton 		argno--;
61373a32ae3Slinton 		break;
61473a32ae3Slinton 
61573a32ae3Slinton 	    case REG:
61673a32ae3Slinton 		printf("%s", reg);
61773a32ae3Slinton 		break;
61873a32ae3Slinton 
61973a32ae3Slinton 	    case REGDEF:
62073a32ae3Slinton 		printf("(%s)", reg);
62173a32ae3Slinton 		break;
62273a32ae3Slinton 
62373a32ae3Slinton 	    case AUTODEC:
62473a32ae3Slinton 		printf("-(%s)", reg);
62573a32ae3Slinton 		break;
62673a32ae3Slinton 
62773a32ae3Slinton 	    case AUTOINC:
62873a32ae3Slinton 		if (reg != regname[PROGCTR]) {
62973a32ae3Slinton 		    printf("(%s)+", reg);
63073a32ae3Slinton 		} else {
63173a32ae3Slinton 		    printf("$");
63273a32ae3Slinton 		    switch (typelen(argtype)) {
63373a32ae3Slinton 			case TYPB:
63473a32ae3Slinton 			    argval = printdisp(addr, 1, reg, amode);
63573a32ae3Slinton 			    addr += 1;
63673a32ae3Slinton 			    break;
63773a32ae3Slinton 
63873a32ae3Slinton 			case TYPW:
63973a32ae3Slinton 			    argval = printdisp(addr, 2, reg, amode);
64073a32ae3Slinton 			    addr += 2;
64173a32ae3Slinton 			    break;
64273a32ae3Slinton 
64373a32ae3Slinton 			case TYPL:
64473a32ae3Slinton 			    argval = printdisp(addr, 4, reg, amode);
64573a32ae3Slinton 			    addr += 4;
64673a32ae3Slinton 			    break;
64773a32ae3Slinton 
64873a32ae3Slinton 			case TYPF:
64973a32ae3Slinton 			    iread(&argval, addr, sizeof(argval));
65039b89a1fSdonn 			    if ((argval & 0xffff007f) == 0x8000) {
65139b89a1fSdonn 				printf("[reserved operand]");
65239b89a1fSdonn 			    } else {
65339b89a1fSdonn 				printf("%g", *(float *)&argval);
65439b89a1fSdonn 			    }
65573a32ae3Slinton 			    addr += 4;
65673a32ae3Slinton 			    break;
65773a32ae3Slinton 
65873a32ae3Slinton 			case TYPD:
65939b89a1fSdonn 			    /* XXX this bags the low order bits */
66073a32ae3Slinton 			    iread(&argval, addr, sizeof(argval));
66139b89a1fSdonn 			    if ((argval & 0xffff007f) == 0x8000) {
66239b89a1fSdonn 				printf("[reserved operand]");
66339b89a1fSdonn 			    } else {
66439b89a1fSdonn 				printf("%g", *(float *)&argval);
66539b89a1fSdonn 			    }
66673a32ae3Slinton 			    addr += 8;
66773a32ae3Slinton 			    break;
66839b89a1fSdonn 
66939b89a1fSdonn 			case TYPG:
67039b89a1fSdonn 			case TYPQ:
67139b89a1fSdonn 			    iread(&argval, addr+4, sizeof(argval));
67239b89a1fSdonn 			    printf("%08x", argval);
67339b89a1fSdonn 			    iread(&argval, addr, sizeof(argval));
67439b89a1fSdonn 			    printf("%08x", argval);
67539b89a1fSdonn 			    addr += 8;
67639b89a1fSdonn 			    break;
67739b89a1fSdonn 
67839b89a1fSdonn 			case TYPH:
67939b89a1fSdonn 			case TYPO:
68039b89a1fSdonn 			    iread(&argval, addr+12, sizeof(argval));
68139b89a1fSdonn 			    printf("%08x", argval);
68239b89a1fSdonn 			    iread(&argval, addr+8, sizeof(argval));
68339b89a1fSdonn 			    printf("%08x", argval);
68439b89a1fSdonn 			    iread(&argval, addr+4, sizeof(argval));
68539b89a1fSdonn 			    printf("%08x", argval);
68639b89a1fSdonn 			    iread(&argval, addr, sizeof(argval));
68739b89a1fSdonn 			    printf("%08x", argval);
68839b89a1fSdonn 			    addr += 16;
68939b89a1fSdonn 			    break;
69073a32ae3Slinton 		    }
69173a32ae3Slinton 		}
69273a32ae3Slinton 		break;
69373a32ae3Slinton 
69473a32ae3Slinton 	    case AUTOINCDEF:
69573a32ae3Slinton 		if (reg == regname[PROGCTR]) {
69673a32ae3Slinton 		    printf("*$");
69773a32ae3Slinton 		    argval = printdisp(addr, 4, reg, amode);
69873a32ae3Slinton 		    addr += 4;
69973a32ae3Slinton 		} else {
70073a32ae3Slinton 		    printf("*(%s)+", reg);
70173a32ae3Slinton 		}
70273a32ae3Slinton 		break;
70373a32ae3Slinton 
70473a32ae3Slinton 	    case BYTEDISP:
70573a32ae3Slinton 		argval = printdisp(addr, 1, reg, amode);
70673a32ae3Slinton 		addr += 1;
70773a32ae3Slinton 		break;
70873a32ae3Slinton 
70973a32ae3Slinton 	    case BYTEDISPDEF:
71073a32ae3Slinton 		printf("*");
71173a32ae3Slinton 		argval = printdisp(addr, 1, reg, amode);
71273a32ae3Slinton 		addr += 1;
71373a32ae3Slinton 		break;
71473a32ae3Slinton 
71573a32ae3Slinton 	    case WORDDISP:
71673a32ae3Slinton 		argval = printdisp(addr, 2, reg, amode);
71773a32ae3Slinton 		addr += 2;
71873a32ae3Slinton 		break;
71973a32ae3Slinton 
72073a32ae3Slinton 	    case WORDDISPDEF:
72173a32ae3Slinton 		printf("*");
72273a32ae3Slinton 		argval = printdisp(addr, 2, reg, amode);
72373a32ae3Slinton 		addr += 2;
72473a32ae3Slinton 		break;
72573a32ae3Slinton 
72673a32ae3Slinton 	    case LONGDISP:
72773a32ae3Slinton 		argval = printdisp(addr, 4, reg, amode);
72873a32ae3Slinton 		addr += 4;
72973a32ae3Slinton 		break;
73073a32ae3Slinton 
73173a32ae3Slinton 	    case LONGDISPDEF:
73273a32ae3Slinton 		printf("*");
73373a32ae3Slinton 		argval = printdisp(addr, 4, reg, amode);
73473a32ae3Slinton 		addr += 4;
73573a32ae3Slinton 		break;
73673a32ae3Slinton 	}
73773a32ae3Slinton     }
73873a32ae3Slinton     if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
73973a32ae3Slinton 	for (argno = 0; argno <= argval; argno++) {
74073a32ae3Slinton 	    iread(&offset, addr, sizeof(offset));
74173a32ae3Slinton 	    printf("\n\t\t%d", offset);
74273a32ae3Slinton 	    addr += 2;
74373a32ae3Slinton 	}
74473a32ae3Slinton     }
74573a32ae3Slinton     printf("\n");
74673a32ae3Slinton     return addr;
74773a32ae3Slinton }
74873a32ae3Slinton 
74973a32ae3Slinton /*
75073a32ae3Slinton  * Print the displacement of an instruction that uses displacement
75173a32ae3Slinton  * addressing.
75273a32ae3Slinton  */
75373a32ae3Slinton 
printdisp(addr,nbytes,reg,mode)75473a32ae3Slinton private int printdisp(addr, nbytes, reg, mode)
75573a32ae3Slinton Address addr;
75673a32ae3Slinton int nbytes;
75773a32ae3Slinton char *reg;
75873a32ae3Slinton int mode;
75973a32ae3Slinton {
76073a32ae3Slinton     char byte;
76173a32ae3Slinton     short hword;
76273a32ae3Slinton     int argval;
7636903f08cSlinton     Symbol f;
76473a32ae3Slinton 
76573a32ae3Slinton     switch (nbytes) {
76673a32ae3Slinton 	case 1:
76773a32ae3Slinton 	    iread(&byte, addr, sizeof(byte));
76873a32ae3Slinton 	    argval = byte;
76973a32ae3Slinton 	    break;
77073a32ae3Slinton 
77173a32ae3Slinton 	case 2:
77273a32ae3Slinton 	    iread(&hword, addr, sizeof(hword));
77373a32ae3Slinton 	    argval = hword;
77473a32ae3Slinton 	    break;
77573a32ae3Slinton 
77673a32ae3Slinton 	case 4:
77773a32ae3Slinton 	    iread(&argval, addr, sizeof(argval));
77873a32ae3Slinton 	    break;
77973a32ae3Slinton     }
78073a32ae3Slinton     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
78173a32ae3Slinton 	argval += addr + nbytes;
78273a32ae3Slinton     }
78373a32ae3Slinton     if (reg == regname[PROGCTR]) {
7846903f08cSlinton 	f = whatblock((Address) argval + 2);
7856903f08cSlinton 	if (codeloc(f) == argval + 2) {
7866903f08cSlinton 	    printf("%s", symname(f));
7876903f08cSlinton 	} else {
78873a32ae3Slinton 	    printf("%x", argval);
7896903f08cSlinton 	}
79073a32ae3Slinton     } else {
791671f89b3Slinton 	if (varIsSet("$hexoffsets")) {
792671f89b3Slinton 	    if (argval < 0) {
793671f89b3Slinton 		printf("-%x(%s)", -(argval), reg);
794671f89b3Slinton 	    } else {
795671f89b3Slinton 		printf("%x(%s)", argval, reg);
796671f89b3Slinton 	    }
797671f89b3Slinton 	} else {
79873a32ae3Slinton 	    printf("%d(%s)", argval, reg);
79973a32ae3Slinton 	}
800671f89b3Slinton     }
80173a32ae3Slinton     return argval;
80273a32ae3Slinton }
80373a32ae3Slinton 
80473a32ae3Slinton /*
80573a32ae3Slinton  * Compute the next address that will be executed from the given one.
80673a32ae3Slinton  * If "isnext" is true then consider a procedure call as straight line code.
80773a32ae3Slinton  *
80873a32ae3Slinton  * We must unfortunately do much of the same work that is necessary
80973a32ae3Slinton  * to print instructions.  In addition we have to deal with branches.
81073a32ae3Slinton  * Unconditional branches we just follow, for conditional branches
81173a32ae3Slinton  * we continue execution to the current location and then single step
81273a32ae3Slinton  * the machine.  We assume that the last argument in an instruction
81373a32ae3Slinton  * that branches is the branch address (or relative offset).
81473a32ae3Slinton  */
81573a32ae3Slinton 
816671f89b3Slinton private Address findnextaddr();
817671f89b3Slinton 
nextaddr(startaddr,isnext)81873a32ae3Slinton public Address nextaddr(startaddr, isnext)
81973a32ae3Slinton Address startaddr;
820014c42d4Ssam boolean isnext;
821014c42d4Ssam {
822014c42d4Ssam     Address addr;
823014c42d4Ssam 
824014c42d4Ssam     addr = usignal(process);
825014c42d4Ssam     if (addr == 0 or addr == 1) {
826014c42d4Ssam 	addr = findnextaddr(startaddr, isnext);
827014c42d4Ssam     }
828014c42d4Ssam     return addr;
829014c42d4Ssam }
830014c42d4Ssam 
831671f89b3Slinton /*
832671f89b3Slinton  * Determine if it's ok to skip function f entered by instruction ins.
833671f89b3Slinton  * If so, we're going to compute the return address and step to it.
834671f89b3Slinton  * Therefore we cannot skip over a function entered by a jsb or bsb,
835671f89b3Slinton  * since the return address is not easily computed for them.
836671f89b3Slinton  */
837671f89b3Slinton 
skipfunc(ins,f)838671f89b3Slinton private boolean skipfunc (ins, f)
839671f89b3Slinton VaxOpcode ins;
840671f89b3Slinton Symbol f;
841671f89b3Slinton {
842671f89b3Slinton     boolean b;
843671f89b3Slinton 
844671f89b3Slinton     b = (boolean) (
845671f89b3Slinton 	ins != O_JSB and ins != O_BSBB and ins != O_BSBW and
846671f89b3Slinton 	not inst_tracing and nlhdr.nlines != 0 and
847671f89b3Slinton 	nosource(curfunc) and canskip(curfunc)
848671f89b3Slinton     );
849671f89b3Slinton     return b;
850671f89b3Slinton }
851671f89b3Slinton 
findnextaddr(startaddr,isnext)852014c42d4Ssam private Address findnextaddr(startaddr, isnext)
853014c42d4Ssam Address startaddr;
85473a32ae3Slinton Boolean isnext;
85573a32ae3Slinton {
85673a32ae3Slinton     register Address addr;
857c6ec783fSdonn     register Optab *op;
85839b89a1fSdonn     VaxOpcode ins, ins2;
85973a32ae3Slinton     unsigned char mode;
86073a32ae3Slinton     int argtype, amode, argno, argval;
86173a32ae3Slinton     String r;
86273a32ae3Slinton     Boolean indexf;
86373a32ae3Slinton     enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus;
86473a32ae3Slinton 
86573a32ae3Slinton     argval = 0;
86673a32ae3Slinton     indexf = false;
86773a32ae3Slinton     addr = startaddr;
86873a32ae3Slinton     iread(&ins, addr, sizeof(ins));
86973a32ae3Slinton     switch (ins) {
870671f89b3Slinton 	/*
871671f89b3Slinton 	 * It used to be that unconditional jumps and branches were handled
872671f89b3Slinton 	 * by taking their destination address as the next address.  While
873671f89b3Slinton 	 * saving the cost of starting up the process, this approach
874671f89b3Slinton 	 * doesn't work when jumping indirect (since the value in the
875671f89b3Slinton 	 * register might not yet have been set).
876671f89b3Slinton 	 *
877671f89b3Slinton 	 * So unconditional jumps and branches are now handled the same way
878671f89b3Slinton 	 * as conditional jumps and branches.
879671f89b3Slinton 	 *
88073a32ae3Slinton 	case O_BRB:
88173a32ae3Slinton 	case O_BRW:
88273a32ae3Slinton 	    addrstatus = BRANCH;
88373a32ae3Slinton 	    break;
884671f89b3Slinton 	 *
885671f89b3Slinton 	 */
88673a32ae3Slinton 
88773a32ae3Slinton 	case O_BSBB:
88873a32ae3Slinton 	case O_BSBW:
88973a32ae3Slinton 	case O_JSB:
89073a32ae3Slinton 	case O_CALLG:
89173a32ae3Slinton 	case O_CALLS:
89273a32ae3Slinton 	    addrstatus = KNOWN;
89373a32ae3Slinton 	    stepto(addr);
894014c42d4Ssam 	    pstep(process, DEFSIG);
89573a32ae3Slinton 	    addr = reg(PROGCTR);
89673a32ae3Slinton 	    pc = addr;
897014c42d4Ssam 	    setcurfunc(whatblock(pc));
89873a32ae3Slinton 	    if (not isbperr()) {
89973a32ae3Slinton 		printstatus();
90044bbc32bSlinton 		/* NOTREACHED */
90144bbc32bSlinton 	    }
90273a32ae3Slinton 	    bpact();
903671f89b3Slinton 	    if (isnext or skipfunc(ins, curfunc)) {
90444bbc32bSlinton 		addrstatus = KNOWN;
90544bbc32bSlinton 		addr = return_addr();
90644bbc32bSlinton 		stepto(addr);
907c2ee75afSlinton 		bpact();
90844bbc32bSlinton 	    } else {
90944bbc32bSlinton 		callnews(/* iscall = */ true);
91073a32ae3Slinton 	    }
91173a32ae3Slinton 	    break;
91273a32ae3Slinton 
91373a32ae3Slinton 	case O_RSB:
91473a32ae3Slinton 	case O_RET:
91573a32ae3Slinton 	    addrstatus = KNOWN;
91673a32ae3Slinton 	    stepto(addr);
917671f89b3Slinton 	    callnews(/* iscall = */ false);
918671f89b3Slinton 	    pstep(process, DEFSIG);
919671f89b3Slinton 	    addr = reg(PROGCTR);
920671f89b3Slinton 	    pc = addr;
921671f89b3Slinton 	    if (not isbperr()) {
922671f89b3Slinton 		printstatus();
923014c42d4Ssam 	    }
924c2ee75afSlinton 	    bpact();
92573a32ae3Slinton 	    break;
92673a32ae3Slinton 
927671f89b3Slinton 	case O_BRB: case O_BRW:
928014c42d4Ssam 	case O_JMP: /* because it may be jmp (r1) */
92973a32ae3Slinton 	case O_BNEQ: case O_BEQL: case O_BGTR:
93073a32ae3Slinton 	case O_BLEQ: case O_BGEQ: case O_BLSS:
93173a32ae3Slinton 	case O_BGTRU: case O_BLEQU: case O_BVC:
93273a32ae3Slinton 	case O_BVS: case O_BCC: case O_BCS:
93373a32ae3Slinton 	case O_CASEB: case O_CASEW: case O_CASEL:
93473a32ae3Slinton 	case O_BBS: case O_BBC: case O_BBSS: case O_BBCS:
93573a32ae3Slinton 	case O_BBSC: case O_BBCC: case O_BBSSI:
93673a32ae3Slinton 	case O_BBCCI: case O_BLBS: case O_BLBC:
93773a32ae3Slinton 	case O_ACBL: case O_AOBLSS: case O_AOBLEQ:
93873a32ae3Slinton 	case O_SOBGEQ: case O_SOBGTR:
93939b89a1fSdonn 	case O_ESCF: /* bugchecks */
94039b89a1fSdonn 	branches:
94173a32ae3Slinton 	    addrstatus = KNOWN;
94273a32ae3Slinton 	    stepto(addr);
943014c42d4Ssam 	    pstep(process, DEFSIG);
94473a32ae3Slinton 	    addr = reg(PROGCTR);
94573a32ae3Slinton 	    pc = addr;
94673a32ae3Slinton 	    if (not isbperr()) {
94773a32ae3Slinton 		printstatus();
94873a32ae3Slinton 	    }
94973a32ae3Slinton 	    break;
95073a32ae3Slinton 
95139b89a1fSdonn 	case O_ESCD:
95239b89a1fSdonn 	    iread(&ins2, addr+1, sizeof(ins2));
95339b89a1fSdonn 	    if (ins2 == O_ACBF || ins2 == O_ACBD)
95439b89a1fSdonn 		/* actually ACBG and ACBH */
95539b89a1fSdonn 		goto branches;
95639b89a1fSdonn 	    /* fall through */
95739b89a1fSdonn 
95873a32ae3Slinton 	default:
95973a32ae3Slinton 	    addrstatus = SEQUENTIAL;
96073a32ae3Slinton 	    break;
96173a32ae3Slinton     }
96273a32ae3Slinton     if (addrstatus != KNOWN) {
96373a32ae3Slinton 	addr += 1;
96439b89a1fSdonn 	if (ins == O_ESCD) {
96539b89a1fSdonn 	    ins = ins2;
96639b89a1fSdonn 	    addr += 1;
96739b89a1fSdonn 	    op = esctab[ins];
96839b89a1fSdonn 	    if (op == nil) {
96939b89a1fSdonn 		printf("[bad extended opcode %#x in findnextaddr]\n", ins);
97039b89a1fSdonn 		return addr;
97139b89a1fSdonn 	    }
97239b89a1fSdonn 	} else {
973c6ec783fSdonn 	    op = ioptab[ins];
97439b89a1fSdonn 	    if (op == nil) {
97539b89a1fSdonn 		printf("[bad opcode %#x in findnextaddr]\n", ins);
97639b89a1fSdonn 		return addr;
97739b89a1fSdonn 	    }
97839b89a1fSdonn 	}
979c6ec783fSdonn 	for (argno = 0; argno < op->numargs; argno++) {
98073a32ae3Slinton 	    if (indexf == true) {
98173a32ae3Slinton 		indexf = false;
98273a32ae3Slinton 	    }
983c6ec783fSdonn 	    argtype = op->argtype[argno];
98473a32ae3Slinton 	    if (is_branch_disp(argtype)) {
98573a32ae3Slinton 		mode = 0xAF + (typelen(argtype) << 5);
98673a32ae3Slinton 	    } else {
98773a32ae3Slinton 		iread(&mode, addr, sizeof(mode));
98873a32ae3Slinton 		addr += 1;
98973a32ae3Slinton 	    }
99073a32ae3Slinton 	    r = regname[regnm(mode)];
99173a32ae3Slinton 	    amode = addrmode(mode);
99273a32ae3Slinton 	    switch (amode) {
99373a32ae3Slinton 		case LITSHORT:
99473a32ae3Slinton 		case LITUPTO31:
99573a32ae3Slinton 		case LITUPTO47:
99673a32ae3Slinton 		case LITUPTO63:
99773a32ae3Slinton 		    argval = mode;
99873a32ae3Slinton 		    break;
99973a32ae3Slinton 
100073a32ae3Slinton 		case INDEX:
100173a32ae3Slinton 		    indexf = true;
100273a32ae3Slinton 		    --argno;
100373a32ae3Slinton 		    break;
100473a32ae3Slinton 
100573a32ae3Slinton 		case REG:
100673a32ae3Slinton 		case REGDEF:
100773a32ae3Slinton 		case AUTODEC:
100873a32ae3Slinton 		    break;
100973a32ae3Slinton 
101073a32ae3Slinton 		case AUTOINC:
101173a32ae3Slinton 		    if (r == regname[PROGCTR]) {
101273a32ae3Slinton 			switch (typelen(argtype)) {
101373a32ae3Slinton 			    case TYPB:
101473a32ae3Slinton 				argval = getdisp(addr, 1, r, amode);
101573a32ae3Slinton 				addr += 1;
101673a32ae3Slinton 				break;
101773a32ae3Slinton 
101873a32ae3Slinton 			    case TYPW:
101973a32ae3Slinton 				argval = getdisp(addr, 2, r, amode);
102073a32ae3Slinton 				addr += 2;
102173a32ae3Slinton 				break;
102273a32ae3Slinton 
102373a32ae3Slinton 			    case TYPL:
102473a32ae3Slinton 				argval = getdisp(addr, 4, r, amode);
102573a32ae3Slinton 				addr += 4;
102673a32ae3Slinton 				break;
102773a32ae3Slinton 
102873a32ae3Slinton 			    case TYPF:
102973a32ae3Slinton 				iread(&argval, addr, sizeof(argval));
103073a32ae3Slinton 				addr += 4;
103173a32ae3Slinton 				break;
103273a32ae3Slinton 
103373a32ae3Slinton 			    case TYPQ:
103473a32ae3Slinton 			    case TYPD:
103539b89a1fSdonn 			    case TYPG:
103673a32ae3Slinton 				iread(&argval, addr+4, sizeof(argval));
103773a32ae3Slinton 				addr += 8;
103873a32ae3Slinton 				break;
103939b89a1fSdonn 
104039b89a1fSdonn 			    case TYPO:
104139b89a1fSdonn 			    case TYPH:
104239b89a1fSdonn 				iread(&argval, addr+12, sizeof(argval));
104339b89a1fSdonn 				addr += 16;
104439b89a1fSdonn 				break;
104573a32ae3Slinton 			}
104673a32ae3Slinton 		    }
104773a32ae3Slinton 		    break;
104873a32ae3Slinton 
104973a32ae3Slinton 		case AUTOINCDEF:
105073a32ae3Slinton 		    if (r == regname[PROGCTR]) {
105173a32ae3Slinton 			argval = getdisp(addr, 4, r, amode);
105273a32ae3Slinton 			addr += 4;
105373a32ae3Slinton 		    }
105473a32ae3Slinton 		    break;
105573a32ae3Slinton 
105673a32ae3Slinton 		case BYTEDISP:
105773a32ae3Slinton 		case BYTEDISPDEF:
105873a32ae3Slinton 		    argval = getdisp(addr, 1, r, amode);
105973a32ae3Slinton 		    addr += 1;
106073a32ae3Slinton 		    break;
106173a32ae3Slinton 
106273a32ae3Slinton 		case WORDDISP:
106373a32ae3Slinton 		case WORDDISPDEF:
106473a32ae3Slinton 		    argval = getdisp(addr, 2, r, amode);
106573a32ae3Slinton 		    addr += 2;
106673a32ae3Slinton 		    break;
106773a32ae3Slinton 
106873a32ae3Slinton 		case LONGDISP:
106973a32ae3Slinton 		case LONGDISPDEF:
107073a32ae3Slinton 		    argval = getdisp(addr, 4, r, amode);
107173a32ae3Slinton 		    addr += 4;
107273a32ae3Slinton 		    break;
107373a32ae3Slinton 	    }
107473a32ae3Slinton 	}
107573a32ae3Slinton 	if (ins == O_CALLS or ins == O_CALLG) {
107673a32ae3Slinton 	    argval += 2;
107773a32ae3Slinton 	}
107873a32ae3Slinton 	if (addrstatus == BRANCH) {
107973a32ae3Slinton 	    addr = argval;
108073a32ae3Slinton 	}
108173a32ae3Slinton     }
108273a32ae3Slinton     return addr;
108373a32ae3Slinton }
108473a32ae3Slinton 
108573a32ae3Slinton /*
108673a32ae3Slinton  * Get the displacement of an instruction that uses displacement addressing.
108773a32ae3Slinton  */
108873a32ae3Slinton 
getdisp(addr,nbytes,reg,mode)108973a32ae3Slinton private int getdisp(addr, nbytes, reg, mode)
109073a32ae3Slinton Address addr;
109173a32ae3Slinton int nbytes;
109273a32ae3Slinton String reg;
109373a32ae3Slinton int mode;
109473a32ae3Slinton {
109573a32ae3Slinton     char byte;
109673a32ae3Slinton     short hword;
109773a32ae3Slinton     int argval;
109873a32ae3Slinton 
109973a32ae3Slinton     switch (nbytes) {
110073a32ae3Slinton 	case 1:
110173a32ae3Slinton 	    iread(&byte, addr, sizeof(byte));
110273a32ae3Slinton 	    argval = byte;
110373a32ae3Slinton 	    break;
110473a32ae3Slinton 
110573a32ae3Slinton 	case 2:
110673a32ae3Slinton 	    iread(&hword, addr, sizeof(hword));
110773a32ae3Slinton 	    argval = hword;
110873a32ae3Slinton 	    break;
110973a32ae3Slinton 
111073a32ae3Slinton 	case 4:
111173a32ae3Slinton 	    iread(&argval, addr, sizeof(argval));
111273a32ae3Slinton 	    break;
111373a32ae3Slinton     }
111473a32ae3Slinton     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
111573a32ae3Slinton 	argval += addr + nbytes;
111673a32ae3Slinton     }
111773a32ae3Slinton     return argval;
111873a32ae3Slinton }
111973a32ae3Slinton 
112073a32ae3Slinton /*
112173a32ae3Slinton  * Enter a procedure by creating and executing a call instruction.
112273a32ae3Slinton  */
112373a32ae3Slinton 
112473a32ae3Slinton #define CALLSIZE 7	/* size of call instruction */
112573a32ae3Slinton 
beginproc(p,argc)112673a32ae3Slinton public beginproc(p, argc)
112773a32ae3Slinton Symbol p;
112873a32ae3Slinton Integer argc;
112973a32ae3Slinton {
113073a32ae3Slinton     char save[CALLSIZE];
113173a32ae3Slinton     struct {
113273a32ae3Slinton 	VaxOpcode op;
113373a32ae3Slinton 	unsigned char numargs;
113473a32ae3Slinton 	unsigned char mode;
113573a32ae3Slinton 	char addr[sizeof(long)];	/* unaligned long */
113673a32ae3Slinton     } call;
113773a32ae3Slinton     long dest;
113873a32ae3Slinton 
113973a32ae3Slinton     pc = 2;
114073a32ae3Slinton     iread(save, pc, sizeof(save));
114173a32ae3Slinton     call.op = O_CALLS;
114273a32ae3Slinton     call.numargs = argc;
114373a32ae3Slinton     call.mode = 0xef;
114473a32ae3Slinton     dest = codeloc(p) - 2 - (pc + 7);
114573a32ae3Slinton     mov(&dest, call.addr, sizeof(call.addr));
114673a32ae3Slinton     iwrite(&call, pc, sizeof(call));
114773a32ae3Slinton     setreg(PROGCTR, pc);
1148014c42d4Ssam     pstep(process, DEFSIG);
114973a32ae3Slinton     iwrite(save, pc, sizeof(save));
115073a32ae3Slinton     pc = reg(PROGCTR);
115173a32ae3Slinton     if (not isbperr()) {
115273a32ae3Slinton 	printstatus();
115373a32ae3Slinton     }
115473a32ae3Slinton }
11551cb06afbSsam 
11561cb06afbSsam /*
11571cb06afbSsam  * Special variables for debugging the kernel.
11581cb06afbSsam  */
11591cb06afbSsam 
11601cb06afbSsam public integer masterpcbb;
11611cb06afbSsam public integer slr;
11621cb06afbSsam public struct pte *sbr;
1163c6ec783fSdonn private struct pcb pcb;
11641cb06afbSsam 
getpcb()11651cb06afbSsam public getpcb ()
11661cb06afbSsam {
1167c6ec783fSdonn     integer i;
1168c6ec783fSdonn 
1169c6ec783fSdonn     fseek(corefile, masterpcbb & ~0x80000000, 0);
11701cb06afbSsam     get(corefile, pcb);
11711cb06afbSsam     pcb.pcb_p0lr &= ~AST_CLR;
11721cb06afbSsam     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
11731cb06afbSsam 	pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
11741cb06afbSsam     );
11751cb06afbSsam     setreg(0, pcb.pcb_r0);
11761cb06afbSsam     setreg(1, pcb.pcb_r1);
11771cb06afbSsam     setreg(2, pcb.pcb_r2);
11781cb06afbSsam     setreg(3, pcb.pcb_r3);
11791cb06afbSsam     setreg(4, pcb.pcb_r4);
11801cb06afbSsam     setreg(5, pcb.pcb_r5);
11811cb06afbSsam     setreg(6, pcb.pcb_r6);
11821cb06afbSsam     setreg(7, pcb.pcb_r7);
11831cb06afbSsam     setreg(8, pcb.pcb_r8);
11841cb06afbSsam     setreg(9, pcb.pcb_r9);
11851cb06afbSsam     setreg(10, pcb.pcb_r10);
11861cb06afbSsam     setreg(11, pcb.pcb_r11);
11871cb06afbSsam     setreg(ARGP, pcb.pcb_ap);
11881cb06afbSsam     setreg(FRP, pcb.pcb_fp);
11891cb06afbSsam     setreg(STKP, pcb.pcb_ksp);
11901cb06afbSsam     setreg(PROGCTR, pcb.pcb_pc);
11911cb06afbSsam }
11921cb06afbSsam 
copyregs(savreg,reg)11931cb06afbSsam public copyregs (savreg, reg)
11941cb06afbSsam Word savreg[], reg[];
11951cb06afbSsam {
11961cb06afbSsam     reg[0] = savreg[R0];
11971cb06afbSsam     reg[1] = savreg[R1];
11981cb06afbSsam     reg[2] = savreg[R2];
11991cb06afbSsam     reg[3] = savreg[R3];
12001cb06afbSsam     reg[4] = savreg[R4];
12011cb06afbSsam     reg[5] = savreg[R5];
12021cb06afbSsam     reg[6] = savreg[R6];
12031cb06afbSsam     reg[7] = savreg[R7];
12041cb06afbSsam     reg[8] = savreg[R8];
12051cb06afbSsam     reg[9] = savreg[R9];
12061cb06afbSsam     reg[10] = savreg[R10];
12071cb06afbSsam     reg[11] = savreg[R11];
12081cb06afbSsam     reg[ARGP] = savreg[AP];
12091cb06afbSsam     reg[FRP] = savreg[FP];
12101cb06afbSsam     reg[STKP] = savreg[SP];
12111cb06afbSsam     reg[PROGCTR] = savreg[PC];
12121cb06afbSsam }
12131cb06afbSsam 
12141cb06afbSsam /*
12151cb06afbSsam  * Map a virtual address to a physical address.
12161cb06afbSsam  */
12171cb06afbSsam 
vmap(addr)12181cb06afbSsam public Address vmap (addr)
12191cb06afbSsam Address addr;
12201cb06afbSsam {
12211cb06afbSsam     Address r;
12221cb06afbSsam     integer v, n;
12231cb06afbSsam     struct pte pte;
12241cb06afbSsam 
12251cb06afbSsam     r = addr & ~0xc0000000;
12261cb06afbSsam     v = btop(r);
12271cb06afbSsam     switch (addr&0xc0000000) {
12281cb06afbSsam 	case 0xc0000000:
12291cb06afbSsam 	case 0x80000000:
12301cb06afbSsam 	    /*
12311cb06afbSsam 	     * In system space, so get system pte.
12321cb06afbSsam 	     * If it is valid or reclaimable then the physical address
12331cb06afbSsam 	     * is the combination of its page number and the page offset
12341cb06afbSsam 	     * of the original address.
12351cb06afbSsam 	     */
12361cb06afbSsam 	    if (v >= slr) {
12371cb06afbSsam 		error("address %x out of segment", addr);
12381cb06afbSsam 	    }
12391cb06afbSsam 	    r = ((long) (sbr + v)) & ~0x80000000;
12401cb06afbSsam 	    goto simple;
12411cb06afbSsam 
12421cb06afbSsam 	case 0x40000000:
12431cb06afbSsam 	    /*
12441cb06afbSsam 	     * In p1 space, must not be in shadow region.
12451cb06afbSsam 	     */
12461cb06afbSsam 	    if (v < pcb.pcb_p1lr) {
12471cb06afbSsam 		error("address %x out of segment", addr);
12481cb06afbSsam 	    }
12491cb06afbSsam 	    r = (Address) (pcb.pcb_p1br + v);
12501cb06afbSsam 	    break;
12511cb06afbSsam 
12521cb06afbSsam 	case 0x00000000:
12531cb06afbSsam 	    /*
12541cb06afbSsam 	     * In p0 space, must not be off end of region.
12551cb06afbSsam 	     */
12561cb06afbSsam 	    if (v >= pcb.pcb_p0lr) {
12571cb06afbSsam 		error("address %x out of segment", addr);
12581cb06afbSsam 	    }
12591cb06afbSsam 	    r = (Address) (pcb.pcb_p0br + v);
12601cb06afbSsam 	    break;
12611cb06afbSsam 
12621cb06afbSsam 	default:
12631cb06afbSsam 	    /* do nothing */
12641cb06afbSsam 	    break;
12651cb06afbSsam     }
12661cb06afbSsam     /*
12671cb06afbSsam      * For p0/p1 address, user-level page table should be in
12681cb06afbSsam      * kernel virtual memory.  Do second-level indirect by recursing.
12691cb06afbSsam      */
12701cb06afbSsam     if ((r & 0x80000000) == 0) {
12711cb06afbSsam 	error("bad p0br or p1br in pcb");
12721cb06afbSsam     }
12731cb06afbSsam     r = vmap(r);
12741cb06afbSsam simple:
12751cb06afbSsam     /*
12761cb06afbSsam      * "r" is now the address of the pte of the page
12771cb06afbSsam      * we are interested in; get the pte and paste up the physical address.
12781cb06afbSsam      */
12791cb06afbSsam     fseek(corefile, r, 0);
12801cb06afbSsam     n = fread(&pte, sizeof(pte), 1, corefile);
12811cb06afbSsam     if (n != 1) {
12821cb06afbSsam 	error("page table botch (fread at %x returns %d)", r, n);
12831cb06afbSsam     }
12841cb06afbSsam     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
12851cb06afbSsam 	error("page no valid or reclamable");
12861cb06afbSsam     }
12871cb06afbSsam     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
12881cb06afbSsam }
1289c6ec783fSdonn 
1290c6ec783fSdonn /*
1291c6ec783fSdonn  * Extract a bit field from an integer.
1292c6ec783fSdonn  */
1293c6ec783fSdonn 
extractField(s)1294c6ec783fSdonn public integer extractField (s)
1295c6ec783fSdonn Symbol s;
1296c6ec783fSdonn {
1297c6ec783fSdonn     integer n, nbytes, r;
1298c6ec783fSdonn 
1299c6ec783fSdonn     n = 0;
1300c6ec783fSdonn     nbytes = size(s);
1301c6ec783fSdonn     if (nbytes > sizeof(n)) {
1302c6ec783fSdonn 	printf("[bad size in extractField -- word assumed]\n");
1303c6ec783fSdonn 	nbytes = sizeof(n);
1304c6ec783fSdonn     }
1305c6ec783fSdonn     popn(nbytes, &n);
1306c6ec783fSdonn     r = n >> (s->symvalue.field.offset mod BITSPERBYTE);
1307c6ec783fSdonn     r &= ((1 << s->symvalue.field.length) - 1);
1308c6ec783fSdonn     return r;
1309c6ec783fSdonn }
1310c6ec783fSdonn 
1311c6ec783fSdonn /*
1312c6ec783fSdonn  * Change the length of a value in memory according to a given difference
1313c6ec783fSdonn  * in the lengths of its new and old types.
1314c6ec783fSdonn  */
1315c6ec783fSdonn 
loophole(oldlen,newlen)1316c6ec783fSdonn public loophole (oldlen, newlen)
1317c6ec783fSdonn integer oldlen, newlen;
1318c6ec783fSdonn {
1319c6ec783fSdonn     integer n, i;
1320c6ec783fSdonn 
1321c6ec783fSdonn     n = newlen - oldlen;
1322c6ec783fSdonn     if (n > 0) {
1323c6ec783fSdonn 	for (i = 0; i < n; i++) {
1324c6ec783fSdonn 	    sp[i] = '\0';
1325c6ec783fSdonn 	}
1326c6ec783fSdonn     }
1327c6ec783fSdonn     sp += n;
1328c6ec783fSdonn }
1329