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