121608Sdist /* 221608Sdist * Copyright (c) 1983 Regents of the University of California. 321608Sdist * All rights reserved. The Berkeley software License Agreement 421608Sdist * specifies the terms and conditions for redistribution. 521608Sdist */ 69668Slinton 721608Sdist #ifndef lint 8*33340Sdonn static char sccsid[] = "@(#)vax.c 5.4 (Berkeley) 01/12/88"; 921608Sdist #endif not lint 109668Slinton 11*33340Sdonn static char rcsid[] = "$Header: machine.c,v 1.2 87/03/26 14:54:55 donn Exp $"; 1218222Slinton 139668Slinton /* 149668Slinton * Target machine dependent stuff. 159668Slinton */ 169668Slinton 179668Slinton #include "defs.h" 189668Slinton #include "machine.h" 199668Slinton #include "process.h" 2016612Ssam #include "runtime.h" 219668Slinton #include "events.h" 229668Slinton #include "main.h" 239668Slinton #include "symbols.h" 249668Slinton #include "source.h" 259668Slinton #include "mappings.h" 269668Slinton #include "object.h" 27*33340Sdonn #include "tree.h" 28*33340Sdonn #include "eval.h" 2918222Slinton #include "keywords.h" 309693Slinton #include "ops.h" 319668Slinton 329668Slinton #ifndef public 339668Slinton typedef unsigned int Address; 349668Slinton typedef unsigned char Byte; 359668Slinton typedef unsigned int Word; 369668Slinton 379668Slinton #define NREG 16 389668Slinton 399668Slinton #define ARGP 12 409668Slinton #define FRP 13 419668Slinton #define STKP 14 429668Slinton #define PROGCTR 15 439668Slinton 44*33340Sdonn #define CODESTART 0 45*33340Sdonn #define FUNCOFFSET 2 46*33340Sdonn 47*33340Sdonn #define nargspassed(frame) argn(0, frame) 48*33340Sdonn 499668Slinton #define BITSPERBYTE 8 509668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) 519668Slinton 5226336Ssam /* 53*33340Sdonn * This magic macro enables us to look at the process' registers 54*33340Sdonn * in its user structure. 5526336Ssam */ 569668Slinton 57*33340Sdonn #define regloc(reg) (ctob(UPAGES) + (sizeof(Word) * (reg))) 5826336Ssam 599668Slinton #include "source.h" 609668Slinton #include "symbols.h" 61*33340Sdonn #include <signal.h> 6226344Ssam #include <sys/param.h> 6326344Ssam #include <sys/dir.h> 6426344Ssam #include <machine/psl.h> 6526344Ssam #include <machine/pte.h> 6626344Ssam #include <sys/user.h> 67*33340Sdonn #undef DELETE /* XXX */ 6826344Ssam #include <sys/vm.h> 6926344Ssam #include <machine/reg.h> 709668Slinton 719668Slinton Address pc; 729668Slinton Address prtaddr; 739668Slinton 749668Slinton #endif 759668Slinton 76*33340Sdonn /* 77*33340Sdonn * Indices into u. for use in collecting registers values. 78*33340Sdonn */ 79*33340Sdonn public int rloc[] ={ 80*33340Sdonn R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC 81*33340Sdonn }; 82*33340Sdonn 839668Slinton private Address printop(); 849668Slinton 85*33340Sdonn private Optab *ioptab[256]; /* index by opcode to optab */ 86*33340Sdonn 879668Slinton /* 88*33340Sdonn * Initialize the opcode lookup table. 8926344Ssam */ 90*33340Sdonn public optab_init() 91*33340Sdonn { 92*33340Sdonn register Optab *p; 9326344Ssam 94*33340Sdonn for (p = optab; p->iname; p++) 95*33340Sdonn ioptab[p->val & 0xff] = p; 96*33340Sdonn } 97*33340Sdonn 9826344Ssam /* 999668Slinton * Decode and print the instructions within the given address range. 1009668Slinton */ 1019668Slinton 1029668Slinton public printinst(lowaddr, highaddr) 1039668Slinton Address lowaddr; 1049668Slinton Address highaddr; 1059668Slinton { 1069668Slinton register Address addr; 1079668Slinton 1089668Slinton for (addr = lowaddr; addr <= highaddr; ) { 1099668Slinton addr = printop(addr); 1109668Slinton } 1119668Slinton prtaddr = addr; 1129668Slinton } 1139668Slinton 1149668Slinton /* 1159668Slinton * Another approach: print n instructions starting at the given address. 1169668Slinton */ 1179668Slinton 1189668Slinton public printninst(count, addr) 1199668Slinton int count; 1209668Slinton Address addr; 1219668Slinton { 1229668Slinton register Integer i; 1239668Slinton register Address newaddr; 1249668Slinton 1259668Slinton if (count <= 0) { 1269668Slinton error("non-positive repetition count"); 1279668Slinton } else { 1289668Slinton newaddr = addr; 1299668Slinton for (i = 0; i < count; i++) { 1309668Slinton newaddr = printop(newaddr); 1319668Slinton } 1329668Slinton prtaddr = newaddr; 1339668Slinton } 1349668Slinton } 1359668Slinton 1369668Slinton /* 1379668Slinton * Print the contents of the addresses within the given range 1389668Slinton * according to the given format. 1399668Slinton */ 1409668Slinton 1419668Slinton typedef struct { 1429668Slinton String name; 1439668Slinton String printfstring; 1449668Slinton int length; 1459668Slinton } Format; 1469668Slinton 1479668Slinton private Format fmt[] = { 1489668Slinton { "d", " %d", sizeof(short) }, 1499668Slinton { "D", " %ld", sizeof(long) }, 1509668Slinton { "o", " %o", sizeof(short) }, 1519668Slinton { "O", " %lo", sizeof(long) }, 1529668Slinton { "x", " %04x", sizeof(short) }, 1539668Slinton { "X", " %08x", sizeof(long) }, 1549668Slinton { "b", " \\%o", sizeof(char) }, 1559668Slinton { "c", " '%c'", sizeof(char) }, 1569668Slinton { "s", "%c", sizeof(char) }, 15714338Slinton { "f", " %f", sizeof(float) }, 1589668Slinton { "g", " %g", sizeof(double) }, 1599668Slinton { nil, nil, 0 } 1609668Slinton }; 1619668Slinton 16211174Slinton private Format *findformat(s) 16311174Slinton String s; 16411174Slinton { 16511174Slinton register Format *f; 16611174Slinton 16711174Slinton f = &fmt[0]; 16811174Slinton while (f->name != nil and not streq(f->name, s)) { 16911174Slinton ++f; 17011174Slinton } 17111174Slinton if (f->name == nil) { 17211174Slinton error("bad print format \"%s\"", s); 17311174Slinton } 17411174Slinton return f; 17511174Slinton } 17611174Slinton 177*33340Sdonn /* 178*33340Sdonn * Retrieve and print out the appropriate data in the given format. 179*33340Sdonn * Floats have to be handled specially to allow the compiler to 180*33340Sdonn * convert them to doubles when passing to printf. 181*33340Sdonn */ 182*33340Sdonn 183*33340Sdonn private printformat (f, addr) 184*33340Sdonn Format *f; 185*33340Sdonn Address addr; 186*33340Sdonn { 187*33340Sdonn union { 188*33340Sdonn char charv; 189*33340Sdonn short shortv; 190*33340Sdonn int intv; 191*33340Sdonn float floatv; 192*33340Sdonn double doublev; 193*33340Sdonn } value; 194*33340Sdonn 195*33340Sdonn value.intv = 0; 196*33340Sdonn dread(&value, addr, f->length); 197*33340Sdonn if (streq(f->name, "f")) { 198*33340Sdonn printf(f->printfstring, value.floatv); 199*33340Sdonn } else { 200*33340Sdonn printf(f->printfstring, value); 201*33340Sdonn } 202*33340Sdonn } 203*33340Sdonn 2049668Slinton public Address printdata(lowaddr, highaddr, format) 2059668Slinton Address lowaddr; 2069668Slinton Address highaddr; 2079668Slinton String format; 2089668Slinton { 209*33340Sdonn int n; 2109668Slinton register Address addr; 211*33340Sdonn Format *f; 2129668Slinton 2139668Slinton if (lowaddr > highaddr) { 2149668Slinton error("first address larger than second"); 2159668Slinton } 21611174Slinton f = findformat(format); 2179668Slinton n = 0; 2189668Slinton for (addr = lowaddr; addr <= highaddr; addr += f->length) { 2199668Slinton if (n == 0) { 2209668Slinton printf("%08x: ", addr); 2219668Slinton } 222*33340Sdonn printformat(f, addr); 2239668Slinton ++n; 2249668Slinton if (n >= (16 div f->length)) { 225*33340Sdonn printf("\n"); 2269668Slinton n = 0; 2279668Slinton } 2289668Slinton } 2299668Slinton if (n != 0) { 230*33340Sdonn printf("\n"); 2319668Slinton } 2329668Slinton prtaddr = addr; 2339668Slinton return addr; 2349668Slinton } 2359668Slinton 2369668Slinton /* 2379668Slinton * The other approach is to print n items starting with a given address. 2389668Slinton */ 2399668Slinton 2409668Slinton public printndata(count, startaddr, format) 2419668Slinton int count; 2429668Slinton Address startaddr; 2439668Slinton String format; 2449668Slinton { 245*33340Sdonn int i, n; 246*33340Sdonn Address addr; 247*33340Sdonn Format *f; 248*33340Sdonn Boolean isstring; 24914338Slinton char c; 2509668Slinton 2519668Slinton if (count <= 0) { 2529668Slinton error("non-positive repetition count"); 2539668Slinton } 25411174Slinton f = findformat(format); 2559668Slinton isstring = (Boolean) streq(f->name, "s"); 2569668Slinton n = 0; 2579668Slinton addr = startaddr; 2589668Slinton for (i = 0; i < count; i++) { 2599668Slinton if (n == 0) { 2609668Slinton printf("%08x: ", addr); 2619668Slinton } 2629668Slinton if (isstring) { 263*33340Sdonn printf("\""); 26414338Slinton dread(&c, addr, sizeof(char)); 26514338Slinton while (c != '\0') { 26614338Slinton printchar(c); 2679668Slinton ++addr; 26814338Slinton dread(&c, addr, sizeof(char)); 2699668Slinton } 270*33340Sdonn printf("\"\n"); 2719668Slinton n = 0; 2729668Slinton addr += sizeof(String); 2739668Slinton } else { 274*33340Sdonn printformat(f, addr); 2759668Slinton ++n; 2769668Slinton if (n >= (16 div f->length)) { 277*33340Sdonn printf("\n"); 2789668Slinton n = 0; 2799668Slinton } 2809668Slinton addr += f->length; 2819668Slinton } 2829668Slinton } 2839668Slinton if (n != 0) { 284*33340Sdonn printf("\n"); 2859668Slinton } 2869668Slinton prtaddr = addr; 2879668Slinton } 2889668Slinton 2899668Slinton /* 29011174Slinton * Print out a value according to the given format. 29111174Slinton */ 29211174Slinton 29311174Slinton public printvalue(v, format) 29411174Slinton long v; 29511174Slinton String format; 29611174Slinton { 29711174Slinton Format *f; 29811174Slinton char *p, *q; 29911174Slinton 30011174Slinton f = findformat(format); 30111174Slinton if (streq(f->name, "s")) { 30211174Slinton putchar('"'); 30311174Slinton p = (char *) &v; 30411174Slinton q = p + sizeof(v); 30511174Slinton while (p < q) { 30611174Slinton printchar(*p); 30711174Slinton ++p; 30811174Slinton } 30911174Slinton putchar('"'); 31011174Slinton } else { 31111174Slinton printf(f->printfstring, v); 31211174Slinton } 31311174Slinton putchar('\n'); 31411174Slinton } 31511174Slinton 31611174Slinton /* 3179668Slinton * Print out an execution time error. 3189842Slinton * Assumes the source position of the error has been calculated. 3199668Slinton * 3209668Slinton * Have to check if the -r option was specified; if so then 3219668Slinton * the object file information hasn't been read in yet. 3229668Slinton */ 3239668Slinton 3249668Slinton public printerror() 3259668Slinton { 3269668Slinton extern Integer sys_nsig; 3279668Slinton extern String sys_siglist[]; 32818222Slinton integer err; 3299668Slinton 3309668Slinton if (isfinished(process)) { 33116932Ssam err = exitcode(process); 33218222Slinton if (err == 0) { 33318222Slinton printf("\"%s\" terminated normally\n", objname); 33418222Slinton } else { 33518222Slinton printf("\"%s\" terminated abnormally (exit code %d)\n", 33618222Slinton objname, err 33718222Slinton ); 33818222Slinton } 3399668Slinton erecover(); 3409668Slinton } 3419668Slinton err = errnum(process); 3429668Slinton putchar('\n'); 34316932Ssam printsig(err); 34418222Slinton putchar(' '); 34516932Ssam printloc(); 34616932Ssam putchar('\n'); 3479668Slinton if (curline > 0) { 3489668Slinton printlines(curline, curline); 3499668Slinton } else { 3509668Slinton printinst(pc, pc); 3519668Slinton } 3529668Slinton erecover(); 3539668Slinton } 3549668Slinton 35518222Slinton /* 35618222Slinton * Print out a signal. 35718222Slinton */ 35818222Slinton 35916932Ssam private String illinames[] = { 36018222Slinton "reserved addressing fault", 361*33340Sdonn "privileged instruction fault", 36218222Slinton "reserved operand fault" 36316932Ssam }; 36418222Slinton 36516932Ssam private String fpenames[] = { 36618222Slinton nil, 36718222Slinton "integer overflow trap", 36818222Slinton "integer divide by zero trap", 36918222Slinton "floating overflow trap", 37018222Slinton "floating/decimal divide by zero trap", 37118222Slinton "floating underflow trap", 37218222Slinton "decimal overflow trap", 37318222Slinton "subscript out of range trap", 37418222Slinton "floating overflow fault", 37518222Slinton "floating divide by zero fault", 376*33340Sdonn "floating underflow fault" 37716932Ssam }; 37816932Ssam 37918222Slinton public printsig (signo) 38018222Slinton integer signo; 38116932Ssam { 38218222Slinton integer code; 38316932Ssam 38418222Slinton if (signo < 0 or signo > sys_nsig) { 38518222Slinton printf("[signal %d]", signo); 38618222Slinton } else { 38718222Slinton printf("%s", sys_siglist[signo]); 38816932Ssam } 38918222Slinton code = errcode(process); 39018222Slinton if (signo == SIGILL) { 39118222Slinton if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) { 39218222Slinton printf(" (%s)", illinames[code]); 39318222Slinton } 39418222Slinton } else if (signo == SIGFPE) { 39518222Slinton if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) { 39618222Slinton printf(" (%s)", fpenames[code]); 39718222Slinton } 39818222Slinton } 39916932Ssam } 40016932Ssam 4019668Slinton /* 4029668Slinton * Note the termination of the program. We do this so as to avoid 4039668Slinton * having the process exit, which would make the values of variables 4049668Slinton * inaccessible. We do want to flush all output buffers here, 4059668Slinton * otherwise it'll never get done. 4069668Slinton */ 4079668Slinton 4089668Slinton public endprogram() 4099668Slinton { 4109668Slinton Integer exitcode; 4119668Slinton 4129668Slinton stepto(nextaddr(pc, true)); 4139668Slinton printnews(); 4149668Slinton exitcode = argn(1, nil); 41518222Slinton if (exitcode != 0) { 41618222Slinton printf("\nexecution completed (exit code %d)\n", exitcode); 41718222Slinton } else { 41818222Slinton printf("\nexecution completed\n"); 41918222Slinton } 4209668Slinton getsrcpos(); 4219668Slinton erecover(); 4229668Slinton } 4239668Slinton 4249668Slinton /* 4259668Slinton * Single step the machine a source line (or instruction if "inst_tracing" 42610621Slinton * is true). If "isnext" is true, skip over procedure calls. 4279668Slinton */ 4289668Slinton 4299668Slinton private Address getcall(); 4309668Slinton 4319668Slinton public dostep(isnext) 4329668Slinton Boolean isnext; 4339668Slinton { 4349668Slinton register Address addr; 4359668Slinton register Lineno line; 4369668Slinton String filename; 43718222Slinton Address startaddr; 4389668Slinton 43916612Ssam startaddr = pc; 4409668Slinton addr = nextaddr(pc, isnext); 44110621Slinton if (not inst_tracing and nlhdr.nlines != 0) { 4429668Slinton line = linelookup(addr); 4439668Slinton while (line == 0) { 44418222Slinton addr = nextaddr(addr, isnext); 4459668Slinton line = linelookup(addr); 4469668Slinton } 44710621Slinton curline = line; 44810621Slinton } else { 44910621Slinton curline = 0; 4509668Slinton } 4519668Slinton stepto(addr); 4529668Slinton filename = srcfilename(addr); 4539668Slinton setsource(filename); 4549668Slinton } 4559668Slinton 456*33340Sdonn typedef char Bpinst; 457*33340Sdonn 458*33340Sdonn #define BP_OP O_BPT /* breakpoint trap */ 459*33340Sdonn 460*33340Sdonn #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 461*33340Sdonn 4629668Slinton /* 463*33340Sdonn * Setting a breakpoint at a location consists of saving 464*33340Sdonn * the word at the location and poking a BP_OP there. 465*33340Sdonn * 466*33340Sdonn * We save the locations and words on a list for use in unsetting. 467*33340Sdonn */ 468*33340Sdonn 469*33340Sdonn typedef struct Savelist *Savelist; 470*33340Sdonn 471*33340Sdonn struct Savelist { 472*33340Sdonn Address location; 473*33340Sdonn Bpinst save; 474*33340Sdonn short refcount; 475*33340Sdonn Savelist link; 476*33340Sdonn }; 477*33340Sdonn 478*33340Sdonn private Savelist savelist; 479*33340Sdonn 480*33340Sdonn /* 481*33340Sdonn * Set a breakpoint at the given address. Only save the word there 482*33340Sdonn * if it's not already a breakpoint. 483*33340Sdonn */ 484*33340Sdonn 485*33340Sdonn public setbp(addr) 486*33340Sdonn Address addr; 487*33340Sdonn { 488*33340Sdonn Bpinst w, save; 489*33340Sdonn register Savelist newsave, s; 490*33340Sdonn 491*33340Sdonn for (s = savelist; s != nil; s = s->link) { 492*33340Sdonn if (s->location == addr) { 493*33340Sdonn s->refcount++; 494*33340Sdonn return; 495*33340Sdonn } 496*33340Sdonn } 497*33340Sdonn iread(&save, addr, sizeof(save)); 498*33340Sdonn newsave = new(Savelist); 499*33340Sdonn newsave->location = addr; 500*33340Sdonn newsave->save = save; 501*33340Sdonn newsave->refcount = 1; 502*33340Sdonn newsave->link = savelist; 503*33340Sdonn savelist = newsave; 504*33340Sdonn w = BP_OP; 505*33340Sdonn iwrite(&w, addr, sizeof(w)); 506*33340Sdonn } 507*33340Sdonn 508*33340Sdonn /* 509*33340Sdonn * Unset a breakpoint; unfortunately we have to search the SAVELIST 510*33340Sdonn * to find the saved value. The assumption is that the SAVELIST will 511*33340Sdonn * usually be quite small. 512*33340Sdonn */ 513*33340Sdonn 514*33340Sdonn public unsetbp(addr) 515*33340Sdonn Address addr; 516*33340Sdonn { 517*33340Sdonn register Savelist s, prev; 518*33340Sdonn 519*33340Sdonn prev = nil; 520*33340Sdonn for (s = savelist; s != nil; s = s->link) { 521*33340Sdonn if (s->location == addr) { 522*33340Sdonn iwrite(&s->save, addr, sizeof(s->save)); 523*33340Sdonn s->refcount--; 524*33340Sdonn if (s->refcount == 0) { 525*33340Sdonn if (prev == nil) { 526*33340Sdonn savelist = s->link; 527*33340Sdonn } else { 528*33340Sdonn prev->link = s->link; 529*33340Sdonn } 530*33340Sdonn dispose(s); 531*33340Sdonn } 532*33340Sdonn return; 533*33340Sdonn } 534*33340Sdonn prev = s; 535*33340Sdonn } 536*33340Sdonn panic("unsetbp: couldn't find address %d", addr); 537*33340Sdonn } 538*33340Sdonn 539*33340Sdonn /* 540*33340Sdonn * VAX instruction decoder, derived from adb. 541*33340Sdonn */ 542*33340Sdonn 543*33340Sdonn private Address printop(addr) 544*33340Sdonn Address addr; 545*33340Sdonn { 546*33340Sdonn register Optab *op; 547*33340Sdonn VaxOpcode ins; 548*33340Sdonn unsigned char mode; 549*33340Sdonn int argtype, amode, argno, argval; 550*33340Sdonn String reg; 551*33340Sdonn Boolean indexf; 552*33340Sdonn short offset; 553*33340Sdonn 554*33340Sdonn argval = 0; 555*33340Sdonn indexf = false; 556*33340Sdonn printf("%08x ", addr); 557*33340Sdonn iread(&ins, addr, sizeof(ins)); 558*33340Sdonn addr += 1; 559*33340Sdonn op = ioptab[ins]; 560*33340Sdonn printf("%s", op->iname); 561*33340Sdonn for (argno = 0; argno < op->numargs; argno++) { 562*33340Sdonn if (indexf == true) { 563*33340Sdonn indexf = false; 564*33340Sdonn } else if (argno == 0) { 565*33340Sdonn printf("\t"); 566*33340Sdonn } else { 567*33340Sdonn printf(","); 568*33340Sdonn } 569*33340Sdonn argtype = op->argtype[argno]; 570*33340Sdonn if (is_branch_disp(argtype)) { 571*33340Sdonn mode = 0xAF + (typelen(argtype) << 5); 572*33340Sdonn } else { 573*33340Sdonn iread(&mode, addr, sizeof(mode)); 574*33340Sdonn addr += 1; 575*33340Sdonn } 576*33340Sdonn reg = regname[regnm(mode)]; 577*33340Sdonn amode = addrmode(mode); 578*33340Sdonn switch (amode) { 579*33340Sdonn case LITSHORT: 580*33340Sdonn case LITUPTO31: 581*33340Sdonn case LITUPTO47: 582*33340Sdonn case LITUPTO63: 583*33340Sdonn if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD) 584*33340Sdonn printf("$%s", fltimm[mode]); 585*33340Sdonn else 586*33340Sdonn printf("$%x", mode); 587*33340Sdonn argval = mode; 588*33340Sdonn break; 589*33340Sdonn 590*33340Sdonn case INDEX: 591*33340Sdonn printf("[%s]", reg); 592*33340Sdonn indexf = true; 593*33340Sdonn argno--; 594*33340Sdonn break; 595*33340Sdonn 596*33340Sdonn case REG: 597*33340Sdonn printf("%s", reg); 598*33340Sdonn break; 599*33340Sdonn 600*33340Sdonn case REGDEF: 601*33340Sdonn printf("(%s)", reg); 602*33340Sdonn break; 603*33340Sdonn 604*33340Sdonn case AUTODEC: 605*33340Sdonn printf("-(%s)", reg); 606*33340Sdonn break; 607*33340Sdonn 608*33340Sdonn case AUTOINC: 609*33340Sdonn if (reg != regname[PROGCTR]) { 610*33340Sdonn printf("(%s)+", reg); 611*33340Sdonn } else { 612*33340Sdonn printf("$"); 613*33340Sdonn switch (typelen(argtype)) { 614*33340Sdonn case TYPB: 615*33340Sdonn argval = printdisp(addr, 1, reg, amode); 616*33340Sdonn addr += 1; 617*33340Sdonn break; 618*33340Sdonn 619*33340Sdonn case TYPW: 620*33340Sdonn argval = printdisp(addr, 2, reg, amode); 621*33340Sdonn addr += 2; 622*33340Sdonn break; 623*33340Sdonn 624*33340Sdonn case TYPL: 625*33340Sdonn argval = printdisp(addr, 4, reg, amode); 626*33340Sdonn addr += 4; 627*33340Sdonn break; 628*33340Sdonn 629*33340Sdonn case TYPF: 630*33340Sdonn iread(&argval, addr, sizeof(argval)); 631*33340Sdonn printf("%06x", argval); 632*33340Sdonn addr += 4; 633*33340Sdonn break; 634*33340Sdonn 635*33340Sdonn case TYPQ: 636*33340Sdonn case TYPD: 637*33340Sdonn iread(&argval, addr, sizeof(argval)); 638*33340Sdonn printf("%06x", argval); 639*33340Sdonn iread(&argval, addr+4, sizeof(argval)); 640*33340Sdonn printf("%06x", argval); 641*33340Sdonn addr += 8; 642*33340Sdonn break; 643*33340Sdonn } 644*33340Sdonn } 645*33340Sdonn break; 646*33340Sdonn 647*33340Sdonn case AUTOINCDEF: 648*33340Sdonn if (reg == regname[PROGCTR]) { 649*33340Sdonn printf("*$"); 650*33340Sdonn argval = printdisp(addr, 4, reg, amode); 651*33340Sdonn addr += 4; 652*33340Sdonn } else { 653*33340Sdonn printf("*(%s)+", reg); 654*33340Sdonn } 655*33340Sdonn break; 656*33340Sdonn 657*33340Sdonn case BYTEDISP: 658*33340Sdonn argval = printdisp(addr, 1, reg, amode); 659*33340Sdonn addr += 1; 660*33340Sdonn break; 661*33340Sdonn 662*33340Sdonn case BYTEDISPDEF: 663*33340Sdonn printf("*"); 664*33340Sdonn argval = printdisp(addr, 1, reg, amode); 665*33340Sdonn addr += 1; 666*33340Sdonn break; 667*33340Sdonn 668*33340Sdonn case WORDDISP: 669*33340Sdonn argval = printdisp(addr, 2, reg, amode); 670*33340Sdonn addr += 2; 671*33340Sdonn break; 672*33340Sdonn 673*33340Sdonn case WORDDISPDEF: 674*33340Sdonn printf("*"); 675*33340Sdonn argval = printdisp(addr, 2, reg, amode); 676*33340Sdonn addr += 2; 677*33340Sdonn break; 678*33340Sdonn 679*33340Sdonn case LONGDISP: 680*33340Sdonn argval = printdisp(addr, 4, reg, amode); 681*33340Sdonn addr += 4; 682*33340Sdonn break; 683*33340Sdonn 684*33340Sdonn case LONGDISPDEF: 685*33340Sdonn printf("*"); 686*33340Sdonn argval = printdisp(addr, 4, reg, amode); 687*33340Sdonn addr += 4; 688*33340Sdonn break; 689*33340Sdonn } 690*33340Sdonn } 691*33340Sdonn if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) { 692*33340Sdonn for (argno = 0; argno <= argval; argno++) { 693*33340Sdonn iread(&offset, addr, sizeof(offset)); 694*33340Sdonn printf("\n\t\t%d", offset); 695*33340Sdonn addr += 2; 696*33340Sdonn } 697*33340Sdonn } 698*33340Sdonn printf("\n"); 699*33340Sdonn return addr; 700*33340Sdonn } 701*33340Sdonn 702*33340Sdonn /* 703*33340Sdonn * Print the displacement of an instruction that uses displacement 704*33340Sdonn * addressing. 705*33340Sdonn */ 706*33340Sdonn 707*33340Sdonn private int printdisp(addr, nbytes, reg, mode) 708*33340Sdonn Address addr; 709*33340Sdonn int nbytes; 710*33340Sdonn char *reg; 711*33340Sdonn int mode; 712*33340Sdonn { 713*33340Sdonn char byte; 714*33340Sdonn short hword; 715*33340Sdonn int argval; 716*33340Sdonn Symbol f; 717*33340Sdonn 718*33340Sdonn switch (nbytes) { 719*33340Sdonn case 1: 720*33340Sdonn iread(&byte, addr, sizeof(byte)); 721*33340Sdonn argval = byte; 722*33340Sdonn break; 723*33340Sdonn 724*33340Sdonn case 2: 725*33340Sdonn iread(&hword, addr, sizeof(hword)); 726*33340Sdonn argval = hword; 727*33340Sdonn break; 728*33340Sdonn 729*33340Sdonn case 4: 730*33340Sdonn iread(&argval, addr, sizeof(argval)); 731*33340Sdonn break; 732*33340Sdonn } 733*33340Sdonn if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 734*33340Sdonn argval += addr + nbytes; 735*33340Sdonn } 736*33340Sdonn if (reg == regname[PROGCTR]) { 737*33340Sdonn f = whatblock((Address) argval + 2); 738*33340Sdonn if (codeloc(f) == argval + 2) { 739*33340Sdonn printf("%s", symname(f)); 740*33340Sdonn } else { 741*33340Sdonn printf("%x", argval); 742*33340Sdonn } 743*33340Sdonn } else { 744*33340Sdonn if (varIsSet("$hexoffsets")) { 745*33340Sdonn if (argval < 0) { 746*33340Sdonn printf("-%x(%s)", -(argval), reg); 747*33340Sdonn } else { 748*33340Sdonn printf("%x(%s)", argval, reg); 749*33340Sdonn } 750*33340Sdonn } else { 751*33340Sdonn printf("%d(%s)", argval, reg); 752*33340Sdonn } 753*33340Sdonn } 754*33340Sdonn return argval; 755*33340Sdonn } 756*33340Sdonn 757*33340Sdonn /* 7589668Slinton * Compute the next address that will be executed from the given one. 7599668Slinton * If "isnext" is true then consider a procedure call as straight line code. 7609668Slinton * 7619668Slinton * We must unfortunately do much of the same work that is necessary 7629668Slinton * to print instructions. In addition we have to deal with branches. 7639668Slinton * Unconditional branches we just follow, for conditional branches 7649668Slinton * we continue execution to the current location and then single step 7659668Slinton * the machine. We assume that the last argument in an instruction 7669668Slinton * that branches is the branch address (or relative offset). 7679668Slinton */ 7689668Slinton 76918222Slinton private Address findnextaddr(); 77018222Slinton 7719668Slinton public Address nextaddr(startaddr, isnext) 7729668Slinton Address startaddr; 77316612Ssam boolean isnext; 77416612Ssam { 77516612Ssam Address addr; 77616612Ssam 77716612Ssam addr = usignal(process); 77816612Ssam if (addr == 0 or addr == 1) { 77916612Ssam addr = findnextaddr(startaddr, isnext); 78016612Ssam } 78116612Ssam return addr; 78216612Ssam } 78316612Ssam 78418222Slinton /* 78518222Slinton * Determine if it's ok to skip function f entered by instruction ins. 78618222Slinton * If so, we're going to compute the return address and step to it. 78718222Slinton * Therefore we cannot skip over a function entered by a jsb or bsb, 78818222Slinton * since the return address is not easily computed for them. 78918222Slinton */ 79018222Slinton 79118222Slinton private boolean skipfunc (ins, f) 79218222Slinton VaxOpcode ins; 79318222Slinton Symbol f; 79418222Slinton { 79518222Slinton boolean b; 79618222Slinton 79718222Slinton b = (boolean) ( 79818222Slinton ins != O_JSB and ins != O_BSBB and ins != O_BSBW and 79918222Slinton not inst_tracing and nlhdr.nlines != 0 and 80018222Slinton nosource(curfunc) and canskip(curfunc) 80118222Slinton ); 80218222Slinton return b; 80318222Slinton } 80418222Slinton 80516612Ssam private Address findnextaddr(startaddr, isnext) 80616612Ssam Address startaddr; 8079668Slinton Boolean isnext; 8089668Slinton { 8099668Slinton register Address addr; 810*33340Sdonn register Optab *op; 8119668Slinton VaxOpcode ins; 8129668Slinton unsigned char mode; 8139668Slinton int argtype, amode, argno, argval; 8149668Slinton String r; 8159668Slinton Boolean indexf; 8169668Slinton enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; 8179668Slinton 8189668Slinton argval = 0; 8199668Slinton indexf = false; 8209668Slinton addr = startaddr; 8219668Slinton iread(&ins, addr, sizeof(ins)); 8229668Slinton switch (ins) { 82318222Slinton /* 82418222Slinton * It used to be that unconditional jumps and branches were handled 82518222Slinton * by taking their destination address as the next address. While 82618222Slinton * saving the cost of starting up the process, this approach 82718222Slinton * doesn't work when jumping indirect (since the value in the 82818222Slinton * register might not yet have been set). 82918222Slinton * 83018222Slinton * So unconditional jumps and branches are now handled the same way 83118222Slinton * as conditional jumps and branches. 83218222Slinton * 8339668Slinton case O_BRB: 8349668Slinton case O_BRW: 8359668Slinton addrstatus = BRANCH; 8369668Slinton break; 83718222Slinton * 83818222Slinton */ 8399668Slinton 8409668Slinton case O_BSBB: 8419668Slinton case O_BSBW: 8429668Slinton case O_JSB: 8439668Slinton case O_CALLG: 8449668Slinton case O_CALLS: 84518222Slinton addrstatus = KNOWN; 84618222Slinton stepto(addr); 84718222Slinton pstep(process, DEFSIG); 84818222Slinton addr = reg(PROGCTR); 84918222Slinton pc = addr; 85018222Slinton setcurfunc(whatblock(pc)); 85118222Slinton if (not isbperr()) { 85218222Slinton printstatus(); 85318222Slinton /* NOTREACHED */ 85418222Slinton } 85518222Slinton bpact(); 85618222Slinton if (isnext or skipfunc(ins, curfunc)) { 8579668Slinton addrstatus = KNOWN; 85818222Slinton addr = return_addr(); 8599668Slinton stepto(addr); 86011864Slinton bpact(); 86118222Slinton } else { 86218222Slinton callnews(/* iscall = */ true); 8639668Slinton } 8649668Slinton break; 8659668Slinton 8669668Slinton case O_RSB: 8679668Slinton case O_RET: 8689668Slinton addrstatus = KNOWN; 86918222Slinton stepto(addr); 8709668Slinton callnews(/* iscall = */ false); 87118222Slinton pstep(process, DEFSIG); 87218222Slinton addr = reg(PROGCTR); 87318222Slinton pc = addr; 87418222Slinton if (not isbperr()) { 87518222Slinton printstatus(); 87616612Ssam } 87711874Slinton bpact(); 8789668Slinton break; 8799668Slinton 88018222Slinton case O_BRB: case O_BRW: 88116612Ssam case O_JMP: /* because it may be jmp (r1) */ 8829668Slinton case O_BNEQ: case O_BEQL: case O_BGTR: 8839668Slinton case O_BLEQ: case O_BGEQ: case O_BLSS: 8849668Slinton case O_BGTRU: case O_BLEQU: case O_BVC: 8859668Slinton case O_BVS: case O_BCC: case O_BCS: 8869668Slinton case O_CASEB: case O_CASEW: case O_CASEL: 8879668Slinton case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 8889668Slinton case O_BBSC: case O_BBCC: case O_BBSSI: 8899668Slinton case O_BBCCI: case O_BLBS: case O_BLBC: 8909668Slinton case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 8919668Slinton case O_SOBGEQ: case O_SOBGTR: 8929668Slinton addrstatus = KNOWN; 8939668Slinton stepto(addr); 89416612Ssam pstep(process, DEFSIG); 8959668Slinton addr = reg(PROGCTR); 8969668Slinton pc = addr; 8979668Slinton if (not isbperr()) { 8989668Slinton printstatus(); 8999668Slinton } 9009668Slinton break; 9019668Slinton 9029668Slinton default: 9039668Slinton addrstatus = SEQUENTIAL; 9049668Slinton break; 9059668Slinton } 9069668Slinton if (addrstatus != KNOWN) { 9079668Slinton addr += 1; 908*33340Sdonn op = ioptab[ins]; 909*33340Sdonn for (argno = 0; argno < op->numargs; argno++) { 9109668Slinton if (indexf == true) { 9119668Slinton indexf = false; 9129668Slinton } 913*33340Sdonn argtype = op->argtype[argno]; 9149668Slinton if (is_branch_disp(argtype)) { 9159668Slinton mode = 0xAF + (typelen(argtype) << 5); 9169668Slinton } else { 9179668Slinton iread(&mode, addr, sizeof(mode)); 9189668Slinton addr += 1; 9199668Slinton } 9209668Slinton r = regname[regnm(mode)]; 9219668Slinton amode = addrmode(mode); 9229668Slinton switch (amode) { 9239668Slinton case LITSHORT: 9249668Slinton case LITUPTO31: 9259668Slinton case LITUPTO47: 9269668Slinton case LITUPTO63: 9279668Slinton argval = mode; 9289668Slinton break; 9299668Slinton 9309668Slinton case INDEX: 9319668Slinton indexf = true; 9329668Slinton --argno; 9339668Slinton break; 9349668Slinton 9359668Slinton case REG: 9369668Slinton case REGDEF: 9379668Slinton case AUTODEC: 9389668Slinton break; 9399668Slinton 9409668Slinton case AUTOINC: 9419668Slinton if (r == regname[PROGCTR]) { 9429668Slinton switch (typelen(argtype)) { 9439668Slinton case TYPB: 9449668Slinton argval = getdisp(addr, 1, r, amode); 9459668Slinton addr += 1; 9469668Slinton break; 9479668Slinton 9489668Slinton case TYPW: 9499668Slinton argval = getdisp(addr, 2, r, amode); 9509668Slinton addr += 2; 9519668Slinton break; 9529668Slinton 9539668Slinton case TYPL: 9549668Slinton argval = getdisp(addr, 4, r, amode); 9559668Slinton addr += 4; 9569668Slinton break; 9579668Slinton 9589668Slinton case TYPF: 9599668Slinton iread(&argval, addr, sizeof(argval)); 9609668Slinton addr += 4; 9619668Slinton break; 9629668Slinton 9639668Slinton case TYPQ: 9649668Slinton case TYPD: 9659668Slinton iread(&argval, addr+4, sizeof(argval)); 9669668Slinton addr += 8; 9679668Slinton break; 9689668Slinton } 9699668Slinton } 9709668Slinton break; 9719668Slinton 9729668Slinton case AUTOINCDEF: 9739668Slinton if (r == regname[PROGCTR]) { 9749668Slinton argval = getdisp(addr, 4, r, amode); 9759668Slinton addr += 4; 9769668Slinton } 9779668Slinton break; 9789668Slinton 9799668Slinton case BYTEDISP: 9809668Slinton case BYTEDISPDEF: 9819668Slinton argval = getdisp(addr, 1, r, amode); 9829668Slinton addr += 1; 9839668Slinton break; 9849668Slinton 9859668Slinton case WORDDISP: 9869668Slinton case WORDDISPDEF: 9879668Slinton argval = getdisp(addr, 2, r, amode); 9889668Slinton addr += 2; 9899668Slinton break; 9909668Slinton 9919668Slinton case LONGDISP: 9929668Slinton case LONGDISPDEF: 9939668Slinton argval = getdisp(addr, 4, r, amode); 9949668Slinton addr += 4; 9959668Slinton break; 9969668Slinton } 9979668Slinton } 9989668Slinton if (ins == O_CALLS or ins == O_CALLG) { 9999668Slinton argval += 2; 10009668Slinton } 10019668Slinton if (addrstatus == BRANCH) { 10029668Slinton addr = argval; 10039668Slinton } 10049668Slinton } 10059668Slinton return addr; 10069668Slinton } 10079668Slinton 10089668Slinton /* 10099668Slinton * Get the displacement of an instruction that uses displacement addressing. 10109668Slinton */ 10119668Slinton 10129668Slinton private int getdisp(addr, nbytes, reg, mode) 10139668Slinton Address addr; 10149668Slinton int nbytes; 10159668Slinton String reg; 10169668Slinton int mode; 10179668Slinton { 10189668Slinton char byte; 10199668Slinton short hword; 10209668Slinton int argval; 10219668Slinton 10229668Slinton switch (nbytes) { 10239668Slinton case 1: 10249668Slinton iread(&byte, addr, sizeof(byte)); 10259668Slinton argval = byte; 10269668Slinton break; 10279668Slinton 10289668Slinton case 2: 10299668Slinton iread(&hword, addr, sizeof(hword)); 10309668Slinton argval = hword; 10319668Slinton break; 10329668Slinton 10339668Slinton case 4: 10349668Slinton iread(&argval, addr, sizeof(argval)); 10359668Slinton break; 10369668Slinton } 10379668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 10389668Slinton argval += addr + nbytes; 10399668Slinton } 10409668Slinton return argval; 10419668Slinton } 10429668Slinton 10439668Slinton /* 10449668Slinton * Enter a procedure by creating and executing a call instruction. 10459668Slinton */ 10469668Slinton 10479668Slinton #define CALLSIZE 7 /* size of call instruction */ 10489668Slinton 10499668Slinton public beginproc(p, argc) 10509668Slinton Symbol p; 10519668Slinton Integer argc; 10529668Slinton { 10539668Slinton char save[CALLSIZE]; 10549668Slinton struct { 10559668Slinton VaxOpcode op; 10569668Slinton unsigned char numargs; 10579668Slinton unsigned char mode; 10589668Slinton char addr[sizeof(long)]; /* unaligned long */ 10599668Slinton } call; 10609668Slinton long dest; 10619668Slinton 10629668Slinton pc = 2; 10639668Slinton iread(save, pc, sizeof(save)); 10649668Slinton call.op = O_CALLS; 10659668Slinton call.numargs = argc; 10669668Slinton call.mode = 0xef; 10679668Slinton dest = codeloc(p) - 2 - (pc + 7); 10689668Slinton mov(&dest, call.addr, sizeof(call.addr)); 10699668Slinton iwrite(&call, pc, sizeof(call)); 10709668Slinton setreg(PROGCTR, pc); 107116612Ssam pstep(process, DEFSIG); 10729668Slinton iwrite(save, pc, sizeof(save)); 10739668Slinton pc = reg(PROGCTR); 10749668Slinton if (not isbperr()) { 10759668Slinton printstatus(); 10769668Slinton } 10779668Slinton } 107826336Ssam 107926336Ssam /* 108026336Ssam * Special variables for debugging the kernel. 108126336Ssam */ 108226336Ssam 108326336Ssam public integer masterpcbb; 108426336Ssam public integer slr; 108526336Ssam public struct pte *sbr; 1086*33340Sdonn private struct pcb pcb; 108726336Ssam 108826336Ssam public getpcb () 108926336Ssam { 1090*33340Sdonn integer i; 1091*33340Sdonn 1092*33340Sdonn fseek(corefile, masterpcbb & ~0x80000000, 0); 109326336Ssam get(corefile, pcb); 109426336Ssam pcb.pcb_p0lr &= ~AST_CLR; 109526336Ssam printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n", 109626336Ssam pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr 109726336Ssam ); 109826336Ssam setreg(0, pcb.pcb_r0); 109926336Ssam setreg(1, pcb.pcb_r1); 110026336Ssam setreg(2, pcb.pcb_r2); 110126336Ssam setreg(3, pcb.pcb_r3); 110226336Ssam setreg(4, pcb.pcb_r4); 110326336Ssam setreg(5, pcb.pcb_r5); 110426336Ssam setreg(6, pcb.pcb_r6); 110526336Ssam setreg(7, pcb.pcb_r7); 110626336Ssam setreg(8, pcb.pcb_r8); 110726336Ssam setreg(9, pcb.pcb_r9); 110826336Ssam setreg(10, pcb.pcb_r10); 110926336Ssam setreg(11, pcb.pcb_r11); 111026336Ssam setreg(ARGP, pcb.pcb_ap); 111126336Ssam setreg(FRP, pcb.pcb_fp); 111226336Ssam setreg(STKP, pcb.pcb_ksp); 111326336Ssam setreg(PROGCTR, pcb.pcb_pc); 111426336Ssam } 111526336Ssam 111626336Ssam public copyregs (savreg, reg) 111726336Ssam Word savreg[], reg[]; 111826336Ssam { 111926336Ssam reg[0] = savreg[R0]; 112026336Ssam reg[1] = savreg[R1]; 112126336Ssam reg[2] = savreg[R2]; 112226336Ssam reg[3] = savreg[R3]; 112326336Ssam reg[4] = savreg[R4]; 112426336Ssam reg[5] = savreg[R5]; 112526336Ssam reg[6] = savreg[R6]; 112626336Ssam reg[7] = savreg[R7]; 112726336Ssam reg[8] = savreg[R8]; 112826336Ssam reg[9] = savreg[R9]; 112926336Ssam reg[10] = savreg[R10]; 113026336Ssam reg[11] = savreg[R11]; 113126336Ssam reg[ARGP] = savreg[AP]; 113226336Ssam reg[FRP] = savreg[FP]; 113326336Ssam reg[STKP] = savreg[SP]; 113426336Ssam reg[PROGCTR] = savreg[PC]; 113526336Ssam } 113626336Ssam 113726336Ssam /* 113826336Ssam * Map a virtual address to a physical address. 113926336Ssam */ 114026336Ssam 114126336Ssam public Address vmap (addr) 114226336Ssam Address addr; 114326336Ssam { 114426336Ssam Address r; 114526336Ssam integer v, n; 114626336Ssam struct pte pte; 114726336Ssam 114826336Ssam r = addr & ~0xc0000000; 114926336Ssam v = btop(r); 115026336Ssam switch (addr&0xc0000000) { 115126336Ssam case 0xc0000000: 115226336Ssam case 0x80000000: 115326336Ssam /* 115426336Ssam * In system space, so get system pte. 115526336Ssam * If it is valid or reclaimable then the physical address 115626336Ssam * is the combination of its page number and the page offset 115726336Ssam * of the original address. 115826336Ssam */ 115926336Ssam if (v >= slr) { 116026336Ssam error("address %x out of segment", addr); 116126336Ssam } 116226336Ssam r = ((long) (sbr + v)) & ~0x80000000; 116326336Ssam goto simple; 116426336Ssam 116526336Ssam case 0x40000000: 116626336Ssam /* 116726336Ssam * In p1 space, must not be in shadow region. 116826336Ssam */ 116926336Ssam if (v < pcb.pcb_p1lr) { 117026336Ssam error("address %x out of segment", addr); 117126336Ssam } 117226336Ssam r = (Address) (pcb.pcb_p1br + v); 117326336Ssam break; 117426336Ssam 117526336Ssam case 0x00000000: 117626336Ssam /* 117726336Ssam * In p0 space, must not be off end of region. 117826336Ssam */ 117926336Ssam if (v >= pcb.pcb_p0lr) { 118026336Ssam error("address %x out of segment", addr); 118126336Ssam } 118226336Ssam r = (Address) (pcb.pcb_p0br + v); 118326336Ssam break; 118426336Ssam 118526336Ssam default: 118626336Ssam /* do nothing */ 118726336Ssam break; 118826336Ssam } 118926336Ssam /* 119026336Ssam * For p0/p1 address, user-level page table should be in 119126336Ssam * kernel virtual memory. Do second-level indirect by recursing. 119226336Ssam */ 119326336Ssam if ((r & 0x80000000) == 0) { 119426336Ssam error("bad p0br or p1br in pcb"); 119526336Ssam } 119626336Ssam r = vmap(r); 119726336Ssam simple: 119826336Ssam /* 119926336Ssam * "r" is now the address of the pte of the page 120026336Ssam * we are interested in; get the pte and paste up the physical address. 120126336Ssam */ 120226336Ssam fseek(corefile, r, 0); 120326336Ssam n = fread(&pte, sizeof(pte), 1, corefile); 120426336Ssam if (n != 1) { 120526336Ssam error("page table botch (fread at %x returns %d)", r, n); 120626336Ssam } 120726336Ssam if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) { 120826336Ssam error("page no valid or reclamable"); 120926336Ssam } 121026336Ssam return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum)); 121126336Ssam } 1212*33340Sdonn 1213*33340Sdonn /* 1214*33340Sdonn * Extract a bit field from an integer. 1215*33340Sdonn */ 1216*33340Sdonn 1217*33340Sdonn public integer extractField (s) 1218*33340Sdonn Symbol s; 1219*33340Sdonn { 1220*33340Sdonn integer n, nbytes, r; 1221*33340Sdonn 1222*33340Sdonn n = 0; 1223*33340Sdonn nbytes = size(s); 1224*33340Sdonn if (nbytes > sizeof(n)) { 1225*33340Sdonn printf("[bad size in extractField -- word assumed]\n"); 1226*33340Sdonn nbytes = sizeof(n); 1227*33340Sdonn } 1228*33340Sdonn popn(nbytes, &n); 1229*33340Sdonn r = n >> (s->symvalue.field.offset mod BITSPERBYTE); 1230*33340Sdonn r &= ((1 << s->symvalue.field.length) - 1); 1231*33340Sdonn return r; 1232*33340Sdonn } 1233*33340Sdonn 1234*33340Sdonn /* 1235*33340Sdonn * Change the length of a value in memory according to a given difference 1236*33340Sdonn * in the lengths of its new and old types. 1237*33340Sdonn */ 1238*33340Sdonn 1239*33340Sdonn public loophole (oldlen, newlen) 1240*33340Sdonn integer oldlen, newlen; 1241*33340Sdonn { 1242*33340Sdonn integer n, i; 1243*33340Sdonn 1244*33340Sdonn n = newlen - oldlen; 1245*33340Sdonn if (n > 0) { 1246*33340Sdonn for (i = 0; i < n; i++) { 1247*33340Sdonn sp[i] = '\0'; 1248*33340Sdonn } 1249*33340Sdonn } 1250*33340Sdonn sp += n; 1251*33340Sdonn } 1252