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