15508Slinton /* Copyright (c) 1982 Regents of the University of California */
25508Slinton 
3*10766Slinton static char sccsid[] = "@(#)resume.c 1.8 02/08/83";
45508Slinton 
55508Slinton /*
65508Slinton  * resume execution, first setting appropriate registers
75508Slinton  */
85508Slinton 
95508Slinton #include "defs.h"
105508Slinton #include <signal.h>
115508Slinton #include "process.h"
125508Slinton #include "machine.h"
135508Slinton #include "main.h"
145508Slinton #include "process.rep"
155508Slinton #include "runtime/frame.rep"
165508Slinton 
175714Slinton #   if (isvaxpx)
185714Slinton #       include "machine/pxerrors.h"
195714Slinton #       include "pxinfo.h"
205714Slinton #   endif
215508Slinton 
22*10766Slinton #ifdef vax
235508Slinton LOCAL ADDRESS fetchpc();
24*10766Slinton #endif
255508Slinton 
26*10766Slinton LOCAL ADDRESS *pcaddr;
27*10766Slinton 
285508Slinton /*
29*10766Slinton  * Resume execution, set (get) pcode location counter before (after) resuming.
305508Slinton  */
315508Slinton 
325508Slinton resume()
335508Slinton {
345714Slinton     register PROCESS *p;
355714Slinton     int oldsigno;
365508Slinton 
375714Slinton     p = process;
385714Slinton     do {
395714Slinton 	if (option('e')) {
405714Slinton 	    printf("execution resumes at pc 0x%x, lc %d\n", process->pc, pc);
415714Slinton 	    fflush(stdout);
425714Slinton 	}
435714Slinton 	pcont(p);
445714Slinton #       if (isvaxpx)
45*10766Slinton #           ifdef sun
46*10766Slinton 		if (pcaddr == 0) {
47*10766Slinton 		    dread(&pcaddr, PCADDRP, sizeof(pcaddr));
485508Slinton 		}
49*10766Slinton 		dread(&pc, pcaddr, sizeof(pc));
50*10766Slinton #           else ifdef vax
51*10766Slinton 		if (p->status == STOPPED) {
52*10766Slinton 		    if (isbperr()) {
53*10766Slinton 			pc = p->reg[11];
54*10766Slinton 		    } else {
55*10766Slinton 			dread(&pcframe, PCADDRP, sizeof(pcframe));
56*10766Slinton 			pcframe++;
57*10766Slinton 			pc = fetchpc(pcframe);
58*10766Slinton 		    }
59*10766Slinton 		    pc -= (sizeof(char) + ENDOFF);
60*10766Slinton 		}
61*10766Slinton #           endif
62*10766Slinton #       else /* compiled code */
635714Slinton 	    pc = process->pc;
645714Slinton #       endif
655714Slinton 	if (option('e')) {
665714Slinton 	    printf("execution stops at pc 0x%x, lc %d on sig %d\n",
675714Slinton 		process->pc, pc, p->signo);
685714Slinton 	    fflush(stdout);
695714Slinton 	}
705714Slinton 	if (p->status == STOPPED) {
715714Slinton 	    errnum = 0;
725714Slinton 	}
735714Slinton     } while (p->signo == SIGCONT);
745714Slinton #   if (isvaxpx)
755714Slinton 	if (option('r') && p->signo != 0) {
765714Slinton 	    choose();
775714Slinton 	}
78*10766Slinton 
79*10766Slinton     /*
80*10766Slinton      * If px implements a breakpoint by executing a halt instruction
81*10766Slinton      * (which is true on the VAX), the real pc must be incremented to
82*10766Slinton      * skip over it.  On other machines (such as SUNs), px sends itself
83*10766Slinton      * a signal and no incrementing is needed.
84*10766Slinton      */
85*10766Slinton #       ifdef vax
86*10766Slinton 	    if (isbperr()) {
87*10766Slinton 		p->pc++;
88*10766Slinton 	    }
89*10766Slinton #       endif
905714Slinton #   endif
915508Slinton }
925508Slinton 
935508Slinton # if (isvaxpx)
94*10766Slinton # ifdef vax
955508Slinton 
965508Slinton /*
975508Slinton  * Find the location in the Pascal object where execution was suspended.
985875Slinton  *
995875Slinton  * We basically walk back through the frames looking for saved
1005875Slinton  * register 11's.  Each time we find one, we remember it.  When we reach
1015875Slinton  * the frame associated with the interpreter procedure, the most recently
1025875Slinton  * saved register 11 is the one we want.
1035508Slinton  */
1045508Slinton 
1055508Slinton typedef struct {
1065714Slinton     int fr_handler;
1075714Slinton     unsigned int fr_psw : 16;   /* saved psw */
1085714Slinton     unsigned int fr_mask : 12;  /* register save mask */
1095714Slinton     unsigned int fr_unused : 1;
1105714Slinton     unsigned int fr_s : 1;      /* call was a calls, not callg */
1115714Slinton     unsigned int fr_spa : 2;    /* stack pointer alignment */
1125714Slinton     unsigned int fr_savap;      /* saved arg pointer */
1135714Slinton     unsigned int fr_savfp;      /* saved frame pointer */
1145714Slinton     int fr_savpc;           /* saved program counter */
1155508Slinton } Vaxframe;
1165508Slinton 
1175875Slinton #define regsaved(frame, n) ((frame.fr_mask&(1 << n)) != 0)
1185875Slinton 
1195508Slinton LOCAL ADDRESS fetchpc(framep)
1205508Slinton ADDRESS *framep;
1215508Slinton {
1225714Slinton     register PROCESS *p;
1235714Slinton     Vaxframe vframe;
1245714Slinton     ADDRESS *savfp;
1255714Slinton     ADDRESS r;
1265508Slinton 
1275714Slinton     p = process;
1285875Slinton     r = p->reg[11];
1295714Slinton     if (p->fp == (ADDRESS) framep) {
1305875Slinton 	return r;
1315714Slinton     }
1325714Slinton     savfp = (ADDRESS *) p->fp;
1335714Slinton     dread(&vframe, savfp, sizeof(vframe));
1345714Slinton     while (vframe.fr_savfp != (int) framep && vframe.fr_savfp != 0) {
1355875Slinton 	if (regsaved(vframe, 11)) {
1365875Slinton 	    dread(&r, savfp + 5, sizeof(r));
1375875Slinton 	    r -= sizeof(char);
1385875Slinton 	}
1395714Slinton 	savfp = (ADDRESS *) vframe.fr_savfp;
1405508Slinton 	dread(&vframe, savfp, sizeof(vframe));
1415714Slinton     }
1425714Slinton     if (vframe.fr_savfp == 0) {
1435714Slinton 	panic("resume: can't find interpreter frame 0x%x", framep);
1445714Slinton     }
1455875Slinton     if (regsaved(vframe, 11)) {
1465714Slinton 	dread(&r, savfp + 5, sizeof(r));
1475714Slinton 	r -= sizeof(char);
1485714Slinton     }
1495714Slinton     return(r);
1505508Slinton }
1515508Slinton 
152*10766Slinton # endif
153*10766Slinton 
1545508Slinton /*
1555508Slinton  * Under the -r option, we offer the opportunity to just get
1565508Slinton  * the px traceback and not actually enter the debugger.
1576074Slinton  *
1586074Slinton  * If the standard input is not a tty but standard error is,
1596074Slinton  * change standard input to be /dev/tty.
1605508Slinton  */
1615508Slinton 
1625508Slinton LOCAL choose()
1635508Slinton {
1645714Slinton     register int c;
1655508Slinton 
1666873Slinton     if (!isterm(stdin)) {
1676873Slinton 	if (!isterm(stderr) || freopen("/dev/tty", "r", stdin) == NIL) {
1686074Slinton 	    unsetsigtraces(process);
1696074Slinton 	    pcont(process);
1706074Slinton 	    quit(process->exitval);
1716074Slinton 	    /* NOTREACHED */
1726074Slinton 	}
1736074Slinton     }
1745714Slinton     fprintf(stderr, "\nProgram error");
1755714Slinton     if (errnum != 0) {
1765714Slinton 	fprintf(stderr, " -- %s", pxerrmsg[errnum]);
1775714Slinton     }
1785714Slinton     fprintf(stderr, "\nDo you wish to enter the debugger? ");
1795714Slinton     c = getchar();
1805714Slinton     if (c == 'n') {
1815714Slinton 	unsetsigtraces(process);
1825714Slinton 	pcont(process);
1835714Slinton 	quit(process->exitval);
1845714Slinton     }
1856074Slinton     while (c != '\n' && c != EOF) {
1865508Slinton 	c = getchar();
1875714Slinton     }
1885714Slinton     fprintf(stderr, "\nEntering debugger ...");
1895714Slinton     init();
1905714Slinton     option('r') = FALSE;
1915714Slinton     fprintf(stderr, " type 'help' for help.\n");
1925508Slinton }
1935508Slinton 
1945508Slinton # endif
195